VirtualBox

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

Last change on this file since 108220 was 108220, checked in by vboxsync, 4 weeks ago

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