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

Commit 08306ce6 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Ingo Molnar
Browse files

x86: apic - introduce dummy apic operations



Impact: refactor, speed up and robustize code

In case if apic was disabled by kernel option
or by hardware limits we can use dummy operations
in apic->write to simplify the ack_APIC_irq() code.

At the lame time the patch fixes the missed EOI in
do_IRQ function (which has place if kernel is compiled
as X86-32 and interrupt without handler happens where
apic was not asked to be disabled via kernel option).

Note that native_apic_write_dummy() consists of
WARN_ON_ONCE to catch any buggy writes on enabled
APICs. Could be removed after some time of testing.

Signed-off-by: default avatarCyrill Gorcunov <gorcunov@openvz.org>
LKML-Reference: <20090412165058.724788431@openvz.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent c0eaa453
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -212,6 +212,7 @@ static inline void ack_x2APIC_irq(void)
}
}
#endif
#endif


extern void apic_disable(void);
extern int lapic_get_maxlvt(void);
extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC(void);
extern void connect_bsp_APIC(void);
@@ -252,7 +253,7 @@ static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok		1
#define local_apic_timer_c2_ok		1
static inline void init_apic_mappings(void) { }
static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }
static inline void disable_local_APIC(void) { }

static inline void apic_disable(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */
#endif /* !CONFIG_X86_LOCAL_APIC */


#ifdef CONFIG_X86_64
#ifdef CONFIG_X86_64
+24 −0
Original line number Original line Diff line number Diff line
@@ -232,6 +232,24 @@ static int modern_apic(void)
	return lapic_get_version() >= 0x14;
	return lapic_get_version() >= 0x14;
}
}


/*
 * bare function to substitute write operation
 * and it's _that_ fast :)
 */
void native_apic_write_dummy(u32 reg, u32 v)
{
	WARN_ON_ONCE((cpu_has_apic || !disable_apic));
}

/*
 * right after this call apic->write doesn't do anything
 * note that there is no restore operation it works one way
 */
void apic_disable(void)
{
	apic->write = native_apic_write_dummy;
}

void native_apic_wait_icr_idle(void)
void native_apic_wait_icr_idle(void)
{
{
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
@@ -1582,6 +1600,12 @@ void __init init_apic_mappings(void)
	 */
	 */
	if (boot_cpu_physical_apicid == -1U)
	if (boot_cpu_physical_apicid == -1U)
		boot_cpu_physical_apicid = read_apic_id();
		boot_cpu_physical_apicid = read_apic_id();

	/* lets check if we may to NOP'ify apic operations */
	if (!cpu_has_apic) {
		pr_info("APIC: disable apic facility\n");
		apic_disable();
	}
}
}


/*
/*
+2 −8
Original line number Original line Diff line number Diff line
@@ -27,7 +27,6 @@ void ack_bad_irq(unsigned int irq)
	if (printk_ratelimit())
	if (printk_ratelimit())
		pr_err("unexpected IRQ trap at vector %02x\n", irq);
		pr_err("unexpected IRQ trap at vector %02x\n", irq);


#ifdef CONFIG_X86_LOCAL_APIC
	/*
	/*
	 * Currently unexpected vectors happen only on SMP and APIC.
	 * Currently unexpected vectors happen only on SMP and APIC.
	 * We _must_ ack these because every local APIC has only N
	 * We _must_ ack these because every local APIC has only N
@@ -37,9 +36,7 @@ void ack_bad_irq(unsigned int irq)
	 * completely.
	 * completely.
	 * But only ack when the APIC is enabled -AK
	 * But only ack when the APIC is enabled -AK
	 */
	 */
	if (cpu_has_apic)
	ack_APIC_irq();
	ack_APIC_irq();
#endif
}
}


#define irq_stats(x)		(&per_cpu(irq_stat, x))
#define irq_stats(x)		(&per_cpu(irq_stat, x))
@@ -214,10 +211,7 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
	irq = __get_cpu_var(vector_irq)[vector];
	irq = __get_cpu_var(vector_irq)[vector];


	if (!handle_irq(irq, regs)) {
	if (!handle_irq(irq, regs)) {
#ifdef CONFIG_X86_64
		if (!disable_apic)
		ack_APIC_irq();
		ack_APIC_irq();
#endif


		if (printk_ratelimit())
		if (printk_ratelimit())
			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",