[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 3/3] x86/pv: Don't use IST for NMI/#MC/#DB in !CONFIG_PV builds
ISTs are used to force a stack switch on CPL0=>0 interrupts/exceptions. They however come with a nasty corner case in the case of reentrancy where the outer exception frame gets clobbered. When the SYSCALL/SYSRET instructions aren't used, there is no need to use IST for anything other than #DF, which reduces the number of corner cases. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Wei Liu <wl@xxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/arch/x86/cpu/common.c | 8 +++++--- xen/include/asm-x86/processor.h | 12 +++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index 7b093cb421..d45495c701 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -732,15 +732,17 @@ void load_system_tables(void) .rsp2 = 0x8600111111111111ul, /* - * MCE, NMI and Double Fault handlers get their own stacks. + * #DF always uses a separate stack. NMI/#MC/#DB only need a + * separate stacks when PV guests are used. * All others poisoned. */ .ist = { - [IST_MCE - 1] = stack_top + IST_MCE * PAGE_SIZE, [IST_DF - 1] = stack_top + IST_DF * PAGE_SIZE, +#ifdef CONFIG_PV [IST_NMI - 1] = stack_top + IST_NMI * PAGE_SIZE, + [IST_MCE - 1] = stack_top + IST_MCE * PAGE_SIZE, [IST_DB - 1] = stack_top + IST_DB * PAGE_SIZE, - +#endif [IST_MAX ... ARRAY_SIZE(tss->ist) - 1] = 0x8600111111111111ul, }, diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index ea6e5497f4..33f2052c8e 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -441,12 +441,18 @@ struct tss_page { }; DECLARE_PER_CPU(struct tss_page, tss_page); +/* + * Interrupt Stack Tables. Used to force a stack switch on a CPL0=>0 + * interrupt/exception. #DF uses IST all the time to detect stack overflows + * cleanly. NMI/#MC/#DB only need IST to cover the SYSCALL gap, and therefore + * only necessary with PV guests. + */ #define IST_NONE 0UL #define IST_DF 1UL #define IST_NMI 2UL #define IST_MCE 3UL #define IST_DB 4UL -#define IST_MAX 4UL +#define IST_MAX (IS_ENABLED(CONFIG_PV) ? 4ul : 1ul) /* Set the Interrupt Stack Table used by a particular IDT entry. */ static inline void set_ist(idt_entry_t *idt, unsigned int ist) @@ -461,6 +467,8 @@ static inline void set_ist(idt_entry_t *idt, unsigned int ist) static inline void enable_each_ist(idt_entry_t *idt) { set_ist(&idt[TRAP_double_fault], IST_DF); + if ( !IS_ENABLED(CONFIG_PV) ) + return; set_ist(&idt[TRAP_nmi], IST_NMI); set_ist(&idt[TRAP_machine_check], IST_MCE); set_ist(&idt[TRAP_debug], IST_DB); @@ -469,6 +477,8 @@ static inline void enable_each_ist(idt_entry_t *idt) static inline void disable_each_ist(idt_entry_t *idt) { set_ist(&idt[TRAP_double_fault], IST_NONE); + if ( !IS_ENABLED(CONFIG_PV) ) + return; set_ist(&idt[TRAP_nmi], IST_NONE); set_ist(&idt[TRAP_machine_check], IST_NONE); set_ist(&idt[TRAP_debug], IST_NONE); -- 2.11.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |