VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllExec-x86.cpp@ 108260

Last change on this file since 108260 was 108260, checked in by vboxsync, 3 months ago

VMM/IEM: Splitting up IEMInline.h. jiraref:VBP-1531

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.4 KB
Line 
1/* $Id: IEMAllExec-x86.cpp 108260 2025-02-17 15:24:14Z vboxsync $ */
2/** @file
3 * IEM - Interpreted Execution Manager - x86 target, decoded instruction execution.
4 */
5
6/*
7 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.215389.xyz.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_IEM
33#define VMCPU_INCL_CPUM_GST_CTX
34#ifdef IN_RING0
35# define VBOX_VMM_TARGET_X86
36#endif
37#include <VBox/vmm/iem.h>
38#include <VBox/vmm/cpum.h>
39#include <VBox/vmm/dbgf.h>
40#include <VBox/vmm/iom.h>
41#include <VBox/vmm/gcm.h>
42#include <VBox/vmm/gim.h>
43#include "IEMInternal.h"
44#include <VBox/vmm/vmcc.h>
45#include <VBox/log.h>
46#include <VBox/err.h>
47#include <iprt/assert.h>
48#include <iprt/string.h>
49#include <iprt/x86.h>
50
51#include "IEMInline.h"
52#include "IEMInline-x86.h"
53
54
55/**
56 * Interface for HM and EM for executing string I/O OUT (write) instructions.
57 *
58 * This API ASSUMES that the caller has already verified that the guest code is
59 * allowed to access the I/O port. (The I/O port is in the DX register in the
60 * guest state.)
61 *
62 * @returns Strict VBox status code.
63 * @param pVCpu The cross context virtual CPU structure.
64 * @param cbValue The size of the I/O port access (1, 2, or 4).
65 * @param enmAddrMode The addressing mode.
66 * @param fRepPrefix Indicates whether a repeat prefix is used
67 * (doesn't matter which for this instruction).
68 * @param cbInstr The instruction length in bytes.
69 * @param iEffSeg The effective segment address.
70 * @param fIoChecked Whether the access to the I/O port has been
71 * checked or not. It's typically checked in the
72 * HM scenario.
73 */
74VMM_INT_DECL(VBOXSTRICTRC) IEMExecStringIoWrite(PVMCPUCC pVCpu, uint8_t cbValue, IEMMODE enmAddrMode,
75 bool fRepPrefix, uint8_t cbInstr, uint8_t iEffSeg, bool fIoChecked)
76{
77 AssertMsgReturn(iEffSeg < X86_SREG_COUNT, ("%#x\n", iEffSeg), VERR_IEM_INVALID_EFF_SEG);
78 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
79
80 /*
81 * State init.
82 */
83 iemInitExec(pVCpu, 0 /*fExecOpts*/);
84
85 /*
86 * Switch orgy for getting to the right handler.
87 */
88 VBOXSTRICTRC rcStrict;
89 if (fRepPrefix)
90 {
91 switch (enmAddrMode)
92 {
93 case IEMMODE_16BIT:
94 switch (cbValue)
95 {
96 case 1: rcStrict = iemCImpl_rep_outs_op8_addr16(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
97 case 2: rcStrict = iemCImpl_rep_outs_op16_addr16(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
98 case 4: rcStrict = iemCImpl_rep_outs_op32_addr16(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
99 default:
100 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
101 }
102 break;
103
104 case IEMMODE_32BIT:
105 switch (cbValue)
106 {
107 case 1: rcStrict = iemCImpl_rep_outs_op8_addr32(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
108 case 2: rcStrict = iemCImpl_rep_outs_op16_addr32(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
109 case 4: rcStrict = iemCImpl_rep_outs_op32_addr32(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
110 default:
111 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
112 }
113 break;
114
115 case IEMMODE_64BIT:
116 switch (cbValue)
117 {
118 case 1: rcStrict = iemCImpl_rep_outs_op8_addr64(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
119 case 2: rcStrict = iemCImpl_rep_outs_op16_addr64(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
120 case 4: rcStrict = iemCImpl_rep_outs_op32_addr64(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
121 default:
122 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
123 }
124 break;
125
126 default:
127 AssertMsgFailedReturn(("enmAddrMode=%d\n", enmAddrMode), VERR_IEM_INVALID_ADDRESS_MODE);
128 }
129 }
130 else
131 {
132 switch (enmAddrMode)
133 {
134 case IEMMODE_16BIT:
135 switch (cbValue)
136 {
137 case 1: rcStrict = iemCImpl_outs_op8_addr16(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
138 case 2: rcStrict = iemCImpl_outs_op16_addr16(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
139 case 4: rcStrict = iemCImpl_outs_op32_addr16(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
140 default:
141 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
142 }
143 break;
144
145 case IEMMODE_32BIT:
146 switch (cbValue)
147 {
148 case 1: rcStrict = iemCImpl_outs_op8_addr32(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
149 case 2: rcStrict = iemCImpl_outs_op16_addr32(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
150 case 4: rcStrict = iemCImpl_outs_op32_addr32(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
151 default:
152 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
153 }
154 break;
155
156 case IEMMODE_64BIT:
157 switch (cbValue)
158 {
159 case 1: rcStrict = iemCImpl_outs_op8_addr64(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
160 case 2: rcStrict = iemCImpl_outs_op16_addr64(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
161 case 4: rcStrict = iemCImpl_outs_op32_addr64(pVCpu, cbInstr, iEffSeg, fIoChecked); break;
162 default:
163 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
164 }
165 break;
166
167 default:
168 AssertMsgFailedReturn(("enmAddrMode=%d\n", enmAddrMode), VERR_IEM_INVALID_ADDRESS_MODE);
169 }
170 }
171
172 if (pVCpu->iem.s.cActiveMappings)
173 iemMemRollback(pVCpu);
174
175 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
176}
177
178
179/**
180 * Interface for HM and EM for executing string I/O IN (read) instructions.
181 *
182 * This API ASSUMES that the caller has already verified that the guest code is
183 * allowed to access the I/O port. (The I/O port is in the DX register in the
184 * guest state.)
185 *
186 * @returns Strict VBox status code.
187 * @param pVCpu The cross context virtual CPU structure.
188 * @param cbValue The size of the I/O port access (1, 2, or 4).
189 * @param enmAddrMode The addressing mode.
190 * @param fRepPrefix Indicates whether a repeat prefix is used
191 * (doesn't matter which for this instruction).
192 * @param cbInstr The instruction length in bytes.
193 * @param fIoChecked Whether the access to the I/O port has been
194 * checked or not. It's typically checked in the
195 * HM scenario.
196 */
197VMM_INT_DECL(VBOXSTRICTRC) IEMExecStringIoRead(PVMCPUCC pVCpu, uint8_t cbValue, IEMMODE enmAddrMode,
198 bool fRepPrefix, uint8_t cbInstr, bool fIoChecked)
199{
200 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
201
202 /*
203 * State init.
204 */
205 iemInitExec(pVCpu, 0 /*fExecOpts*/);
206
207 /*
208 * Switch orgy for getting to the right handler.
209 */
210 VBOXSTRICTRC rcStrict;
211 if (fRepPrefix)
212 {
213 switch (enmAddrMode)
214 {
215 case IEMMODE_16BIT:
216 switch (cbValue)
217 {
218 case 1: rcStrict = iemCImpl_rep_ins_op8_addr16(pVCpu, cbInstr, fIoChecked); break;
219 case 2: rcStrict = iemCImpl_rep_ins_op16_addr16(pVCpu, cbInstr, fIoChecked); break;
220 case 4: rcStrict = iemCImpl_rep_ins_op32_addr16(pVCpu, cbInstr, fIoChecked); break;
221 default:
222 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
223 }
224 break;
225
226 case IEMMODE_32BIT:
227 switch (cbValue)
228 {
229 case 1: rcStrict = iemCImpl_rep_ins_op8_addr32(pVCpu, cbInstr, fIoChecked); break;
230 case 2: rcStrict = iemCImpl_rep_ins_op16_addr32(pVCpu, cbInstr, fIoChecked); break;
231 case 4: rcStrict = iemCImpl_rep_ins_op32_addr32(pVCpu, cbInstr, fIoChecked); break;
232 default:
233 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
234 }
235 break;
236
237 case IEMMODE_64BIT:
238 switch (cbValue)
239 {
240 case 1: rcStrict = iemCImpl_rep_ins_op8_addr64(pVCpu, cbInstr, fIoChecked); break;
241 case 2: rcStrict = iemCImpl_rep_ins_op16_addr64(pVCpu, cbInstr, fIoChecked); break;
242 case 4: rcStrict = iemCImpl_rep_ins_op32_addr64(pVCpu, cbInstr, fIoChecked); break;
243 default:
244 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
245 }
246 break;
247
248 default:
249 AssertMsgFailedReturn(("enmAddrMode=%d\n", enmAddrMode), VERR_IEM_INVALID_ADDRESS_MODE);
250 }
251 }
252 else
253 {
254 switch (enmAddrMode)
255 {
256 case IEMMODE_16BIT:
257 switch (cbValue)
258 {
259 case 1: rcStrict = iemCImpl_ins_op8_addr16(pVCpu, cbInstr, fIoChecked); break;
260 case 2: rcStrict = iemCImpl_ins_op16_addr16(pVCpu, cbInstr, fIoChecked); break;
261 case 4: rcStrict = iemCImpl_ins_op32_addr16(pVCpu, cbInstr, fIoChecked); break;
262 default:
263 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
264 }
265 break;
266
267 case IEMMODE_32BIT:
268 switch (cbValue)
269 {
270 case 1: rcStrict = iemCImpl_ins_op8_addr32(pVCpu, cbInstr, fIoChecked); break;
271 case 2: rcStrict = iemCImpl_ins_op16_addr32(pVCpu, cbInstr, fIoChecked); break;
272 case 4: rcStrict = iemCImpl_ins_op32_addr32(pVCpu, cbInstr, fIoChecked); break;
273 default:
274 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
275 }
276 break;
277
278 case IEMMODE_64BIT:
279 switch (cbValue)
280 {
281 case 1: rcStrict = iemCImpl_ins_op8_addr64(pVCpu, cbInstr, fIoChecked); break;
282 case 2: rcStrict = iemCImpl_ins_op16_addr64(pVCpu, cbInstr, fIoChecked); break;
283 case 4: rcStrict = iemCImpl_ins_op32_addr64(pVCpu, cbInstr, fIoChecked); break;
284 default:
285 AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_IEM_INVALID_OPERAND_SIZE);
286 }
287 break;
288
289 default:
290 AssertMsgFailedReturn(("enmAddrMode=%d\n", enmAddrMode), VERR_IEM_INVALID_ADDRESS_MODE);
291 }
292 }
293
294 if ( pVCpu->iem.s.cActiveMappings == 0
295 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM))
296 { /* likely */ }
297 else
298 {
299 AssertMsg(!IOM_SUCCESS(rcStrict), ("%#x\n", VBOXSTRICTRC_VAL(rcStrict)));
300 iemMemRollback(pVCpu);
301 }
302 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
303}
304
305
306/**
307 * Interface for rawmode to write execute an OUT instruction.
308 *
309 * @returns Strict VBox status code.
310 * @param pVCpu The cross context virtual CPU structure.
311 * @param cbInstr The instruction length in bytes.
312 * @param u16Port The port to read.
313 * @param fImm Whether the port is specified using an immediate operand or
314 * using the implicit DX register.
315 * @param cbReg The register size.
316 *
317 * @remarks In ring-0 not all of the state needs to be synced in.
318 */
319VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedOut(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t u16Port, bool fImm, uint8_t cbReg)
320{
321 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
322 Assert(cbReg <= 4 && cbReg != 3);
323
324 iemInitExec(pVCpu, 0 /*fExecOpts*/);
325 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_3(iemCImpl_out, u16Port, cbReg,
326 ((uint8_t)fImm << 7) | 0xf /** @todo never worked with intercepts */);
327 Assert(!pVCpu->iem.s.cActiveMappings);
328 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
329}
330
331
332/**
333 * Interface for rawmode to write execute an IN instruction.
334 *
335 * @returns Strict VBox status code.
336 * @param pVCpu The cross context virtual CPU structure.
337 * @param cbInstr The instruction length in bytes.
338 * @param u16Port The port to read.
339 * @param fImm Whether the port is specified using an immediate operand or
340 * using the implicit DX.
341 * @param cbReg The register size.
342 */
343VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedIn(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t u16Port, bool fImm, uint8_t cbReg)
344{
345 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
346 Assert(cbReg <= 4 && cbReg != 3);
347
348 iemInitExec(pVCpu, 0 /*fExecOpts*/);
349 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_3(iemCImpl_in, u16Port, cbReg,
350 ((uint8_t)fImm << 7) | 0xf /** @todo never worked with intercepts */);
351 Assert(!pVCpu->iem.s.cActiveMappings);
352 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
353}
354
355
356/**
357 * Interface for HM and EM to write to a CRx register.
358 *
359 * @returns Strict VBox status code.
360 * @param pVCpu The cross context virtual CPU structure.
361 * @param cbInstr The instruction length in bytes.
362 * @param iCrReg The control register number (destination).
363 * @param iGReg The general purpose register number (source).
364 *
365 * @remarks In ring-0 not all of the state needs to be synced in.
366 */
367VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovCRxWrite(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iCrReg, uint8_t iGReg)
368{
369 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
370 Assert(iCrReg < 16);
371 Assert(iGReg < 16);
372
373 iemInitExec(pVCpu, 0 /*fExecOpts*/);
374 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_mov_Cd_Rd, iCrReg, iGReg);
375 Assert(!pVCpu->iem.s.cActiveMappings);
376 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
377}
378
379
380/**
381 * Interface for HM and EM to read from a CRx register.
382 *
383 * @returns Strict VBox status code.
384 * @param pVCpu The cross context virtual CPU structure.
385 * @param cbInstr The instruction length in bytes.
386 * @param iGReg The general purpose register number (destination).
387 * @param iCrReg The control register number (source).
388 *
389 * @remarks In ring-0 not all of the state needs to be synced in.
390 */
391VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovCRxRead(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
392{
393 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
394 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4
395 | CPUMCTX_EXTRN_APIC_TPR);
396 Assert(iCrReg < 16);
397 Assert(iGReg < 16);
398
399 iemInitExec(pVCpu, 0 /*fExecOpts*/);
400 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_mov_Rd_Cd, iGReg, iCrReg);
401 Assert(!pVCpu->iem.s.cActiveMappings);
402 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
403}
404
405
406/**
407 * Interface for HM and EM to write to a DRx register.
408 *
409 * @returns Strict VBox status code.
410 * @param pVCpu The cross context virtual CPU structure.
411 * @param cbInstr The instruction length in bytes.
412 * @param iDrReg The debug register number (destination).
413 * @param iGReg The general purpose register number (source).
414 *
415 * @remarks In ring-0 not all of the state needs to be synced in.
416 */
417VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovDRxWrite(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iDrReg, uint8_t iGReg)
418{
419 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
420 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_DR7);
421 Assert(iDrReg < 8);
422 Assert(iGReg < 16);
423
424 iemInitExec(pVCpu, 0 /*fExecOpts*/);
425 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_mov_Dd_Rd, iDrReg, iGReg);
426 Assert(!pVCpu->iem.s.cActiveMappings);
427 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
428}
429
430
431/**
432 * Interface for HM and EM to read from a DRx register.
433 *
434 * @returns Strict VBox status code.
435 * @param pVCpu The cross context virtual CPU structure.
436 * @param cbInstr The instruction length in bytes.
437 * @param iGReg The general purpose register number (destination).
438 * @param iDrReg The debug register number (source).
439 *
440 * @remarks In ring-0 not all of the state needs to be synced in.
441 */
442VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovDRxRead(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iGReg, uint8_t iDrReg)
443{
444 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
445 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_DR7);
446 Assert(iDrReg < 8);
447 Assert(iGReg < 16);
448
449 iemInitExec(pVCpu, 0 /*fExecOpts*/);
450 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_mov_Rd_Dd, iGReg, iDrReg);
451 Assert(!pVCpu->iem.s.cActiveMappings);
452 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
453}
454
455
456/**
457 * Interface for HM and EM to clear the CR0[TS] bit.
458 *
459 * @returns Strict VBox status code.
460 * @param pVCpu The cross context virtual CPU structure.
461 * @param cbInstr The instruction length in bytes.
462 *
463 * @remarks In ring-0 not all of the state needs to be synced in.
464 */
465VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedClts(PVMCPUCC pVCpu, uint8_t cbInstr)
466{
467 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
468
469 iemInitExec(pVCpu, 0 /*fExecOpts*/);
470 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_clts);
471 Assert(!pVCpu->iem.s.cActiveMappings);
472 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
473}
474
475
476/**
477 * Interface for HM and EM to emulate the LMSW instruction (loads CR0).
478 *
479 * @returns Strict VBox status code.
480 * @param pVCpu The cross context virtual CPU structure.
481 * @param cbInstr The instruction length in bytes.
482 * @param uValue The value to load into CR0.
483 * @param GCPtrEffDst The guest-linear address if the LMSW instruction has a
484 * memory operand. Otherwise pass NIL_RTGCPTR.
485 *
486 * @remarks In ring-0 not all of the state needs to be synced in.
487 */
488VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedLmsw(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t uValue, RTGCPTR GCPtrEffDst)
489{
490 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 3);
491
492 iemInitExec(pVCpu, 0 /*fExecOpts*/);
493 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_lmsw, uValue, GCPtrEffDst);
494 Assert(!pVCpu->iem.s.cActiveMappings);
495 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
496}
497
498
499/**
500 * Interface for HM and EM to emulate the XSETBV instruction (loads XCRx).
501 *
502 * Takes input values in ecx and edx:eax of the CPU context of the calling EMT.
503 *
504 * @returns Strict VBox status code.
505 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
506 * @param cbInstr The instruction length in bytes.
507 * @remarks In ring-0 not all of the state needs to be synced in.
508 * @thread EMT(pVCpu)
509 */
510VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedXsetbv(PVMCPUCC pVCpu, uint8_t cbInstr)
511{
512 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 3);
513
514 iemInitExec(pVCpu, 0 /*fExecOpts*/);
515 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_xsetbv);
516 Assert(!pVCpu->iem.s.cActiveMappings);
517 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
518}
519
520
521/**
522 * Interface for HM and EM to emulate the WBINVD instruction.
523 *
524 * @returns Strict VBox status code.
525 * @param pVCpu The cross context virtual CPU structure.
526 * @param cbInstr The instruction length in bytes.
527 *
528 * @remarks In ring-0 not all of the state needs to be synced in.
529 */
530VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedWbinvd(PVMCPUCC pVCpu, uint8_t cbInstr)
531{
532 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
533
534 iemInitExec(pVCpu, 0 /*fExecOpts*/);
535 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_wbinvd);
536 Assert(!pVCpu->iem.s.cActiveMappings);
537 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
538}
539
540
541/**
542 * Interface for HM and EM to emulate the INVD instruction.
543 *
544 * @returns Strict VBox status code.
545 * @param pVCpu The cross context virtual CPU structure.
546 * @param cbInstr The instruction length in bytes.
547 *
548 * @remarks In ring-0 not all of the state needs to be synced in.
549 */
550VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvd(PVMCPUCC pVCpu, uint8_t cbInstr)
551{
552 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
553
554 iemInitExec(pVCpu, 0 /*fExecOpts*/);
555 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_invd);
556 Assert(!pVCpu->iem.s.cActiveMappings);
557 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
558}
559
560
561/**
562 * Interface for HM and EM to emulate the INVLPG instruction.
563 *
564 * @returns Strict VBox status code.
565 * @retval VINF_PGM_SYNC_CR3
566 *
567 * @param pVCpu The cross context virtual CPU structure.
568 * @param cbInstr The instruction length in bytes.
569 * @param GCPtrPage The effective address of the page to invalidate.
570 *
571 * @remarks In ring-0 not all of the state needs to be synced in.
572 */
573VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvlpg(PVMCPUCC pVCpu, uint8_t cbInstr, RTGCPTR GCPtrPage)
574{
575 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 3);
576
577 iemInitExec(pVCpu, 0 /*fExecOpts*/);
578 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_1(iemCImpl_invlpg, GCPtrPage);
579 Assert(!pVCpu->iem.s.cActiveMappings);
580 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
581}
582
583
584/**
585 * Interface for HM and EM to emulate the INVPCID instruction.
586 *
587 * @returns Strict VBox status code.
588 * @retval VINF_PGM_SYNC_CR3
589 *
590 * @param pVCpu The cross context virtual CPU structure.
591 * @param cbInstr The instruction length in bytes.
592 * @param iEffSeg The effective segment register.
593 * @param GCPtrDesc The effective address of the INVPCID descriptor.
594 * @param uType The invalidation type.
595 *
596 * @remarks In ring-0 not all of the state needs to be synced in.
597 */
598VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvpcid(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iEffSeg, RTGCPTR GCPtrDesc,
599 uint64_t uType)
600{
601 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 4);
602
603 iemInitExec(pVCpu, 0 /*fExecOpts*/);
604 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_3(iemCImpl_invpcid, iEffSeg, GCPtrDesc, uType);
605 Assert(!pVCpu->iem.s.cActiveMappings);
606 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
607}
608
609
610/**
611 * Interface for HM and EM to emulate the CPUID instruction.
612 *
613 * @returns Strict VBox status code.
614 *
615 * @param pVCpu The cross context virtual CPU structure.
616 * @param cbInstr The instruction length in bytes.
617 *
618 * @remarks Not all of the state needs to be synced in, the usual pluss RAX and RCX.
619 */
620VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedCpuid(PVMCPUCC pVCpu, uint8_t cbInstr)
621{
622 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
623 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX);
624
625 iemInitExec(pVCpu, 0 /*fExecOpts*/);
626 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_cpuid);
627 Assert(!pVCpu->iem.s.cActiveMappings);
628 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
629}
630
631
632/**
633 * Interface for HM and EM to emulate the RDPMC instruction.
634 *
635 * @returns Strict VBox status code.
636 *
637 * @param pVCpu The cross context virtual CPU structure.
638 * @param cbInstr The instruction length in bytes.
639 *
640 * @remarks Not all of the state needs to be synced in.
641 */
642VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdpmc(PVMCPUCC pVCpu, uint8_t cbInstr)
643{
644 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
645 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4);
646
647 iemInitExec(pVCpu, 0 /*fExecOpts*/);
648 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_rdpmc);
649 Assert(!pVCpu->iem.s.cActiveMappings);
650 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
651}
652
653
654/**
655 * Interface for HM and EM to emulate the RDTSC instruction.
656 *
657 * @returns Strict VBox status code.
658 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
659 *
660 * @param pVCpu The cross context virtual CPU structure.
661 * @param cbInstr The instruction length in bytes.
662 *
663 * @remarks Not all of the state needs to be synced in.
664 */
665VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdtsc(PVMCPUCC pVCpu, uint8_t cbInstr)
666{
667 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
668 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4);
669
670 iemInitExec(pVCpu, 0 /*fExecOpts*/);
671 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_rdtsc);
672 Assert(!pVCpu->iem.s.cActiveMappings);
673 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
674}
675
676
677/**
678 * Interface for HM and EM to emulate the RDTSCP instruction.
679 *
680 * @returns Strict VBox status code.
681 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
682 *
683 * @param pVCpu The cross context virtual CPU structure.
684 * @param cbInstr The instruction length in bytes.
685 *
686 * @remarks Not all of the state needs to be synced in. Recommended
687 * to include CPUMCTX_EXTRN_TSC_AUX, to avoid extra fetch call.
688 */
689VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdtscp(PVMCPUCC pVCpu, uint8_t cbInstr)
690{
691 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 3);
692 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_TSC_AUX);
693
694 iemInitExec(pVCpu, 0 /*fExecOpts*/);
695 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_rdtscp);
696 Assert(!pVCpu->iem.s.cActiveMappings);
697 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
698}
699
700
701/**
702 * Interface for HM and EM to emulate the RDMSR instruction.
703 *
704 * @returns Strict VBox status code.
705 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
706 *
707 * @param pVCpu The cross context virtual CPU structure.
708 * @param cbInstr The instruction length in bytes.
709 *
710 * @remarks Not all of the state needs to be synced in. Requires RCX and
711 * (currently) all MSRs.
712 */
713VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdmsr(PVMCPUCC pVCpu, uint8_t cbInstr)
714{
715 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
716 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_ALL_MSRS);
717
718 iemInitExec(pVCpu, 0 /*fExecOpts*/);
719 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_rdmsr);
720 Assert(!pVCpu->iem.s.cActiveMappings);
721 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
722}
723
724
725/**
726 * Interface for HM and EM to emulate the WRMSR instruction.
727 *
728 * @returns Strict VBox status code.
729 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
730 *
731 * @param pVCpu The cross context virtual CPU structure.
732 * @param cbInstr The instruction length in bytes.
733 *
734 * @remarks Not all of the state needs to be synced in. Requires RCX, RAX, RDX,
735 * and (currently) all MSRs.
736 */
737VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedWrmsr(PVMCPUCC pVCpu, uint8_t cbInstr)
738{
739 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 2);
740 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK
741 | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_ALL_MSRS);
742
743 iemInitExec(pVCpu, 0 /*fExecOpts*/);
744 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_wrmsr);
745 Assert(!pVCpu->iem.s.cActiveMappings);
746 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
747}
748
749
750/**
751 * Interface for HM and EM to emulate the MONITOR instruction.
752 *
753 * @returns Strict VBox status code.
754 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
755 *
756 * @param pVCpu The cross context virtual CPU structure.
757 * @param cbInstr The instruction length in bytes.
758 *
759 * @remarks Not all of the state needs to be synced in.
760 * @remarks ASSUMES the default segment of DS and no segment override prefixes
761 * are used.
762 */
763VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMonitor(PVMCPUCC pVCpu, uint8_t cbInstr)
764{
765 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 3);
766 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
767
768 iemInitExec(pVCpu, 0 /*fExecOpts*/);
769 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_1(iemCImpl_monitor, X86_SREG_DS);
770 Assert(!pVCpu->iem.s.cActiveMappings);
771 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
772}
773
774
775/**
776 * Interface for HM and EM to emulate the MWAIT instruction.
777 *
778 * @returns Strict VBox status code.
779 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
780 *
781 * @param pVCpu The cross context virtual CPU structure.
782 * @param cbInstr The instruction length in bytes.
783 *
784 * @remarks Not all of the state needs to be synced in.
785 */
786VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMwait(PVMCPUCC pVCpu, uint8_t cbInstr)
787{
788 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 3);
789 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RAX);
790
791 iemInitExec(pVCpu, 0 /*fExecOpts*/);
792 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_mwait);
793 Assert(!pVCpu->iem.s.cActiveMappings);
794 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
795}
796
797
798/**
799 * Interface for HM and EM to emulate the HLT instruction.
800 *
801 * @returns Strict VBox status code.
802 * @retval VINF_IEM_RAISED_XCPT (VINF_EM_RESCHEDULE) if exception is raised.
803 *
804 * @param pVCpu The cross context virtual CPU structure.
805 * @param cbInstr The instruction length in bytes.
806 *
807 * @remarks Not all of the state needs to be synced in.
808 */
809VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedHlt(PVMCPUCC pVCpu, uint8_t cbInstr)
810{
811 IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
812
813 iemInitExec(pVCpu, 0 /*fExecOpts*/);
814 VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_0(iemCImpl_hlt);
815 Assert(!pVCpu->iem.s.cActiveMappings);
816 return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
817}
818
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette