- Timestamp:
- May 22, 2023 10:31:37 AM (20 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/GICAll.cpp
r99737 r99885 134 134 135 135 136 /** 137 * Updates the internal IRQ state and sets or clears the appropirate force action flags. 138 * 139 * @returns Strict VBox status code. 140 * @param pThis The GIC re-distributor state for the associated vCPU. 141 * @param pVCpu The cross context virtual CPU structure. 142 */ 143 static VBOXSTRICTRC gicReDistUpdateIrqState(PGICCPU pThis, PVMCPUCC pVCpu) 136 DECLINLINE(void) gicUpdateInterruptFF(PVMCPUCC pVCpu, bool fIrq, bool fFiq) 137 { 138 if (fIrq || fFiq) 139 gicSetInterruptFF(pVCpu, fIrq, fFiq); 140 141 if (!fIrq || !fFiq) 142 gicClearInterruptFF(pVCpu, !fIrq, !fFiq); 143 } 144 145 146 DECLINLINE(void) gicReDistHasIrqPending(PGICCPU pThis, bool *pfIrq, bool *pfFiq) 144 147 { 145 148 /* Read the interrupt state. */ … … 156 159 { 157 160 /* Determine whether we have to assert the IRQ or FIQ line. */ 158 bool fIrq = RT_BOOL(bmIntForward & u32RegIGrp0) && fIrqGrp1Enabled; 159 bool fFiq = RT_BOOL(bmIntForward & ~u32RegIGrp0) && fIrqGrp0Enabled; 160 161 if (fIrq || fFiq) 162 gicSetInterruptFF(pVCpu, fIrq, fFiq); 163 164 if (!fIrq || !fFiq) 165 gicClearInterruptFF(pVCpu, !fIrq, !fFiq); 161 *pfIrq = RT_BOOL(bmIntForward & u32RegIGrp0) && fIrqGrp1Enabled; 162 *pfFiq = RT_BOOL(bmIntForward & ~u32RegIGrp0) && fIrqGrp0Enabled; 166 163 } 167 164 else 168 gicClearInterruptFF(pVCpu, true /*fIrq*/, true /*fFiq*/); 169 165 { 166 *pfIrq = false; 167 *pfFiq = false; 168 } 169 } 170 171 172 DECLINLINE(void) gicDistHasIrqPendingForVCpu(PGICDEV pThis, bool *pfIrq, bool *pfFiq) 173 { 174 /* Read the interrupt state. */ 175 uint32_t u32RegIGrp0 = ASMAtomicReadU32(&pThis->u32RegIGrp0); 176 uint32_t bmIntEnabled = ASMAtomicReadU32(&pThis->bmIntEnabled); 177 uint32_t bmIntPending = ASMAtomicReadU32(&pThis->bmIntPending); 178 uint32_t bmIntActive = ASMAtomicReadU32(&pThis->bmIntActive); 179 bool fIrqGrp0Enabled = ASMAtomicReadBool(&pThis->fIrqGrp0Enabled); 180 bool fIrqGrp1Enabled = ASMAtomicReadBool(&pThis->fIrqGrp1Enabled); 181 182 /* Is anything enabled at all? */ 183 uint32_t bmIntForward = (bmIntPending & bmIntEnabled) & ~bmIntActive; /* Exclude the currently active interrupt. */ 184 if (bmIntForward) 185 { 186 /* Determine whether we have to assert the IRQ or FIQ line. */ 187 *pfIrq = RT_BOOL(bmIntForward & u32RegIGrp0) && fIrqGrp1Enabled; 188 *pfFiq = RT_BOOL(bmIntForward & ~u32RegIGrp0) && fIrqGrp0Enabled; 189 } 190 else 191 { 192 *pfIrq = false; 193 *pfFiq = false; 194 } 195 } 196 197 198 /** 199 * Updates the internal IRQ state and sets or clears the appropirate force action flags. 200 * 201 * @returns Strict VBox status code. 202 * @param pThis The GIC re-distributor state for the associated vCPU. 203 * @param pVCpu The cross context virtual CPU structure. 204 */ 205 static VBOXSTRICTRC gicReDistUpdateIrqState(PGICCPU pThis, PVMCPUCC pVCpu) 206 { 207 bool fIrq, fFiq; 208 gicReDistHasIrqPending(pThis, &fIrq, &fFiq); 209 210 PPDMDEVINS pDevIns = VMCPU_TO_DEVINS(pVCpu); 211 PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV); 212 bool fIrqDist, fFiqDist; 213 gicDistHasIrqPendingForVCpu(pGicDev, &fIrqDist, &fFiqDist); 214 fIrq |= fIrqDist; 215 fFiq |= fFiqDist; 216 217 gicUpdateInterruptFF(pVCpu, fIrq, fFiq); 218 return VINF_SUCCESS; 219 } 220 221 222 /** 223 * Updates the internal IRQ state of the distributor and sets or clears the appropirate force action flags. 224 * 225 * @returns Strict VBox status code. 226 * @param pVM The cross context VM state. 227 * @param pThis The GIC distributor state. 228 */ 229 static VBOXSTRICTRC gicDistUpdateIrqState(PVMCC pVM, PGICDEV pThis) 230 { 231 PVMCPUCC pVCpu = pVM->CTX_SUFF(apCpus)[0]; /** @todo SMP */ 232 233 bool fIrq, fFiq; 234 gicReDistHasIrqPending(VMCPU_TO_GICCPU(pVCpu), &fIrq, &fFiq); 235 236 bool fIrqDist, fFiqDist; 237 gicDistHasIrqPendingForVCpu(pThis, &fIrqDist, &fFiqDist); 238 fIrq |= fIrqDist; 239 fFiq |= fFiqDist; 240 241 gicUpdateInterruptFF(pVCpu, fIrq, fFiq); 170 242 return VINF_SUCCESS; 171 243 } … … 205 277 DECLINLINE(VBOXSTRICTRC) gicDistRegisterRead(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t offReg, uint32_t *puValue) 206 278 { 207 VMCPU_ASSERT_EMT(pVCpu); 208 RT_NOREF(pDevIns, pVCpu, offReg);279 VMCPU_ASSERT_EMT(pVCpu); RT_NOREF(pVCpu); 280 PGICDEV pThis = PDMDEVINS_2_DATA(pDevIns, PGICDEV); 209 281 210 282 switch (offReg) 211 283 { 284 case GIC_DIST_REG_CTLR_OFF: 285 *puValue = (ASMAtomicReadBool(&pThis->fIrqGrp0Enabled) ? GIC_DIST_REG_CTRL_ENABLE_GRP0 : 0) 286 | (ASMAtomicReadBool(&pThis->fIrqGrp1Enabled) ? GIC_DIST_REG_CTRL_ENABLE_GRP1_NS : 0); 287 break; 212 288 case GIC_DIST_REG_TYPER_OFF: 213 289 *puValue = GIC_DIST_REG_TYPER_NUM_ITLINES_SET(1) /** @todo 32 SPIs for now. */ … … 220 296 | GIC_DIST_REG_TYPER_IDBITS_SET(16); 221 297 break; 298 case GIC_DIST_REG_STATUSR_OFF: 299 AssertReleaseFailed(); 300 break; 301 case GIC_DIST_REG_IGROUPRn_OFF_START: /* Only 32 lines for now. */ 302 AssertReleaseFailed(); 303 break; 304 case GIC_DIST_REG_ISENABLERn_OFF_START + 4: /* Only 32 lines for now. */ 305 case GIC_DIST_REG_ICENABLERn_OFF_START + 4: /* Only 32 lines for now. */ 306 *puValue = ASMAtomicReadU32(&pThis->bmIntEnabled); 307 break; 308 case GIC_DIST_REG_ISPENDRn_OFF_START: /* Only 32 lines for now. */ 309 AssertReleaseFailed(); 310 break; 311 case GIC_DIST_REG_ICPENDRn_OFF_START: /* Only 32 lines for now. */ 312 AssertReleaseFailed(); 313 break; 314 case GIC_DIST_REG_ISACTIVERn_OFF_START: /* Only 32 lines for now. */ 315 AssertReleaseFailed(); 316 break; 317 case GIC_DIST_REG_ICACTIVERn_OFF_START: /* Only 32 lines for now. */ 318 AssertReleaseFailed(); 319 break; 320 case GIC_DIST_REG_IPRIORITYn_OFF_START + 32: /* Only 32 lines for now. */ 321 { 322 /* Figure out the register which is written. */ 323 uint8_t idxPrio = offReg - GIC_REDIST_SGI_PPI_REG_IPRIORITYn_OFF_START - 32; 324 Assert(idxPrio <= RT_ELEMENTS(pThis->abIntPriority) - sizeof(uint32_t)); 325 326 uint32_t u32Value = 0; 327 for (uint32_t i = idxPrio; i < idxPrio + sizeof(uint32_t); i++) 328 u32Value |= pThis->abIntPriority[i] << ((i - idxPrio) * 8); 329 330 *puValue = u32Value; 331 break; 332 } 333 case GIC_DIST_REG_ITARGETSRn_OFF_START: /* Only 32 lines for now. */ 334 AssertReleaseFailed(); 335 break; 336 case GIC_DIST_REG_ICFGRn_OFF_START: /* Only 32 lines for now. */ 337 AssertReleaseFailed(); 338 break; 339 case GIC_DIST_REG_IGRPMODRn_OFF_START: /* Only 32 lines for now. */ 340 AssertReleaseFailed(); 341 break; 342 case GIC_DIST_REG_NSACRn_OFF_START: /* Only 32 lines for now. */ 343 AssertReleaseFailed(); 344 break; 345 case GIC_DIST_REG_SGIR_OFF: 346 AssertReleaseFailed(); 347 break; 348 case GIC_DIST_REG_CPENDSGIRn_OFF_START: 349 AssertReleaseFailed(); 350 break; 351 case GIC_DIST_REG_SPENDSGIRn_OFF_START: 352 AssertReleaseFailed(); 353 break; 354 case GIC_DIST_REG_INMIn_OFF_START: 355 AssertReleaseFailed(); 356 break; 357 case GIC_DIST_REG_IROUTERn_OFF_START: /* Only 32 lines for now. */ 358 *puValue = 0; /** @todo */ 359 break; 222 360 case GIC_DIST_REG_PIDR2_OFF: 223 361 *puValue = GIC_REDIST_REG_PIDR2_ARCH_REV_SET(GIC_REDIST_REG_PIDR2_ARCH_REV_GICV3); … … 225 363 case GIC_DIST_REG_IIDR_OFF: 226 364 case GIC_DIST_REG_TYPER2_OFF: 365 *puValue = 0; 366 break; 227 367 default: 228 368 *puValue = 0; … … 243 383 DECLINLINE(VBOXSTRICTRC) gicDistRegisterWrite(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t offReg, uint32_t uValue) 244 384 { 245 VMCPU_ASSERT_EMT(pVCpu); 246 RT_NOREF(pDevIns, pVCpu, offReg, uValue); 385 VMCPU_ASSERT_EMT(pVCpu); RT_NOREF(pVCpu); 386 PGICDEV pThis = PDMDEVINS_2_DATA(pDevIns, PGICDEV); 387 PVMCC pVM = PDMDevHlpGetVM(pDevIns); 247 388 248 389 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 390 switch (offReg) 391 { 392 case GIC_DIST_REG_CTLR_OFF: 393 ASMAtomicWriteBool(&pThis->fIrqGrp0Enabled, RT_BOOL(uValue & GIC_DIST_REG_CTRL_ENABLE_GRP0)); 394 ASMAtomicWriteBool(&pThis->fIrqGrp1Enabled, RT_BOOL(uValue & GIC_DIST_REG_CTRL_ENABLE_GRP1_NS)); 395 rcStrict = gicDistUpdateIrqState(pVM, pThis); 396 break; 397 case GIC_DIST_REG_STATUSR_OFF: 398 AssertReleaseFailed(); 399 break; 400 case GIC_DIST_REG_SETSPI_NSR_OFF: 401 AssertReleaseFailed(); 402 break; 403 case GIC_DIST_REG_CLRSPI_NSR_OFF: 404 AssertReleaseFailed(); 405 break; 406 case GIC_DIST_REG_SETSPI_SR_OFF: 407 AssertReleaseFailed(); 408 break; 409 case GIC_DIST_REG_CLRSPI_SR_OFF: 410 AssertReleaseFailed(); 411 break; 412 case GIC_DIST_REG_IGROUPRn_OFF_START: /* Only 32 lines for now. */ 413 AssertReleaseFailed(); 414 break; 415 case GIC_DIST_REG_IGROUPRn_OFF_START + 4: /* Only 32 lines for now. */ 416 ASMAtomicOrU32(&pThis->u32RegIGrp0, uValue); 417 rcStrict = gicDistUpdateIrqState(pVM, pThis); 418 break; 419 case GIC_DIST_REG_ISENABLERn_OFF_START + 4: /* Only 32 lines for now. */ 420 ASMAtomicOrU32(&pThis->bmIntEnabled, uValue); 421 rcStrict = gicDistUpdateIrqState(pVM, pThis); 422 break; 423 case GIC_DIST_REG_ICENABLERn_OFF_START: 424 //AssertReleaseFailed(); 425 break; 426 case GIC_DIST_REG_ICENABLERn_OFF_START + 4: /* Only 32 lines for now. */ 427 ASMAtomicAndU32(&pThis->bmIntEnabled, ~uValue); 428 rcStrict = gicDistUpdateIrqState(pVM, pThis); 429 break; 430 case GIC_DIST_REG_ISPENDRn_OFF_START: /* Only 32 lines for now. */ 431 AssertReleaseFailed(); 432 break; 433 case GIC_DIST_REG_ICPENDRn_OFF_START: /* Only 32 lines for now. */ 434 AssertReleaseFailed(); 435 break; 436 case GIC_DIST_REG_ISACTIVERn_OFF_START: /* Only 32 lines for now. */ 437 AssertReleaseFailed(); 438 break; 439 case GIC_DIST_REG_ICACTIVERn_OFF_START + 4: /* Only 32 lines for now. */ 440 ASMAtomicAndU32(&pThis->bmIntActive, ~uValue); 441 rcStrict = gicDistUpdateIrqState(pVM, pThis); 442 break; 443 case GIC_DIST_REG_IPRIORITYn_OFF_START + 32: /* Only 32 lines for now. */ 444 case GIC_DIST_REG_IPRIORITYn_OFF_START + 36: 445 case GIC_DIST_REG_IPRIORITYn_OFF_START + 40: 446 case GIC_DIST_REG_IPRIORITYn_OFF_START + 44: 447 case GIC_DIST_REG_IPRIORITYn_OFF_START + 48: 448 case GIC_DIST_REG_IPRIORITYn_OFF_START + 52: 449 case GIC_DIST_REG_IPRIORITYn_OFF_START + 56: 450 case GIC_DIST_REG_IPRIORITYn_OFF_START + 60: 451 { 452 /* Figure out the register whch is written. */ 453 uint8_t idxPrio = offReg - GIC_REDIST_SGI_PPI_REG_IPRIORITYn_OFF_START - 32; 454 Assert(idxPrio <= RT_ELEMENTS(pThis->abIntPriority) - sizeof(uint32_t)); 455 for (uint32_t i = idxPrio; i < idxPrio + sizeof(uint32_t); i++) 456 { 457 pThis->abIntPriority[i] = (uint8_t)(uValue & 0xff); 458 uValue >>= 8; 459 } 460 break; 461 } 462 case GIC_DIST_REG_ITARGETSRn_OFF_START: /* Only 32 lines for now. */ 463 AssertReleaseFailed(); 464 break; 465 case GIC_DIST_REG_ICFGRn_OFF_START + 8: /* Only 32 lines for now. */ 466 ASMAtomicWriteU32(&pThis->u32RegICfg0, uValue); 467 break; 468 case GIC_DIST_REG_ICFGRn_OFF_START+ 12: 469 ASMAtomicWriteU32(&pThis->u32RegICfg1, uValue); 470 break; 471 case GIC_DIST_REG_IGRPMODRn_OFF_START: /* Only 32 lines for now. */ 472 AssertReleaseFailed(); 473 break; 474 case GIC_DIST_REG_NSACRn_OFF_START: /* Only 32 lines for now. */ 475 AssertReleaseFailed(); 476 break; 477 case GIC_DIST_REG_SGIR_OFF: 478 AssertReleaseFailed(); 479 break; 480 case GIC_DIST_REG_CPENDSGIRn_OFF_START: 481 AssertReleaseFailed(); 482 break; 483 case GIC_DIST_REG_SPENDSGIRn_OFF_START: 484 AssertReleaseFailed(); 485 break; 486 case GIC_DIST_REG_INMIn_OFF_START: 487 AssertReleaseFailed(); 488 break; 489 case GIC_DIST_REG_IROUTERn_OFF_START ... GIC_DIST_REG_IROUTERn_OFF_LAST: /* Only 32 lines for now. */ 490 /** @todo Ignored for now, probably make this a MMIO2 region as it begins on 0x6000, see 12.9.22 of the GICv3 architecture 491 * reference manual. */ 492 break; 493 default: 494 //AssertReleaseFailed(); 495 break; 496 } 497 249 498 return rcStrict; 250 499 } … … 316 565 case GIC_REDIST_SGI_PPI_REG_IPRIORITYn_OFF_START + 28: 317 566 { 318 /* Figure out the register wh ch is written. */567 /* Figure out the register which is written. */ 319 568 uint8_t idxPrio = offReg - GIC_REDIST_SGI_PPI_REG_IPRIORITYn_OFF_START; 320 569 Assert(idxPrio <= RT_ELEMENTS(pThis->abIntPriority) - sizeof(uint32_t)); … … 458 707 *pu64Value = 0; 459 708 PGICCPU pThis = VMCPU_TO_GICCPU(pVCpu); 709 PPDMDEVINS pDevIns = VMCPU_TO_DEVINS(pVCpu); 710 PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV); 460 711 switch (u32Reg) 461 712 { … … 529 780 } 530 781 else 531 *pu64Value = GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT; 782 { 783 /** @todo This is wrong as the guest might decide to prioritize PPIs and SPIs differently. */ 784 bmPending = ASMAtomicReadU32(&pGicDev->bmIntPending); 785 idxIntPending = ASMBitFirstSet(&bmPending, sizeof(bmPending) * 8); 786 if (idxIntPending > -1) 787 { 788 /* Mark the interrupt as active. */ 789 ASMAtomicOrU32(&pGicDev->bmIntActive, idxIntPending); 790 *pu64Value = idxIntPending + GIC_INTID_RANGE_SPI_START; 791 } 792 else 793 *pu64Value = GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT; 794 } 532 795 break; 533 796 } … … 583 846 584 847 PGICCPU pThis = VMCPU_TO_GICCPU(pVCpu); 848 PPDMDEVINS pDevIns = VMCPU_TO_DEVINS(pVCpu); 849 PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV); 585 850 switch (u32Reg) 586 851 { … … 648 913 { 649 914 /* Mark the interrupt as not active anymore, though it might still be pending. */ 650 Assert(u64Value < GIC_INTID_RANGE_SPI_START); 651 ASMAtomicAndU32(&pThis->bmIntActive, (uint32_t)u64Value); 915 if (u64Value < GIC_INTID_RANGE_SPI_START) 916 ASMAtomicAndU32(&pThis->bmIntActive, (uint32_t)u64Value); 917 else 918 ASMAtomicAndU32(&pGicDev->bmIntActive, (uint32_t)u64Value); 919 gicReDistUpdateIrqState(pThis, pVCpu); 652 920 break; 653 921 } … … 690 958 VMM_INT_DECL(int) GICSpiSet(PVMCC pVM, uint32_t uIntId, bool fAsserted) 691 959 { 692 RT_NOREF(pVM, uIntId, fAsserted); 693 AssertReleaseFailed(); 694 return VERR_NOT_IMPLEMENTED; 960 AssertReturn(uIntId < GIC_SPI_MAX, VERR_INVALID_PARAMETER); 961 962 PGIC pGic = VM_TO_GIC(pVM); 963 PGICDEV pThis = PDMDEVINS_2_DATA(pGic->CTX_SUFF(pDevIns), PGICDEV); 964 965 /* Update the interrupts pending state. */ 966 if (fAsserted) 967 ASMAtomicOrU32(&pThis->bmIntPending, RT_BIT_32(uIntId)); 968 else 969 ASMAtomicAndU32(&pThis->bmIntPending, ~RT_BIT_32(uIntId)); 970 971 return VBOXSTRICTRC_VAL(gicDistUpdateIrqState(pVM, pThis)); 695 972 } 696 973 … … 706 983 VMM_INT_DECL(int) GICPpiSet(PVMCPUCC pVCpu, uint32_t uIntId, bool fAsserted) 707 984 { 985 LogFlowFunc(("pVCpu=%p{.idCpu=%u} uIntId=%u fAsserted=%RTbool\n", 986 pVCpu, pVCpu->idCpu, uIntId, fAsserted)); 987 708 988 AssertReturn(uIntId >= 0 && uIntId <= (GIC_INTID_RANGE_PPI_LAST - GIC_INTID_RANGE_PPI_START), VERR_INVALID_PARAMETER); 709 989 return gicReDistInterruptSet(pVCpu, uIntId + GIC_INTID_RANGE_PPI_START, fAsserted); -
trunk/src/VBox/VMM/include/GICInternal.h
r99734 r99885 51 51 #endif 52 52 53 /** Maximum number of SPI interrupts. */ 54 #define GIC_SPI_MAX 32 55 53 56 /** 54 57 * GIC PDM instance data (per-VM). … … 60 63 /** The redistributor MMIO handle. */ 61 64 IOMMMIOHANDLE hMmioReDist; 65 66 /** @name SPI disitributor register state. 67 * @{ */ 68 /** Interrupt Group 0 Register. */ 69 volatile uint32_t u32RegIGrp0; 70 /** Interrupt Configuration Register 0. */ 71 volatile uint32_t u32RegICfg0; 72 /** Interrupt Configuration Register 1. */ 73 volatile uint32_t u32RegICfg1; 74 /** Interrupt enabled bitmap. */ 75 volatile uint32_t bmIntEnabled; 76 /** Current interrupt pending state. */ 77 volatile uint32_t bmIntPending; 78 /** The current interrupt active state. */ 79 volatile uint32_t bmIntActive; 80 /** The interrupt priority for each of the SGI/PPIs */ 81 volatile uint8_t abIntPriority[GIC_SPI_MAX]; 82 83 /** Flag whether group 0 interrupts are currently enabled. */ 84 volatile bool fIrqGrp0Enabled; 85 /** Flag whether group 1 interrupts are currently enabled. */ 86 volatile bool fIrqGrp1Enabled; 87 /** @} */ 88 62 89 } GICDEV; 63 90 /** Pointer to a GIC device. */
Note:
See TracChangeset
for help on using the changeset viewer.