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 Original line Diff line number Diff line
@@ -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
+6 −5
Original line number Original line Diff line number Diff line
@@ -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 @@ void __init enable_IR_x2apic(void)
	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");
+23 −11
Original line number Original line 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];
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)
	}
	}


	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 @@ int save_mask_IO_APIC_setup(void)
	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;