Changeset 108864 in vbox for trunk/src/VBox/VMM/VMMAll/GITSAll.cpp
- Timestamp:
- Apr 7, 2025 9:10:44 AM (2 weeks ago)
- svn:sync-xref-src-repo-rev:
- 168314
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/GITSAll.cpp
r108835 r108864 35 35 #include <VBox/log.h> 36 36 #include <VBox/gic.h> 37 #include <VBox/vmm/pdmdev.h> 37 38 #include <VBox/vmm/dbgf.h> 38 39 #include <iprt/errcore.h> /* VINF_SUCCESS */ 39 40 #include <iprt/string.h> /* RT_ZERO */ 41 #include <iprt/mem.h> /* RTMemAllocZ, RTMemFree */ 40 42 41 43 … … 103 105 default: 104 106 return "<UNKNOWN>"; 107 } 108 } 109 110 111 DECL_FORCE_INLINE(bool) gitsCmdQueueIsEmptyEx(PCGITSDEV pGitsDev, uint32_t *poffRead, uint32_t *poffWrite) 112 { 113 *poffRead = pGitsDev->uCmdReadReg & GITS_BF_CTRL_REG_CREADR_OFFSET_MASK; 114 *poffWrite = pGitsDev->uCmdWriteReg & GITS_BF_CTRL_REG_CWRITER_OFFSET_MASK; 115 return *poffRead == *poffWrite; 116 } 117 118 119 DECL_HIDDEN_CALLBACK(bool) gitsCmdQueueIsEmpty(PCGITSDEV pGitsDev) 120 { 121 uint32_t offRead; 122 uint32_t offWrite; 123 return gitsCmdQueueIsEmptyEx(pGitsDev, &offRead, &offWrite); 124 } 125 126 127 DECL_HIDDEN_CALLBACK(bool) gitsCmdQueueCanProcessRequests(PCGITSDEV pGitsDev) 128 { 129 if ( pGitsDev->fEnabled 130 && (pGitsDev->uCmdBaseReg.u & GITS_BF_CTRL_REG_CBASER_VALID_MASK) 131 && !(pGitsDev->uCmdReadReg & GITS_BF_CTRL_REG_CREADR_STALLED_MASK)) 132 return true; 133 return false; 134 } 135 136 137 static void gitsCmdQueueThreadWakeUpIfNeeded(PPDMDEVINS pDevIns, PGITSDEV pGitsDev) 138 { 139 Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); 140 if ( gitsCmdQueueCanProcessRequests(pGitsDev) 141 && !gitsCmdQueueIsEmpty(pGitsDev)) 142 { 143 int const rc = PDMDevHlpSUPSemEventSignal(pDevIns, pGitsDev->hEvtCmdQueue); 144 AssertRC(rc); 105 145 } 106 146 } … … 218 258 219 259 220 DECL_HIDDEN_CALLBACK(void) gitsMmioWriteCtrl(P GITSDEV pGitsDev, uint16_t offReg, uint64_t uValue, unsigned cb)260 DECL_HIDDEN_CALLBACK(void) gitsMmioWriteCtrl(PPDMDEVINS pDevIns, PGITSDEV pGitsDev, uint16_t offReg, uint64_t uValue, unsigned cb) 221 261 { 222 262 Assert(cb == 8 || cb == 4); … … 250 290 Assert(cb == 4); 251 291 pGitsDev->fEnabled = RT_BF_GET(uValue, GITS_BF_CTRL_REG_CTLR_ENABLED); 292 gitsCmdQueueThreadWakeUpIfNeeded(pDevIns, pGitsDev); 252 293 break; 253 294 … … 258 299 else 259 300 pGitsDev->uCmdBaseReg.s.Lo = (uint32_t)uValue; 301 gitsCmdQueueThreadWakeUpIfNeeded(pDevIns, pGitsDev); 260 302 break; 261 303 … … 263 305 Assert(cb == 4); 264 306 pGitsDev->uCmdBaseReg.s.Hi = uValue & RT_HI_U32(GITS_CTRL_REG_CBASER_RW_MASK); 307 gitsCmdQueueThreadWakeUpIfNeeded(pDevIns, pGitsDev); 265 308 break; 266 309 267 310 case GITS_CTRL_REG_CWRITER_OFF: 268 311 pGitsDev->uCmdWriteReg = uValue & RT_LO_U32(GITS_CTRL_REG_CWRITER_RW_MASK); 312 gitsCmdQueueThreadWakeUpIfNeeded(pDevIns, pGitsDev); 269 313 break; 270 314 … … 272 316 /* Upper 32-bits are all reserved, ignore write. Fedora 40 arm64 guests (and probably others) do this. */ 273 317 Assert(uValue == 0); 318 gitsCmdQueueThreadWakeUpIfNeeded(pDevIns, pGitsDev); 274 319 break; 275 320 … … 371 416 } 372 417 } 418 419 420 DECL_HIDDEN_CALLBACK(int) gitsR3CmdQueueProcess(PPDMDEVINS pDevIns, PGITSDEV pGitsDev, void *pvBuf, uint32_t cbBuf) 421 { 422 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VINF_SUCCESS); 423 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock); 424 425 if (gitsCmdQueueCanProcessRequests(pGitsDev)) 426 { 427 uint32_t offRead; 428 uint32_t offWrite; 429 bool const fIsEmpty = gitsCmdQueueIsEmptyEx(pGitsDev, &offRead, &offWrite); 430 if (!fIsEmpty) 431 { 432 uint32_t const cCmdQueuePages = (pGitsDev->uCmdBaseReg.u & GITS_BF_CTRL_REG_CBASER_SIZE_MASK) + 1; 433 uint32_t const cbCmdQueue = cCmdQueuePages << GITS_CMD_QUEUE_PAGE_SHIFT; 434 AssertRelease(cbCmdQueue <= cbBuf); /** @todo Paranoia; make this a debug assert later. */ 435 436 #if 0 437 /* 438 * Allocate space for the command-queue if we haven't done so already. 439 */ 440 if (pGitsDev->pvCmdQueue != NULL) 441 { 442 if (pGitsDev->cbCmdQueue <= cbCmdQueue) 443 { /* Already allocated sufficient space. */ } 444 else 445 { 446 /* Free old allocation and allocate a new one. */ 447 RTMemFree(pGitsDev->pvCmdQueue); 448 pGitsDev->cbCmdQueue = cbCmdQueue; 449 pGitsDev->pvCmdQueue = RTMemAllocZ(cbCmdQueue); 450 if (pGitsDev->pvCmdQueue) 451 { /* likely */ } 452 else 453 return VERR_NO_MEMORY; 454 } 455 } 456 else 457 { 458 /* Allocate one. */ 459 pGitsDev->cbCmdQueue = cbCmdQueue; 460 pGitsDev->pvCmdQueue = RTMemAllocZ(cbCmdQueue); 461 if (pGitsDev->pvCmdQueue) 462 { /* likely */ } 463 else 464 return VERR_NO_MEMORY; 465 } 466 #endif 467 468 /* 469 * Read all the commands into the command queue. 470 */ 471 RTGCPHYS const GCPhysCmds = pGitsDev->uCmdBaseReg.u & GITS_BF_CTRL_REG_CBASER_PHYS_ADDR_MASK; 472 473 /* Leave the critical section before reading (a potentially large amount of) commands. */ 474 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3); 475 476 int rc; 477 uint32_t cbCmds; 478 if (offWrite > offRead) 479 { 480 /* The commands have not wrapped around, read them in one go. */ 481 cbCmds = offWrite - offRead; 482 Assert(cbCmds <= cbBuf); 483 rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysCmds, pvBuf, cbCmds); 484 } 485 else 486 { 487 /* The commands have wrapped around, read forward and wrapped-around. */ 488 uint32_t const cbForward = cbCmdQueue - offRead; 489 uint32_t const cbWrapped = offWrite; 490 Assert(cbForward + cbWrapped <= cbBuf); 491 rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysCmds, pvBuf, cbForward); 492 if ( RT_SUCCESS(rc) 493 && cbWrapped > 0) 494 rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysCmds + cbForward, 495 (void *)((uintptr_t)pvBuf + cbForward), cbWrapped); 496 cbCmds = cbForward + cbWrapped; 497 } 498 499 /* Re-acquire the critical section as we now need to modify device state. */ 500 int const rcLock2 = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VINF_SUCCESS); 501 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock2); 502 503 /* 504 * Process the commands in the queue. 505 */ 506 if (RT_SUCCESS(rc)) 507 { 508 509 uint32_t const cCmds = cbCmds / GITS_CMD_SIZE; 510 for (uint32_t idxCmd = 0; idxCmd < cCmds; idxCmd++) 511 { 512 PCGITSCMD pCmd = (PCGITSCMD)((uintptr_t)pvBuf + (idxCmd * sizeof(GITSCMD))); 513 AssertReleaseMsgFailed(("Cmd=%#x\n", pCmd->clear.uCmdId)); 514 } 515 516 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3); 517 return VINF_SUCCESS; 518 } 519 520 /* Failed to read command queue from the physical address specified by the guest, stall queue and retry later. */ 521 522 523 /** @todo Stall the command queue. */ 524 return VINF_TRY_AGAIN; 525 } 526 } 527 528 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3); 529 return VINF_SUCCESS; 530 } 373 531 #endif /* IN_RING3 */ 374 532
Note:
See TracChangeset
for help on using the changeset viewer.