For the AMD SB700 projects, the SB ioapic id is being assigned the same value as one of the processor core local apic ids. Apparently this is not such a serious problem as I had once thought. On the other hand, AMD recommends using a unique value for each apic id.
Assigning a unique id to the SB ioapic is not as simple as choosing the next biggest available value, because the ioapic is traditionally a 4-bit value. Though the south bridge has an option for an 8-bit ioapic id, using such a value might confuse older operating systems. Choosing the next available id value for the ioapic works when the number of processor cores is small, and that is what the AMD BKDG recommends. If this would result in an ioapic id that exceeds 4 bits, the recommendation is to lift the processor local apic id numbering so that ioapics can be assigned values starting at zero. The patch below attempts to implement these recommendations. The case of lifting local apic ids has not been tested. In order to meet the 4-bit ioapic id limit without lifting the processor local apic id values, the patch reduces MAX_PHYSICAL_CPUS from 2 to 1, which is consistent with the currently supported boards and processors. The patch is for asus/m4a785-m, but can be adapted for other supported sb700 desktop projects. Tested by booting amd/m4a785-m/seabios to win7 on simnow. The initial and final ioapic id, as well as the value in the acpi apic table, are 8.
Signed-off-by: Scott Duplichan scott@notabs.org
Index: src/southbridge/amd/sb700/sb700_sm.c =================================================================== --- src/southbridge/amd/sb700/sb700_sm.c (revision 5814) +++ src/southbridge/amd/sb700/sb700_sm.c (working copy) @@ -57,12 +57,20 @@ printk(BIOS_INFO, "sm_init().\n");
ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0); /* some like mem resource, but does not have enable bit */ - /* Don't rename APIC ID */ - /* TODO: We should call setup_ioapic() here. But kernel hangs if cpu is K8. - * We need to check out why and change back. */ + clear_ioapic(ioapic_base); + /* I/O APIC IDs are normally limited to 4-bits. Enforce this limit. */ + #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16) + /* Assign the ioapic ID the next available number after the processor core local APIC IDs */ + setup_ioapic(ioapic_base, CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS); + #elif (CONFIG_APIC_ID_OFFSET > 0) + /* Assign the ioapic ID the value 0. Processor APIC IDs follow. */ + setup_ioapic(ioapic_base, 0); + #else + #error "The processor APIC IDs must be lifted to make room for the I/O APIC ID" + #endif
- /* 2.10 Interrupt Routing/Filtering */ + /* 2.10 Interrupt Routing/Filtering */ dword = pci_read_config8(dev, 0x62); dword |= 3; pci_write_config8(dev, 0x62, dword); Index: src/mainboard/asus/m4a785-m/Kconfig =================================================================== --- src/mainboard/asus/m4a785-m/Kconfig (revision 5814) +++ src/mainboard/asus/m4a785-m/Kconfig (working copy) @@ -49,7 +49,7 @@
config MAX_PHYSICAL_CPUS int - default 2 + default 1
config HW_MEM_HOLE_SIZE_AUTO_INC bool Index: src/mainboard/asus/m4a785-m/acpi_tables.c =================================================================== --- src/mainboard/asus/m4a785-m/acpi_tables.c (revision 5814) +++ src/mainboard/asus/m4a785-m/acpi_tables.c (working copy) @@ -70,7 +70,13 @@ current = acpi_create_madt_lapics(current);
/* Write SB700 IOAPIC, only one */ - current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, 2, + #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16) + #define IO_APIC_ID (CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS) + #else + #define IO_APIC_ID 0 + #endif + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + IO_APIC_ID, IO_APIC_ADDR, 0);
current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)