aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Romer <benjamin.romer@unisys.com>2007-02-13 07:26:25 -0500
committerAndi Kleen <andi@basil.nowhere.org>2007-02-13 07:26:25 -0500
commitee4eff6ff6cbfc8ce38131058a18802bf6206879 (patch)
tree7cb9e7f7072fee788284c099f6f3f229bfefc20a
parenta4af60aa64c828b7c047e7a67b2f896d4bfbd700 (diff)
[PATCH] x86-64: update IO-APIC dest field to 8-bit for xAPIC
On the Unisys ES7000/ONE system, we encountered a problem where performing a kexec reboot or dump on any cell other than cell 0 causes the system timer to stop working, resulting in a hang during timer calibration in the new kernel. We traced the problem to one line of code in disable_IO_APIC(), which needs to restore the timer's IO-APIC configuration before rebooting. The code is currently using the 4-bit physical destination field, rather than using the 8-bit logical destination field, and it cuts off the upper 4 bits of the timer's APIC ID. If we change this to use the logical destination field, the timer works and we can kexec on the upper cells. This was tested on two different cells (0 and 2) in an ES7000/ONE system. For reference, the relevant Intel xAPIC spec is kept at ftp://download.intel.com/design/chipsets/e8501/datashts/30962001.pdf, specifically on page 334. Signed-off-by: Benjamin M Romer <benjamin.romer@unisys.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@suse.de> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Vivek Goyal <vgoyal@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r--arch/x86_64/kernel/io_apic.c24
-rw-r--r--include/asm-x86_64/io_apic.h14
2 files changed, 13 insertions, 25 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 6be6730acb5c..566e64d966c4 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -831,7 +831,7 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
831 entry.delivery_mode = INT_DELIVERY_MODE; 831 entry.delivery_mode = INT_DELIVERY_MODE;
832 entry.dest_mode = INT_DEST_MODE; 832 entry.dest_mode = INT_DEST_MODE;
833 entry.mask = 0; /* enable IRQ */ 833 entry.mask = 0; /* enable IRQ */
834 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); 834 entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
835 835
836 entry.trigger = irq_trigger(idx); 836 entry.trigger = irq_trigger(idx);
837 entry.polarity = irq_polarity(idx); 837 entry.polarity = irq_polarity(idx);
@@ -839,7 +839,7 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
839 if (irq_trigger(idx)) { 839 if (irq_trigger(idx)) {
840 entry.trigger = 1; 840 entry.trigger = 1;
841 entry.mask = 1; 841 entry.mask = 1;
842 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); 842 entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
843 } 843 }
844 844
845 if (!apic && !IO_APIC_IRQ(irq)) 845 if (!apic && !IO_APIC_IRQ(irq))
@@ -851,7 +851,7 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
851 if (vector < 0) 851 if (vector < 0)
852 return; 852 return;
853 853
854 entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask); 854 entry.dest = cpu_mask_to_apicid(mask);
855 entry.vector = vector; 855 entry.vector = vector;
856 856
857 ioapic_register_intr(irq, vector, IOAPIC_AUTO); 857 ioapic_register_intr(irq, vector, IOAPIC_AUTO);
@@ -920,7 +920,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
920 */ 920 */
921 entry.dest_mode = INT_DEST_MODE; 921 entry.dest_mode = INT_DEST_MODE;
922 entry.mask = 0; /* unmask IRQ now */ 922 entry.mask = 0; /* unmask IRQ now */
923 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); 923 entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
924 entry.delivery_mode = INT_DELIVERY_MODE; 924 entry.delivery_mode = INT_DELIVERY_MODE;
925 entry.polarity = 0; 925 entry.polarity = 0;
926 entry.trigger = 0; 926 entry.trigger = 0;
@@ -1020,18 +1020,17 @@ void __apicdebuginit print_IO_APIC(void)
1020 1020
1021 printk(KERN_DEBUG ".... IRQ redirection table:\n"); 1021 printk(KERN_DEBUG ".... IRQ redirection table:\n");
1022 1022
1023 printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol" 1023 printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
1024 " Stat Dest Deli Vect: \n"); 1024 " Stat Dmod Deli Vect: \n");
1025 1025
1026 for (i = 0; i <= reg_01.bits.entries; i++) { 1026 for (i = 0; i <= reg_01.bits.entries; i++) {
1027 struct IO_APIC_route_entry entry; 1027 struct IO_APIC_route_entry entry;
1028 1028
1029 entry = ioapic_read_entry(apic, i); 1029 entry = ioapic_read_entry(apic, i);
1030 1030
1031 printk(KERN_DEBUG " %02x %03X %02X ", 1031 printk(KERN_DEBUG " %02x %03X ",
1032 i, 1032 i,
1033 entry.dest.logical.logical_dest, 1033 entry.dest
1034 entry.dest.physical.physical_dest
1035 ); 1034 );
1036 1035
1037 printk("%1d %1d %1d %1d %1d %1d %1d %02X\n", 1036 printk("%1d %1d %1d %1d %1d %1d %1d %02X\n",
@@ -1293,8 +1292,7 @@ void disable_IO_APIC(void)
1293 entry.dest_mode = 0; /* Physical */ 1292 entry.dest_mode = 0; /* Physical */
1294 entry.delivery_mode = dest_ExtINT; /* ExtInt */ 1293 entry.delivery_mode = dest_ExtINT; /* ExtInt */
1295 entry.vector = 0; 1294 entry.vector = 0;
1296 entry.dest.physical.physical_dest = 1295 entry.dest = GET_APIC_ID(apic_read(APIC_ID));
1297 GET_APIC_ID(apic_read(APIC_ID));
1298 1296
1299 /* 1297 /*
1300 * Add it to the IO-APIC irq-routing table: 1298 * Add it to the IO-APIC irq-routing table:
@@ -1556,7 +1554,7 @@ static inline void unlock_ExtINT_logic(void)
1556 1554
1557 entry1.dest_mode = 0; /* physical delivery */ 1555 entry1.dest_mode = 0; /* physical delivery */
1558 entry1.mask = 0; /* unmask IRQ now */ 1556 entry1.mask = 0; /* unmask IRQ now */
1559 entry1.dest.physical.physical_dest = hard_smp_processor_id(); 1557 entry1.dest = hard_smp_processor_id();
1560 entry1.delivery_mode = dest_ExtINT; 1558 entry1.delivery_mode = dest_ExtINT;
1561 entry1.polarity = entry0.polarity; 1559 entry1.polarity = entry0.polarity;
1562 entry1.trigger = 0; 1560 entry1.trigger = 0;
@@ -2131,7 +2129,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
2131 2129
2132 entry.delivery_mode = INT_DELIVERY_MODE; 2130 entry.delivery_mode = INT_DELIVERY_MODE;
2133 entry.dest_mode = INT_DEST_MODE; 2131 entry.dest_mode = INT_DEST_MODE;
2134 entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask); 2132 entry.dest = cpu_mask_to_apicid(mask);
2135 entry.trigger = triggering; 2133 entry.trigger = triggering;
2136 entry.polarity = polarity; 2134 entry.polarity = polarity;
2137 entry.mask = 1; /* Disabled (masked) */ 2135 entry.mask = 1; /* Disabled (masked) */
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index 561ecbfd4cb5..f4fb238c89f1 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -85,18 +85,8 @@ struct IO_APIC_route_entry {
85 mask : 1, /* 0: enabled, 1: disabled */ 85 mask : 1, /* 0: enabled, 1: disabled */
86 __reserved_2 : 15; 86 __reserved_2 : 15;
87 87
88 union { struct { __u32 88 __u32 __reserved_3 : 24,
89 __reserved_1 : 24, 89 dest : 8;
90 physical_dest : 4,
91 __reserved_2 : 4;
92 } physical;
93
94 struct { __u32
95 __reserved_1 : 24,
96 logical_dest : 8;
97 } logical;
98 } dest;
99
100} __attribute__ ((packed)); 90} __attribute__ ((packed));
101 91
102/* 92/*