On Wed, Nov 09, 2022 at 10:15:41PM -0800, Xin Li wrote: > Upon receiving an external interrupt, KVM VMX reinjects it through > calling the interrupt handler in its IDT descriptor on the current > kernel stack, which essentially uses the IDT as an interrupt dispatch > table. > > However the IDT is one of the lowest level critical data structures > between a x86 CPU and the Linux kernel, we should avoid using it > *directly* whenever possible, espeically in a software defined manner. > > On x86, external interrupts are divided into the following groups > 1) system interrupts > 2) external device interrupts > With the IDT, system interrupts are dispatched through the IDT > directly, while external device interrupts are all routed to the > external interrupt dispatch function common_interrupt(), which > dispatches external device interrupts through a per-CPU external > interrupt dispatch table vector_irq. > > To eliminate dispatching external interrupts through the IDT, add > a system interrupt handler table for dispatching a system interrupt > to its corresponding handler directly. Thus a software based dispatch > function will be: > > void external_interrupt(struct pt_regs *regs, u8 vector) > { > if (is_system_interrupt(vector)) > system_interrupt_handler_table[vector_to_sysvec(vector)](regs); > else /* external device interrupt */ > common_interrupt(regs, vector); > } > > What's more, with the Intel FRED (Flexible Return and Event Delivery) > architecture, IDT, the hardware based event dispatch table, is gone, > and the Linux kernel needs to dispatch events to their handlers with > vector to handler mappings, the dispatch function external_interrupt() > is also needed. > > Signed-off-by: H. Peter Anvin (Intel) <hpa@xxxxxxxxx> > Signed-off-by: Xin Li <xin3.li@xxxxxxxxx> This is not a valid SOB, it would suggest hpa is the author, but he's not in in From. > --- > arch/x86/include/asm/traps.h | 8 ++++++ > arch/x86/kernel/traps.c | 55 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 63 insertions(+) > > diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h > index 47ecfff2c83d..3dc63d753bda 100644 > --- a/arch/x86/include/asm/traps.h > +++ b/arch/x86/include/asm/traps.h > @@ -47,4 +47,12 @@ void __noreturn handle_stack_overflow(struct pt_regs *regs, > struct stack_info *info); > #endif > > +/* > + * How system interrupt handlers are called. > + */ > +#define DECLARE_SYSTEM_INTERRUPT_HANDLER(f) \ > + void f (struct pt_regs *regs __maybe_unused, \ > + unsigned long vector __maybe_unused) > +typedef DECLARE_SYSTEM_INTERRUPT_HANDLER((*system_interrupt_handler)); > + > #endif /* _ASM_X86_TRAPS_H */ > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c > index 178015a820f0..95dd917ef9ad 100644 > --- a/arch/x86/kernel/traps.c > +++ b/arch/x86/kernel/traps.c > @@ -1444,6 +1444,61 @@ DEFINE_IDTENTRY_SW(iret_error) > } > #endif > > +#define SYSV(x,y) [(x) - FIRST_SYSTEM_VECTOR] = (system_interrupt_handler)y > + > +#pragma GCC diagnostic push > +#pragma GCC diagnostic ignored "-Wcast-function-type" How does this not break CFI ?