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:
Tor Egge 2000-08-06 00:04:03 +00:00
parent 54af9cb58f
commit e666f57c3e
11 changed files with 1008 additions and 14 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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.
*/

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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)