x86/mpspec: order the I/O APICs by the APIC Id
Linux (4.16) assumes that the PIT interrupt is connected to the pin 0 of the IOAPIC[0] and panics otherwise. This might be a Linux bug. The MP Specification 1.4 does seem to mandate sequential ordering for bus entries, but not for the I/O APICs. Change-Id: Ibf823eb5b3a29e4590cba915069cdfe5f780edcd Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Reviewed-on: https://review.coreboot.org/25799 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
parent
9ba8f7c28e
commit
294446a137
|
@ -524,6 +524,22 @@ void *mptable_finalize(struct mp_config_table *mc)
|
||||||
return smp_next_mpe_entry(mc);
|
return smp_next_mpe_entry(mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct device *find_next_ioapic(unsigned int last_ioapic_id)
|
||||||
|
{
|
||||||
|
const struct device *dev;
|
||||||
|
const struct device *result = NULL;
|
||||||
|
unsigned int ioapic_id = MAX_APICS;
|
||||||
|
|
||||||
|
for (dev = all_devices; dev; dev = dev->next) {
|
||||||
|
if (dev->path.type == DEVICE_PATH_IOAPIC &&
|
||||||
|
dev->path.ioapic.ioapic_id > last_ioapic_id &&
|
||||||
|
dev->path.ioapic.ioapic_id <= ioapic_id) {
|
||||||
|
result = dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long __weak write_smp_table(unsigned long addr)
|
unsigned long __weak write_smp_table(unsigned long addr)
|
||||||
{
|
{
|
||||||
struct drivers_generic_ioapic_config *ioapic_config;
|
struct drivers_generic_ioapic_config *ioapic_config;
|
||||||
|
@ -535,6 +551,7 @@ unsigned long __weak write_smp_table(unsigned long addr)
|
||||||
void *tmp, *v;
|
void *tmp, *v;
|
||||||
int isaioapic = -1, have_fixed_entries;
|
int isaioapic = -1, have_fixed_entries;
|
||||||
const struct pci_irq_info *pci_irq_info;
|
const struct pci_irq_info *pci_irq_info;
|
||||||
|
unsigned int ioapic_id = 0;
|
||||||
|
|
||||||
v = smp_write_floating_table(addr, 0);
|
v = smp_write_floating_table(addr, 0);
|
||||||
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
|
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
|
||||||
|
@ -545,17 +562,17 @@ unsigned long __weak write_smp_table(unsigned long addr)
|
||||||
|
|
||||||
mptable_write_buses(mc, NULL, &isa_bus);
|
mptable_write_buses(mc, NULL, &isa_bus);
|
||||||
|
|
||||||
for (dev = all_devices; dev; dev = dev->next) {
|
while ((dev = find_next_ioapic(ioapic_id))) {
|
||||||
if (dev->path.type != DEVICE_PATH_IOAPIC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ioapic_config = dev->chip_info;
|
ioapic_config = dev->chip_info;
|
||||||
if (!ioapic_config) {
|
if (!ioapic_config) {
|
||||||
printk(BIOS_ERR, "%s has no config, ignoring\n",
|
printk(BIOS_ERR, "%s has no config, ignoring\n",
|
||||||
dev_path(dev));
|
dev_path(dev));
|
||||||
|
ioapic_id++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
smp_write_ioapic(mc, dev->path.ioapic.ioapic_id,
|
|
||||||
|
ioapic_id = dev->path.ioapic.ioapic_id;
|
||||||
|
smp_write_ioapic(mc, ioapic_id,
|
||||||
ioapic_config->version,
|
ioapic_config->version,
|
||||||
ioapic_config->base);
|
ioapic_config->base);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue