aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2009-03-16 20:05:03 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2009-03-17 18:45:29 -0400
commit05c3dc2c4b60387769cbe73174347de4cf85f0c9 (patch)
tree7e5918518c5f22f6121ff885283bef5397a0a842 /arch
parent29b61be65a33c95564fa82e7e8d60d97adb68ea8 (diff)
x86, ioapic: Fix non atomic allocation with interrupts disabled
Impact: fix possible race save_mask_IO_APIC_setup() was using non atomic memory allocation while getting called with interrupts disabled. Fix this by splitting this into two different function. Allocation part save_IO_APIC_setup() now happens before disabling interrupts. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/io_apic.h3
-rw-r--r--arch/x86/kernel/apic/apic.c11
-rw-r--r--arch/x86/kernel/apic/io_apic.c34
3 files changed, 31 insertions, 17 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index ffcd08f96e47..373cc2bbcad2 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -162,7 +162,8 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
162extern void ioapic_init_mappings(void); 162extern void ioapic_init_mappings(void);
163 163
164#ifdef CONFIG_X86_64 164#ifdef CONFIG_X86_64
165extern int save_mask_IO_APIC_setup(void); 165extern int save_IO_APIC_setup(void);
166extern void mask_IO_APIC_setup(void);
166extern void restore_IO_APIC_setup(void); 167extern void restore_IO_APIC_setup(void);
167extern void reinit_intr_remapped_IO_APIC(int); 168extern void reinit_intr_remapped_IO_APIC(int);
168#endif 169#endif
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 699f8cf76bbb..85eb8e100818 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1334,15 +1334,16 @@ void __init enable_IR_x2apic(void)
1334 return; 1334 return;
1335 } 1335 }
1336 1336
1337 local_irq_save(flags); 1337 ret = save_IO_APIC_setup();
1338 mask_8259A();
1339
1340 ret = save_mask_IO_APIC_setup();
1341 if (ret) { 1338 if (ret) {
1342 pr_info("Saving IO-APIC state failed: %d\n", ret); 1339 pr_info("Saving IO-APIC state failed: %d\n", ret);
1343 goto end; 1340 goto end;
1344 } 1341 }
1345 1342
1343 local_irq_save(flags);
1344 mask_IO_APIC_setup();
1345 mask_8259A();
1346
1346 ret = enable_intr_remapping(1); 1347 ret = enable_intr_remapping(1);
1347 1348
1348 if (ret && x2apic_preenabled) { 1349 if (ret && x2apic_preenabled) {
@@ -1367,10 +1368,10 @@ end_restore:
1367 else 1368 else
1368 reinit_intr_remapped_IO_APIC(x2apic_preenabled); 1369 reinit_intr_remapped_IO_APIC(x2apic_preenabled);
1369 1370
1370end:
1371 unmask_8259A(); 1371 unmask_8259A();
1372 local_irq_restore(flags); 1372 local_irq_restore(flags);
1373 1373
1374end:
1374 if (!ret) { 1375 if (!ret) {
1375 if (!x2apic_preenabled) 1376 if (!x2apic_preenabled)
1376 pr_info("Enabled x2apic and interrupt-remapping\n"); 1377 pr_info("Enabled x2apic and interrupt-remapping\n");
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index cf27795c641c..ff1759a1128e 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -853,9 +853,9 @@ __setup("pirq=", ioapic_pirq_setup);
853static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS]; 853static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
854 854
855/* 855/*
856 * Saves and masks all the unmasked IO-APIC RTE's 856 * Saves all the IO-APIC RTE's
857 */ 857 */
858int save_mask_IO_APIC_setup(void) 858int save_IO_APIC_setup(void)
859{ 859{
860 union IO_APIC_reg_01 reg_01; 860 union IO_APIC_reg_01 reg_01;
861 unsigned long flags; 861 unsigned long flags;
@@ -880,16 +880,9 @@ int save_mask_IO_APIC_setup(void)
880 } 880 }
881 881
882 for (apic = 0; apic < nr_ioapics; apic++) 882 for (apic = 0; apic < nr_ioapics; apic++)
883 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { 883 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
884 struct IO_APIC_route_entry entry; 884 early_ioapic_entries[apic][pin] =
885
886 entry = early_ioapic_entries[apic][pin] =
887 ioapic_read_entry(apic, pin); 885 ioapic_read_entry(apic, pin);
888 if (!entry.mask) {
889 entry.mask = 1;
890 ioapic_write_entry(apic, pin, entry);
891 }
892 }
893 886
894 return 0; 887 return 0;
895 888
@@ -902,6 +895,25 @@ nomem:
902 return -ENOMEM; 895 return -ENOMEM;
903} 896}
904 897
898void mask_IO_APIC_setup(void)
899{
900 int apic, pin;
901
902 for (apic = 0; apic < nr_ioapics; apic++) {
903 if (!early_ioapic_entries[apic])
904 break;
905 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
906 struct IO_APIC_route_entry entry;
907
908 entry = early_ioapic_entries[apic][pin];
909 if (!entry.mask) {
910 entry.mask = 1;
911 ioapic_write_entry(apic, pin, entry);
912 }
913 }
914 }
915}
916
905void restore_IO_APIC_setup(void) 917void restore_IO_APIC_setup(void)
906{ 918{
907 int apic, pin; 919 int apic, pin;