Changeset 81167 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 9, 2019 8:15:37 AM (5 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 6 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/Makefile.kmk
r81156 r81167 121 121 VMMR3/IOM.cpp \ 122 122 VMMR3/IOMR3IoPort.cpp \ 123 VMMR3/IOMR3Mmio.cpp \ 123 124 VMMR3/GMM.cpp \ 124 125 VMMR3/MM.cpp \ … … 482 483 VMMR0/HMSVMR0.cpp \ 483 484 VMMR0/IOMR0.cpp \ 485 VMMR0/IOMR0IoPort.cpp \ 484 486 VMMR0/PDMR0Device.cpp \ 485 487 VMMR0/PDMR0Driver.cpp \ -
trunk/src/VBox/VMM/VMMR0/IOMR0.cpp
r81136 r81167 23 23 #include <VBox/vmm/iom.h> 24 24 #include "IOMInternal.h" 25 #include <VBox/vmm/pdmdev.h>26 25 #include <VBox/vmm/vmcc.h> 27 26 #include <VBox/err.h> 28 27 #include <VBox/log.h> 29 #include <iprt/assert.h> 30 #include <iprt/mem.h> 31 #include <iprt/memobj.h> 32 #include <iprt/process.h> 33 #include <iprt/string.h> 28 #include <iprt/assertcompile.h> 34 29 35 30 … … 48 43 AssertCompile(sizeof(pGVM->iomr0.s) <= sizeof(pGVM->iomr0.padding)); 49 44 50 pGVM->iomr0.s.hIoPortMapObj = NIL_RTR0MEMOBJ; 51 pGVM->iomr0.s.hIoPortMemObj = NIL_RTR0MEMOBJ; 52 #ifdef VBOX_WITH_STATISTICS 53 pGVM->iomr0.s.hIoPortStatsMapObj = NIL_RTR0MEMOBJ; 54 pGVM->iomr0.s.hIoPortStatsMemObj = NIL_RTR0MEMOBJ; 55 #endif 45 iomR0IoPortInitPerVMData(pGVM); 56 46 } 57 47 … … 62 52 VMMR0_INT_DECL(void) IOMR0CleanupVM(PGVM pGVM) 63 53 { 64 RTR0MemObjFree(pGVM->iomr0.s.hIoPortMapObj, true /*fFreeMappings*/); 65 pGVM->iomr0.s.hIoPortMapObj = NIL_RTR0MEMOBJ; 66 RTR0MemObjFree(pGVM->iomr0.s.hIoPortMemObj, true /*fFreeMappings*/); 67 pGVM->iomr0.s.hIoPortMemObj = NIL_RTR0MEMOBJ; 68 #ifdef VBOX_WITH_STATISTICS 69 RTR0MemObjFree(pGVM->iomr0.s.hIoPortStatsMapObj, true /*fFreeMappings*/); 70 pGVM->iomr0.s.hIoPortStatsMapObj = NIL_RTR0MEMOBJ; 71 RTR0MemObjFree(pGVM->iomr0.s.hIoPortStatsMemObj, true /*fFreeMappings*/); 72 pGVM->iomr0.s.hIoPortStatsMemObj = NIL_RTR0MEMOBJ; 73 #endif 54 iomR0IoPortCleanupVM(pGVM); 74 55 } 75 56 76 77 /**78 * Implements PDMDEVHLPR0::pfnIoPortSetUpContext.79 *80 * @param pGVM The global (ring-0) VM structure.81 * @param pDevIns The device instance.82 * @param hIoPorts The I/O port handle (already registered in ring-3).83 * @param pfnOut The OUT handler callback, optional.84 * @param pfnIn The IN handler callback, optional.85 * @param pfnOutStr The REP OUTS handler callback, optional.86 * @param pfnInStr The REP INS handler callback, optional.87 * @param pvUser User argument for the callbacks.88 * @thread EMT(0)89 * @note Only callable at VM creation time.90 */91 VMMR0_INT_DECL(int) IOMR0IoPortSetUpContext(PGVM pGVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,92 PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,93 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, void *pvUser)94 {95 /*96 * Validate input and state.97 */98 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);99 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);100 AssertReturn(hIoPorts < pGVM->iomr0.s.cIoPortAlloc, VERR_IOM_INVALID_IOPORT_HANDLE);101 AssertReturn(hIoPorts < pGVM->iom.s.cIoPortRegs, VERR_IOM_INVALID_IOPORT_HANDLE);102 AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE);103 AssertReturn(pDevIns->pDevInsForR3 != NIL_RTR3PTR && !(pDevIns->pDevInsForR3 & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);104 AssertReturn(pGVM->iomr0.s.paIoPortRing3Regs[hIoPorts].pDevIns == pDevIns->pDevInsForR3, VERR_IOM_INVALID_IOPORT_HANDLE);105 AssertReturn(pGVM->iomr0.s.paIoPortRegs[hIoPorts].pDevIns == NULL, VERR_WRONG_ORDER);106 107 AssertReturn(pfnOut || pfnIn || pfnOutStr || pfnInStr, VERR_INVALID_PARAMETER);108 AssertPtrNullReturn(pfnOut, VERR_INVALID_POINTER);109 AssertPtrNullReturn(pfnIn, VERR_INVALID_POINTER);110 AssertPtrNullReturn(pfnOutStr, VERR_INVALID_POINTER);111 AssertPtrNullReturn(pfnInStr, VERR_INVALID_POINTER);112 113 uint16_t const fFlags = pGVM->iomr0.s.paIoPortRing3Regs[hIoPorts].fFlags;114 RTIOPORT const cPorts = pGVM->iomr0.s.paIoPortRing3Regs[hIoPorts].cPorts;115 AssertMsgReturn(cPorts > 0 && cPorts <= _8K, ("cPorts=%s\n", cPorts), VERR_IOM_INVALID_IOPORT_HANDLE);116 117 /*118 * Do the job.119 */120 pGVM->iomr0.s.paIoPortRegs[hIoPorts].pvUser = pvUser;121 pGVM->iomr0.s.paIoPortRegs[hIoPorts].pDevIns = pDevIns;122 pGVM->iomr0.s.paIoPortRegs[hIoPorts].pfnOutCallback = pfnOut;123 pGVM->iomr0.s.paIoPortRegs[hIoPorts].pfnInCallback = pfnIn;124 pGVM->iomr0.s.paIoPortRegs[hIoPorts].pfnOutStrCallback = pfnOutStr;125 pGVM->iomr0.s.paIoPortRegs[hIoPorts].pfnInStrCallback = pfnInStr;126 pGVM->iomr0.s.paIoPortRegs[hIoPorts].cPorts = cPorts;127 pGVM->iomr0.s.paIoPortRegs[hIoPorts].fFlags = fFlags;128 #ifdef VBOX_WITH_STATISTICS129 uint16_t const idxStats = pGVM->iomr0.s.paIoPortRing3Regs[hIoPorts].idxStats;130 pGVM->iomr0.s.paIoPortRegs[hIoPorts].idxStats = (uint32_t)idxStats + cPorts <= pGVM->iomr0.s.cIoPortStatsAllocation131 ? idxStats : UINT16_MAX;132 #else133 pGVM->iomr0.s.paIoPortRegs[hIoPorts].idxStats = UINT16_MAX;134 #endif135 136 pGVM->iomr0.s.paIoPortRing3Regs[hIoPorts].fRing0 = true;137 138 return VINF_SUCCESS;139 }140 141 142 /**143 * Grows the I/O port registration (all contexts) and lookup tables.144 *145 * @returns VBox status code.146 * @param pGVM The global (ring-0) VM structure.147 * @param cReqMinEntries The minimum growth (absolute).148 * @thread EMT(0)149 * @note Only callable at VM creation time.150 */151 VMMR0_INT_DECL(int) IOMR0IoPortGrowRegistrationTables(PGVM pGVM, uint64_t cReqMinEntries)152 {153 /*154 * Validate input and state.155 */156 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);157 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);158 AssertReturn(cReqMinEntries <= _4K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS);159 uint32_t cNewEntries = (uint32_t)cReqMinEntries;160 AssertReturn(cNewEntries >= pGVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_1);161 uint32_t const cOldEntries = pGVM->iomr0.s.cIoPortAlloc;162 ASMCompilerBarrier();163 AssertReturn(cNewEntries >= cOldEntries, VERR_IOM_IOPORT_IPE_2);164 AssertReturn(pGVM->iom.s.cIoPortRegs >= pGVM->iomr0.s.cIoPortMax, VERR_IOM_IOPORT_IPE_3);165 166 /*167 * Allocate the new tables. We use a single allocation for the three tables (ring-0,168 * ring-3, lookup) and does a partial mapping of the result to ring-3.169 */170 uint32_t const cbRing0 = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTENTRYR0), PAGE_SIZE);171 uint32_t const cbRing3 = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTENTRYR3), PAGE_SIZE);172 uint32_t const cbShared = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTLOOKUPENTRY), PAGE_SIZE);173 uint32_t const cbNew = cbRing0 + cbRing3 + cbShared;174 175 /* Use the rounded up space as best we can. */176 cNewEntries = RT_MIN(RT_MIN(cbRing0 / sizeof(IOMIOPORTENTRYR0), cbRing3 / sizeof(IOMIOPORTENTRYR3)),177 cbShared / sizeof(IOMIOPORTLOOKUPENTRY));178 179 RTR0MEMOBJ hMemObj;180 int rc = RTR0MemObjAllocPage(&hMemObj, cbNew, false /*fExecutable*/);181 if (RT_SUCCESS(rc))182 {183 /*184 * Zero and map it.185 */186 RT_BZERO(RTR0MemObjAddress(hMemObj), cbNew);187 188 RTR0MEMOBJ hMapObj;189 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE,190 RTR0ProcHandleSelf(), cbRing0, cbNew - cbRing0);191 if (RT_SUCCESS(rc))192 {193 PIOMIOPORTENTRYR0 const paRing0 = (PIOMIOPORTENTRYR0)RTR0MemObjAddress(hMemObj);194 PIOMIOPORTENTRYR3 const paRing3 = (PIOMIOPORTENTRYR3)((uintptr_t)paRing0 + cbRing0);195 PIOMIOPORTLOOKUPENTRY const paLookup = (PIOMIOPORTLOOKUPENTRY)((uintptr_t)paRing3 + cbRing3);196 RTR3UINTPTR const uAddrRing3 = RTR0MemObjAddressR3(hMapObj);197 198 /*199 * Copy over the old info and initialize the idxSelf and idxStats members.200 */201 if (pGVM->iomr0.s.paIoPortRegs != NULL)202 {203 memcpy(paRing0, pGVM->iomr0.s.paIoPortRegs, sizeof(paRing0[0]) * cOldEntries);204 memcpy(paRing3, pGVM->iomr0.s.paIoPortRing3Regs, sizeof(paRing3[0]) * cOldEntries);205 memcpy(paLookup, pGVM->iomr0.s.paIoPortLookup, sizeof(paLookup[0]) * cOldEntries);206 }207 208 size_t i = cbRing0 / sizeof(*paRing0);209 while (i-- > cOldEntries)210 {211 paRing0[i].idxSelf = (uint16_t)i;212 paRing0[i].idxStats = UINT16_MAX;213 paRing3[i].idxSelf = (uint16_t)i;214 paRing3[i].idxStats = UINT16_MAX;215 }216 217 /*218 * Switch the memory handles.219 */220 RTR0MEMOBJ hTmp = pGVM->iomr0.s.hIoPortMapObj;221 pGVM->iomr0.s.hIoPortMapObj = hMapObj;222 hMapObj = hTmp;223 224 hTmp = pGVM->iomr0.s.hIoPortMemObj;225 pGVM->iomr0.s.hIoPortMemObj = hMemObj;226 hMemObj = hTmp;227 228 /*229 * Update the variables.230 */231 pGVM->iomr0.s.paIoPortRegs = paRing0;232 pGVM->iomr0.s.paIoPortRing3Regs = paRing3;233 pGVM->iomr0.s.paIoPortLookup = paLookup;234 pGVM->iom.s.paIoPortRegs = uAddrRing3;235 pGVM->iom.s.paIoPortLookup = uAddrRing3 + cbRing3;236 pGVM->iom.s.cIoPortAlloc = cNewEntries;237 pGVM->iomr0.s.cIoPortAlloc = cNewEntries;238 239 /*240 * Free the old allocation.241 */242 RTR0MemObjFree(hMapObj, true /*fFreeMappings*/);243 }244 RTR0MemObjFree(hMemObj, true /*fFreeMappings*/);245 }246 247 return rc;248 }249 250 251 /**252 * Grows the I/O port statistics table.253 *254 * @returns VBox status code.255 * @param pGVM The global (ring-0) VM structure.256 * @param cReqMinEntries The minimum growth (absolute).257 * @thread EMT(0)258 * @note Only callable at VM creation time.259 */260 VMMR0_INT_DECL(int) IOMR0IoPortGrowStatisticsTable(PGVM pGVM, uint64_t cReqMinEntries)261 {262 /*263 * Validate input and state.264 */265 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);266 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);267 AssertReturn(cReqMinEntries <= _64K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS);268 uint32_t cNewEntries = (uint32_t)cReqMinEntries;269 #ifdef VBOX_WITH_STATISTICS270 uint32_t const cOldEntries = pGVM->iomr0.s.cIoPortStatsAllocation;271 ASMCompilerBarrier();272 #else273 uint32_t const cOldEntries = 0;274 #endif275 AssertReturn(cNewEntries > cOldEntries, VERR_IOM_IOPORT_IPE_1);276 AssertReturn(pGVM->iom.s.cIoPortStatsAllocation == cOldEntries, VERR_IOM_IOPORT_IPE_1);277 AssertReturn(pGVM->iom.s.cIoPortStats <= cOldEntries, VERR_IOM_IOPORT_IPE_2);278 279 /*280 * Allocate a new table, zero it and map it.281 */282 #ifndef VBOX_WITH_STATISTICS283 AssertFailedReturn(VERR_NOT_SUPPORTED);284 #else285 uint32_t const cbNew = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTSTATSENTRY), PAGE_SIZE);286 cNewEntries = cbNew / sizeof(IOMIOPORTSTATSENTRY);287 288 RTR0MEMOBJ hMemObj;289 int rc = RTR0MemObjAllocPage(&hMemObj, cbNew, false /*fExecutable*/);290 if (RT_SUCCESS(rc))291 {292 RT_BZERO(RTR0MemObjAddress(hMemObj), cbNew);293 294 RTR0MEMOBJ hMapObj;295 rc = RTR0MemObjMapUser(&hMapObj, hMemObj, (RTR3PTR)-1, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf());296 if (RT_SUCCESS(rc))297 {298 PIOMIOPORTSTATSENTRY pIoPortStats = (PIOMIOPORTSTATSENTRY)RTR0MemObjAddress(hMemObj);299 300 /*301 * Anything to copy over and free up?302 */303 if (pGVM->iomr0.s.paIoPortStats)304 memcpy(pIoPortStats, pGVM->iomr0.s.paIoPortStats, cOldEntries * sizeof(IOMIOPORTSTATSENTRY));305 306 /*307 * Switch the memory handles.308 */309 RTR0MEMOBJ hTmp = pGVM->iomr0.s.hIoPortStatsMapObj;310 pGVM->iomr0.s.hIoPortStatsMapObj = hMapObj;311 hMapObj = hTmp;312 313 hTmp = pGVM->iomr0.s.hIoPortStatsMemObj;314 pGVM->iomr0.s.hIoPortStatsMemObj = hMemObj;315 hMemObj = hTmp;316 317 /*318 * Update the variables.319 */320 pGVM->iomr0.s.paIoPortStats = pIoPortStats;321 pGVM->iom.s.paIoPortStats = RTR0MemObjAddressR3(pGVM->iomr0.s.hIoPortStatsMapObj);322 pGVM->iom.s.cIoPortStatsAllocation = cNewEntries;323 pGVM->iomr0.s.cIoPortStatsAllocation = cNewEntries;324 325 /*326 * Free the old allocation.327 */328 RTR0MemObjFree(hMapObj, true /*fFreeMappings*/);329 }330 RTR0MemObjFree(hMemObj, true /*fFreeMappings*/);331 }332 return rc;333 #endif /* VBOX_WITH_STATISTICS */334 }335 -
trunk/src/VBox/VMM/VMMR0/IOMR0IoPort.cpp
r81166 r81167 1 1 /* $Id$ */ 2 2 /** @file 3 * IOM - Host Context Ring 0 .3 * IOM - Host Context Ring 0, I/O ports. 4 4 */ 5 5 … … 36 36 37 37 /** 38 * Initializes the per-VM data for the IOM. 39 * 40 * This is called from under the GVMM lock, so it should only initialize the 41 * data so IOMR0CleanupVM and others will work smoothly. 38 * Initializes the I/O port related members. 42 39 * 43 40 * @param pGVM Pointer to the global VM structure. 44 41 */ 45 VMMR0_INT_DECL(void) IOMR0InitPerVMData(PGVM pGVM) 46 { 47 AssertCompile(sizeof(pGVM->iom.s) <= sizeof(pGVM->iom.padding)); 48 AssertCompile(sizeof(pGVM->iomr0.s) <= sizeof(pGVM->iomr0.padding)); 49 42 void iomR0IoPortInitPerVMData(PGVM pGVM) 43 { 50 44 pGVM->iomr0.s.hIoPortMapObj = NIL_RTR0MEMOBJ; 51 45 pGVM->iomr0.s.hIoPortMemObj = NIL_RTR0MEMOBJ; … … 58 52 59 53 /** 60 * Cleans up any loose ends before the GVM structure is destroyed.61 */ 62 VMMR0_INT_DECL(void) IOMR0CleanupVM(PGVM pGVM)54 * Cleans up I/O port related resources. 55 */ 56 void iomR0IoPortCleanupVM(PGVM pGVM) 63 57 { 64 58 RTR0MemObjFree(pGVM->iomr0.s.hIoPortMapObj, true /*fFreeMappings*/); -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r81161 r81167 2199 2199 } 2200 2200 2201 case VMMR0_DO_IOM_GROW_MMIO_REGS: 2202 { 2203 if (pReqHdr || idCpu != 0) 2204 return VERR_INVALID_PARAMETER; 2205 rc = VERR_NOT_SUPPORTED; //rc = IOMR0MmioGrowRegistrationTables(pGVM, u64Arg); 2206 VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING); 2207 break; 2208 } 2209 2210 case VMMR0_DO_IOM_GROW_MMIO_STATS: 2211 { 2212 if (pReqHdr || idCpu != 0) 2213 return VERR_INVALID_PARAMETER; 2214 rc = VERR_NOT_SUPPORTED; //rc = IOMR0MmioGrowStatisticsTable(pGVM, u64Arg); 2215 VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING); 2216 break; 2217 } 2218 2201 2219 /* 2202 2220 * For profiling. -
trunk/src/VBox/VMM/VMMR3/IOM.cpp
r81156 r81167 2327 2327 #endif /* VBOX_WITH_STATISTICS */ 2328 2328 2329 2330 VMMR3_INT_DECL(int) IOMR3MmioCreate(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS cbRegion, uint32_t fFlags, PPDMPCIDEV pPciDev,2331 uint32_t iPciRegion, PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead,2332 PFNIOMMMIONEWFILL pfnFill, void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)2333 {2334 RT_NOREF(pVM, pDevIns, cbRegion, fFlags, pPciDev, iPciRegion, pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, phRegion);2335 return VERR_NOT_IMPLEMENTED;2336 }2337 2338 VMMR3_INT_DECL(int) IOMR3MmioMap(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)2339 {2340 RT_NOREF(pVM, pDevIns, hRegion, GCPhys);2341 return VERR_NOT_IMPLEMENTED;2342 }2343 2344 VMMR3_INT_DECL(int) IOMR3MmioUnmap(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)2345 {2346 RT_NOREF(pVM, pDevIns, hRegion);2347 return VERR_NOT_IMPLEMENTED;2348 }2349 2350 VMMR3_INT_DECL(int) IOMR3MmioReduce(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion)2351 {2352 RT_NOREF(pVM, pDevIns, hRegion, cbRegion);2353 return VERR_NOT_IMPLEMENTED;2354 }2355 -
trunk/src/VBox/VMM/VMMR3/IOMR3Mmio.cpp
r81162 r81167 291 291 { 292 292 AssertFailed(); 293 rc = VERR_IOM_MMIO_ ALREADY_MAPPED;293 rc = VERR_IOM_MMIO_REGION_ALREADY_MAPPED; 294 294 } 295 295 … … 401 401 { 402 402 AssertFailed(); 403 rc = VERR_IOM_MMIO_ NOT_MAPPED;403 rc = VERR_IOM_MMIO_REGION_NOT_MAPPED; 404 404 } 405 405 406 406 IOM_UNLOCK_EXCL(pVM); 407 407 return rc; 408 } 409 410 411 VMMR3_INT_DECL(int) IOMR3MmioReduce(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion) 412 { 413 RT_NOREF(pVM, pDevIns, hRegion, cbRegion); 414 return VERR_NOT_IMPLEMENTED; 408 415 } 409 416 -
trunk/src/VBox/VMM/include/IOMInternal.h
r81162 r81167 842 842 void iomR3IoPortRegStats(PVM pVM, PIOMIOPORTENTRYR3 pRegEntry); 843 843 #endif /* IN_RING3 */ 844 #ifdef IN_RING0 845 void iomR0IoPortCleanupVM(PGVM pGVM); 846 void iomR0IoPortInitPerVMData(PGVM pGVM); 847 #endif 844 848 845 849 #ifndef IN_RING3
Note:
See TracChangeset
for help on using the changeset viewer.