Changeset 92716 in vbox for trunk/src/VBox/VMM/VMMR3/IOMR3IoPort.cpp
- Timestamp:
- Dec 2, 2021 9:17:42 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 148617
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/IOMR3IoPort.cpp
r82968 r92716 33 33 #include <VBox/param.h> 34 34 #include <iprt/assert.h> 35 #include <iprt/mem.h> 35 36 #include <iprt/string.h> 36 37 #include <VBox/log.h> … … 198 199 199 200 201 #ifdef VBOX_WITH_STATISTICS 202 /** 203 * Grows the statistics table. 204 * 205 * @returns VBox status code. 206 * @param pVM The cross context VM structure. 207 * @param cNewEntries The minimum number of new entrie. 208 * @see IOMR0IoPortGrowStatisticsTable 209 */ 210 static int iomR3IoPortGrowStatisticsTable(PVM pVM, uint32_t cNewEntries) 211 { 212 AssertReturn(cNewEntries <= _64K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS); 213 214 int rc; 215 if (!SUPR3IsDriverless()) 216 { 217 rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORT_STATS, cNewEntries, NULL); 218 AssertLogRelRCReturn(rc, rc); 219 AssertReturn(cNewEntries <= pVM->iom.s.cIoPortStatsAllocation, VERR_IOM_IOPORT_IPE_2); 220 } 221 else 222 { 223 /* 224 * Validate input and state. 225 */ 226 uint32_t const cOldEntries = pVM->iom.s.cIoPortStatsAllocation; 227 AssertReturn(cNewEntries > cOldEntries, VERR_IOM_IOPORT_IPE_1); 228 AssertReturn(pVM->iom.s.cIoPortStats <= cOldEntries, VERR_IOM_IOPORT_IPE_2); 229 230 /* 231 * Calc size and allocate a new table. 232 */ 233 uint32_t const cbNew = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTSTATSENTRY), PAGE_SIZE); 234 cNewEntries = cbNew / sizeof(IOMIOPORTSTATSENTRY); 235 236 PIOMIOPORTSTATSENTRY const paIoPortStats = (PIOMIOPORTSTATSENTRY)RTMemPageAllocZ(cbNew); 237 if (paIoPortStats) 238 { 239 /* 240 * Anything to copy over, update and free the old one. 241 */ 242 PIOMIOPORTSTATSENTRY const pOldIoPortStats = pVM->iom.s.paIoPortStats; 243 if (pOldIoPortStats) 244 memcpy(paIoPortStats, pOldIoPortStats, cOldEntries * sizeof(IOMIOPORTSTATSENTRY)); 245 246 pVM->iom.s.paIoPortStats = paIoPortStats; 247 pVM->iom.s.cIoPortStatsAllocation = cNewEntries; 248 249 RTMemPageFree(pOldIoPortStats, RT_ALIGN_32(cOldEntries * sizeof(IOMIOPORTSTATSENTRY), PAGE_SIZE)); 250 251 rc = VINF_SUCCESS; 252 } 253 else 254 rc = VERR_NO_PAGE_MEMORY; 255 } 256 257 return rc; 258 } 259 #endif 260 261 262 /** 263 * Grows the I/O port registration statistics table. 264 * 265 * @returns VBox status code. 266 * @param pVM The cross context VM structure. 267 * @param cNewEntries The minimum number of new entrie. 268 * @see IOMR0IoPortGrowRegistrationTables 269 */ 270 static int iomR3IoPortGrowTable(PVM pVM, uint32_t cNewEntries) 271 { 272 AssertReturn(cNewEntries <= _4K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS); 273 274 int rc; 275 if (!SUPR3IsDriverless()) 276 { 277 rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORTS, cNewEntries, NULL); 278 AssertLogRelRCReturn(rc, rc); 279 AssertReturn(cNewEntries <= pVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_2); 280 } 281 else 282 { 283 /* 284 * Validate input and state. 285 */ 286 uint32_t const cOldEntries = pVM->iom.s.cIoPortAlloc; 287 AssertReturn(cNewEntries >= cOldEntries, VERR_IOM_IOPORT_IPE_1); 288 289 /* 290 * Allocate the new tables. We use a single allocation for the three tables (ring-0, 291 * ring-3, lookup) and does a partial mapping of the result to ring-3. 292 */ 293 uint32_t const cbRing3 = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTENTRYR3), PAGE_SIZE); 294 uint32_t const cbShared = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTLOOKUPENTRY), PAGE_SIZE); 295 uint32_t const cbNew = cbRing3 + cbShared; 296 297 /* Use the rounded up space as best we can. */ 298 cNewEntries = RT_MIN(cbRing3 / sizeof(IOMIOPORTENTRYR3), cbShared / sizeof(IOMIOPORTLOOKUPENTRY)); 299 300 PIOMIOPORTENTRYR3 const paRing3 = (PIOMIOPORTENTRYR3)RTMemPageAllocZ(cbNew); 301 if (paRing3) 302 { 303 PIOMIOPORTLOOKUPENTRY const paLookup = (PIOMIOPORTLOOKUPENTRY)((uintptr_t)paRing3 + cbRing3); 304 305 /* 306 * Copy over the old info and initialize the idxSelf and idxStats members. 307 */ 308 if (pVM->iom.s.paIoPortRegs != NULL) 309 { 310 memcpy(paRing3, pVM->iom.s.paIoPortRegs, sizeof(paRing3[0]) * cOldEntries); 311 memcpy(paLookup, pVM->iom.s.paIoPortLookup, sizeof(paLookup[0]) * cOldEntries); 312 } 313 314 size_t i = cbRing3 / sizeof(*paRing3); 315 while (i-- > cOldEntries) 316 { 317 paRing3[i].idxSelf = (uint16_t)i; 318 paRing3[i].idxStats = UINT16_MAX; 319 } 320 321 /* 322 * Update the variables and free the old memory. 323 */ 324 void * const pvFree = pVM->iom.s.paIoPortRegs; 325 326 pVM->iom.s.paIoPortRegs = paRing3; 327 pVM->iom.s.paIoPortLookup = paLookup; 328 pVM->iom.s.cIoPortAlloc = cNewEntries; 329 330 RTMemPageFree(pvFree, 331 RT_ALIGN_32(cOldEntries * sizeof(IOMIOPORTENTRYR3), PAGE_SIZE) 332 + RT_ALIGN_32(cOldEntries * sizeof(IOMIOPORTLOOKUPENTRY), PAGE_SIZE)); 333 334 rc = VINF_SUCCESS; 335 } 336 else 337 rc = VERR_NO_PAGE_MEMORY; 338 } 339 return rc; 340 } 341 200 342 201 343 /** … … 254 396 if (cNewIoPortStats > pVM->iom.s.cIoPortStatsAllocation) 255 397 { 256 int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORT_STATS, cNewIoPortStats, NULL);257 Assert LogRelRCReturn(rc, rc);398 int rc = iomR3IoPortGrowStatisticsTable(pVM, cNewIoPortStats); 399 AssertRCReturn(rc, rc); 258 400 AssertReturn(idxStats == pVM->iom.s.cIoPortStats, VERR_IOM_IOPORT_IPE_1); 259 AssertReturn(cNewIoPortStats <= pVM->iom.s.cIoPortStatsAllocation, VERR_IOM_IOPORT_IPE_2);260 401 } 261 402 #endif … … 264 405 if (idx >= pVM->iom.s.cIoPortAlloc) 265 406 { 266 int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORTS, pVM->iom.s.cIoPortAlloc + 1, NULL);267 Assert LogRelRCReturn(rc, rc);407 int rc = iomR3IoPortGrowTable(pVM, pVM->iom.s.cIoPortAlloc + 1); 408 AssertRCReturn(rc, rc); 268 409 AssertReturn(idx == pVM->iom.s.cIoPortRegs, VERR_IOM_IOPORT_IPE_1); 269 410 AssertReturn(idx < pVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_2);
Note:
See TracChangeset
for help on using the changeset viewer.