Changeset 51643 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Jun 18, 2014 11:06:06 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 94404
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/GIM.cpp
r51560 r51643 90 90 */ 91 91 int rc; 92 #if 0 93 rc = SSMR3RegisterInternal(pVM, "GIM", 0, GIM_SSM_VERSION, sizeof(GIM), 94 NULL, NULL, NULL, 95 NULL, gimR3Save, NULL, 96 NULL, gimR3Load, NULL); 92 rc = SSMR3RegisterInternal(pVM, "GIM", 0 /* uInstance */, GIM_SSM_VERSION, sizeof(GIM), 93 NULL /* pfnLivePrep */, NULL /* pfnLiveExec */, NULL /* pfnLiveVote*/, 94 NULL /* pfnSavePrep */, gimR3Save, NULL /* pfnSaveDone */, 95 NULL /* pfnLoadPrep */, gimR3Load, NULL /* pfnLoadDone */); 97 96 if (RT_FAILURE(rc)) 98 97 return rc; 99 #endif100 98 101 99 /* … … 226 224 227 225 /** 228 * Execute statesave operation.226 * Executes state-save operation. 229 227 * 230 228 * @returns VBox status code. … … 234 232 DECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM) 235 233 { 236 /** @todo save state. */ 237 return VINF_SUCCESS; 234 AssertReturn(pVM, VERR_INVALID_PARAMETER); 235 AssertReturn(pSSM, VERR_SSM_INVALID_STATE); 236 237 /** @todo Save per-CPU data. */ 238 int rc; 239 #if 0 240 for (VMCPUID i = 0; i < pVM->cCpus; i++) 241 { 242 rc = SSMR3PutXYZ(pSSM, pVM->aCpus[i].gim.s.XYZ); 243 } 244 #endif 245 246 /* 247 * Save per-VM data. 248 */ 249 rc = SSMR3PutBool(pSSM, pVM->gim.s.fEnabled); 250 AssertRCReturn(rc, rc); 251 rc = SSMR3PutU32(pSSM, pVM->gim.s.enmProviderId); 252 AssertRCReturn(rc, rc); 253 rc = SSMR3PutU32(pSSM, pVM->gim.s.u32Version); 254 AssertRCReturn(rc, rc); 255 256 /* 257 * Save provider-specific data. 258 */ 259 if (pVM->gim.s.fEnabled) 260 { 261 switch (pVM->gim.s.enmProviderId) 262 { 263 case GIMPROVIDERID_HYPERV: 264 rc = GIMR3HvSave(pVM, pSSM); 265 AssertRCReturn(rc, rc); 266 break; 267 268 default: 269 break; 270 } 271 } 272 273 return rc; 238 274 } 239 275 … … 250 286 DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 251 287 { 252 /** @todo load state. */ 253 return VINF_SUCCESS; 288 if (uPass != SSM_PASS_FINAL) 289 return VINF_SUCCESS; 290 291 /** @todo Load per-CPU data. */ 292 int rc; 293 #if 0 294 for (VMCPUID i = 0; i < pVM->cCpus; i++) 295 { 296 rc = SSMR3PutXYZ(pSSM, pVM->aCpus[i].gim.s.XYZ); 297 } 298 #endif 299 300 /* 301 * Load per-VM data. 302 */ 303 rc = SSMR3GetBool(pSSM, &pVM->gim.s.fEnabled); 304 AssertRCReturn(rc, rc); 305 rc = SSMR3GetU32(pSSM, (uint32_t *)&pVM->gim.s.enmProviderId); 306 AssertRCReturn(rc, rc); 307 rc = SSMR3GetU32(pSSM, &pVM->gim.s.u32Version); 308 AssertRCReturn(rc, rc); 309 310 /* 311 * Load provider-specific data. 312 */ 313 if (pVM->gim.s.fEnabled) 314 { 315 switch (pVM->gim.s.enmProviderId) 316 { 317 case GIMPROVIDERID_HYPERV: 318 rc = GIMR3HvLoad(pVM, pSSM, uVersion); 319 AssertRCReturn(rc, rc); 320 break; 321 322 default: 323 break; 324 } 325 } 326 327 return rc; 254 328 } 255 329 … … 266 340 VMMR3_INT_DECL(int) GIMR3Term(PVM pVM) 267 341 { 342 if (!pVM->gim.s.fEnabled) 343 return VINF_SUCCESS; 344 345 switch (pVM->gim.s.enmProviderId) 346 { 347 case GIMPROVIDERID_HYPERV: 348 return GIMR3HvTerm(pVM); 349 350 default: 351 break; 352 } 268 353 return VINF_SUCCESS; 269 354 } … … 350 435 * @param pRegion Pointer to the GIM MMIO2 region. 351 436 */ 352 VMM _INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion)437 VMMR3_INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion) 353 438 { 354 439 AssertPtr(pVM); … … 359 444 if (pRegion->fMapped) 360 445 { 361 PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage); 362 int rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage); 446 int rc = PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage); 447 AssertRC(rc); 448 449 rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage); 363 450 if (RT_SUCCESS(rc)) 364 451 { … … 372 459 373 460 /** 374 * Write access handler for a mapped MMIO2 region that presently ignores writes. 461 * Write access handler for a mapped MMIO2 region. At present, this handler 462 * simply ignores writes. 463 * 464 * In the future we might want to let the GIM provider decide what the handler 465 * should do (like throwing #GP faults). 375 466 * 376 467 * @returns VBox status code. … … 383 474 * @param pvUser User argument (NULL, not used). 384 475 */ 385 static DECLCALLBACK(int) gimR3Mmio2 PageWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,386 476 static DECLCALLBACK(int) gimR3Mmio2WriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, 477 PGMACCESSTYPE enmAccessType, void *pvUser) 387 478 { 388 479 /* … … 402 493 * @param pRegion Pointer to the GIM MMIO2 region. 403 494 * @param GCPhysRegion Where in the guest address space to map the region. 404 * @param pszDesc Description of the region being mapped. 405 */ 406 VMM_INT_DECL(int) GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion, const char *pszDesc) 495 */ 496 VMMR3_INT_DECL(int) GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion) 407 497 { 408 498 PPDMDEVINS pDevIns = pVM->gim.s.pDevInsR3; … … 412 502 if (GCPhysRegion & PAGE_OFFSET_MASK) 413 503 { 414 LogFunc(("%s: %#RGp not paging aligned\n", p szDesc, GCPhysRegion));504 LogFunc(("%s: %#RGp not paging aligned\n", pRegion->szDescription, GCPhysRegion)); 415 505 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS; 416 506 } … … 421 511 if (!PGMPhysIsGCPhysNormal(pVM, GCPhysRegion)) 422 512 { 423 LogFunc(("%s: %#RGp is not normal memory\n", p szDesc, GCPhysRegion));513 LogFunc(("%s: %#RGp is not normal memory\n", pRegion->szDescription, GCPhysRegion)); 424 514 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS; 425 515 } 426 516 427 if ( pRegion->fMapped)428 { 429 LogFunc(("%s: A mapping for %#RGp already exists.\n", pszDesc, GCPhysRegion));430 return VERR_ PGM_MAPPING_CONFLICT;431 } 432 433 /* 434 * Map the MMIO2 region over the guest-physical address.517 if (!pRegion->fRegistered) 518 { 519 LogFunc(("%s: Region has not been registered.\n")); 520 return VERR_GIM_IPE_1; 521 } 522 523 /* 524 * Map the MMIO2 region over the specified guest-physical address. 435 525 */ 436 526 int rc = PDMDevHlpMMIO2Map(pDevIns, pRegion->iRegion, GCPhysRegion); … … 443 533 PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, 444 534 GCPhysRegion, GCPhysRegion + (pRegion->cbRegion - 1), 445 gimR3Mmio2 PageWriteHandler, NULL /* pvUserR3 */,535 gimR3Mmio2WriteHandler, NULL /* pvUserR3 */, 446 536 NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */, 447 537 NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */, 448 p szDesc);538 pRegion->szDescription); 449 539 if (RT_SUCCESS(rc)) 450 540 { 451 541 pRegion->fMapped = true; 452 542 pRegion->GCPhysPage = GCPhysRegion; 453 return VINF_SUCCESS;543 return rc; 454 544 } 455 545 … … 460 550 } 461 551 552 #if 0 553 /** 554 * Registers the physical handler for the registered and mapped MMIO2 region. 555 * 556 * @returns VBox status code. 557 * @param pVM Pointer to the VM. 558 * @param pRegion Pointer to the GIM MMIO2 region. 559 */ 560 VMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalRegister(PVM pVM, PGIMMMIO2REGION pRegion) 561 { 562 AssertPtr(pRegion); 563 AssertReturn(pRegion->fRegistered, VERR_GIM_IPE_2); 564 AssertReturn(pRegion->fMapped, VERR_GIM_IPE_3); 565 566 return PGMR3HandlerPhysicalRegister(pVM, 567 PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, 568 pRegion->GCPhysPage, pRegion->GCPhysPage + (pRegion->cbRegion - 1), 569 gimR3Mmio2WriteHandler, NULL /* pvUserR3 */, 570 NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */, 571 NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */, 572 pRegion->szDescription); 573 } 574 575 576 /** 577 * Deregisters the physical handler for the MMIO2 region. 578 * 579 * @returns VBox status code. 580 * @param pVM Pointer to the VM. 581 * @param pRegion Pointer to the GIM MMIO2 region. 582 */ 583 VMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalDeregister(PVM pVM, PGIMMMIO2REGION pRegion) 584 { 585 return PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage); 586 } 587 #endif 588 -
trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
r51560 r51643 26 26 #include <iprt/string.h> 27 27 #include <iprt/mem.h> 28 #include <iprt/spinlock.h> 28 29 29 30 #include <VBox/vmm/cpum.h> 31 #include <VBox/vmm/ssm.h> 30 32 #include <VBox/vmm/vm.h> 31 33 #include <VBox/vmm/hm.h> … … 111 113 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 112 114 pRegion->iRegion = GIM_HV_HYPERCALL_PAGE_REGION_IDX; 115 pRegion->fRCMapping = false; 113 116 pRegion->cbRegion = PAGE_SIZE; 114 117 pRegion->GCPhysPage = NIL_RTGCPHYS; 115 RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hypercall Page"); 116 Assert(!pRegion->fRCMapping); 117 Assert(!pRegion->fMapped); 118 RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hyper-V hypercall page"); 118 119 119 120 pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; 120 121 pRegion->iRegion = GIM_HV_REF_TSC_PAGE_REGION_IDX; 122 pRegion->fRCMapping = false; 121 123 pRegion->cbRegion = PAGE_SIZE; 122 124 pRegion->GCPhysPage = NIL_RTGCPHYS; 123 RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), " TSC Page");125 RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hyper-V TSC page"); 124 126 125 127 /* … … 219 221 220 222 223 VMMR3_INT_DECL(int) GIMR3HvTerm(PVM pVM) 224 { 225 GIMR3HvReset(pVM); 226 return VINF_SUCCESS; 227 } 228 229 221 230 VMMR3_INT_DECL(void) GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta) 222 231 { … … 239 248 * Unmap MMIO2 pages that the guest may have setup. 240 249 */ 250 LogRelFunc(("Resetting Hyper-V MMIO2 regions and MSRs...\n")); 241 251 PGIMHV pHv = &pVM->gim.s.u.Hv; 242 252 for (unsigned i = 0; i < RT_ELEMENTS(pHv->aMmio2Regions); i++) … … 272 282 } 273 283 284 285 /** 286 * Hyper-V state-save operation. 287 * 288 * @returns VBox status code. 289 * @param pVM Pointer to the VM. 290 * @param pSSM Pointer to the SSM handle. 291 */ 292 VMMR3_INT_DECL(int) GIMR3HvSave(PVM pVM, PSSMHANDLE pSSM) 293 { 294 PCGIMHV pcHv = &pVM->gim.s.u.Hv; 295 296 /** @todo Save per-VCPU data. */ 297 298 /* 299 * Save per-VM MSRs. 300 */ 301 int rc = SSMR3PutU64(pSSM, pcHv->u64GuestOsIdMsr); AssertRCReturn(rc, rc); 302 rc = SSMR3PutU64(pSSM, pcHv->u64HypercallMsr); AssertRCReturn(rc, rc); 303 rc = SSMR3PutU64(pSSM, pcHv->u64TscPageMsr); AssertRCReturn(rc, rc); 304 305 /* 306 * Save Hyper-V features / capabilities. 307 */ 308 rc = SSMR3PutU32(pSSM, pcHv->uBaseFeat); AssertRCReturn(rc, rc); 309 rc = SSMR3PutU32(pSSM, pcHv->uPartFlags); AssertRCReturn(rc, rc); 310 rc = SSMR3PutU32(pSSM, pcHv->uPowMgmtFeat); AssertRCReturn(rc, rc); 311 rc = SSMR3PutU32(pSSM, pcHv->uMiscFeat); AssertRCReturn(rc, rc); 312 rc = SSMR3PutU32(pSSM, pcHv->uHyperHints); AssertRCReturn(rc, rc); 313 314 /* 315 * Save per-VM MMIO2 regions. 316 */ 317 rc = SSMR3PutU32(pSSM, RT_ELEMENTS(pcHv->aMmio2Regions)); 318 for (unsigned i = 0; i < RT_ELEMENTS(pcHv->aMmio2Regions); i++) 319 { 320 /* Save the fields necessary to remap the regions upon load.*/ 321 PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[i]; 322 rc = SSMR3PutU8(pSSM, pcRegion->iRegion); AssertRCReturn(rc, rc); 323 rc = SSMR3PutBool(pSSM, pcRegion->fRCMapping); AssertRCReturn(rc, rc); 324 rc = SSMR3PutU32(pSSM, pcRegion->cbRegion); AssertRCReturn(rc, rc); 325 rc = SSMR3PutGCPhys(pSSM, pcRegion->GCPhysPage); AssertRCReturn(rc, rc); 326 rc = SSMR3PutStrZ(pSSM, pcRegion->szDescription); AssertRCReturn(rc, rc); 327 } 328 329 return VINF_SUCCESS; 330 } 331 332 333 /** 334 * Hyper-V state-load operation, final pass. 335 * 336 * @returns VBox status code. 337 * @param pVM Pointer to the VM. 338 * @param pSSM Pointer to the SSM handle. 339 * @param uSSMVersion The saved-state version. 340 */ 341 VMMR3_INT_DECL(int) GIMR3HvLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion) 342 { 343 PGIMHV pHv = &pVM->gim.s.u.Hv; 344 345 /** @todo Load per-VCPU data. */ 346 347 /* 348 * Load per-VM MSRs. 349 */ 350 int rc = SSMR3GetU64(pSSM, &pHv->u64GuestOsIdMsr); AssertRCReturn(rc, rc); 351 rc = SSMR3GetU64(pSSM, &pHv->u64HypercallMsr); AssertRCReturn(rc, rc); 352 rc = SSMR3GetU64(pSSM, &pHv->u64TscPageMsr); AssertRCReturn(rc, rc); 353 354 /* 355 * Save Hyper-V features / capabilities. 356 */ 357 rc = SSMR3GetU32(pSSM, &pHv->uBaseFeat); AssertRCReturn(rc, rc); 358 rc = SSMR3GetU32(pSSM, &pHv->uPartFlags); AssertRCReturn(rc, rc); 359 rc = SSMR3GetU32(pSSM, &pHv->uPowMgmtFeat); AssertRCReturn(rc, rc); 360 rc = SSMR3GetU32(pSSM, &pHv->uMiscFeat); AssertRCReturn(rc, rc); 361 rc = SSMR3GetU32(pSSM, &pHv->uHyperHints); AssertRCReturn(rc, rc); 362 363 /* 364 * Load per-VM MMIO2 regions. 365 */ 366 uint32_t cRegions; 367 rc = SSMR3GetU32(pSSM, &cRegions); 368 if (cRegions != RT_ELEMENTS(pHv->aMmio2Regions)) 369 { 370 LogRelFunc(("MMIO2 region array size mismatch. size=%u expected=%u\n", cRegions, RT_ELEMENTS(pHv->aMmio2Regions))); 371 return VERR_SSM_FIELD_INVALID_VALUE; 372 } 373 374 for (unsigned i = 0; i < RT_ELEMENTS(pHv->aMmio2Regions); i++) 375 { 376 /* The regions would have been registered while constructing the GIM device. */ 377 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[i]; 378 rc = SSMR3GetU8(pSSM, &pRegion->iRegion); AssertRCReturn(rc, rc); 379 rc = SSMR3GetBool(pSSM, &pRegion->fRCMapping); AssertRCReturn(rc, rc); 380 rc = SSMR3GetU32(pSSM, &pRegion->cbRegion); AssertRCReturn(rc, rc); 381 rc = SSMR3GetGCPhys(pSSM, &pRegion->GCPhysPage); AssertRCReturn(rc, rc); 382 rc = SSMR3GetStrZ(pSSM, pRegion->szDescription, sizeof(pRegion->szDescription)); 383 AssertRCReturn(rc, rc); 384 } 385 386 /* 387 * Enable the Hypercall-page. 388 */ 389 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 390 if (MSR_GIM_HV_HYPERCALL_IS_ENABLED(pHv->u64HypercallMsr)) 391 { 392 Assert(pRegion->GCPhysPage != NIL_RTGCPHYS); 393 if (pRegion->fRegistered) 394 { 395 rc = GIMR3HvEnableHypercallPage(pVM, pRegion->GCPhysPage); 396 if (RT_FAILURE(rc)) 397 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to enable the hypercall page. GCPhys=%#RGp rc=%Rrc"), 398 pRegion->GCPhysPage, rc); 399 } 400 else 401 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Hypercall MMIO2 region not registered. Missing GIM device?!")); 402 } 403 404 /* 405 * Enable the TSC-page. 406 */ 407 pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; 408 if (MSR_GIM_HV_REF_TSC_IS_ENABLED(pHv->u64TscPageMsr)) 409 { 410 Assert(pRegion->GCPhysPage != NIL_RTGCPHYS); 411 if (pRegion->fRegistered) 412 { 413 rc = GIMR3HvEnableTscPage(pVM, pRegion->GCPhysPage); 414 if (RT_FAILURE(rc)) 415 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to enable the TSC page. GCPhys=%#RGp rc=%Rrc"), 416 pRegion->GCPhysPage, rc); 417 } 418 else 419 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("TSC-page MMIO2 region not registered. Missing GIM device?!")); 420 } 421 422 return rc; 423 } 424 425 426 /** 427 * Enables the Hyper-V TSC page. 428 * 429 * @returns VBox status code. 430 * @param pVM Pointer to the VM. 431 * @param GCPhysTscPage Where to map the TSC page. 432 */ 433 VMMR3_INT_DECL(int) GIMR3HvEnableTscPage(PVM pVM, RTGCPHYS GCPhysTscPage) 434 { 435 PPDMDEVINSR3 pDevIns = pVM->gim.s.pDevInsR3; 436 PGIMMMIO2REGION pRegion = &pVM->gim.s.u.Hv.aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; 437 AssertPtrReturn(pDevIns, VERR_GIM_DEVICE_NOT_REGISTERED); 438 439 int rc; 440 if (pRegion->fMapped) 441 { 442 /* 443 * Is it already enabled at the given guest-address? 444 */ 445 if (pRegion->GCPhysPage == GCPhysTscPage) 446 return VINF_SUCCESS; 447 448 /* 449 * If it's mapped at a different address, unmap the previous address. 450 */ 451 rc = GIMR3HvDisableTscPage(pVM); 452 AssertRC(rc); 453 } 454 455 /* 456 * Map the TSC-page at the specified address. 457 */ 458 Assert(!pRegion->fMapped); 459 rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysTscPage); 460 if (RT_SUCCESS(rc)) 461 { 462 Assert(pRegion->GCPhysPage == GCPhysTscPage); 463 464 /* 465 * Update the TSC scale. Windows guests expect a non-zero TSC sequence, otherwise 466 * they fallback to using the reference count MSR which is not ideal in terms of VM-exits. 467 * 468 * Also, Hyper-V normalizes the time in 10 MHz, see: 469 * http://technet.microsoft.com/it-it/sysinternals/dn553408%28v=vs.110%29 470 */ 471 PGIMHVREFTSC pRefTsc = (PGIMHVREFTSC)pRegion->pvPageR3; 472 Assert(pRefTsc); 473 474 uint64_t const u64TscKHz = TMCpuTicksPerSecond(pVM) / UINT64_C(1000); 475 pRefTsc->u32TscSequence = 1; 476 //pRefTsc->u64TscScale = ((UINT64_C(10000) << 32) / u64TscKHz) << 32; 477 pRefTsc->u64TscScale = 0xf4000000000000; 478 479 LogRel(("GIM: HyperV: Enabled TSC page at %#RGp (u64TscScale=%#RX64 u64TscKHz=%#RX64)\n", GCPhysTscPage, 480 pRefTsc->u64TscScale, u64TscKHz)); 481 return VINF_SUCCESS; 482 } 483 else 484 LogRelFunc(("GIMR3Mmio2Map failed. rc=%Rrc\n", rc)); 485 486 return VERR_GIM_OPERATION_FAILED; 487 } 488 489 490 /** 491 * Disables the Hyper-V TSC page. 492 * 493 * @returns VBox status code. 494 * @param pVM Pointer to the VM. 495 */ 496 VMMR3_INT_DECL(int) GIMR3HvDisableTscPage(PVM pVM) 497 { 498 PGIMHV pHv = &pVM->gim.s.u.Hv; 499 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; 500 if (pRegion->fMapped) 501 { 502 GIMR3Mmio2Unmap(pVM, pRegion); 503 Assert(!pRegion->fMapped); 504 LogRel(("GIM: HyperV: Disabled TSC-page\n")); 505 return VINF_SUCCESS; 506 } 507 return VERR_GIM_PVTSC_NOT_ENABLED; 508 } 509 510 511 /** 512 * Disables the Hyper-V Hypercall page. 513 * 514 * @returns VBox status code. 515 */ 516 VMMR3_INT_DECL(int) GIMR3HvDisableHypercallPage(PVM pVM) 517 { 518 PGIMHV pHv = &pVM->gim.s.u.Hv; 519 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 520 if (pRegion->fMapped) 521 { 522 GIMR3Mmio2Unmap(pVM, pRegion); 523 Assert(!pRegion->fMapped); 524 LogRel(("GIM: HyperV: Disabled Hypercall-page\n")); 525 return VINF_SUCCESS; 526 } 527 return VERR_GIM_HYPERCALLS_NOT_ENABLED; 528 } 529 530 531 /** 532 * Enables the Hyper-V Hypercall page. 533 * 534 * @returns VBox status code. 535 * @param pVM Pointer to the VM. 536 * @param GCPhysHypercallPage Where to map the hypercall page. 537 */ 538 VMMR3_INT_DECL(int) GIMR3HvEnableHypercallPage(PVM pVM, RTGCPHYS GCPhysHypercallPage) 539 { 540 PPDMDEVINSR3 pDevIns = pVM->gim.s.pDevInsR3; 541 PGIMMMIO2REGION pRegion = &pVM->gim.s.u.Hv.aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 542 AssertPtrReturn(pDevIns, VERR_GIM_DEVICE_NOT_REGISTERED); 543 544 if (pRegion->fMapped) 545 { 546 /* 547 * Is it already enabled at the given guest-address? 548 */ 549 if (pRegion->GCPhysPage == GCPhysHypercallPage) 550 return VINF_SUCCESS; 551 552 /* 553 * If it's mapped at a different address, unmap the previous address. 554 */ 555 int rc2 = GIMR3HvDisableHypercallPage(pVM); 556 AssertRC(rc2); 557 } 558 559 /* 560 * Map the hypercall-page at the specified address. 561 */ 562 Assert(!pRegion->fMapped); 563 int rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysHypercallPage); 564 if (RT_SUCCESS(rc)) 565 { 566 Assert(pRegion->GCPhysPage == GCPhysHypercallPage); 567 568 /* 569 * Patch the hypercall-page. 570 */ 571 if (HMIsEnabled(pVM)) 572 { 573 size_t cbWritten = 0; 574 rc = HMPatchHypercall(pVM, pRegion->pvPageR3, PAGE_SIZE, &cbWritten); 575 if ( RT_SUCCESS(rc) 576 && cbWritten < PAGE_SIZE - 1) 577 { 578 uint8_t *pbLast = (uint8_t *)pRegion->pvPageR3 + cbWritten; 579 *pbLast = 0xc3; /* RET */ 580 581 LogRel(("GIM: HyperV: Enabled hypercalls at %#RGp\n", GCPhysHypercallPage)); 582 return VINF_SUCCESS; 583 } 584 else 585 LogRelFunc(("HMPatchHypercall failed. rc=%Rrc cbWritten=%u\n", rc, cbWritten)); 586 } 587 else 588 { 589 /** @todo Handle raw-mode hypercall page patching. */ 590 LogRelFunc(("Raw-mode not yet implemented!\n")); 591 } 592 GIMR3Mmio2Unmap(pVM, pRegion); 593 } 594 else 595 LogRelFunc(("GIMR3Mmio2Map failed. rc=%Rrc\n", rc)); 596 597 return rc; 598 } 599 -
trunk/src/VBox/VMM/VMMR3/HM.cpp
r51220 r51643 733 733 HM_REG_COUNTER(&pVCpu->hm.s.StatTlbShootdownFlush, "/HM/CPU%d/Flush/Shootdown/TLB", "Inter-VCPU request to flush entire guest-TLB."); 734 734 735 HM_REG_COUNTER(&pVCpu->hm.s.StatTscOffsetAdjusted, "/HM/CPU%d/TSC/OffsetAdjusted", "TSC offset overflowed for paravirt. TSC. Fudged."); 736 HM_REG_COUNTER(&pVCpu->hm.s.StatTscParavirt, "/HM/CPU%d/TSC/Paravirt", "Paravirtualized TSC in effect."); 735 737 HM_REG_COUNTER(&pVCpu->hm.s.StatTscOffset, "/HM/CPU%d/TSC/Offset", "TSC offsetting is in effect."); 736 738 HM_REG_COUNTER(&pVCpu->hm.s.StatTscIntercept, "/HM/CPU%d/TSC/Intercept", "Guest is in catchup mode, intercept TSC accesses."); … … 1172 1174 { 1173 1175 CPUMClearGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP); 1174 LogRel(("HM: RDTSCP disabled .\n"));1176 LogRel(("HM: RDTSCP disabled\n")); 1175 1177 } 1176 1178 … … 1241 1243 1242 1244 LogRel((pVM->hm.s.fAllow64BitGuests 1243 ? "HM: Guest support: 32-bit and 64-bit .\n"1244 : "HM: Guest support: 32-bit only .\n"));1245 ? "HM: Guest support: 32-bit and 64-bit\n" 1246 : "HM: Guest support: 32-bit only\n")); 1245 1247 1246 1248 /* … … 1287 1289 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX); 1288 1290 else 1289 LogRel(("HM: NX not enabled on the host, unavailable to PAE guest .\n"));1291 LogRel(("HM: NX not enabled on the host, unavailable to PAE guest\n")); 1290 1292 } 1291 1293 … … 1296 1298 { 1297 1299 LogRel(("HM: Nested paging enabled!\n")); 1298 if (pVM->hm.s.vmx.enmFlushEpt == VMX _FLUSH_EPT_SINGLE_CONTEXT)1299 LogRel(("HM: EPT flush type = VMX _FLUSH_EPT_SINGLE_CONTEXT\n"));1300 else if (pVM->hm.s.vmx.enmFlushEpt == VMX _FLUSH_EPT_ALL_CONTEXTS)1301 LogRel(("HM: EPT flush type = VMX _FLUSH_EPT_ALL_CONTEXTS\n"));1302 else if (pVM->hm.s.vmx.enmFlushEpt == VMX _FLUSH_EPT_NOT_SUPPORTED)1303 LogRel(("HM: EPT flush type = VMX _FLUSH_EPT_NOT_SUPPORTED\n"));1300 if (pVM->hm.s.vmx.enmFlushEpt == VMXFLUSHEPT_SINGLE_CONTEXT) 1301 LogRel(("HM: EPT flush type = VMXFLUSHEPT_SINGLE_CONTEXT\n")); 1302 else if (pVM->hm.s.vmx.enmFlushEpt == VMXFLUSHEPT_ALL_CONTEXTS) 1303 LogRel(("HM: EPT flush type = VMXFLUSHEPT_ALL_CONTEXTS\n")); 1304 else if (pVM->hm.s.vmx.enmFlushEpt == VMXFLUSHEPT_NOT_SUPPORTED) 1305 LogRel(("HM: EPT flush type = VMXFLUSHEPT_NOT_SUPPORTED\n")); 1304 1306 else 1305 1307 LogRel(("HM: EPT flush type = %d\n", pVM->hm.s.vmx.enmFlushEpt)); … … 1313 1315 /* Use large (2 MB) pages for our EPT PDEs where possible. */ 1314 1316 PGMSetLargePageUsage(pVM, true); 1315 LogRel(("HM: Large page support enabled !\n"));1317 LogRel(("HM: Large page support enabled\n")); 1316 1318 } 1317 1319 #endif … … 1323 1325 { 1324 1326 LogRel(("HM: VPID enabled!\n")); 1325 if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_INDIV_ADDR)1326 LogRel(("HM: VPID flush type = VMX _FLUSH_VPID_INDIV_ADDR\n"));1327 else if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_SINGLE_CONTEXT)1328 LogRel(("HM: VPID flush type = VMX _FLUSH_VPID_SINGLE_CONTEXT\n"));1329 else if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_ALL_CONTEXTS)1330 LogRel(("HM: VPID flush type = VMX _FLUSH_VPID_ALL_CONTEXTS\n"));1331 else if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS)1332 LogRel(("HM: VPID flush type = VMX _FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS\n"));1327 if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_INDIV_ADDR) 1328 LogRel(("HM: VPID flush type = VMXFLUSHVPID_INDIV_ADDR\n")); 1329 else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_SINGLE_CONTEXT) 1330 LogRel(("HM: VPID flush type = VMXFLUSHVPID_SINGLE_CONTEXT\n")); 1331 else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_ALL_CONTEXTS) 1332 LogRel(("HM: VPID flush type = VMXFLUSHVPID_ALL_CONTEXTS\n")); 1333 else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS) 1334 LogRel(("HM: VPID flush type = VMXFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS\n")); 1333 1335 else 1334 1336 LogRel(("HM: VPID flush type = %d\n", pVM->hm.s.vmx.enmFlushVpid)); 1335 1337 } 1336 else if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_NOT_SUPPORTED)1337 LogRel(("HM: Ignoring VPID capabilities of CPU .\n"));1338 else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_NOT_SUPPORTED) 1339 LogRel(("HM: Ignoring VPID capabilities of CPU\n")); 1338 1340 1339 1341 /* … … 1347 1349 } 1348 1350 if (pVM->hm.s.vmx.fUsePreemptTimer) 1349 LogRel(("HM: VMX-preemption timer enabled (cPreemptTimerShift=%u) .\n", pVM->hm.s.vmx.cPreemptTimerShift));1351 LogRel(("HM: VMX-preemption timer enabled (cPreemptTimerShift=%u)\n", pVM->hm.s.vmx.cPreemptTimerShift)); 1350 1352 else 1351 LogRel(("HM: VMX-preemption timer disabled .\n"));1353 LogRel(("HM: VMX-preemption timer disabled\n")); 1352 1354 1353 1355 return VINF_SUCCESS; … … 1465 1467 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX); 1466 1468 1467 LogRel(("HM: TPR patching %s .\n", (pVM->hm.s.fTprPatchingAllowed) ? "enabled" : "disabled"));1469 LogRel(("HM: TPR patching %s\n", (pVM->hm.s.fTprPatchingAllowed) ? "enabled" : "disabled")); 1468 1470 1469 1471 LogRel((pVM->hm.s.fAllow64BitGuests 1470 ? "HM: Guest support: 32-bit and 64-bit .\n"1471 : "HM: Guest support: 32-bit only .\n"));1472 ? "HM: Guest support: 32-bit and 64-bit\n" 1473 : "HM: Guest support: 32-bit only\n")); 1472 1474 1473 1475 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.