Changeset 33314 in vbox for trunk/src/VBox/Devices/Bus
- Timestamp:
- Oct 21, 2010 3:51:17 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 66890
- Location:
- trunk/src/VBox/Devices/Bus
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
r33236 r33314 787 787 return rc; 788 788 789 rc = MsixInit(pPciDev , pMsiReg);789 rc = MsixInit(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), pPciDev, pMsiReg); 790 790 if (rc != VINF_SUCCESS) 791 791 return rc; -
trunk/src/VBox/Devices/Bus/MsiCommon.cpp
r33236 r33314 262 262 uint32_t* puPending = msiGetPendingBits(pDev); 263 263 264 LogFlow(("M SINotify: %d pending=%x mask=%x\n", iVector, *puPending, uMask));264 LogFlow(("MsiNotify: %d pending=%x mask=%x\n", iVector, *puPending, uMask)); 265 265 266 266 /* We only trigger MSI on level up */ -
trunk/src/VBox/Devices/Bus/MsixCommon.cpp
r33236 r33314 22 22 #include <VBox/pdmdev.h> 23 23 #include <VBox/log.h> 24 #include <VBox/mm.h> 25 26 #include <iprt/assert.h> 24 27 25 28 #include "MsiCommon.h" 26 29 27 DECLINLINE(uint16_t) msixGetMessageControl(PPCIDEVICE pDev) 30 #pragma pack(1) 31 typedef struct { 32 uint32_t u32MsgAddressLo; 33 uint32_t u32MsgAddressHi; 34 uint32_t u32MsgData; 35 uint32_t u32VectorControl; 36 } MsixTableRecord; 37 AssertCompileSize(MsixTableRecord, VBOX_MSIX_ENTRY_SIZE); 38 #pragma pack(0) 39 40 DECLINLINE(uint16_t) msixGetMessageControl(PPCIDEVICE pDev) 28 41 { 29 42 return PCIDevGetWord(pDev, pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL); 30 43 } 31 44 32 DECLINLINE(bool) msixIsEnabled(PPCIDEVICE pDev)45 DECLINLINE(bool) msixIsEnabled(PPCIDEVICE pDev) 33 46 { 34 47 return (msixGetMessageControl(pDev) & VBOX_PCI_MSIX_FLAGS_ENABLE) != 0; 35 48 } 36 49 37 38 int MsixInit(PPCIDEVICE pDev, PPDMMSIREG pMsiReg) 50 DECLINLINE(bool) msixIsMasked(PPCIDEVICE pDev) 51 { 52 return (msixGetMessageControl(pDev) & VBOX_PCI_MSIX_FLAGS_FUNCMASK) != 0; 53 } 54 55 DECLINLINE(uint16_t) msixTableSize(PPCIDEVICE pDev) 56 { 57 return (msixGetMessageControl(pDev) & 0x3ff) + 1; 58 } 59 60 DECLINLINE(uint8_t*) msixGetPageOffset(PPCIDEVICE pDev, uint32_t off) 61 { 62 return (uint8_t*)pDev->Int.s.CTX_SUFF(pMsixPage) + off; 63 } 64 65 DECLINLINE(MsixTableRecord*) msixGetVectorRecord(PPCIDEVICE pDev, uint32_t iVector) 66 { 67 return (MsixTableRecord*)msixGetPageOffset(pDev, iVector * VBOX_MSIX_ENTRY_SIZE); 68 } 69 70 DECLINLINE(RTGCPHYS) msixGetMsiAddress(PPCIDEVICE pDev, uint32_t iVector) 71 { 72 MsixTableRecord* pRec = msixGetVectorRecord(pDev, iVector); 73 return RT_MAKE_U64(pRec->u32MsgAddressLo & ~UINT32_C(0x3), pRec->u32MsgAddressHi); 74 } 75 76 DECLINLINE(uint32_t) msixGetMsiData(PPCIDEVICE pDev, uint32_t iVector) 77 { 78 return msixGetVectorRecord(pDev, iVector)->u32MsgData; 79 } 80 81 DECLINLINE(uint32_t) msixIsVectorMasked(PPCIDEVICE pDev, uint32_t iVector) 82 { 83 return (msixGetVectorRecord(pDev, iVector)->u32VectorControl & 0x1) != 0; 84 } 85 86 DECLINLINE(uint8_t*) msixPendingByte(PPCIDEVICE pDev, uint32_t iVector) 87 { 88 return msixGetPageOffset(pDev, 0x800 + iVector / 8); 89 } 90 91 DECLINLINE(void) msixSetPending(PPCIDEVICE pDev, uint32_t iVector) 92 { 93 *msixPendingByte(pDev, iVector) |= (1 << (iVector & 0x7)); 94 } 95 96 DECLINLINE(void) msixClearPending(PPCIDEVICE pDev, uint32_t iVector) 97 { 98 *msixPendingByte(pDev, iVector) &= ~(1 << (iVector & 0x7)); 99 } 100 101 DECLINLINE(bool) msixIsPending(PPCIDEVICE pDev, uint32_t iVector) 102 { 103 return (*msixPendingByte(pDev, iVector) & (1 << (iVector & 0x7))) != 0; 104 } 105 106 static void msixCheckPendingVector(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, uint32_t iVector) 107 { 108 if (msixIsPending(pDev, iVector) && !msixIsVectorMasked(pDev, iVector)) 109 MsixNotify(pDevIns, pPciHlp, pDev, iVector, 1 /* iLevel */); 110 } 111 112 #ifdef IN_RING3 113 114 PDMBOTHCBDECL(int) msixMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 115 { 116 /// @todo: qword accesses? 117 AssertMsgReturn(cb == 4, 118 ("MSI-X must be accessed with 4-byte reads"), 119 VERR_INTERNAL_ERROR); 120 121 uint32_t off = (uint32_t)(GCPhysAddr & 0xfff); 122 PPCIDEVICE pPciDev = (PPCIDEVICE)pvUser; 123 124 *(uint32_t*)pv = *(uint32_t*)msixGetPageOffset(pPciDev, off); 125 126 return VINF_SUCCESS; 127 } 128 129 PDMBOTHCBDECL(int) msixMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 130 { 131 /// @todo: qword accesses? 132 AssertMsgReturn(cb == 4, 133 ("MSI-X must be accessed with 4-byte reads"), 134 VERR_INTERNAL_ERROR); 135 PPCIDEVICE pPciDev = (PPCIDEVICE)pvUser; 136 137 uint32_t off = (uint32_t)(GCPhysAddr & 0xfff); 138 139 AssertMsgReturn(off < 0x800, ("Trying to write to PBA\n"), VINF_SUCCESS); 140 141 *(uint32_t*)msixGetPageOffset(pPciDev, off) = *(uint32_t*)pv; 142 143 msixCheckPendingVector(pDevIns, (PCPDMPCIHLP)pPciDev->Int.s.pPciBusPtrR3, pPciDev, off / VBOX_MSIX_ENTRY_SIZE); 144 145 return VINF_SUCCESS; 146 } 147 148 static DECLCALLBACK(int) msixMap (PPCIDEVICE pPciDev, int iRegion, 149 RTGCPHYS GCPhysAddress, uint32_t cb, 150 PCIADDRESSSPACE enmType) 151 { 152 Assert(enmType == PCI_ADDRESS_SPACE_MEM); 153 154 int rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, pPciDev, 155 msixMMIOWrite, msixMMIORead, NULL, "MSI-X tables"); 156 157 if (RT_FAILURE(rc)) 158 return rc; 159 160 return VINF_SUCCESS; 161 } 162 163 int MsixInit(PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, PPDMMSIREG pMsiReg) 39 164 { 40 165 if (pMsiReg->cMsixVectors == 0) … … 44 169 uint8_t iCapOffset = pMsiReg->iMsixCapOffset; 45 170 uint8_t iNextOffset = pMsiReg->iMsixNextOffset; 46 uint16_t iFlags = pMsiReg->iMsixFlags; 47 48 if (cVectors != 1) 49 /* We cannot handle multiple vectors yet */ 50 return VERR_TOO_MUCH_DATA; 51 171 uint8_t iBar = pMsiReg->iMsixBar; 172 52 173 if (cVectors > VBOX_MSIX_MAX_ENTRIES) 53 174 return VERR_TOO_MUCH_DATA; 54 175 176 if (iBar > 5) 177 return VERR_INVALID_PARAMETER; 178 55 179 Assert(iCapOffset != 0 && iCapOffset < 0xff && iNextOffset < 0xff); 56 180 181 int rc; 182 183 rc = PDMDevHlpPCIIORegionRegister (pDev->pDevIns, iBar, 0x1000, PCI_ADDRESS_SPACE_MEM, msixMap); 184 if (RT_FAILURE (rc)) 185 return rc; 186 57 187 pDev->Int.s.u8MsixCapOffset = iCapOffset; 58 188 pDev->Int.s.u8MsixCapSize = VBOX_MSIX_CAP_SIZE; 59 189 PVM pVM = PDMDevHlpGetVM(pDev->pDevIns); 190 191 pDev->Int.s.pMsixPageR3 = NULL; 192 193 rc = MMHyperAlloc(pVM, 0x1000, 1, MM_TAG_PDM_DEVICE_USER, (void **)&pDev->Int.s.pMsixPageR3); 194 if (RT_FAILURE(rc) || (pDev->Int.s.pMsixPageR3 == NULL)) 195 return VERR_NO_VM_MEMORY; 196 RT_BZERO(pDev->Int.s.pMsixPageR3, 0x1000); 197 pDev->Int.s.pMsixPageR0 = MMHyperR3ToR0(pVM, pDev->Int.s.pMsixPageR3); 198 pDev->Int.s.pMsixPageRC = MMHyperR3ToRC(pVM, pDev->Int.s.pMsixPageR3); 199 200 /* R3 PCI helper */ 201 pDev->Int.s.pPciBusPtrR3 = pPciHlp; 202 60 203 PCIDevSetByte(pDev, iCapOffset + 0, VBOX_PCI_CAP_ID_MSIX); 61 204 PCIDevSetByte(pDev, iCapOffset + 1, iNextOffset); /* next */ 62 PCIDevSetWord(pDev, iCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL, iFlags); 205 PCIDevSetWord(pDev, iCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL, cVectors - 1); 206 207 uint32_t offTable = 0, offPBA = 0x800; 208 209 PCIDevSetDWord(pDev, iCapOffset + VBOX_MSIX_TABLE_BIROFFSET, offTable | iBar); 210 PCIDevSetDWord(pDev, iCapOffset + VBOX_MSIX_PBA_BIROFFSET, offPBA | iBar); 63 211 64 212 PCISetMsixCapable(pDev); … … 66 214 return VINF_SUCCESS; 67 215 } 68 216 #endif 69 217 70 218 bool MsixIsEnabled(PPCIDEVICE pDev) … … 78 226 79 227 Assert(pPciHlp->pfnIoApicSendMsi != NULL); 80 } 81 82 83 void MsixPciConfigWrite(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, uint32_t u32Address, uint32_t val, unsigned len) 228 229 /* We only trigger MSI-X on level up */ 230 if ((iLevel & PDM_IRQ_LEVEL_HIGH) == 0) 231 { 232 return; 233 } 234 235 // if this vector is somehow disabled 236 if (msixIsMasked(pDev) || msixIsVectorMasked(pDev, iVector)) 237 { 238 // mark pending bit 239 msixSetPending(pDev, iVector); 240 return; 241 } 242 243 // clear pending bit 244 msixClearPending(pDev, iVector); 245 246 RTGCPHYS GCAddr = msixGetMsiAddress(pDev, iVector); 247 uint32_t u32Value = msixGetMsiData(pDev, iVector); 248 249 pPciHlp->pfnIoApicSendMsi(pDevIns, GCAddr, u32Value); 250 } 251 252 DECLINLINE(bool) msixBitJustCleared(uint32_t uOldValue, 253 uint32_t uNewValue, 254 uint32_t uMask) 255 { 256 return (!!(uOldValue & uMask) && !(uNewValue & uMask)); 257 } 258 259 static void msixCheckPendingVectors(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev) 260 { 261 for (uint32_t i = 0; i < msixTableSize(pDev); i++) 262 msixCheckPendingVector(pDevIns, pPciHlp, pDev, i); 263 } 264 265 266 void MsixPciConfigWrite(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, uint32_t u32Address, uint32_t val, unsigned len) 84 267 { 85 268 int32_t iOff = u32Address - pDev->Int.s.u8MsixCapOffset; … … 89 272 90 273 uint32_t uAddr = u32Address; 274 uint8_t u8NewVal; 275 bool fJustEnabled = false; 91 276 92 277 for (uint32_t i = 0; i < len; i++) … … 103 288 break; 104 289 case VBOX_MSIX_CAP_MESSAGE_CONTROL + 1: 290 { 105 291 /* don't change read-only bits 8-13 */ 106 pDev->config[uAddr] = (u8Val & UINT8_C(~0x3f)) | (pDev->config[uAddr] & UINT8_C(0x3f)); 292 u8NewVal = (u8Val & UINT8_C(~0x3f)) | (pDev->config[uAddr] & UINT8_C(0x3f)); 293 /* If just enabled globally - check pending vectors */ 294 fJustEnabled |= msixBitJustCleared(pDev->config[uAddr], u8NewVal, VBOX_PCI_MSIX_FLAGS_ENABLE >> 8); 295 fJustEnabled |= msixBitJustCleared(pDev->config[uAddr], u8NewVal, VBOX_PCI_MSIX_FLAGS_FUNCMASK >> 8); 296 pDev->config[uAddr] = u8NewVal; 107 297 break; 298 } 108 299 default: 109 300 /* other fields read-only too */ … … 113 304 val >>= 8; 114 305 } 306 307 if (fJustEnabled) 308 msixCheckPendingVectors(pDevIns, pPciHlp, pDev); 115 309 } 116 310 uint32_t MsixPciConfigRead (PPDMDEVINS pDevIns, PPCIDEVICE pDev, uint32_t u32Address, unsigned len) -
trunk/src/VBox/Devices/Bus/PCIInternal.h
r32861 r33314 107 107 #endif 108 108 109 /* Page used for MSI-X state. - R3 ptr */ 110 R3PTRTYPE(void*) pMsixPageR3; 111 /* Page used for MSI-X state. - R0 ptr */ 112 R0PTRTYPE(void*) pMsixPageR0; 113 /* Page used for MSI-X state. - RC ptr */ 114 RCPTRTYPE(void*) pMsixPageRC; 115 #if HC_ARCH_BITS == 64 116 RTRCPTR Alignment1; 117 #endif 118 119 109 120 /** Read config callback. */ 110 121 R3PTRTYPE(PFNPCICONFIGREAD) pfnConfigRead; … … 126 137 uint8_t u8MsixCapSize; 127 138 128 uint32_t Alignment1; 139 uint32_t Alignment2; 140 141 /* Pointer to bus specific data. - R3 ptr */ 142 R3PTRTYPE(const void*) pPciBusPtrR3; 129 143 130 144 /** Read config callback for PCI bridges to pass requests
Note:
See TracChangeset
for help on using the changeset viewer.