Changeset 104516 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- May 4, 2024 1:53:42 AM (9 months ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/GCMAll.cpp
r104511 r104516 35 35 36 36 #include <VBox/dis.h> /* For DISSTATE */ 37 #include < iprt/errcore.h>37 #include <VBox/err.h> 38 38 #include <iprt/string.h> 39 40 41 /********************************************************************************************************************************* 42 * Defined Constants And Macros * 43 *********************************************************************************************************************************/ 44 #define VMWARE_HYPERVISOR_PORT UINT16_C(0x5658) 45 #define VMWARE_HYPERVISOR_PORT_HB UINT16_C(0x5659) 46 #define VMWARE_HYPERVISOR_MAGIC UINT32_C(0x564d5868) /**< eax value */ 47 48 #define VMWARE_HYPERVISOR_CMD_MSG 0x001e 49 #define VMWARE_HYPERVISOR_CMD_HB_MSG 0x0000 50 #define VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 0) /**< ecx */ 51 #define VMWARE_OC_RPCI_PROTOCOL_NUM UINT32_C(0x49435052) /**< VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL: ebx[30:0] */ 52 #define VMWARE_OC_GUESTMSG_FLAG_COOKIE UINT32_C(0x80000000) /**< VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL: ebx bit 31 */ 53 #define VMWARE_HYPERVISOR_CMD_SEND_SIZE RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 1) /**< ecx */ 54 #define VMWARE_HYPERVISOR_CMD_SEND_PAYLOAD RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 2) /**< ecx */ 55 #define VMWARE_HYPERVISOR_CMD_RECV_SIZE RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 3) /**< ecx */ 56 #define VMWARE_HYPERVISOR_CMD_RECV_PAYLOAD RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 4) /**< ecx */ 57 #define VMWARE_HYPERVISOR_CMD_RECV_STATUS RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 5) /**< ecx */ 58 #define VMWARE_HYPERVISOR_CMD_CLOSE_CHANNEL RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 6) /**< ecx */ 59 60 #define VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS 0x0055 61 #define VMWARE_HYPERVISOR_CMD_MKSGS_RESET RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS, 0) /**< ecx */ 62 #define VMWARE_HYPERVISOR_CMD_MKSGS_ADD_PPN RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS, 1) /**< ecx */ 63 #define VMWARE_HYPERVISOR_CMD_MKSGS_REMOVE_PPN RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS, 2) /**< ecx */ 64 65 /** @name Message status return flags (ecx). 66 * @{ */ 67 #define VMWARE_MSG_STATUS_F_SUCCESS UINT32_C(0x00010000) 68 #define VMWARE_MSG_STATUS_F_DO_RECV UINT32_C(0x00020000) 69 #define VMWARE_MSG_STATUS_F_CPT UINT32_C(0x00100000) 70 #define VMWARE_MSG_STATUS_F_HB UINT32_C(0x00800000) 71 /** @} */ 39 72 40 73 … … 198 231 } 199 232 233 234 #if 0 235 /** 236 * Whether \#GP exceptions in the guest should be intercepted by GCM and 237 * possibly fixed up. 238 * 239 * @returns true if needed, false otherwise. 240 * @param pVCpu The cross context virtual CPU structure. 241 */ 242 VMM_INT_DECL(bool) GCMIsInterceptingXcptGP(PVMCPUCC pVCpu) 243 { 244 /* See if the enabled fixers require #GP interception. */ 245 PVM const pVM = pVCpu->CTX_SUFF(pVM); 246 bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0; 247 LogFlow(("GCMIsInterceptingXcptDE: returns %d\n", fRet)); 248 return fRet; 249 } 250 251 252 /** 253 * Exception handler for \#GP when registered by GCM. 254 * 255 * @returns VBox status code. 256 * @retval VINF_SUCCESS retry the instruction and continue. 257 * @retval VERR_NOT_FOUND deliver exception to guest. 258 * 259 * @param pVCpu The cross context virtual CPU structure. 260 * @param pCtx Pointer to the guest-CPU context. 261 * 262 * @thread EMT(pVCpu). 263 */ 264 VMM_INT_DECL(int) GCMXcptGP(PVMCPUCC pVCpu, PCPUMCTX pCtx) 265 { 266 267 } 268 #endif 269 270 271 /** 272 * Checks if I/O port reads for the given port need GCM attention. 273 * 274 * @returns true if needed, false otherwise. 275 * @param pVCpu The cross context virtual CPU structure. 276 * @param u16Port The port being accessed. UINT16_MAX and cbReg == 277 * UINT8_MAX for any port. 278 * @param cbReg The access size. UINT8_MAX and u16Port == UINT16_MAX for 279 * any size. 280 */ 281 VMM_INT_DECL(bool) GCMIsInterceptingIOPortReadSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg) 282 { 283 PVM const pVM = pVCpu->CTX_SUFF(pVM); 284 bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0 285 && ( (u16Port == VMWARE_HYPERVISOR_PORT && cbReg == 4) 286 || (u16Port == UINT16_MAX && cbReg == UINT8_MAX) ); 287 LogFlow(("GCMIsInterceptingIOPortReadSlow(,%#x,%#x): returns %d\n", u16Port, cbReg, fRet)); 288 return fRet; 289 } 290 291 292 /** 293 * Processes an intercepted IO port read instruction. 294 * 295 * @returns Strict VBox status code. Only two informational status codes 296 * are returned VINF_GCM_HANDLED and VINF_GCM_HANDLED_ADVANCE_RIP. 297 * @retval VINF_GCM_HANDLED 298 * @retval VINF_GCM_HANDLED_ADVANCE_RIP 299 * @retval VERR_GCM_NOT_HANDLED 300 * @param pVCpu The cross context virtual CPU structure. 301 * @param pCtx The CPU context. 302 * @param u16Port The port being accessed. 303 * @param cbReg The size of the access. 304 */ 305 VMM_INT_DECL(VBOXSTRICTRC) GCMInterceptedIOPortRead(PVMCPUCC pVCpu, PCPUMCTX pCtx, uint16_t u16Port, uint8_t cbReg) 306 { 307 Assert((pVCpu->CTX_SUFF(pVM)->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0); 308 if (u16Port == VMWARE_HYPERVISOR_PORT && cbReg == 4) 309 { 310 CPUM_IMPORT_EXTRN_WITH_CTX_RET(pVCpu, pCtx, 311 CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX 312 | CPUMCTX_EXTRN_RBX | CPUMCTX_EXTRN_RSI | CPUMCTX_EXTRN_RDI); 313 if (pCtx->rax == VMWARE_HYPERVISOR_MAGIC) 314 { 315 switch (pCtx->rcx) 316 { 317 case VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL: 318 Log(("GCMInterceptedIOPortRead: vmware open channel: protocol=%#RX64\n", pCtx->rbx)); 319 break; 320 case VMWARE_HYPERVISOR_CMD_SEND_SIZE: 321 Log(("GCMInterceptedIOPortRead: vmware send size\n")); 322 break; 323 case VMWARE_HYPERVISOR_CMD_SEND_PAYLOAD: 324 Log(("GCMInterceptedIOPortRead: vmware send payload\n")); 325 break; 326 case VMWARE_HYPERVISOR_CMD_RECV_SIZE: 327 Log(("GCMInterceptedIOPortRead: vmware recv size\n")); 328 break; 329 case VMWARE_HYPERVISOR_CMD_RECV_PAYLOAD: 330 Log(("GCMInterceptedIOPortRead: vmware recv payload\n")); 331 break; 332 case VMWARE_HYPERVISOR_CMD_RECV_STATUS: 333 Log(("GCMInterceptedIOPortRead: vmware recv status\n")); 334 break; 335 case VMWARE_HYPERVISOR_CMD_CLOSE_CHANNEL: 336 Log(("GCMInterceptedIOPortRead: vmware close channel\n")); 337 break; 338 339 case VMWARE_HYPERVISOR_CMD_MKSGS_RESET: 340 Log(("GCMInterceptedIOPortRead: vmware mks guest stats reset\n")); 341 break; 342 case VMWARE_HYPERVISOR_CMD_MKSGS_ADD_PPN: 343 Log(("GCMInterceptedIOPortRead: vmware mks guest stats add ppn\n")); 344 break; 345 case VMWARE_HYPERVISOR_CMD_MKSGS_REMOVE_PPN: 346 Log(("GCMInterceptedIOPortRead: vmware mks guest stats remove ppn\n")); 347 break; 348 349 default: 350 LogRelMax(64, ("GCMInterceptedIOPortRead: Unknown vmware hypervisor call: rcx=%#RX64 (cmd), rbx=%#RX64 (len/whatever), rsi=%#RX64 (input), rdi=%#RX64 (input), rdx=%#RX64 (flags + chid) at %04x:%08RX64\n", 351 pCtx->rcx, pCtx->rbx, pCtx->rsi, pCtx->rdi, pCtx->rdx, pCtx->cs.Sel, pCtx->rip)); 352 return VERR_GCM_NOT_HANDLED; 353 } 354 355 /* Just fail the command. */ 356 pCtx->ecx &= ~VMWARE_MSG_STATUS_F_SUCCESS; 357 return VINF_GCM_HANDLED_ADVANCE_RIP; 358 } 359 } 360 return VERR_GCM_NOT_HANDLED; 361 } 362 363 364 #if 0 /* If we need to deal with high speed vmware hypervisor calls */ 365 366 /** 367 * Checks if I/O port string reads for the given port need GCM attention. 368 * 369 * @returns true if needed, false otherwise. 370 * @param pVCpu The cross context virtual CPU structure. 371 * @param u16Port The port being accessed. UINT16_MAX and cbReg == 372 * UINT8_MAX for any port. 373 * @param cbReg The access size. UINT8_MAX and u16Port == UINT16_MAX for 374 * any size. 375 */ 376 VMM_INT_DECL(bool) GCMIsInterceptingIOPortReadStringSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg) 377 { 378 PVM const pVM = pVCpu->CTX_SUFF(pVM); 379 bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0 380 && ( (u16Port == VMWARE_HYPERVISOR_PORT_HB && cbReg == 1) 381 || (u16Port == UINT16_MAX && cbReg == UINT8_MAX) ); 382 LogFlow(("GCMIsInterceptingIOPortReadStringSlow(,%#x,%#x): returns %d\n", u16Port, cbReg, fRet)); 383 return fRet; 384 } 385 386 387 /** 388 * Checks if I/O port string writes for the given port need GCM attention. 389 * 390 * @returns true if needed, false otherwise. 391 * @param pVCpu The cross context virtual CPU structure. 392 * @param u16Port The port being accessed. UINT16_MAX and cbReg == 393 * UINT8_MAX for any port. 394 * @param cbReg The access size. UINT8_MAX and u16Port == UINT16_MAX for 395 * any size. 396 */ 397 VMM_INT_DECL(bool) GCMIsInterceptingIOPortWriteStringSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg) 398 { 399 PVM const pVM = pVCpu->CTX_SUFF(pVM); 400 bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0 401 && ( (u16Port == VMWARE_HYPERVISOR_PORT_HB && cbReg == 1) 402 || (u16Port == UINT16_MAX && cbReg == UINT8_MAX) ); 403 LogFlow(("GCMIsInterceptingIOPortWriteStringSlow(,%#x,%#x): returns %d\n", u16Port, cbReg, fRet)); 404 return fRet; 405 } 406 407 #endif 408 -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r104129 r104516 131 131 #include <VBox/vmm/hm.h> 132 132 #include <VBox/vmm/nem.h> 133 #include <VBox/vmm/gcm.h> 133 134 #include <VBox/vmm/gim.h> 134 135 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM … … 4197 4198 VBOXSTRICTRC iemRaiseDivideError(PVMCPUCC pVCpu) RT_NOEXCEPT 4198 4199 { 4200 if (GCMIsInterceptingXcptDE(pVCpu)) 4201 { 4202 int rc = GCMXcptDE(pVCpu, &pVCpu->cpum.GstCtx); 4203 if (rc == VINF_SUCCESS) 4204 { 4205 Log(("iemRaiseDivideError: Restarting instruction because of GCMXcptDE\n")); 4206 return VINF_IEM_RAISED_XCPT; /* must return non-zero status here to cause a instruction restart */ 4207 } 4208 } 4199 4209 return iemRaiseXcptOrInt(pVCpu, 0, X86_XCPT_DE, IEM_XCPT_FLAGS_T_CPU_XCPT, 0, 0); 4200 4210 } -
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp
r104419 r104516 43 43 #include <VBox/vmm/nem.h> 44 44 #include <VBox/vmm/gim.h> 45 #include <VBox/vmm/gcm.h> 45 46 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 46 47 # include <VBox/vmm/em.h> … … 7294 7295 IEM_CIMPL_DEF_3(iemCImpl_in, uint16_t, u16Port, uint8_t, cbReg, uint8_t, bImmAndEffAddrMode) 7295 7296 { 7297 /* 7298 * GCM intercept. 7299 * 7300 * This must be placed before the IOPL check as the mesa driver intercept 7301 * would otherwise trigger a #GP(0). 7302 */ 7303 if (!IEM_IS_IN_GUEST(pVCpu) && GCMIsInterceptingIOPortRead(pVCpu, u16Port, cbReg)) 7304 { 7305 VBOXSTRICTRC rcStrict = GCMInterceptedIOPortRead(pVCpu, &pVCpu->cpum.GstCtx, u16Port, cbReg); 7306 if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP || rcStrict == VINF_GCM_HANDLED) 7307 { 7308 Log(("iemCImpl_in: u16Port=%#x cbReg=%d was handled by GCMIOPortRead (%d)\n", u16Port, cbReg, VBOXSTRICTRC_VAL(rcStrict))); 7309 if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP) 7310 rcStrict = iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr); 7311 else 7312 rcStrict = VINF_SUCCESS; 7313 return rcStrict; 7314 } 7315 Assert(rcStrict == VERR_GCM_NOT_HANDLED); 7316 } 7317 7296 7318 /* 7297 7319 * CPL check -
trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h
r104512 r104516 9003 9003 else 9004 9004 { 9005 uint32_t u32Result = 0; 9006 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue); 9007 if (IOM_SUCCESS(rcStrict)) 9005 rcStrict = VERR_GCM_NOT_HANDLED; 9006 if (GCMIsInterceptingIOPortRead(pVCpu, uIOPort, cbValue)) 9008 9007 { 9009 /* Save result of I/O IN instr. in AL/AX/EAX. */ 9010 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal); 9008 rcStrict = GCMInterceptedIOPortRead(pVCpu, pCtx, uIOPort, cbValue); 9009 if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP || rcStrict == VINF_GCM_HANDLED) 9010 { 9011 /* ASSUMES we don't need to update fCtxChanged when regular GPRs change here. */ 9012 fUpdateRipAlready = rcStrict == VINF_GCM_HANDLED; 9013 if (rcStrict == VINF_GCM_HANDLED) 9014 ASMAtomicUoOrU64(&VCPU_2_VMXSTATE(pVCpu).fCtxChanged, HM_CHANGED_GUEST_RIP); 9015 rcStrict = VINF_SUCCESS; 9016 } 9017 else 9018 Assert(rcStrict == VERR_GCM_NOT_HANDLED); 9011 9019 } 9020 9021 if (rcStrict == VERR_GCM_NOT_HANDLED) 9022 { 9023 uint32_t u32Result = 0; 9024 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue); 9025 if (IOM_SUCCESS(rcStrict)) 9026 { 9027 /* Save result of I/O IN instr. in AL/AX/EAX. */ 9028 /** @todo r=bird: 32-bit op size should clear high bits of rax! */ 9029 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal); 9030 } 9012 9031 #ifndef IN_NEM_DARWIN 9013 if ( rcStrict == VINF_IOM_R3_IOPORT_READ 9014 && !pCtx->eflags.Bits.u1TF) 9015 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue); 9016 #endif 9032 if ( rcStrict == VINF_IOM_R3_IOPORT_READ 9033 && !pCtx->eflags.Bits.u1TF) 9034 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue); 9035 #endif 9036 } 9017 9037 STAM_COUNTER_INC(&VCPU_2_VMXSTATS(pVCpu).StatExitIORead); 9018 9038 }
Note:
See TracChangeset
for help on using the changeset viewer.