Changeset 99316 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Apr 6, 2023 3:19:22 PM (21 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp
r99051 r99316 125 125 126 126 /** 127 * Creates a physical access handler, allocation part. 128 * 129 * @returns VBox status code. 130 * @retval VERR_OUT_OF_RESOURCES if no more handlers available. 131 * 132 * @param pVM The cross context VM structure. 133 * @param hType The handler type registration handle. 134 * @param uUser User argument to the handlers (not pointer). 135 * @param pszDesc Description of this handler. If NULL, the type 136 * description will be used instead. 137 * @param ppPhysHandler Where to return the access handler structure on 138 * success. 139 */ 140 int pgmHandlerPhysicalExCreate(PVMCC pVM, PGMPHYSHANDLERTYPE hType, uint64_t uUser, 141 R3PTRTYPE(const char *) pszDesc, PPGMPHYSHANDLER *ppPhysHandler) 142 { 143 /* 144 * Validate input. 145 */ 146 PCPGMPHYSHANDLERTYPEINT const pType = pgmHandlerPhysicalTypeHandleToPtr(pVM, hType); 147 AssertReturn(pType, VERR_INVALID_HANDLE); 148 AssertReturn(pType->enmKind > PGMPHYSHANDLERKIND_INVALID && pType->enmKind < PGMPHYSHANDLERKIND_END, VERR_INVALID_HANDLE); 149 AssertPtr(ppPhysHandler); 150 151 Log(("pgmHandlerPhysicalExCreate: uUser=%#RX64 hType=%#x (%d, %s) pszDesc=%RHv:%s\n", 152 uUser, hType, pType->enmKind, pType->pszDesc, pszDesc, R3STRING(pszDesc))); 153 154 /* 155 * Allocate and initialize the new entry. 156 */ 157 int rc = PGM_LOCK(pVM); 158 AssertRCReturn(rc, rc); 159 127 * Worker for pgmHandlerPhysicalExCreate. 128 * 129 * @returns A new physical handler on success or NULL on failure. 130 * @param pVM The cross context VM structure. 131 * @param pType The physical handler type. 132 * @param hType The physical handler type registeration handle. 133 * @param uUser User argument to the handlers (not pointer). 134 * @param pszDesc Description of this handler. If NULL, the type description 135 * will be used instead. 136 */ 137 DECL_FORCE_INLINE(PPGMPHYSHANDLER) pgmHandlerPhysicalExCreateWorker(PVMCC pVM, PCPGMPHYSHANDLERTYPEINT pType, 138 PGMPHYSHANDLERTYPE hType, uint64_t uUser, 139 R3PTRTYPE(const char *) pszDesc) 140 { 141 PGM_LOCK_ASSERT_OWNER(pVM); 160 142 PPGMPHYSHANDLER pNew = pVM->VMCC_CTX(pgm).s.PhysHandlerAllocator.allocateNode(); 161 143 if (pNew) … … 174 156 : pVM->pgm.s.aPhysHandlerTypes[hType & PGMPHYSHANDLERTYPE_IDX_MASK].pszDesc; 175 157 #endif 176 177 PGM_UNLOCK(pVM); 178 *ppPhysHandler = pNew; 158 } 159 return pNew; 160 } 161 162 163 /** 164 * Creates a physical access handler, allocation part. 165 * 166 * @returns VBox status code. 167 * @retval VERR_OUT_OF_RESOURCES if no more handlers available. 168 * 169 * @param pVM The cross context VM structure. 170 * @param hType The handler type registration handle. 171 * @param uUser User argument to the handlers (not pointer). 172 * @param pszDesc Description of this handler. If NULL, the type 173 * description will be used instead. 174 * @param ppPhysHandler Where to return the access handler structure on 175 * success. 176 */ 177 int pgmHandlerPhysicalExCreate(PVMCC pVM, PGMPHYSHANDLERTYPE hType, uint64_t uUser, 178 R3PTRTYPE(const char *) pszDesc, PPGMPHYSHANDLER *ppPhysHandler) 179 { 180 /* 181 * Validate input. 182 */ 183 PCPGMPHYSHANDLERTYPEINT const pType = pgmHandlerPhysicalTypeHandleToPtr(pVM, hType); 184 AssertReturn(pType, VERR_INVALID_HANDLE); 185 AssertReturn(pType->enmKind > PGMPHYSHANDLERKIND_INVALID && pType->enmKind < PGMPHYSHANDLERKIND_END, VERR_INVALID_HANDLE); 186 AssertPtr(ppPhysHandler); 187 188 Log(("pgmHandlerPhysicalExCreate: uUser=%#RX64 hType=%#x (%d, %s) pszDesc=%RHv:%s\n", 189 uUser, hType, pType->enmKind, pType->pszDesc, pszDesc, R3STRING(pszDesc))); 190 191 /* 192 * Allocate and initialize the new entry. 193 */ 194 int rc = PGM_LOCK(pVM); 195 AssertRCReturn(rc, rc); 196 *ppPhysHandler = pgmHandlerPhysicalExCreateWorker(pVM, pType, hType, uUser, pszDesc); 197 PGM_UNLOCK(pVM); 198 if (*ppPhysHandler) 179 199 return VINF_SUCCESS; 180 }181 182 PGM_UNLOCK(pVM);183 200 return VERR_OUT_OF_RESOURCES; 184 201 } … … 313 330 314 331 /** 332 * Worker for pgmHandlerPhysicalRegisterVmxApicAccessPage. 333 * 334 * @returns VBox status code. 335 * @retval VINF_SUCCESS when successfully installed. 336 * @retval VINF_PGM_GCPHYS_ALIASED could be returned. 337 * 338 * @param pVM The cross context VM structure. 339 * @param pPhysHandler The physical handler. 340 * @param GCPhys The address of the virtual VMX APIC-access page. 341 */ 342 static int pgmHandlerPhysicalRegisterVmxApicAccessPage(PVMCC pVM, PPGMPHYSHANDLER pPhysHandler, RTGCPHYS GCPhys) 343 { 344 PGM_LOCK_ASSERT_OWNER(pVM); 345 LogFunc(("GCPhys=%RGp\n", GCPhys)); 346 347 /* 348 * We require the range to be within registered ram. 349 * There is no apparent need to support ranges which cover more than one ram range. 350 */ 351 PPGMRAMRANGE pRam = pgmPhysGetRange(pVM, GCPhys); 352 RTGCPHYS const GCPhysLast = GCPhys | X86_PAGE_4K_OFFSET_MASK; 353 if ( !pRam 354 || GCPhysLast > pRam->GCPhysLast) 355 { 356 #ifdef IN_RING3 357 DBGFR3Info(pVM->pUVM, "phys", NULL, NULL); 358 #endif 359 AssertMsgFailed(("No RAM range for %RGp-%RGp\n", GCPhys, GCPhysLast)); 360 return VERR_PGM_HANDLER_PHYSICAL_NO_RAM_RANGE; 361 } 362 Assert(GCPhys >= pRam->GCPhys && GCPhys < pRam->GCPhysLast); 363 Assert(GCPhysLast <= pRam->GCPhysLast && GCPhysLast >= pRam->GCPhys); 364 365 /* 366 * Try insert into list. 367 */ 368 pPhysHandler->Key = GCPhys; 369 pPhysHandler->KeyLast = GCPhysLast; 370 pPhysHandler->cPages = (GCPhysLast - (GCPhys & X86_PTE_PAE_PG_MASK) + GUEST_PAGE_SIZE) >> GUEST_PAGE_SHIFT; 371 372 int rc = pVM->VMCC_CTX(pgm).s.pPhysHandlerTree->insert(&pVM->VMCC_CTX(pgm).s.PhysHandlerAllocator, pPhysHandler); 373 if (RT_SUCCESS(rc)) 374 { 375 rc = pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(pVM, pPhysHandler, pRam, NULL /*pvBitmap*/, 0 /*offBitmap*/); 376 if (rc == VINF_PGM_SYNC_CR3) 377 rc = VINF_PGM_GCPHYS_ALIASED; 378 379 #if defined(IN_RING3) || defined(IN_RING0) 380 NEMHCNotifyHandlerPhysicalRegister(pVM, PGMPHYSHANDLERKIND_ALL, GCPhys, GCPhysLast - GCPhys + 1); 381 #endif 382 return rc; 383 } 384 385 pPhysHandler->Key = NIL_RTGCPHYS; 386 pPhysHandler->KeyLast = NIL_RTGCPHYS; 387 388 AssertMsgReturn(rc == VERR_ALREADY_EXISTS, ("%Rrc GCPhys=%RGp GCPhysLast=%RGp\n", rc, GCPhys, GCPhysLast), rc); 389 #if defined(IN_RING3) && defined(VBOX_STRICT) 390 DBGFR3Info(pVM->pUVM, "handlers", "phys nostats", NULL); 391 #endif 392 AssertMsgFailed(("Conflict! GCPhys=%RGp GCPhysLast=%RGp\n", GCPhys, GCPhysLast)); 393 return VERR_PGM_HANDLER_PHYSICAL_CONFLICT; 394 } 395 396 397 /** 315 398 * Register a access handler for a physical range. 316 399 * … … 349 432 pgmHandlerPhysicalExDestroy(pVM, pNew); 350 433 } 434 return rc; 435 } 436 437 438 /** 439 * Register an access handler for a virtual VMX APIC-access page. 440 * 441 * This holds the PGM lock across the whole operation to resolve races between 442 * VCPUs registering the same page simultaneously. It's also a slightly slimmer 443 * version of the regular registeration function as it's specific to the VMX 444 * APIC-access page. 445 * 446 * @returns VBox status code. 447 * @retval VINF_SUCCESS when successfully installed. 448 * @retval VINF_PGM_GCPHYS_ALIASED when the shadow PTs could be updated because 449 * the guest page aliased or/and mapped by multiple PTs. A CR3 sync has been 450 * flagged together with a pool clearing. 451 * @retval VERR_PGM_HANDLER_PHYSICAL_CONFLICT if the range conflicts with an existing 452 * one. A debug assertion is raised. 453 * 454 * @param pVM The cross context VM structure. 455 * @param GCPhys Start physical address. 456 * @param hType The handler type registration handle. 457 */ 458 VMMDECL(int) PGMHandlerPhysicalRegisterVmxApicAccessPage(PVMCC pVM, RTGCPHYS GCPhys, PGMPHYSHANDLERTYPE hType) 459 { 460 PCPGMPHYSHANDLERTYPEINT const pType = pgmHandlerPhysicalTypeHandleToPtr(pVM, hType); 461 AssertReturn(pType, VERR_INVALID_HANDLE); 462 AssertReturn(pType->enmKind == PGMPHYSHANDLERKIND_ALL, VERR_INVALID_HANDLE); 463 AssertMsgReturn(!(GCPhys & GUEST_PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_INVALID_PARAMETER); 464 465 /* 466 * Find if the VMX APIC access page has already been registered at this address. 467 */ 468 int rc = PGM_LOCK_VOID(pVM); 469 AssertRCReturn(rc, rc); 470 471 PPGMPHYSHANDLER pHandler; 472 rc = pgmHandlerPhysicalLookup(pVM, GCPhys, &pHandler); 473 if (RT_SUCCESS(rc)) 474 { 475 PCPGMPHYSHANDLERTYPEINT const pHandlerType = PGMPHYSHANDLER_GET_TYPE_NO_NULL(pVM, pHandler); 476 Assert(GCPhys >= pHandler->Key && GCPhys <= pHandler->KeyLast); 477 Assert( pHandlerType->enmKind == PGMPHYSHANDLERKIND_WRITE 478 || pHandlerType->enmKind == PGMPHYSHANDLERKIND_ALL 479 || pHandlerType->enmKind == PGMPHYSHANDLERKIND_MMIO); 480 481 /* Check it's the virtual VMX APIC-access page. */ 482 if ( pHandlerType->fNotInHm 483 && pHandlerType->enmKind == PGMPHYSHANDLERKIND_ALL) 484 rc = VINF_SUCCESS; 485 else 486 { 487 rc = VERR_PGM_HANDLER_PHYSICAL_CONFLICT; 488 AssertMsgFailed(("Conflict! GCPhys=%RGp enmKind=%#x fNotInHm=%RTbool\n", GCPhys, pHandlerType->enmKind, 489 pHandlerType->fNotInHm)); 490 } 491 492 PGM_UNLOCK(pVM); 493 return rc; 494 } 495 496 /* 497 * Create and register a physical handler for the virtual VMX APIC-access page. 498 */ 499 pHandler = pgmHandlerPhysicalExCreateWorker(pVM, pType, hType, 0 /*uUser*/, NULL /*pszDesc*/); 500 if (pHandler) 501 { 502 rc = pgmHandlerPhysicalRegisterVmxApicAccessPage(pVM, pHandler, GCPhys); 503 if (RT_SUCCESS(rc)) 504 { /* likely */ } 505 else 506 pgmHandlerPhysicalExDestroy(pVM, pHandler); 507 } 508 else 509 rc = VERR_OUT_OF_RESOURCES; 510 511 PGM_UNLOCK(pVM); 351 512 return rc; 352 513 }
Note:
See TracChangeset
for help on using the changeset viewer.