Changeset 44684 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- Feb 14, 2013 12:08:46 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevIoApic.cpp
r44681 r44684 229 229 } 230 230 231 static uint32_t ioapic_mem_readl(PIOAPIC pThis, RTGCPHYS addr) 232 { 233 uint32_t val = 0; 234 235 addr &= 0xff; 236 if (addr == 0x00) 237 val = pThis->ioregsel; 238 else if (addr == 0x10) 239 { 240 switch (pThis->ioregsel) 241 { 242 case 0x00: 243 val = pThis->id << 24; 244 break; 245 246 case 0x01: 247 val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */ 248 break; 249 250 case 0x02: 251 val = 0; 252 break; 253 254 default: 255 { 256 int index = (pThis->ioregsel - 0x10) >> 1; 257 if (index >= 0 && index < IOAPIC_NUM_PINS) 258 { 259 if (pThis->ioregsel & 1) 260 val = pThis->ioredtbl[index] >> 32; 261 else 262 val = pThis->ioredtbl[index] & 0xffffffff; 263 } 264 else 265 val = 0; 266 break; 267 } 268 } 269 #ifdef DEBUG_IOAPIC 270 Log(("I/O APIC read: %08x = %08x\n", pThis->ioregsel, val)); 271 #endif 231 232 /** 233 * Handles a read from the IOAPICID register. 234 */ 235 static int ioapic_IoApicId_r(PIOAPIC pThis, uint32_t *pu32Value) 236 { 237 *pu32Value = (uint32_t)pThis->id << 24; 238 return VINF_SUCCESS; 239 } 240 241 242 /** 243 * Handles a write to the IOAPICID register. 244 */ 245 static int ioapic_IoApicId_w(PIOAPIC pThis, uint32_t u32Value) 246 { 247 /* Note! Compared to the 82093AA spec, we've extended the IOAPIC 248 identification from bits 27:24 to bits 31:24. */ 249 Log(("ioapic: IOAPICID %#x -> %#x\n", pThis->id, u32Value >> 24)); 250 pThis->id = u32Value >> 24; 251 return VINF_SUCCESS; 252 } 253 254 255 /** 256 * Handles a read from the IOAPICVER register. 257 */ 258 static int ioapic_IoApicVer_r(PIOAPIC pThis, uint32_t *pu32Value) 259 { 260 *pu32Value = RT_MAKE_U32(0x11, IOAPIC_NUM_PINS - 1); /* (0x11 is the version.) */ 261 return VINF_SUCCESS; 262 } 263 264 265 /** 266 * Handles a read from the IOAPICARB register. 267 */ 268 static int ioapic_IoApicArb_r(PIOAPIC pThis, uint32_t *pu32Value) 269 { 270 *pu32Value = 0; /* (arbitration winner) */ 271 return VINF_SUCCESS; 272 } 273 274 275 /** 276 * Handles a read from the IOREGSEL register. 277 */ 278 static int ioapic_IoRegSel_r(PIOAPIC pThis, uint32_t *pu32Value) 279 { 280 *pu32Value = pThis->ioregsel; 281 return VINF_SUCCESS; 282 } 283 284 /** 285 * Handles a write to the IOREGSEL register. 286 */ 287 static int ioapic_IoRegSel_w(PIOAPIC pThis, uint32_t u32Value) 288 { 289 Log2(("ioapic: IOREGSEL %#04x -> %#04x\n", pThis->ioregsel, u32Value & 0xff)); 290 /* Bits 7:0 are writable, the rest aren't. Confirmed on recent AMD box. */ 291 pThis->ioregsel = u32Value & 0xff; 292 return VINF_SUCCESS; 293 } 294 295 296 /** 297 * Handles a write to the IOWIN register. 298 */ 299 static int ioapic_IoWin_r(PIOAPIC pThis, uint32_t *pu32Value) 300 { 301 int rc = VINF_SUCCESS; 302 uint32_t const uIoRegSel = pThis->ioregsel; 303 304 if (uIoRegSel == 0) 305 rc = ioapic_IoApicId_r(pThis, pu32Value); 306 else if (uIoRegSel == 1) 307 rc = ioapic_IoApicVer_r(pThis, pu32Value); 308 else if (uIoRegSel == 2) 309 rc = ioapic_IoApicArb_r(pThis, pu32Value); 310 /* 311 * IOREDTBL0..IOREDTBL23. 312 */ 313 else if (uIoRegSel - UINT32_C(0x10) < IOAPIC_NUM_PINS * 2) 314 { 315 uint32_t const idxIoRedTbl = (uIoRegSel - UINT32_C(0x10)) >> 1; 316 uint64_t u64NewValue; 317 if (!(uIoRegSel & 1)) 318 /** @todo r=bird: Do we need to emulate DELIVS or/and Remote IRR? */ 319 *pu32Value = RT_LODWORD(pThis->ioredtbl[idxIoRedTbl]); 320 else 321 *pu32Value = RT_HIDWORD(pThis->ioredtbl[idxIoRedTbl]); 272 322 } 273 323 else 274 val = 0; 275 return val; 276 } 277 278 /** Handles a write to the IOREGSEL register. */ 279 static int ioapic_IoRegSel_w(PIOAPIC pThis, uint32_t u32Value) 280 { 281 Log2(("ioapic: IOREGSEL %#04x -> %#04x\n", pThis->ioregsel, u32Value & 0xff)); 282 pThis->ioregsel = u32Value & 0xff; /* This is what the AMD box does here */ 283 return VINF_SUCCESS; 284 } 324 { 325 Log(("ioapic: Attempt to read from register %#x.\n", uIoRegSel)); 326 *pu32Value = UINT32_MAX; 327 } 328 329 return rc; 330 } 331 285 332 286 333 /** … … 289 336 static int ioapic_IoWin_w(PIOAPIC pThis, uint32_t u32Value) 290 337 { 291 uint32_t const uIoRegSel = pThis->ioregsel; 338 int rc = VINF_SUCCESS; 339 uint32_t const uIoRegSel = pThis->ioregsel; 292 340 Log2(("ioapic: IOWIN[%#04x] = %#x\n", uIoRegSel, u32Value)); 293 341 294 342 /* 295 * IO REGSEL.343 * IOAPICID. 296 344 */ 297 345 if (uIoRegSel == 0) 298 { 299 /* Note! Compared to the 82093AA spec, we've extended the IOAPIC 300 identification from bits 27:24 to bits 31:24. */ 301 Log(("ioapic: IOAPICID %#x -> %#x\n", pThis->id, u32Value >> 24)); 302 pThis->id = u32Value >> 24; 303 } 346 rc = ioapic_IoApicId_w(pThis, u32Value); 304 347 /* 305 348 * IOREDTBL0..IOREDTBL23. … … 320 363 * limits the INTVEC range to 0x10 thru 0xfe, so we use this to 321 364 * ignore harmful values. 365 * 366 * Update: Looking at real hw (recent AMD), they don't reject 367 * invalid vector numbers, at least not at this point. Could be that 368 * some other code path needs to refuse something instead. Results: 369 * - Writing 0 to lo+hi -> 0. 370 * - Writing ~0 to lo+hi -> 0xff0000000001afff. 371 * - Writing ~0 w/ DELMOD set to 011b or 110b (both reserved) 372 * results in DELMOD containing the reserved values. 373 * - Ditto with same + DELMOD in [0..7], DELMOD is stored as written. 322 374 */ 323 /** @todo see what happens on real HW when doing that. It probably324 * ignores/rejects other values as well. Could be it ignores invalid325 * values on a per sub-register basis, someone need to check this! */326 375 if ( (u32Value & APIC_LVT_MASKED) 327 376 || ((u32Value & UINT32_C(0xff)) - UINT32_C(0x10)) <= UINT32_C(0xee) /* (0xfe - 0x10 = 0xee) */ ) 328 u64NewValue = (pThis->ioredtbl[idxIoRedTbl] & UINT64_C(0xffffffff00000000)) | u32Value; 377 u64NewValue = (pThis->ioredtbl[idxIoRedTbl] & (UINT64_C(0xffffffff00000000) | RT_BIT(14) | RT_BIT(12))) 378 | (u32Value & ~(RT_BIT(14) | RT_BIT(12))); 329 379 else 330 380 { … … 338 388 * High DWORD. 339 389 */ 340 u64NewValue = (pThis->ioredtbl[idxIoRedTbl] & UINT64_C(0x00000000ffffffff)) | ((uint64_t)u32Value << 32); 390 u64NewValue = (pThis->ioredtbl[idxIoRedTbl] & UINT64_C(0x00000000ffffffff)) 391 | ((uint64_t)(u32Value & UINT32_C(0xff000000)) << 32); 341 392 } 342 393 … … 356 407 Log(("ioapic: Attempt to write (%#x) to register %#x.\n", u32Value, uIoRegSel)); 357 408 358 return VINF_SUCCESS; 359 } 360 361 /* IOAPIC */ 409 return rc; 410 } 411 362 412 363 413 PDMBOTHCBDECL(int) ioapicMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) … … 367 417 368 418 STAM_COUNTER_INC(&CTXSUFF(pThis->StatMMIORead)); 369 switch (cb) 370 { 371 case 1: 372 *(uint8_t *)pv = ioapic_mem_readl(pThis, GCPhysAddr); 373 break; 374 375 case 2: 376 *(uint16_t *)pv = ioapic_mem_readl(pThis, GCPhysAddr); 377 break; 378 379 case 4: 380 *(uint32_t *)pv = ioapic_mem_readl(pThis, GCPhysAddr); 381 break; 382 383 default: 384 AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */ 385 IOAPIC_UNLOCK(pThis); 386 return VERR_INTERNAL_ERROR; 387 } 419 420 /* 421 * Pass it on to the register read handlers. 422 * (See 0xff comments in ioapicMMIOWrite.) 423 */ 424 int rc; 425 uint32_t offReg = GCPhysAddr & 0xff; 426 if (offReg == 0) 427 rc = ioapic_IoRegSel_r(pThis, (uint32_t *)pv); 428 else if (offReg == 0x10) 429 rc = ioapic_IoRegSel_r(pThis, (uint32_t *)pv); 430 else 431 { 432 Log(("ioapicMMIORead: Invalid access: offReg=%#x\n", offReg)); 433 rc = VINF_IOM_MMIO_UNUSED_FF; 434 } 435 388 436 IOAPIC_UNLOCK(pThis); 389 return VINF_SUCCESS;437 return rc; 390 438 } 391 439 … … 484 532 uint32_t uVal; 485 533 486 pHlp->pfnPrintf(pHlp, "I/O APIC at %08x:\n", 0xfec00000); 487 uVal = pThis->id << 24; /* Would be nice to call ioapic_mem_readl() directly, but that's not so simple. */ 488 pHlp->pfnPrintf(pHlp, " IOAPICID : %08x\n", uVal); 489 pHlp->pfnPrintf(pHlp, " APIC ID = %02x\n", (uVal >> 24) & 0xff); 490 uVal = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); 491 unsigned max_redir = RT_BYTE3(uVal); 492 pHlp->pfnPrintf(pHlp, " IOAPICVER : %08x\n", uVal); 493 pHlp->pfnPrintf(pHlp, " version = %02x\n", uVal & 0xff); 494 pHlp->pfnPrintf(pHlp, " redirs = %d\n", RT_BYTE3(uVal) + 1); 495 uVal = 0; 496 pHlp->pfnPrintf(pHlp, " IOAPICARB : %08x\n", uVal); 497 pHlp->pfnPrintf(pHlp, " arb ID = %02x\n", RT_BYTE4(uVal) & 0xff); 498 Assert(sizeof(pThis->ioredtbl) / sizeof(pThis->ioredtbl[0]) > max_redir); 534 pHlp->pfnPrintf(pHlp, "I/O APIC at %#010x:\n", 0xfec00000); 535 536 ioapic_IoApicId_r(pThis, &uVal); 537 pHlp->pfnPrintf(pHlp, " IOAPICID : %#010x\n", uVal); 538 pHlp->pfnPrintf(pHlp, " APIC ID = %#04x\n", (uVal >> 24) & 0xff); 539 540 ioapic_IoApicVer_r(pThis, &uVal); 541 unsigned iLastRedir = RT_BYTE3(uVal); 542 pHlp->pfnPrintf(pHlp, " IOAPICVER : %#010x\n", uVal); 543 pHlp->pfnPrintf(pHlp, " version = %#04x\n", uVal & 0xff); 544 pHlp->pfnPrintf(pHlp, " redirs = %u\n", iLastRedir + 1); 545 546 ioapic_IoApicArb_r(pThis, &uVal); 547 pHlp->pfnPrintf(pHlp, " IOAPICARB : %#0108x\n", uVal); 548 pHlp->pfnPrintf(pHlp, " arb ID = %#04x\n", RT_BYTE4(uVal)); 549 550 Assert(sizeof(pThis->ioredtbl) / sizeof(pThis->ioredtbl[0]) > iLastRedir); 499 551 pHlp->pfnPrintf(pHlp, "I/O redirection table\n"); 500 552 pHlp->pfnPrintf(pHlp, " idx dst_mode dst_addr mask trigger rirr polarity dlvr_st dlvr_mode vector\n"); 501 for (unsigned i = 0; i <= max_redir; ++i)553 for (unsigned i = 0; i <= iLastRedir; ++i) 502 554 { 503 555 static const char * const s_apszDModes[] = … … 508 560 pHlp->pfnPrintf(pHlp, " %02d %s %02x %d %s %d %s %s %s %3d (%016llx)\n", 509 561 i, 510 pThis->ioredtbl[i] & (1 << 11) ? "log " : "phys",/* dest mode */562 pThis->ioredtbl[i] & RT_BIT(11) ? "log " : "phys", /* dest mode */ 511 563 (int)(pThis->ioredtbl[i] >> 56), /* dest addr */ 512 564 (int)(pThis->ioredtbl[i] >> 16) & 1, /* mask */ 513 pThis->ioredtbl[i] & (1 << 15) ? "level" : "edge ",/* trigger */565 pThis->ioredtbl[i] & RT_BIT(15) ? "level" : "edge ", /* trigger */ 514 566 (int)(pThis->ioredtbl[i] >> 14) & 1, /* remote IRR */ 515 pThis->ioredtbl[i] & (1 << 13) ? "activelo" : "activehi",/* polarity */516 pThis->ioredtbl[i] & (1 << 12) ? "pend" : "idle",/* delivery status */567 pThis->ioredtbl[i] & RT_BIT(13) ? "activelo" : "activehi", /* polarity */ 568 pThis->ioredtbl[i] & RT_BIT(12) ? "pend" : "idle", /* delivery status */ 517 569 s_apszDModes[(pThis->ioredtbl[i] >> 8) & 0x07], /* delivery mode */ 518 570 (int)pThis->ioredtbl[i] & 0xff, /* vector */
Note:
See TracChangeset
for help on using the changeset viewer.