Changeset 55118 in vbox
- Timestamp:
- Apr 7, 2015 3:21:45 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 16 edited
-
include/VBox/err.h (modified) (1 diff)
-
include/VBox/vmm/gim.h (modified) (1 diff)
-
include/VBox/vmm/hm.h (modified) (1 diff)
-
include/VBox/vmm/vmm.h (modified) (1 diff)
-
src/VBox/VMM/VMMAll/GIMAll.cpp (modified) (5 diffs)
-
src/VBox/VMM/VMMAll/GIMAllKvm.cpp (modified) (5 diffs)
-
src/VBox/VMM/VMMAll/HMAll.cpp (modified) (1 diff)
-
src/VBox/VMM/VMMAll/VMMAll.cpp (modified) (2 diffs)
-
src/VBox/VMM/VMMR0/HMR0.cpp (modified) (3 diffs)
-
src/VBox/VMM/VMMR0/HMSVMR0.cpp (modified) (7 diffs)
-
src/VBox/VMM/VMMR0/HMVMXR0.cpp (modified) (1 diff)
-
src/VBox/VMM/VMMR3/GIMHv.cpp (modified) (2 diffs)
-
src/VBox/VMM/VMMR3/GIMKvm.cpp (modified) (3 diffs)
-
src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp (modified) (4 diffs)
-
src/VBox/VMM/include/GIMKvmInternal.h (modified) (2 diffs)
-
src/VBox/VMM/include/HMInternal.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r55037 r55118 2622 2622 /** The GIM device is not registered with GIM when it ought to be. */ 2623 2623 #define VERR_GIM_DEVICE_NOT_REGISTERED (-6310) 2624 /** Hypercall cannot be enabled/performed due to access/permissions/CPL. */ 2625 #define VERR_GIM_HYPERCALL_ACCESS_DENIED (-6311) 2624 2626 /** @} */ 2625 2627 -
trunk/include/VBox/vmm/gim.h
r55037 r55118 174 174 VMM_INT_DECL(bool) GIMAreHypercallsEnabled(PVMCPU pVCpu); 175 175 VMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx); 176 VMM_INT_DECL(int) GIMXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx );176 VMM_INT_DECL(int) GIMXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis); 177 177 VMM_INT_DECL(bool) GIMShouldTrapXcptUD(PVM pVM); 178 178 VMM_INT_DECL(VBOXSTRICTRC) GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue); -
trunk/include/VBox/vmm/hm.h
r54878 r55118 144 144 VMM_INT_DECL(int) HMAmdIsSubjectToErratum170(uint32_t *pu32Family, uint32_t *pu32Model, uint32_t *pu32Stepping); 145 145 VMM_INT_DECL(bool) HMSetSingleInstruction(PVMCPU pVCpu, bool fEnable); 146 VMM_INT_DECL(int) HMPatchHypercall(PVM pVM, void *pvBuf, size_t cbBuf, size_t *pcbWritten); 146 VMM_INT_DECL(void) HMHypercallsEnable(PVM pVM); 147 VMM_INT_DECL(void) HMHypercallsDisable(PVM pVM); 147 148 148 149 #ifndef IN_RC -
trunk/include/VBox/vmm/vmm.h
r54720 r55118 268 268 VMM_INT_DECL(bool) VMMIsInRing3Call(PVMCPU pVCpu); 269 269 VMM_INT_DECL(void) VMMTrashVolatileXMMRegs(void); 270 VMM_INT_DECL(int) VMMPatchHypercall(PVM pVM, void *pvBuf, size_t cbBuf, size_t *pcbWritten); 271 VMM_INT_DECL(void) VMMHypercallsEnable(PVM pVM); 272 VMM_INT_DECL(void) VMMHypercallsDisable(PVM pVM); 270 273 271 274 -
trunk/src/VBox/VMM/VMMAll/GIMAll.cpp
r55037 r55118 129 129 return gimHvIsParavirtTscEnabled(pVM); 130 130 131 case GIMPROVIDERID_KVM: 132 return gimKvmIsParavirtTscEnabled(pVM); 133 131 134 default: 132 135 break; … … 151 154 { 152 155 if (!GIMIsEnabled(pVM)) 153 return 0;156 return false; 154 157 155 158 switch (pVM->gim.s.enmProviderId) … … 159 162 160 163 default: 161 return 0;164 return false; 162 165 } 163 166 } … … 169 172 * @param pVCpu Pointer to the VMCPU. 170 173 * @param pCtx Pointer to the guest-CPU context. 171 */ 172 VMM_INT_DECL(int) GIMXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx) 174 * @param pDis Pointer to the disassembled instruction state at RIP. 175 * Optional, can be NULL. 176 */ 177 VMM_INT_DECL(int) GIMXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis) 173 178 { 174 179 PVM pVM = pVCpu->CTX_SUFF(pVM); … … 178 183 { 179 184 case GIMPROVIDERID_KVM: 180 return gimKvmXcptUD(pVCpu, pCtx );185 return gimKvmXcptUD(pVCpu, pCtx, pDis); 181 186 182 187 default: -
trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp
r55039 r55118 112 112 * Place the result in rax/eax. 113 113 */ 114 if (fIs64BitMode) 115 pCtx->rax = uHyperRet; 116 else 117 pCtx->eax = uHyperRet & uAndMask; 114 pCtx->rax = uHyperRet & uAndMask; 118 115 return VINF_SUCCESS; 119 116 } … … 144 141 VMM_INT_DECL(bool) gimKvmIsParavirtTscEnabled(PVM pVM) 145 142 { 146 return false; /** @todo implement this! */ 143 uint32_t cCpus = pVM->cCpus; 144 for (uint32_t i = 0; i < cCpus; i++) 145 { 146 PVMCPU pVCpu = &pVM->aCpus[i]; 147 PGIMKVMCPU pGimKvmCpu = &pVCpu->gim.s.u.KvmCpu; 148 if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pGimKvmCpu->u64SystemTimeMsr)) 149 return true; 150 } 151 return false; 147 152 } 148 153 … … 223 228 if (fEnable) 224 229 { 225 RTCCUINTREG fEFlags = ASMIntDisableFlags();230 RTCCUINTREG fEFlags = ASMIntDisableFlags(); 226 231 pKvmCpu->uTsc = TMCpuTickGetNoCheck(pVCpu); 227 232 pKvmCpu->uVirtNanoTS = TMVirtualGetNoCheck(pVM); … … 317 322 * elegantly by letting the hypervisor supply an opaque hypercall page. 318 323 * 324 * For raw-mode VMs, this function will always return true. See gimR3KvmInit(). 325 * 319 326 * @param pVM Pointer to the VM. 320 327 */ 321 328 VMM_INT_DECL(bool) gimKvmShouldTrapXcptUD(PVM pVM) 322 329 { 323 pVM->gim.s.u.Kvm.fTrapXcptUD = ASMIsAmdCpu();324 330 return pVM->gim.s.u.Kvm.fTrapXcptUD; 325 331 } … … 331 337 * @param pVCpu Pointer to the VMCPU. 332 338 * @param pCtx Pointer to the guest-CPU context. 333 */ 334 VMM_INT_DECL(int) gimKvmXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx) 339 * @param pDis Pointer to the disassembled instruction state at RIP. 340 * Optional, can be NULL. 341 */ 342 VMM_INT_DECL(int) gimKvmXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis) 335 343 { 336 344 /* 337 345 * If we didn't ask for #UD to be trapped, bail. 338 346 */ 339 PVM pVM = pVCpu->CTX_SUFF(pVM); 347 PVM pVM = pVCpu->CTX_SUFF(pVM); 348 PGIMKVM pKvm = &pVM->gim.s.u.Kvm; 340 349 if (RT_UNLIKELY(!pVM->gim.s.u.Kvm.fTrapXcptUD)) 341 350 return VERR_GIM_OPERATION_FAILED; 342 351 343 352 /* 344 * Disassemble the instruction at RIP to figure out if it's the Intel 345 * VMCALL instruction and if so, handle it as a hypercall. 346 */ 347 DISCPUSTATE Dis; 348 unsigned cbInstr; 349 int rc = EMInterpretDisasCurrent(pVM, pVCpu, &Dis, &cbInstr); 353 * Make sure guest ring-0 is the one making the hypercall. 354 */ 355 if (CPUMGetGuestCPL(pVCpu)) 356 return VERR_GIM_HYPERCALL_ACCESS_DENIED; 357 358 int rc = VINF_SUCCESS; 359 if (!pDis) 360 { 361 /* 362 * Disassemble the instruction at RIP to figure out if it's the Intel 363 * VMCALL instruction and if so, handle it as a hypercall. 364 */ 365 DISCPUSTATE Dis; 366 rc = EMInterpretDisasCurrent(pVM, pVCpu, &Dis, NULL /* pcbInstr */); 367 pDis = &Dis; 368 } 369 350 370 if (RT_SUCCESS(rc)) 351 371 { 352 if (Dis.pCurInstr->uOpcode == OP_VMCALL) 353 { 372 /* 373 * Patch the instruction to so we don't have to spend time disassembling it each time. 374 * Makes sense only for HM as with raw-mode we will be getting a #UD regardless. 375 */ 376 if ( pDis->pCurInstr->uOpcode == OP_VMCALL 377 || pDis->pCurInstr->uOpcode == OP_VMMCALL) 378 { 379 uint8_t abHypercall[3]; 380 if ( pDis->pCurInstr->uOpcode != pKvm->uOpCodeNative 381 && HMIsEnabled(pVM)) 382 { 383 size_t cbWritten = 0; 384 rc = VMMPatchHypercall(pVM, &abHypercall, sizeof(abHypercall), &cbWritten); 385 AssertRC(rc); 386 Assert(sizeof(abHypercall) == pDis->cbInstr); 387 Assert(sizeof(abHypercall) == cbWritten); 388 389 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, &abHypercall, sizeof(abHypercall)); 390 } 391 354 392 /* 355 * Patch the instruction to so we don't have to spend time disassembling it each time. 393 * Perform the hypercall and update RIP. 394 * 395 * For HM, we can simply resume guest execution without perform the hypercall now and 396 * do it on the next VMCALL/VMMCALL exit handler on the patched instruction. 397 * 398 * For raw-mode we need to do this now anyway. So we do it here regardless with an added 399 * advantage is that it saves one world-switch for the HM case. 356 400 */ 357 static uint8_t s_abHypercall[3] = { 0x0F, 0x01, 0x00 }; 358 Assert(sizeof(s_abHypercall) == cbInstr); 359 if (!s_abHypercall[2]) 360 s_abHypercall[2] = ASMIsAmdCpu() ? 0xD9 /* VMMCALL */ : 0xC1 /* VMCALL */; 361 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, &s_abHypercall, sizeof(s_abHypercall)); 362 return VINF_SUCCESS; 401 if (RT_SUCCESS(rc)) 402 { 403 int rc2 = gimKvmHypercall(pVCpu, pCtx); 404 AssertRC(rc2); 405 pCtx->rip += pDis->cbInstr; 406 } 407 return rc; 363 408 } 364 409 } -
trunk/src/VBox/VMM/VMMAll/HMAll.cpp
r54878 r55118 508 508 509 509 /** 510 * Patches the instructions necessary for making a hypercall to the hypervisor. 511 * Used by GIM. 512 * 513 * @returns VBox status code. 514 * @param pVM Pointer to the VM. 515 * @param pvBuf The buffer in the hypercall page(s) to be patched. 516 * @param cbBuf The size of the buffer. 517 * @param pcbWritten Where to store the number of bytes patched. This 518 * is reliably updated only when this function returns 519 * VINF_SUCCESS. 520 */ 521 VMM_INT_DECL(int) HMPatchHypercall(PVM pVM, void *pvBuf, size_t cbBuf, size_t *pcbWritten) 522 { 523 AssertReturn(pvBuf, VERR_INVALID_POINTER); 524 AssertReturn(pcbWritten, VERR_INVALID_POINTER); 525 AssertReturn(HMIsEnabled(pVM), VERR_HM_IPE_5); 526 527 if (pVM->hm.s.vmx.fSupported) 528 { 529 uint8_t abHypercall[] = { 0x0F, 0x01, 0xC1 }; /* VMCALL */ 530 if (RT_LIKELY(cbBuf >= sizeof(abHypercall))) 531 { 532 memcpy(pvBuf, abHypercall, sizeof(abHypercall)); 533 *pcbWritten = sizeof(abHypercall); 534 return VINF_SUCCESS; 535 } 536 return VERR_BUFFER_OVERFLOW; 537 } 538 else 539 { 540 Assert(pVM->hm.s.svm.fSupported); 541 uint8_t abHypercall[] = { 0x0F, 0x01, 0xD9 }; /* VMMCALL */ 542 if (RT_LIKELY(cbBuf >= sizeof(abHypercall))) 543 { 544 memcpy(pvBuf, abHypercall, sizeof(abHypercall)); 545 *pcbWritten = sizeof(abHypercall); 546 return VINF_SUCCESS; 547 } 548 return VERR_BUFFER_OVERFLOW; 549 } 550 } 551 510 * Notifies HM that paravirtualized hypercalls are now enabled. 511 * 512 * @param pVM Pointer to the VM. 513 */ 514 VMM_INT_DECL(void) HMHypercallsEnable(PVM pVM) 515 { 516 pVM->hm.s.fHypercallsEnabled = true; 517 } 518 519 520 /** 521 * Notifies HM that paravirtualized hypercalls are now disabled. 522 * 523 * @param pVM Pointer to the VM. 524 */ 525 VMM_INT_DECL(void) HMHypercallsDisable(PVM pVM) 526 { 527 pVM->hm.s.fHypercallsEnabled = false; 528 } 529 -
trunk/src/VBox/VMM/VMMAll/VMMAll.cpp
r54467 r55118 24 24 #include "VMMInternal.h" 25 25 #include <VBox/vmm/vm.h> 26 #include <VBox/vmm/hm.h> 26 27 #include <VBox/vmm/vmcpuset.h> 27 28 #include <VBox/param.h> … … 391 392 } 392 393 394 395 /** 396 * Patches the instructions necessary for making a hypercall to the hypervisor. 397 * Used by GIM. 398 * 399 * @returns VBox status code. 400 * @param pVM Pointer to the VM. 401 * @param pvBuf The buffer in the hypercall page(s) to be patched. 402 * @param cbBuf The size of the buffer. 403 * @param pcbWritten Where to store the number of bytes patched. This 404 * is reliably updated only when this function returns 405 * VINF_SUCCESS. 406 */ 407 VMM_INT_DECL(int) VMMPatchHypercall(PVM pVM, void *pvBuf, size_t cbBuf, size_t *pcbWritten) 408 { 409 AssertReturn(pvBuf, VERR_INVALID_POINTER); 410 AssertReturn(pcbWritten, VERR_INVALID_POINTER); 411 412 if (ASMIsAmdCpu()) 413 { 414 uint8_t abHypercall[] = { 0x0F, 0x01, 0xD9 }; /* VMMCALL */ 415 if (RT_LIKELY(cbBuf >= sizeof(abHypercall))) 416 { 417 memcpy(pvBuf, abHypercall, sizeof(abHypercall)); 418 *pcbWritten = sizeof(abHypercall); 419 return VINF_SUCCESS; 420 } 421 return VERR_BUFFER_OVERFLOW; 422 } 423 else 424 { 425 AssertReturn(ASMIsIntelCpu() || ASMIsViaCentaurCpu(), VERR_UNSUPPORTED_CPU); 426 uint8_t abHypercall[] = { 0x0F, 0x01, 0xC1 }; /* VMCALL */ 427 if (RT_LIKELY(cbBuf >= sizeof(abHypercall))) 428 { 429 memcpy(pvBuf, abHypercall, sizeof(abHypercall)); 430 *pcbWritten = sizeof(abHypercall); 431 return VINF_SUCCESS; 432 } 433 return VERR_BUFFER_OVERFLOW; 434 } 435 } 436 437 438 /** 439 * Notifies VMM that paravirtualized hypercalls are now enabled. 440 * 441 * @param pVM Pointer to the VM. 442 */ 443 VMM_INT_DECL(void) VMMHypercallsEnable(PVM pVM) 444 { 445 /* If there is anything to do for raw-mode, do it here. */ 446 #ifndef IN_RC 447 if (HMIsEnabled(pVM)) 448 HMHypercallsEnable(pVM); 449 #endif 450 } 451 452 453 /** 454 * Notifies VMM that paravirtualized hypercalls are now disabled. 455 * 456 * @param pVM Pointer to the VM. 457 */ 458 VMM_INT_DECL(void) VMMHypercallsDisable(PVM pVM) 459 { 460 /* If there is anything to do for raw-mode, do it here. */ 461 #ifndef IN_RC 462 if (HMIsEnabled(pVM)) 463 HMHypercallsDisable(pVM); 464 #endif 465 } 466 -
trunk/src/VBox/VMM/VMMR0/HMR0.cpp
r55048 r55118 5 5 6 6 /* 7 * Copyright (C) 2006-201 4Oracle Corporation7 * Copyright (C) 2006-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 26 26 #include <VBox/vmm/hm_vmx.h> 27 27 #include <VBox/vmm/hm_svm.h> 28 #include <VBox/vmm/gim.h> 28 29 #include <VBox/err.h> 29 30 #include <VBox/log.h> … … 1211 1212 pVM->hm.s.cpuid.u32AMDFeatureEDX = g_HvmR0.cpuid.u32AMDFeatureEDX; 1212 1213 pVM->hm.s.lLastError = g_HvmR0.lLastError; 1213 1214 1214 pVM->hm.s.uMaxAsid = g_HvmR0.uMaxAsid; 1215 1215 1216 pVM->hm.s.fGIMTrapXcptUD = GIMShouldTrapXcptUD(pVM); 1216 1217 1217 1218 if (!pVM->hm.s.cMaxResumeLoops) /* allow ring-3 overrides */ -
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r55040 r55118 670 670 Assert(pVM->hm.s.svm.fSupported); 671 671 672 pVM->hm.s.fTrapXcptUD = GIMShouldTrapXcptUD(pVM); 673 uint32_t const fGimXcptIntercepts = pVM->hm.s.fTrapXcptUD ? RT_BIT(X86_XCPT_UD) : 0; 672 uint32_t const fGimXcptIntercepts = pVM->hm.s.fGIMTrapXcptUD ? RT_BIT(X86_XCPT_UD) : 0; 674 673 for (VMCPUID i = 0; i < pVM->cCpus; i++) 675 674 { … … 3511 3510 return hmR0SvmExitWriteCRx(pVCpu, pCtx, pSvmTransient); 3512 3511 3512 case SVM_EXIT_VMMCALL: 3513 return hmR0SvmExitVmmCall(pVCpu, pCtx, pSvmTransient); 3514 3513 3515 case SVM_EXIT_VINTR: 3514 3516 return hmR0SvmExitVIntr(pVCpu, pCtx, pSvmTransient); … … 3552 3554 case SVM_EXIT_TASK_SWITCH: 3553 3555 return hmR0SvmExitTaskSwitch(pVCpu, pCtx, pSvmTransient); 3554 3555 case SVM_EXIT_VMMCALL:3556 return hmR0SvmExitVmmCall(pVCpu, pCtx, pSvmTransient);3557 3556 3558 3557 case SVM_EXIT_IRET: … … 3899 3898 * @returns VBox status code. 3900 3899 * @retval VINF_SUCCESS if the access was handled successfully. 3901 * @retval VERR_NOT_FOUND if no patch record for this eipcould be found.3900 * @retval VERR_NOT_FOUND if no patch record for this RIP could be found. 3902 3901 * @retval VERR_SVM_UNEXPECTED_PATCH_TYPE if the found patch type is invalid. 3903 3902 * … … 4998 4997 { 4999 4998 HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(); 4999 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitVmcall); 5000 5000 5001 5001 /* First check if this is a patched VMMCALL for mov TPR */ … … 5008 5008 else if (rc == VERR_NOT_FOUND) 5009 5009 { 5010 /* Handle GIM provider hypercalls. */5011 if ( GIMAreHypercallsEnabled(pVCpu))5010 PVM pVM = pVCpu->CTX_SUFF(pVM); 5011 if (pVM->hm.s.fHypercallsEnabled) 5012 5012 { 5013 5013 rc = GIMHypercall(pVCpu, pCtx); 5014 /* If the hypercall changes anything other than guest general-purpose registers,5015 we would need to reload the guest changed bits on VM-reentry. */5016 5014 if (RT_SUCCESS(rc)) 5017 5015 { 5016 /* If the hypercall changes anything other than guest general-purpose registers, 5017 we would need to reload the guest changed bits here before VM-reentry. */ 5018 5018 hmR0SvmUpdateRip(pVCpu, pCtx, 3); 5019 5019 return VINF_SUCCESS; … … 5228 5228 5229 5229 PVM pVM = pVCpu->CTX_SUFF(pVM); 5230 if ( pVM->hm.s.fTrapXcptUD 5231 && GIMAreHypercallsEnabled(pVCpu)) 5232 GIMXcptUD(pVCpu, pCtx); 5230 if (pVM->hm.s.fGIMTrapXcptUD) 5231 GIMXcptUD(pVCpu, pCtx, NULL /* pDis */); 5233 5232 else 5234 5233 hmR0SvmSetPendingXcptUD(pVCpu); -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r55037 r55118 10241 10241 { 10242 10242 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(); 10243 10244 int rc = VERR_NOT_SUPPORTED; 10245 if (GIMAreHypercallsEnabled(pVCpu)) 10246 { 10247 rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx); 10243 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitVmcall); 10244 10245 PVM pVM = pVCpu->CTX_SUFF(pVM); 10246 if (pVM->hm.s.fHypercallsEnabled) 10247 { 10248 #if 0 10249 int rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx); 10248 10250 AssertRCReturn(rc, rc); 10251 #else 10252 /* Aggressive state sync. for now. */ 10253 int rc = hmR0VmxSaveGuestRip(pVCpu, pMixedCtx); 10254 rc |= hmR0VmxSaveGuestSegmentRegs(pVCpu, pMixedCtx); /* For long-mode checks in gimKvmHypercall(). */ 10255 #endif 10256 AssertRCReturn(rc, rc); 10249 10257 10250 10258 rc = GIMHypercall(pVCpu, pMixedCtx); 10251 } 10252 10253 if (RT_SUCCESS(rc)) 10254 { 10255 rc = hmR0VmxAdvanceGuestRip(pVCpu, pMixedCtx, pVmxTransient); 10256 Assert(pVmxTransient->cbInstr == 3); 10257 10258 /* If the hypercall changes anything other than guest general-purpose registers, 10259 we would need to reload the guest changed bits on VM-reentry. */ 10260 } 10261 else 10262 { 10263 hmR0VmxSetPendingXcptUD(pVCpu, pMixedCtx); 10264 rc = VINF_SUCCESS; 10265 } 10266 10267 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitVmcall); 10268 return rc; 10259 if (RT_SUCCESS(rc)) 10260 { 10261 /* If the hypercall changes anything other than guest general-purpose registers, 10262 we would need to reload the guest changed bits here before VM-reentry. */ 10263 hmR0VmxAdvanceGuestRip(pVCpu, pMixedCtx, pVmxTransient); 10264 return VINF_SUCCESS; 10265 } 10266 } 10267 10268 hmR0VmxSetPendingXcptUD(pVCpu, pMixedCtx); 10269 return VINF_SUCCESS; 10269 10270 } 10270 10271 -
trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
r54819 r55118 633 633 GIMR3Mmio2Unmap(pVM, pRegion); 634 634 Assert(!pRegion->fMapped); 635 VMMHypercallsDisable(pVM); 635 636 LogRel(("GIM: HyperV: Disabled Hypercall-page\n")); 636 637 return VINF_SUCCESS; … … 680 681 * Patch the hypercall-page. 681 682 */ 682 if (HMIsEnabled(pVM)) 683 size_t cbWritten = 0; 684 rc = VMMPatchHypercall(pVM, pRegion->pvPageR3, PAGE_SIZE, &cbWritten); 685 if ( RT_SUCCESS(rc) 686 && cbWritten < PAGE_SIZE) 683 687 { 684 size_t cbWritten = 0; 685 rc = HMPatchHypercall(pVM, pRegion->pvPageR3, PAGE_SIZE, &cbWritten); 686 if ( RT_SUCCESS(rc) 687 && cbWritten < PAGE_SIZE) 688 { 689 uint8_t *pbLast = (uint8_t *)pRegion->pvPageR3 + cbWritten; 690 *pbLast = 0xc3; /* RET */ 691 692 LogRel(("GIM: HyperV: Enabled hypercalls at %#RGp\n", GCPhysHypercallPage)); 693 return VINF_SUCCESS; 694 } 695 else 696 { 697 if (rc == VINF_SUCCESS) 698 rc = VERR_GIM_OPERATION_FAILED; 699 LogRelFunc(("HMPatchHypercall failed. rc=%Rrc cbWritten=%u\n", rc, cbWritten)); 700 } 688 uint8_t *pbLast = (uint8_t *)pRegion->pvPageR3 + cbWritten; 689 *pbLast = 0xc3; /* RET */ 690 691 /* 692 * Notify VMM that hypercalls are now enabled. 693 */ 694 VMMHypercallsEnable(pVM); 695 696 LogRel(("GIM: HyperV: Enabled hypercalls at %#RGp\n", GCPhysHypercallPage)); 697 return VINF_SUCCESS; 701 698 } 702 699 else 703 700 { 704 /** @todo Handle raw-mode hypercall page patching. */ 705 LogRel(("GIM: HyperV: Raw-mode hypercalls not yet implemented!\n")); 701 if (rc == VINF_SUCCESS) 702 rc = VERR_GIM_OPERATION_FAILED; 703 LogRel(("GIM: HyperV: VMMPatchHypercall failed. rc=%Rrc cbWritten=%u\n", rc, cbWritten)); 706 704 } 705 707 706 GIMR3Mmio2Unmap(pVM, pRegion); 708 707 } 709 else 710 LogRelFunc(("GIMR3Mmio2Map failed. rc=%Rrc\n", rc)); 711 708 709 LogRel(("GIM: HyperV: GIMR3Mmio2Map failed. rc=%Rrc\n", rc)); 712 710 return rc; 713 711 } -
trunk/src/VBox/VMM/VMMR3/GIMKvm.cpp
r55037 r55118 30 30 31 31 #include <VBox/vmm/cpum.h> 32 #include <VBox/disopcode.h> 32 33 #include <VBox/vmm/ssm.h> 33 34 #include <VBox/vmm/vm.h> … … 141 142 } 142 143 144 /* 145 * Setup #UD and hypercall behaviour. 146 */ 147 VMMHypercallsEnable(pVM); 148 if (ASMIsAmdCpu()) 149 { 150 pKvm->fTrapXcptUD = true; 151 pKvm->uOpCodeNative = OP_VMMCALL; 152 } 153 else 154 { 155 Assert(ASMIsIntelCpu() || ASMIsViaCentaurCpu()); 156 pKvm->fTrapXcptUD = false; 157 pKvm->uOpCodeNative = OP_VMCALL; 158 } 159 /* We always need to trap VMCALL/VMMCALL hypercall using #UDs for raw-mode VMs. */ 160 if (!HMIsEnabled(pVM)) 161 pKvm->fTrapXcptUD = true; 162 143 163 return VINF_SUCCESS; 144 164 } … … 368 388 * time = ((tsc * SysTime.u32TscScale) >> 32) + SysTime.u64NanoTS 369 389 */ 370 uint64_t u64TscFreq = TMCpuTicksPerSecond(pVM);371 SystemTime.i8TscShift = 0;390 uint64_t u64TscFreq = TMCpuTicksPerSecond(pVM); 391 SystemTime.i8TscShift = 0; 372 392 while (u64TscFreq > 2 * RT_NS_1SEC_64) 373 393 { -
trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
r55001 r55118 27 27 #include <VBox/vmm/dbgf.h> 28 28 #include <VBox/vmm/em.h> 29 #include <VBox/vmm/gim.h> 29 30 #include <VBox/vmm/csam.h> 30 31 #include <VBox/vmm/patm.h> … … 595 596 #ifdef DTRACE_EXPERIMENT /** @todo fix/remove/permanent-enable this when DIS/PATM handles invalid lock sequences. */ 596 597 Assert(!PATMIsPatchGCAddr(pVM, pRegFrame->eip)); 597 rc = TRPMForwardTrap(pVCpu, pRegFrame, 0x6, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_TRAP, 0x6);598 rc = TRPMForwardTrap(pVCpu, pRegFrame, X86_XCPT_UD, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_TRAP, X86_XCPT_UD); 598 599 Assert(rc == VINF_EM_RAW_GUEST_TRAP); 599 600 #else … … 609 610 rc = EMInterpretInstructionDisasState(pVCpu, &Cpu, pRegFrame, PC, EMCODETYPE_SUPERVISOR); 610 611 } 612 else if (GIMShouldTrapXcptUD(pVM)) 613 { 614 LogFlow(("TRPMGCTrap06Handler: -> GIMXcptUD\n")); 615 rc = GIMXcptUD(pVCpu, CPUMCTX_FROM_CORE(pRegFrame), &Cpu); 616 if (RT_FAILURE(rc)) 617 { 618 LogFlow(("TRPMGCTrap06Handler: -> GIMXcptUD -> VINF_EM_RAW_EMULATE_INSTR\n")); 619 rc = VINF_EM_RAW_EMULATE_INSTR; 620 } 621 } 611 622 /* Never generate a raw trap here; it might be an instruction, that requires emulation. */ 612 623 else … … 619 630 { 620 631 LogFlow(("TRPMGCTrap06Handler: -> TRPMForwardTrap\n")); 621 rc = TRPMForwardTrap(pVCpu, pRegFrame, 0x6, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_TRAP, 0x6);632 rc = TRPMForwardTrap(pVCpu, pRegFrame, X86_XCPT_UD, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_TRAP, X86_XCPT_UD); 622 633 Assert(rc == VINF_EM_RAW_GUEST_TRAP); 623 634 } -
trunk/src/VBox/VMM/include/GIMKvmInternal.h
r55037 r55118 193 193 typedef struct GIMKVM 194 194 { 195 /** @name MSRs. */196 195 /** Wall-clock MSR. */ 197 196 uint64_t u64WallClockMsr; 198 /** @} */ 199 200 /** @name CPUID features. */ 201 /** Basic features. */ 197 198 /** CPUID features: Basic. */ 202 199 uint32_t uBaseFeat; 203 /** @} */ 204 205 /** Whether we need to trap #UD exceptions. */ 200 201 /** Whether GIM needs to trap #UD exceptions. */ 206 202 bool fTrapXcptUD; 203 /** Disassembler opcode of hypercall instruction native for this host CPU. */ 204 uint16_t uOpCodeNative; 207 205 } GIMKVM; 208 206 /** Pointer to per-VM GIM KVM instance data. */ … … 264 262 VMM_INT_DECL(VBOXSTRICTRC) gimKvmWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue); 265 263 VMM_INT_DECL(bool) gimKvmShouldTrapXcptUD(PVM pVM); 266 VMM_INT_DECL(int) gimKvmXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx );264 VMM_INT_DECL(int) gimKvmXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis); 267 265 268 266 -
trunk/src/VBox/VMM/include/HMInternal.h
r55037 r55118 344 344 bool fTPRPatchingActive; 345 345 /** Whether #UD needs to be intercepted (required by certain GIM providers). */ 346 bool fTrapXcptUD; 347 bool u8Alignment[2]; 346 bool fGIMTrapXcptUD; 347 /** Whether paravirt. hypercalls are enabled. */ 348 bool fHypercallsEnabled; 349 bool u8Alignment[1]; 348 350 349 351 /** Host kernel flags that HM might need to know (SUPKERNELFEATURES_XXX). */
Note:
See TracChangeset
for help on using the changeset viewer.

