Re: [PATCH] x86_64 io_apic.c: Memorize at bootup where the i8259 is connected

From: yhlu
Date: Fri Jul 29 2005 - 15:54:02 EST


Is that for Nvidia CK804 stuff?

Actually in LinuxBIOS I swap the irq 0 and 2 entries in mptable to
solve the problem. and it could work well with current code.

YH

On 7/29/05, Eric W. Biederman <ebiederm@xxxxxxxxxxxx> wrote:
>
> Currently we attempt to restore virtual wire mode on reboot, which
> only works if we can figure out where the i8259 is connected. This
> is very useful when we kexec another kernel and likely helpful
> when dealing with a BIOS that make assumptions about how the system is setup.
>
> Since the acpi MADT table does not provide the location where the i8259
> is connected we have to look at the hardware to figure it out.
>
> Most systems have the i8259 connected to the local apic of the cpu so
> won't be affected but people running on Opteron and some serverworks chipsets
> should be able to use kexec now.
>
> Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx>
> ---
>
> arch/x86_64/kernel/io_apic.c | 52 ++++++++++++++++++++++++++++++++++++++----
> 1 files changed, 47 insertions(+), 5 deletions(-)
>
> 96c59dd871b00735ef159ddf0d68f338958387fc
> diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
> --- a/arch/x86_64/kernel/io_apic.c
> +++ b/arch/x86_64/kernel/io_apic.c
> @@ -45,6 +45,9 @@ int sis_apic_bug; /* not actually suppor
>
> static int no_timer_check;
>
> +/* Where if anywhere is the i8259 connect in external int mode */
> +static int ioapic_i8259_pin = -1;
> +
> static DEFINE_SPINLOCK(ioapic_lock);
>
> /*
> @@ -330,7 +333,7 @@ static int find_irq_entry(int apic, int
> /*
> * Find the pin to which IRQ[irq] (ISA) is connected
> */
> -static int find_isa_irq_pin(int irq, int type)
> +static int __init find_isa_irq_pin(int irq, int type)
> {
> int i;
>
> @@ -1096,6 +1099,44 @@ void __apicdebuginit print_PIC(void)
>
> #endif /* 0 */
>
> +static void __init find_i8259_pin(void)
> +{
> + struct IO_APIC_route_entry entry;
> + unsigned long flags;
> + int pin, pins;
> +
> + ioapic_i8259_pin = -1;
> +
> + /* Find the number of pins on the primary ioapic */
> + spin_lock_irqsave(&ioapic_lock, flags);
> + pins = ((io_apic_read(0, 0x01) >> 16) & 0xff) + 1;
> + spin_unlock_irqrestore(&ioapic_lock, flags);
> +
> + /* See if any of the pins is in ExtINT mode */
> + for(pin = 0; pin < pins; pin++) {
> + spin_lock_irqsave(&ioapic_lock, flags);
> + *(((int *)&entry) + 0) = io_apic_read(0, 0x10 + 2 * pin);
> + *(((int *)&entry) + 1) = io_apic_read(0, 0x11 + 2 * pin);
> + spin_unlock_irqrestore(&ioapic_lock, flags);
> +
> + /* If the interrupt line is enabled and in ExtInt mode
> + * I have found the pin where the i8259 is connected.
> + */
> + if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
> + ioapic_i8259_pin = pin;
> + break;
> + }
> + }
> +
> + /* If we could not find an appropriate pin by looking at the ioapic
> + * the i8259 probably isn't connected to the ioapic but give
> + * the mptable a chance anyway.
> + */
> + if (ioapic_i8259_pin == -1) {
> + ioapic_i8259_pin = find_isa_irq_pin(0, mp_ExtINT);
> + }
> +}
> +
> static void __init enable_IO_APIC(void)
> {
> union IO_APIC_reg_01 reg_01;
> @@ -1138,11 +1179,11 @@ void disable_IO_APIC(void)
> clear_IO_APIC();
>
> /*
> - * If the i82559 is routed through an IOAPIC
> + * If the i8259 is routed through an IOAPIC
> * Put that IOAPIC in virtual wire mode
> * so legacy interrups can be delivered.
> */
> - pin = find_isa_irq_pin(0, mp_ExtINT);
> + pin = ioapic_i8259_pin;
> if (pin != -1) {
> struct IO_APIC_route_entry entry;
> unsigned long flags;
> @@ -1154,7 +1195,7 @@ void disable_IO_APIC(void)
> entry.polarity = 0; /* High */
> entry.delivery_status = 0;
> entry.dest_mode = 0; /* Physical */
> - entry.delivery_mode = 7; /* ExtInt */
> + entry.delivery_mode = dest_ExtINT; /* ExtInt */
> entry.vector = 0;
> entry.dest.physical.physical_dest = 0;
>
> @@ -1626,7 +1667,7 @@ static inline void check_timer(void)
> enable_8259A_irq(0);
>
> pin1 = find_isa_irq_pin(0, mp_INT);
> - pin2 = find_isa_irq_pin(0, mp_ExtINT);
> + pin2 = ioapic_i8259_pin;
>
> apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
>
> @@ -1723,6 +1764,7 @@ __setup("no_timer_check", notimercheck);
>
> void __init setup_IO_APIC(void)
> {
> + find_i8259_pin();
> enable_IO_APIC();
>
> if (acpi_ioapic)
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/