Commit 05c3dc2c authored by Suresh Siddha's avatar Suresh Siddha Committed by H. Peter Anvin

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: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 29b61be6
...@@ -162,7 +162,8 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq); ...@@ -162,7 +162,8 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void); extern void ioapic_init_mappings(void);
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
extern int save_mask_IO_APIC_setup(void); extern int save_IO_APIC_setup(void);
extern void mask_IO_APIC_setup(void);
extern void restore_IO_APIC_setup(void); extern void restore_IO_APIC_setup(void);
extern void reinit_intr_remapped_IO_APIC(int); extern void reinit_intr_remapped_IO_APIC(int);
#endif #endif
......
...@@ -1334,15 +1334,16 @@ void __init enable_IR_x2apic(void) ...@@ -1334,15 +1334,16 @@ void __init enable_IR_x2apic(void)
return; return;
} }
local_irq_save(flags); ret = save_IO_APIC_setup();
mask_8259A();
ret = save_mask_IO_APIC_setup();
if (ret) { if (ret) {
pr_info("Saving IO-APIC state failed: %d\n", ret); pr_info("Saving IO-APIC state failed: %d\n", ret);
goto end; goto end;
} }
local_irq_save(flags);
mask_IO_APIC_setup();
mask_8259A();
ret = enable_intr_remapping(1); ret = enable_intr_remapping(1);
if (ret && x2apic_preenabled) { if (ret && x2apic_preenabled) {
...@@ -1367,10 +1368,10 @@ end_restore: ...@@ -1367,10 +1368,10 @@ end_restore:
else else
reinit_intr_remapped_IO_APIC(x2apic_preenabled); reinit_intr_remapped_IO_APIC(x2apic_preenabled);
end:
unmask_8259A(); unmask_8259A();
local_irq_restore(flags); local_irq_restore(flags);
end:
if (!ret) { if (!ret) {
if (!x2apic_preenabled) if (!x2apic_preenabled)
pr_info("Enabled x2apic and interrupt-remapping\n"); pr_info("Enabled x2apic and interrupt-remapping\n");
......
...@@ -853,9 +853,9 @@ __setup("pirq=", ioapic_pirq_setup); ...@@ -853,9 +853,9 @@ __setup("pirq=", ioapic_pirq_setup);
static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS]; static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
/* /*
* Saves and masks all the unmasked IO-APIC RTE's * Saves all the IO-APIC RTE's
*/ */
int save_mask_IO_APIC_setup(void) int save_IO_APIC_setup(void)
{ {
union IO_APIC_reg_01 reg_01; union IO_APIC_reg_01 reg_01;
unsigned long flags; unsigned long flags;
...@@ -880,16 +880,9 @@ int save_mask_IO_APIC_setup(void) ...@@ -880,16 +880,9 @@ int save_mask_IO_APIC_setup(void)
} }
for (apic = 0; apic < nr_ioapics; apic++) for (apic = 0; apic < nr_ioapics; apic++)
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
struct IO_APIC_route_entry entry; early_ioapic_entries[apic][pin] =
entry = early_ioapic_entries[apic][pin] =
ioapic_read_entry(apic, pin); ioapic_read_entry(apic, pin);
if (!entry.mask) {
entry.mask = 1;
ioapic_write_entry(apic, pin, entry);
}
}
return 0; return 0;
...@@ -902,6 +895,25 @@ nomem: ...@@ -902,6 +895,25 @@ nomem:
return -ENOMEM; return -ENOMEM;
} }
void mask_IO_APIC_setup(void)
{
int apic, pin;
for (apic = 0; apic < nr_ioapics; apic++) {
if (!early_ioapic_entries[apic])
break;
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
entry = early_ioapic_entries[apic][pin];
if (!entry.mask) {
entry.mask = 1;
ioapic_write_entry(apic, pin, entry);
}
}
}
}
void restore_IO_APIC_setup(void) void restore_IO_APIC_setup(void)
{ {
int apic, pin; int apic, pin;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment