Be more verbose when changing APIC ID on an IO APIC.
Don't allow cpu entries in the MP table to contain APIC IDs out of range. Don't write outside array boundaries if an IO APIC entry in the MP table contains an APIC ID out of range. Assign APIC IDs for all IO APICs according to section 3.6.6 in the Intel MP spec: - If the current APIC ID on an IO APIC doesn't conflict with other IO APICs or CPUs, that APIC ID should be used. The copy of the MP table must be updated if the corresponding APIC ID in the MP table is different. - If the current APIC ID was in conflict with other units, the corresponding APIC ID specified in the MP table is checked for conflict. - If a conflict is still found then fall back to using a new unique ID. The copy of the MP table must be updated. - IDs out of range is considered to be in conflict. During these operations, the IO_TO_ID array cannot be used, since any conflict would have caused information loss. The array is then corrected, since all APIC ID conflicts should have been resolved. PR: 20312, 18919
This commit is contained in:
parent
54af9cb58f
commit
e666f57c3e
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -166,6 +166,7 @@ int apic_ipi __P((int, int, int));
|
||||
int selected_apic_ipi __P((u_int, int, int));
|
||||
int io_apic_setup __P((int));
|
||||
void io_apic_set_id __P((int, int));
|
||||
int io_apic_get_id __P((int));
|
||||
int ext_int_setup __P((int, int));
|
||||
|
||||
#if defined(READY)
|
||||
|
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -150,6 +150,9 @@ io_apic_set_id(int apic, int id)
|
||||
|
||||
ux = io_apic_read(apic, IOAPIC_ID); /* get current contents */
|
||||
if (((ux & APIC_ID_MASK) >> 24) != id) {
|
||||
printf("Changing APIC ID for IO APIC #%d"
|
||||
" from %d to %d on chip\n",
|
||||
apic, ((ux & APIC_ID_MASK) >> 24), id);
|
||||
ux &= ~APIC_ID_MASK; /* clear the ID field */
|
||||
ux |= (id << 24);
|
||||
io_apic_write(apic, IOAPIC_ID, ux); /* write new value */
|
||||
@ -161,6 +164,14 @@ io_apic_set_id(int apic, int id)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
io_apic_get_id(int apic)
|
||||
{
|
||||
return (io_apic_read(apic, IOAPIC_ID) & APIC_ID_MASK) >> 24;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Setup the IO APIC.
|
||||
*/
|
||||
|
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -166,6 +166,7 @@ int apic_ipi __P((int, int, int));
|
||||
int selected_apic_ipi __P((u_int, int, int));
|
||||
int io_apic_setup __P((int));
|
||||
void io_apic_set_id __P((int, int));
|
||||
int io_apic_get_id __P((int));
|
||||
int ext_int_setup __P((int, int));
|
||||
|
||||
#if defined(READY)
|
||||
|
@ -1013,6 +1013,105 @@ revoke_apic_irq(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
swap_apic_id(int apic, int oldid, int newid)
|
||||
{
|
||||
int x;
|
||||
int oapic;
|
||||
|
||||
|
||||
if (oldid == newid)
|
||||
return; /* Nothing to do */
|
||||
|
||||
printf("Changing APIC ID for IO APIC #%d from %d to %d in MP table\n",
|
||||
apic, oldid, newid);
|
||||
|
||||
/* Swap physical APIC IDs in interrupt entries */
|
||||
for (x = 0; x < nintrs; x++) {
|
||||
if (io_apic_ints[x].dst_apic_id == oldid)
|
||||
io_apic_ints[x].dst_apic_id = newid;
|
||||
else if (io_apic_ints[x].dst_apic_id == newid)
|
||||
io_apic_ints[x].dst_apic_id = oldid;
|
||||
}
|
||||
|
||||
/* Swap physical APIC IDs in IO_TO_ID mappings */
|
||||
for (oapic = 0; oapic < mp_napics; oapic++)
|
||||
if (IO_TO_ID(oapic) == newid)
|
||||
break;
|
||||
|
||||
if (oapic < mp_napics) {
|
||||
printf("Changing APIC ID for IO APIC #%d from "
|
||||
"%d to %d in MP table\n",
|
||||
oapic, newid, oldid);
|
||||
IO_TO_ID(oapic) = oldid;
|
||||
}
|
||||
IO_TO_ID(apic) = newid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_id_to_io_mapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < NAPICID; x++)
|
||||
ID_TO_IO(x) = -1;
|
||||
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(CPU_TO_ID(x)) = x;
|
||||
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) < NAPICID)
|
||||
ID_TO_IO(IO_TO_ID(x)) = x;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
first_free_apic_id(void)
|
||||
{
|
||||
int freeid, x;
|
||||
|
||||
for (freeid = 0; freeid < NAPICID; freeid++) {
|
||||
for (x = 0; x <= mp_naps; x++)
|
||||
if (CPU_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x <= mp_naps)
|
||||
continue;
|
||||
for (x = 0; x < mp_napics; x++)
|
||||
if (IO_TO_ID(x) == freeid)
|
||||
break;
|
||||
if (x < mp_napics)
|
||||
continue;
|
||||
return freeid;
|
||||
}
|
||||
return freeid;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
io_apic_id_acceptable(int apic, int id)
|
||||
{
|
||||
int cpu; /* Logical CPU number */
|
||||
int oapic; /* Logical IO APIC number for other IO APIC */
|
||||
|
||||
if (id >= NAPICID)
|
||||
return 0; /* Out of range */
|
||||
|
||||
for (cpu = 0; cpu <= mp_naps; cpu++)
|
||||
if (CPU_TO_ID(cpu) == id)
|
||||
return 0; /* Conflict with CPU */
|
||||
|
||||
for (oapic = 0; oapic < mp_napics && oapic < apic; oapic++)
|
||||
if (IO_TO_ID(oapic) == id)
|
||||
return 0; /* Conflict with other APIC */
|
||||
|
||||
return 1; /* ID is acceptable for IO APIC */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse an Intel MP specification table
|
||||
*/
|
||||
@ -1024,6 +1123,9 @@ fix_mp_table(void)
|
||||
int bus_0 = 0; /* Stop GCC warning */
|
||||
int bus_pci = 0; /* Stop GCC warning */
|
||||
int num_pci_bus;
|
||||
int apic; /* IO APIC unit number */
|
||||
int freeid; /* Free physical APIC ID */
|
||||
int physid; /* Current physical IO APIC ID */
|
||||
|
||||
/*
|
||||
* Fix mis-numbering of the PCI bus and its INT entries if the BIOS
|
||||
@ -1076,6 +1178,42 @@ fix_mp_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign IO APIC IDs.
|
||||
*
|
||||
* First try the existing ID. If a conflict is detected, try
|
||||
* the ID in the MP table. If a conflict is still detected, find
|
||||
* a free id.
|
||||
*
|
||||
* We cannot use the ID_TO_IO table before all conflicts has been
|
||||
* resolved and the table has been corrected.
|
||||
*/
|
||||
for (apic = 0; apic < mp_napics; ++apic) { /* For all IO APICs */
|
||||
|
||||
/* First try to use the value set by the BIOS */
|
||||
physid = io_apic_get_id(apic);
|
||||
if (io_apic_id_acceptable(apic, physid)) {
|
||||
if (IO_TO_ID(apic) != physid)
|
||||
swap_apic_id(apic, IO_TO_ID(apic), physid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if the value in the MP table is acceptable */
|
||||
if (io_apic_id_acceptable(apic, IO_TO_ID(apic)))
|
||||
continue;
|
||||
|
||||
/* Last resort, find a free APIC ID and use it */
|
||||
freeid = first_free_apic_id();
|
||||
if (freeid >= NAPICID)
|
||||
panic("No free physical APIC IDs found");
|
||||
|
||||
if (io_apic_id_acceptable(apic, freeid)) {
|
||||
swap_apic_id(apic, IO_TO_ID(apic), freeid);
|
||||
continue;
|
||||
}
|
||||
panic("Free physical APIC ID not usable");
|
||||
}
|
||||
fix_id_to_io_mapping();
|
||||
}
|
||||
|
||||
|
||||
@ -1159,6 +1297,8 @@ processor_entry(proc_entry_ptr entry, int cpu)
|
||||
if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
|
||||
return 0;
|
||||
|
||||
if(entry->apic_id >= NAPICID)
|
||||
panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
|
||||
/* check for BSP flag */
|
||||
if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
|
||||
boot_cpu_id = entry->apic_id;
|
||||
@ -1209,7 +1349,8 @@ io_apic_entry(io_apic_entry_ptr entry, int apic)
|
||||
return 0;
|
||||
|
||||
IO_TO_ID(apic) = entry->apic_id;
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
if (entry->apic_id < NAPICID)
|
||||
ID_TO_IO(entry->apic_id) = apic;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1602,7 +1743,6 @@ default_mp_table(int type)
|
||||
{
|
||||
int ap_cpu_id;
|
||||
#if defined(APIC_IO)
|
||||
u_int32_t ux;
|
||||
int io_apic_id;
|
||||
int pin;
|
||||
#endif /* APIC_IO */
|
||||
|
@ -166,6 +166,7 @@ int apic_ipi __P((int, int, int));
|
||||
int selected_apic_ipi __P((u_int, int, int));
|
||||
int io_apic_setup __P((int));
|
||||
void io_apic_set_id __P((int, int));
|
||||
int io_apic_get_id __P((int));
|
||||
int ext_int_setup __P((int, int));
|
||||
|
||||
#if defined(READY)
|
||||
|
Loading…
Reference in New Issue
Block a user