x86/crash: Drop manual hooking of exception_table[]

NMI hooking in the crash path has undergone several revisions since its
introduction.  What we have now is not sufficiently different from the regular
nmi_callback() mechanism to warrant special casing.

Use set_nmi_callback() directly, and do away with patching a read-only data
structure via a read-write alias.  This also means that the
vmx_vmexit_handler() can and should call do_nmi() directly, rather than
indirecting through the exception table to pick up the crash path hook.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2021-11-29 13:53:05 +00:00
1 parent 04c48ccd75
commit e7f147bf4a
3 files changed
+8 -14

No files matched your search

+2 -13
View File
@@ -36,10 +36,8 @@ static unsigned int crashing_cpu;
static DEFINE_PER_CPU_READ_MOSTLY(bool, crash_save_done); static DEFINE_PER_CPU_READ_MOSTLY(bool, crash_save_done);
/* This becomes the NMI handler for non-crashing CPUs, when Xen is crashing. */ /* This becomes the NMI handler for non-crashing CPUs, when Xen is crashing. */
static void noreturn do_nmi_crash(const struct cpu_user_regs *regs) static int noreturn do_nmi_crash(const struct cpu_user_regs *regs, int cpu)
{ {
unsigned int cpu = smp_processor_id();
stac(); stac();
/* nmi_shootdown_cpus() should ensure that this assertion is correct. */ /* nmi_shootdown_cpus() should ensure that this assertion is correct. */
@@ -136,16 +134,7 @@ static void nmi_shootdown_cpus(void)
SYS_DESC_irq_gate, 0, &trap_nop); SYS_DESC_irq_gate, 0, &trap_nop);
set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE); set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE);
/* set_nmi_callback(do_nmi_crash);
* Ideally would be:
* exception_table[TRAP_nmi] = &do_nmi_crash;
*
* but the exception_table is read only. Access it via its directmap
* mappings.
*/
write_atomic((unsigned long *)__va(__pa(&exception_table[TRAP_nmi])),
(unsigned long)&do_nmi_crash);
smp_send_nmi_allbutself(); smp_send_nmi_allbutself();
msecs = 1000; /* Wait at most a second for the other cpus to stop */ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+1 -1
View File
@@ -3887,7 +3887,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
((intr_info & INTR_INFO_INTR_TYPE_MASK) == ((intr_info & INTR_INFO_INTR_TYPE_MASK) ==
MASK_INSR(X86_EVENTTYPE_NMI, INTR_INFO_INTR_TYPE_MASK)) ) MASK_INSR(X86_EVENTTYPE_NMI, INTR_INFO_INTR_TYPE_MASK)) )
{ {
exception_table[TRAP_nmi](regs); do_nmi(regs);
enable_nmis(); enable_nmis();
} }
break; break;
+5
View File
@@ -1883,6 +1883,11 @@ void do_nmi(const struct cpu_user_regs *regs)
this_cpu(nmi_count)++; this_cpu(nmi_count)++;
nmi_enter(); nmi_enter();
/*
* Think carefully before putting any logic before this point.
* nmi_callback() might be the crash quiesce...
*/
callback = ACCESS_ONCE(nmi_callback); callback = ACCESS_ONCE(nmi_callback);
if ( unlikely(callback) && callback(regs, cpu) ) if ( unlikely(callback) && callback(regs, cpu) )
goto out; goto out;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.