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: Cyrill Gorcunov <gorcunov@openvz.org> LKML-Reference: <20090412165058.724788431@openvz.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Родитель
c0eaa4536f
Коммит
08306ce61d
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
ack_APIC_irq();
|
||||||
if (!disable_apic)
|
|
||||||
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",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче