VirtualBox

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

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

VMM/IEM: Made IEMAll.cpp build targeting arm. jiraref:VBP-1531

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