fix: boot failure on VirtualBox legacy-BIOS VMs (AC'97 probed as HDA)
VirtualBox default VMs expose an AC'97 audio controller (8086:2415, class 04/subclass 01) whose BAR0 is an I/O-space BAR. The IntelHDA driver matched any Intel multimedia subclass, and ReadBar0 masked the I/O BAR's port number into a bogus 'physical address' that MapMMIO panicked on (non-page-aligned), halting boot. Two fixes: - IntelHDA now matches only subclass 0x03 (HD Audio); AC'97 (0x01) is a different programming model and is not claimed. - ReadBar0 returns 0 (no usable MMIO BAR) for I/O-space BARs instead of handing a port number to MapMMIO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -149,13 +149,15 @@ namespace Drivers {
|
|||||||
ProbeNvme,
|
ProbeNvme,
|
||||||
},
|
},
|
||||||
// Order 7: Intel HDA — Normal phase, match vendor=0x8086 + class=0x04 (Multimedia)
|
// Order 7: Intel HDA — Normal phase, match vendor=0x8086 + class=0x04 (Multimedia)
|
||||||
// SubClass 0x01 = "Multimedia audio controller" (most Intel HDA)
|
// SubClass 0x03 = "Audio device" = HD Audio controller.
|
||||||
// SubClass 0x03 = "Audio device" (HDA-compatible)
|
// SubClass 0x01 = "Multimedia audio controller" = legacy AC'97
|
||||||
|
// (e.g. VirtualBox 8086:2415), which is NOT HDA and has an I/O
|
||||||
|
// BAR, not an MMIO BAR — do NOT match it here.
|
||||||
{
|
{
|
||||||
"IntelHDA",
|
"IntelHDA",
|
||||||
0x8086, // VendorId (Intel)
|
0x8086, // VendorId (Intel)
|
||||||
0x04, // ClassCode (Multimedia)
|
0x04, // ClassCode (Multimedia)
|
||||||
0xFF, // SubClass (any — covers both 0x01 and 0x03)
|
0x03, // SubClass (0x03 = HD Audio; excludes AC'97 0x01)
|
||||||
0xFF, // ProgIf (any)
|
0xFF, // ProgIf (any)
|
||||||
nullptr,
|
nullptr,
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -404,6 +404,14 @@ namespace Pci {
|
|||||||
|
|
||||||
uint64_t ReadBar0(uint8_t bus, uint8_t device, uint8_t function) {
|
uint64_t ReadBar0(uint8_t bus, uint8_t device, uint8_t function) {
|
||||||
uint32_t bar0Low = LegacyRead32(bus, device, function, (uint8_t)PCI_REG_BAR0);
|
uint32_t bar0Low = LegacyRead32(bus, device, function, (uint8_t)PCI_REG_BAR0);
|
||||||
|
|
||||||
|
// Bit 0 == 1 means this is an I/O-space BAR, not memory. The low bits of
|
||||||
|
// an I/O BAR are a port number, not a physical address, and must never be
|
||||||
|
// fed to MapMMIO (it would panic on the non-page-aligned value). Callers
|
||||||
|
// treat 0 as "no usable MMIO BAR". (e.g. VirtualBox AC'97 8086:2415.)
|
||||||
|
if (bar0Low & 0x1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
uint64_t addr = bar0Low & 0xFFFFFFF0u;
|
uint64_t addr = bar0Low & 0xFFFFFFF0u;
|
||||||
|
|
||||||
// Check for 64-bit BAR (type field bits 2:1 == 0b10)
|
// Check for 64-bit BAR (type field bits 2:1 == 0b10)
|
||||||
|
|||||||
Reference in New Issue
Block a user