Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -162,7 +162,8 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);

#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 reinit_intr_remapped_IO_APIC(int);
#endif
+6 −5
Original line number Diff line number Diff line
@@ -1334,15 +1334,16 @@ void __init enable_IR_x2apic(void)
		return;
	}

	local_irq_save(flags);
	mask_8259A();

	ret = save_mask_IO_APIC_setup();
	ret = save_IO_APIC_setup();
	if (ret) {
		pr_info("Saving IO-APIC state failed: %d\n", ret);
		goto end;
	}

	local_irq_save(flags);
	mask_IO_APIC_setup();
	mask_8259A();

	ret = enable_intr_remapping(1);

	if (ret && x2apic_preenabled) {
@@ -1367,10 +1368,10 @@ void __init enable_IR_x2apic(void)
	else
		reinit_intr_remapped_IO_APIC(x2apic_preenabled);

end:
	unmask_8259A();
	local_irq_restore(flags);

end:
	if (!ret) {
		if (!x2apic_preenabled)
			pr_info("Enabled x2apic and interrupt-remapping\n");
+23 −11
Original line number Diff line number Diff line
@@ -853,9 +853,9 @@ __setup("pirq=", ioapic_pirq_setup);
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;
	unsigned long flags;
@@ -880,16 +880,9 @@ int save_mask_IO_APIC_setup(void)
	}

	for (apic = 0; apic < nr_ioapics; apic++)
		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
			struct IO_APIC_route_entry entry;

			entry = early_ioapic_entries[apic][pin] =
		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
			early_ioapic_entries[apic][pin] =
				ioapic_read_entry(apic, pin);
			if (!entry.mask) {
				entry.mask = 1;
				ioapic_write_entry(apic, pin, entry);
			}
		}

	return 0;

@@ -902,6 +895,25 @@ int save_mask_IO_APIC_setup(void)
	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)
{
	int apic, pin;