VirtualBox

source: vbox/trunk/src/VBox/VMM/include/EMHandleRCTmpl.h@ 107044

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
Line 
1/* $Id: EMHandleRCTmpl.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * EM - emR3[Raw|Hm|Nem]HandleRC template.
4 */
5
6/*
7 * Copyright (C) 2006-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#ifndef VMM_INCLUDED_SRC_include_EMHandleRCTmpl_h
29#define VMM_INCLUDED_SRC_include_EMHandleRCTmpl_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#if defined(EMHANDLERC_WITH_PATM) + defined(EMHANDLERC_WITH_HM) + defined(EMHANDLERC_WITH_NEM) != 1
35# error "Exactly one of these must be defined: EMHANDLERC_WITH_PATM, EMHANDLERC_WITH_HM, EMHANDLERC_WITH_NEM"
36#endif
37
38
39/**
40 * Process a subset of the raw-mode, HM and NEM return codes.
41 *
42 * Since we have to share this with raw-mode single stepping, this inline
43 * function has been created to avoid code duplication.
44 *
45 * @returns VINF_SUCCESS if it's ok to continue raw mode.
46 * @returns VBox status code to return to the EM main loop.
47 *
48 * @param pVM The cross context VM structure.
49 * @param pVCpu The cross context virtual CPU structure.
50 * @param rc The return code.
51 */
52#if defined(EMHANDLERC_WITH_HM) || defined(DOXYGEN_RUNNING)
53int emR3HmHandleRC(PVM pVM, PVMCPU pVCpu, int rc)
54#elif defined(EMHANDLERC_WITH_NEM)
55int emR3NemHandleRC(PVM pVM, PVMCPU pVCpu, int rc)
56#endif
57{
58 switch (rc)
59 {
60 /*
61 * Common & simple ones.
62 */
63 case VINF_SUCCESS:
64 break;
65 case VINF_EM_RESCHEDULE_EXEC_ENGINE:
66 case VINF_EM_RAW_INTERRUPT:
67 case VINF_EM_RAW_TO_R3:
68 case VINF_EM_RAW_TIMER_PENDING:
69 case VINF_EM_PENDING_REQUEST:
70 rc = VINF_SUCCESS;
71 break;
72
73#ifndef EMHANDLERC_WITH_NEM
74 /*
75 * Conflict or out of page tables.
76 *
77 * VM_FF_PGM_SYNC_CR3 is set by the hypervisor and all we need to
78 * do here is to execute the pending forced actions.
79 */
80 case VINF_PGM_SYNC_CR3:
81 AssertMsg(VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL),
82 ("VINF_PGM_SYNC_CR3 and no VMCPU_FF_PGM_SYNC_CR3*!\n"));
83 rc = VINF_SUCCESS;
84 break;
85
86 /*
87 * PGM pool flush pending (guest SMP only).
88 */
89 /** @todo jumping back and forth between ring 0 and 3 can burn a lot of cycles
90 * if the EMT thread that's supposed to handle the flush is currently not active
91 * (e.g. waiting to be scheduled) -> fix this properly!
92 *
93 * bird: Since the clearing is global and done via a rendezvous any CPU can do
94 * it. They would have to choose who to call VMMR3EmtRendezvous and send
95 * the rest to VMMR3EmtRendezvousFF ... Hmm ... that's not going to work
96 * all that well since the latter will race the setup done by the
97 * first. Guess that means we need some new magic in that area for
98 * handling this case. :/
99 */
100 case VINF_PGM_POOL_FLUSH_PENDING:
101 rc = VINF_SUCCESS;
102 break;
103#endif /* !EMHANDLERC_WITH_NEM */
104
105 /*
106 * I/O Port access - emulate the instruction.
107 */
108 case VINF_IOM_R3_IOPORT_READ:
109 case VINF_IOM_R3_IOPORT_WRITE:
110 case VINF_EM_RESUME_R3_HISTORY_EXEC: /* Resume EMHistoryExec after VMCPU_FF_IOM. */
111 rc = emR3ExecuteIOInstruction(pVM, pVCpu);
112 break;
113
114#if !defined(VBOX_VMM_TARGET_ARMV8)
115 /*
116 * Execute pending I/O Port access.
117 */
118 case VINF_EM_PENDING_R3_IOPORT_WRITE:
119 rc = VBOXSTRICTRC_TODO(emR3ExecutePendingIoPortWrite(pVM, pVCpu));
120 break;
121 case VINF_EM_PENDING_R3_IOPORT_READ:
122 rc = VBOXSTRICTRC_TODO(emR3ExecutePendingIoPortRead(pVM, pVCpu));
123 break;
124#endif
125
126 /*
127 * Memory mapped I/O access - emulate the instruction.
128 */
129 case VINF_IOM_R3_MMIO_READ:
130 case VINF_IOM_R3_MMIO_WRITE:
131 case VINF_IOM_R3_MMIO_READ_WRITE:
132 rc = emR3ExecuteInstruction(pVM, pVCpu, "MMIO");
133 break;
134
135 /*
136 * Machine specific register access - emulate the instruction.
137 */
138 case VINF_CPUM_R3_MSR_READ:
139 case VINF_CPUM_R3_MSR_WRITE:
140 rc = emR3ExecuteInstruction(pVM, pVCpu, "MSR");
141 break;
142
143 /*
144 * GIM hypercall.
145 */
146 case VINF_GIM_R3_HYPERCALL:
147 rc = emR3ExecuteInstruction(pVM, pVCpu, "Hypercall");
148 break;
149
150#ifdef EMHANDLERC_WITH_HM
151 case VINF_EM_HM_PATCH_TPR_INSTR:
152 rc = HMR3PatchTprInstr(pVM, pVCpu);
153 break;
154#endif
155
156 case VINF_EM_RAW_GUEST_TRAP:
157 case VINF_EM_RAW_EMULATE_INSTR:
158 AssertMsg(!TRPMHasTrap(pVCpu), ("trap=%#x\n", TRPMGetTrapNo(pVCpu))); /* We're directly executing instructions below without respecting any pending traps! */
159 rc = emR3ExecuteInstruction(pVM, pVCpu, "EMUL: ");
160 break;
161
162 case VINF_EM_RAW_INJECT_TRPM_EVENT:
163 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);
164 rc = VBOXSTRICTRC_VAL(IEMInjectTrpmEvent(pVCpu));
165 /* The following condition should be removed when IEM_IMPLEMENTS_TASKSWITCH becomes true. */
166 if (rc == VERR_IEM_ASPECT_NOT_IMPLEMENTED)
167 rc = emR3ExecuteInstruction(pVM, pVCpu, "EVENT: ");
168 break;
169
170#if !defined(VBOX_VMM_TARGET_ARMV8)
171 case VINF_EM_EMULATE_SPLIT_LOCK:
172 rc = VBOXSTRICTRC_TODO(emR3ExecuteSplitLockInstruction(pVM, pVCpu));
173 break;
174#endif
175
176
177 /*
178 * Up a level.
179 */
180 case VINF_EM_TERMINATE:
181 case VINF_EM_OFF:
182 case VINF_EM_RESET:
183 case VINF_EM_SUSPEND:
184 case VINF_EM_HALT:
185 case VINF_EM_RESUME:
186 case VINF_EM_NO_MEMORY:
187 case VINF_EM_RESCHEDULE:
188 case VINF_EM_RESCHEDULE_REM:
189 case VINF_EM_WAIT_SIPI:
190 break;
191
192 /*
193 * Up a level and invoke the debugger.
194 */
195 case VINF_EM_DBG_STEPPED:
196 case VINF_EM_DBG_BREAKPOINT:
197 case VINF_EM_DBG_STEP:
198 case VINF_EM_DBG_HYPER_BREAKPOINT:
199 case VINF_EM_DBG_HYPER_STEPPED:
200 case VINF_EM_DBG_HYPER_ASSERTION:
201 case VINF_EM_DBG_STOP:
202 case VINF_EM_DBG_EVENT:
203 break;
204
205 /*
206 * Up a level, dump and debug.
207 */
208 case VERR_TRPM_DONT_PANIC:
209 case VERR_TRPM_PANIC:
210 case VERR_VMM_RING0_ASSERTION:
211 case VINF_EM_TRIPLE_FAULT:
212 case VERR_VMM_HYPER_CR3_MISMATCH:
213 case VERR_VMM_RING3_CALL_DISABLED:
214 case VERR_IEM_INSTR_NOT_IMPLEMENTED:
215 case VERR_IEM_ASPECT_NOT_IMPLEMENTED:
216 case VERR_EM_GUEST_CPU_HANG:
217 break;
218
219#ifdef EMHANDLERC_WITH_HM
220 /*
221 * Up a level, after Hm have done some release logging.
222 */
223 case VERR_VMX_INVALID_VMCS_FIELD:
224 case VERR_VMX_INVALID_VMCS_PTR:
225 case VERR_VMX_INVALID_VMXON_PTR:
226 case VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE:
227 case VERR_VMX_UNEXPECTED_EXCEPTION:
228 case VERR_VMX_UNEXPECTED_EXIT:
229 case VERR_VMX_INVALID_GUEST_STATE:
230 case VERR_VMX_UNABLE_TO_START_VM:
231 case VERR_SVM_UNKNOWN_EXIT:
232 case VERR_SVM_UNEXPECTED_EXIT:
233 case VERR_SVM_UNEXPECTED_PATCH_TYPE:
234 case VERR_SVM_UNEXPECTED_XCPT_EXIT:
235 HMR3CheckError(pVM, rc);
236 break;
237
238 /* Up a level; fatal */
239 case VERR_VMX_IN_VMX_ROOT_MODE:
240 case VERR_SVM_IN_USE:
241 case VERR_SVM_UNABLE_TO_START_VM:
242 break;
243#endif
244
245#ifdef EMHANDLERC_WITH_NEM
246 /* Fatal stuff, up a level. */
247 case VERR_NEM_IPE_0:
248 case VERR_NEM_IPE_1:
249 case VERR_NEM_IPE_2:
250 case VERR_NEM_IPE_3:
251 case VERR_NEM_IPE_4:
252 case VERR_NEM_IPE_5:
253 case VERR_NEM_IPE_6:
254 case VERR_NEM_IPE_7:
255 case VERR_NEM_IPE_8:
256 case VERR_NEM_IPE_9:
257 break;
258#endif
259
260 /*
261 * These two should be handled via the force flag already, but just in
262 * case they end up here deal with it.
263 */
264 case VINF_IOM_R3_IOPORT_COMMIT_WRITE:
265 case VINF_IOM_R3_MMIO_COMMIT_WRITE:
266 AssertFailed();
267 rc = VBOXSTRICTRC_TODO(IOMR3ProcessForceFlag(pVM, pVCpu, rc));
268 break;
269
270 /*
271 * Anything which is not known to us means an internal error
272 * and the termination of the VM!
273 */
274 default:
275 AssertMsgFailed(("Unknown GC return code: %Rra\n", rc));
276 break;
277 }
278 return rc;
279}
280
281#endif /* !VMM_INCLUDED_SRC_include_EMHandleRCTmpl_h */
282
Note: See TracBrowser for help on using the repository browser.

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