x86/entry: Convert Machine Check to IDTENTRY_IST
Convert #MC to IDTENTRY_MCE: - Implement the C entry points with DEFINE_IDTENTRY_MCE - Emit the ASM stub with DECLARE_IDTENTRY_MCE - Remove the ASM idtentry in 64bit - Remove the open coded ASM entry code in 32bit - Fixup the XEN/PV code - Remove the old prototypes - Remove the error code from *machine_check_vector() as it is always 0 and not used by any of the functions it can point to. Fixup all the functions as well. No functional change. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Acked-by: Andy Lutomirski <luto@kernel.org> Link: https://lkml.kernel.org/r/20200505135314.334980426@linutronix.de
This commit is contained in:
parent
94a46d316f
commit
8cd501c1fa
|
@ -1297,15 +1297,6 @@ SYM_CODE_START(native_iret)
|
||||||
SYM_CODE_END(native_iret)
|
SYM_CODE_END(native_iret)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
SYM_CODE_START(machine_check)
|
|
||||||
ASM_CLAC
|
|
||||||
pushl $0
|
|
||||||
pushl $do_mce
|
|
||||||
jmp common_exception
|
|
||||||
SYM_CODE_END(machine_check)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_XEN_PV
|
#ifdef CONFIG_XEN_PV
|
||||||
SYM_FUNC_START(xen_hypervisor_callback)
|
SYM_FUNC_START(xen_hypervisor_callback)
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1074,9 +1074,6 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt
|
||||||
|
|
||||||
idtentry X86_TRAP_PF page_fault do_page_fault has_error_code=1
|
idtentry X86_TRAP_PF page_fault do_page_fault has_error_code=1
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
idtentry_mce_db X86_TRAP_MCE machine_check do_mce
|
|
||||||
#endif
|
|
||||||
idtentry_mce_db X86_TRAP_DB debug do_debug
|
idtentry_mce_db X86_TRAP_DB debug do_debug
|
||||||
idtentry_df X86_TRAP_DF double_fault do_double_fault
|
idtentry_df X86_TRAP_DF double_fault do_double_fault
|
||||||
|
|
||||||
|
|
|
@ -238,4 +238,8 @@ DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_AC, exc_alignment_check);
|
||||||
/* Raw exception entries which need extra work */
|
/* Raw exception entries which need extra work */
|
||||||
DECLARE_IDTENTRY_RAW(X86_TRAP_BP, exc_int3);
|
DECLARE_IDTENTRY_RAW(X86_TRAP_BP, exc_int3);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_MCE
|
||||||
|
DECLARE_IDTENTRY_MCE(X86_TRAP_MC, exc_machine_check);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -238,7 +238,7 @@ extern void mce_disable_bank(int bank);
|
||||||
/*
|
/*
|
||||||
* Exception handler
|
* Exception handler
|
||||||
*/
|
*/
|
||||||
void do_machine_check(struct pt_regs *, long);
|
void do_machine_check(struct pt_regs *pt_regs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Threshold handler
|
* Threshold handler
|
||||||
|
|
|
@ -18,25 +18,18 @@ asmlinkage void double_fault(void);
|
||||||
#endif
|
#endif
|
||||||
asmlinkage void page_fault(void);
|
asmlinkage void page_fault(void);
|
||||||
asmlinkage void async_page_fault(void);
|
asmlinkage void async_page_fault(void);
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
asmlinkage void machine_check(void);
|
|
||||||
#endif /* CONFIG_X86_MCE */
|
|
||||||
|
|
||||||
#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
|
#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
|
||||||
asmlinkage void xen_xennmi(void);
|
asmlinkage void xen_xennmi(void);
|
||||||
asmlinkage void xen_xendebug(void);
|
asmlinkage void xen_xendebug(void);
|
||||||
asmlinkage void xen_double_fault(void);
|
asmlinkage void xen_double_fault(void);
|
||||||
asmlinkage void xen_page_fault(void);
|
asmlinkage void xen_page_fault(void);
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
asmlinkage void xen_machine_check(void);
|
|
||||||
#endif /* CONFIG_X86_MCE */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dotraplinkage void do_debug(struct pt_regs *regs, long error_code);
|
dotraplinkage void do_debug(struct pt_regs *regs, long error_code);
|
||||||
dotraplinkage void do_nmi(struct pt_regs *regs, long error_code);
|
dotraplinkage void do_nmi(struct pt_regs *regs, long error_code);
|
||||||
dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsigned long cr2);
|
dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsigned long cr2);
|
||||||
dotraplinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address);
|
dotraplinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address);
|
||||||
dotraplinkage void do_mce(struct pt_regs *regs, long error_code);
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs);
|
asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs);
|
||||||
|
|
|
@ -1232,7 +1232,7 @@ static void kill_me_maybe(struct callback_head *cb)
|
||||||
* backing the user stack, tracing that reads the user stack will cause
|
* backing the user stack, tracing that reads the user stack will cause
|
||||||
* potentially infinite recursion.
|
* potentially infinite recursion.
|
||||||
*/
|
*/
|
||||||
void noinstr do_machine_check(struct pt_regs *regs, long error_code)
|
void noinstr do_machine_check(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
|
DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
|
||||||
DECLARE_BITMAP(toclear, MAX_NR_BANKS);
|
DECLARE_BITMAP(toclear, MAX_NR_BANKS);
|
||||||
|
@ -1366,7 +1366,7 @@ void noinstr do_machine_check(struct pt_regs *regs, long error_code)
|
||||||
current->mce_kill_me.func = kill_me_now;
|
current->mce_kill_me.func = kill_me_now;
|
||||||
task_work_add(current, ¤t->mce_kill_me, true);
|
task_work_add(current, ¤t->mce_kill_me, true);
|
||||||
} else {
|
} else {
|
||||||
if (!fixup_exception(regs, X86_TRAP_MC, error_code, 0))
|
if (!fixup_exception(regs, X86_TRAP_MC, 0, 0))
|
||||||
mce_panic("Failed kernel mode recovery", &m, msg);
|
mce_panic("Failed kernel mode recovery", &m, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1895,27 +1895,32 @@ bool filter_mce(struct mce *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle unconfigured int18 (should never happen) */
|
/* Handle unconfigured int18 (should never happen) */
|
||||||
static void unexpected_machine_check(struct pt_regs *regs, long error_code)
|
static void unexpected_machine_check(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
pr_err("CPU#%d: Unexpected int18 (Machine Check)\n",
|
pr_err("CPU#%d: Unexpected int18 (Machine Check)\n",
|
||||||
smp_processor_id());
|
smp_processor_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call the installed machine check handler for this CPU setup. */
|
/* Call the installed machine check handler for this CPU setup. */
|
||||||
void (*machine_check_vector)(struct pt_regs *, long error_code) =
|
void (*machine_check_vector)(struct pt_regs *) = unexpected_machine_check;
|
||||||
unexpected_machine_check;
|
|
||||||
|
|
||||||
dotraplinkage noinstr void do_mce(struct pt_regs *regs, long error_code)
|
DEFINE_IDTENTRY_MCE(exc_machine_check)
|
||||||
{
|
{
|
||||||
if (machine_check_vector == do_machine_check &&
|
if (machine_check_vector == do_machine_check &&
|
||||||
mce_check_crashing_cpu())
|
mce_check_crashing_cpu())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nmi_enter();
|
if (user_mode(regs))
|
||||||
|
idtentry_enter(regs);
|
||||||
|
else
|
||||||
|
nmi_enter();
|
||||||
|
|
||||||
machine_check_vector(regs, error_code);
|
machine_check_vector(regs);
|
||||||
|
|
||||||
nmi_exit();
|
if (user_mode(regs))
|
||||||
|
idtentry_exit(regs);
|
||||||
|
else
|
||||||
|
nmi_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -146,9 +146,9 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs)
|
||||||
regs.cs = m->cs;
|
regs.cs = m->cs;
|
||||||
pregs = ®s;
|
pregs = ®s;
|
||||||
}
|
}
|
||||||
/* in mcheck exeception handler, irq will be disabled */
|
/* do_machine_check() expects interrupts disabled -- at least */
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
do_machine_check(pregs, 0);
|
do_machine_check(pregs);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
m->finished = 0;
|
m->finished = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <asm/mce.h>
|
#include <asm/mce.h>
|
||||||
|
|
||||||
/* Pointer to the installed machine check handler for this CPU setup. */
|
/* Pointer to the installed machine check handler for this CPU setup. */
|
||||||
extern void (*machine_check_vector)(struct pt_regs *, long error_code);
|
extern void (*machine_check_vector)(struct pt_regs *);
|
||||||
|
|
||||||
enum severity_level {
|
enum severity_level {
|
||||||
MCE_NO_SEVERITY,
|
MCE_NO_SEVERITY,
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
int mce_p5_enabled __read_mostly;
|
int mce_p5_enabled __read_mostly;
|
||||||
|
|
||||||
/* Machine check handler for Pentium class Intel CPUs: */
|
/* Machine check handler for Pentium class Intel CPUs: */
|
||||||
static void pentium_machine_check(struct pt_regs *regs, long error_code)
|
static void pentium_machine_check(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
u32 loaddr, hi, lotype;
|
u32 loaddr, hi, lotype;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
/* Machine check handler for WinChip C6: */
|
/* Machine check handler for WinChip C6: */
|
||||||
static void winchip_machine_check(struct pt_regs *regs, long error_code)
|
static void winchip_machine_check(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
pr_emerg("CPU0: Machine Check Exception.\n");
|
pr_emerg("CPU0: Machine Check Exception.\n");
|
||||||
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
|
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
|
||||||
|
|
|
@ -96,7 +96,7 @@ static const __initconst struct idt_data def_idts[] = {
|
||||||
INTG(X86_TRAP_DB, debug),
|
INTG(X86_TRAP_DB, debug),
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MCE
|
#ifdef CONFIG_X86_MCE
|
||||||
INTG(X86_TRAP_MC, machine_check),
|
INTG(X86_TRAP_MC, asm_exc_machine_check),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SYSG(X86_TRAP_OF, asm_exc_overflow),
|
SYSG(X86_TRAP_OF, asm_exc_overflow),
|
||||||
|
@ -185,11 +185,11 @@ gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss;
|
||||||
* cpu_init() when the TSS has been initialized.
|
* cpu_init() when the TSS has been initialized.
|
||||||
*/
|
*/
|
||||||
static const __initconst struct idt_data ist_idts[] = {
|
static const __initconst struct idt_data ist_idts[] = {
|
||||||
ISTG(X86_TRAP_DB, debug, IST_INDEX_DB),
|
ISTG(X86_TRAP_DB, debug, IST_INDEX_DB),
|
||||||
ISTG(X86_TRAP_NMI, nmi, IST_INDEX_NMI),
|
ISTG(X86_TRAP_NMI, nmi, IST_INDEX_NMI),
|
||||||
ISTG(X86_TRAP_DF, double_fault, IST_INDEX_DF),
|
ISTG(X86_TRAP_DF, double_fault, IST_INDEX_DF),
|
||||||
#ifdef CONFIG_X86_MCE
|
#ifdef CONFIG_X86_MCE
|
||||||
ISTG(X86_TRAP_MC, machine_check, IST_INDEX_MCE),
|
ISTG(X86_TRAP_MC, asm_exc_machine_check, IST_INDEX_MCE),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1837,7 +1837,7 @@ static void kvm_machine_check(void)
|
||||||
.flags = X86_EFLAGS_IF,
|
.flags = X86_EFLAGS_IF,
|
||||||
};
|
};
|
||||||
|
|
||||||
do_machine_check(®s, 0);
|
do_machine_check(®s);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4683,7 +4683,7 @@ static void kvm_machine_check(void)
|
||||||
.flags = X86_EFLAGS_IF,
|
.flags = X86_EFLAGS_IF,
|
||||||
};
|
};
|
||||||
|
|
||||||
do_machine_check(®s, 0);
|
do_machine_check(®s);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -613,7 +613,7 @@ static struct trap_array_entry trap_array[] = {
|
||||||
{ debug, xen_xendebug, true },
|
{ debug, xen_xendebug, true },
|
||||||
{ double_fault, xen_double_fault, true },
|
{ double_fault, xen_double_fault, true },
|
||||||
#ifdef CONFIG_X86_MCE
|
#ifdef CONFIG_X86_MCE
|
||||||
{ machine_check, xen_machine_check, true },
|
TRAP_ENTRY(exc_machine_check, true ),
|
||||||
#endif
|
#endif
|
||||||
{ nmi, xen_xennmi, true },
|
{ nmi, xen_xennmi, true },
|
||||||
TRAP_ENTRY(exc_int3, false ),
|
TRAP_ENTRY(exc_int3, false ),
|
||||||
|
|
|
@ -48,7 +48,7 @@ xen_pv_trap asm_exc_spurious_interrupt_bug
|
||||||
xen_pv_trap asm_exc_coprocessor_error
|
xen_pv_trap asm_exc_coprocessor_error
|
||||||
xen_pv_trap asm_exc_alignment_check
|
xen_pv_trap asm_exc_alignment_check
|
||||||
#ifdef CONFIG_X86_MCE
|
#ifdef CONFIG_X86_MCE
|
||||||
xen_pv_trap machine_check
|
xen_pv_trap asm_exc_machine_check
|
||||||
#endif /* CONFIG_X86_MCE */
|
#endif /* CONFIG_X86_MCE */
|
||||||
xen_pv_trap asm_exc_simd_coprocessor_error
|
xen_pv_trap asm_exc_simd_coprocessor_error
|
||||||
#ifdef CONFIG_IA32_EMULATION
|
#ifdef CONFIG_IA32_EMULATION
|
||||||
|
|
Loading…
Reference in New Issue