x86/traps: Add sysvec_install() to install a system interrupt handler
Add sysvec_install() to install a system interrupt handler into the IDT or the FRED system interrupt handler table. Signed-off-by: Xin Li <xin3.li@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Shan Kang <shan.kang@intel.com> Link: https://lore.kernel.org/r/20231205105030.8698-28-xin3.li@intel.com
This commit is contained in:
parent
14619d912b
commit
8f4a29b0e8
@ -119,6 +119,20 @@ static idtentry_t sysvec_table[NR_SYSTEM_VECTORS] __ro_after_init = {
|
||||
SYSVEC(POSTED_INTR_NESTED_VECTOR, kvm_posted_intr_nested_ipi),
|
||||
};
|
||||
|
||||
static bool fred_setup_done __initdata;
|
||||
|
||||
void __init fred_install_sysvec(unsigned int sysvec, idtentry_t handler)
|
||||
{
|
||||
if (WARN_ON_ONCE(sysvec < FIRST_SYSTEM_VECTOR))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(fred_setup_done))
|
||||
return;
|
||||
|
||||
if (!WARN_ON_ONCE(sysvec_table[sysvec - FIRST_SYSTEM_VECTOR]))
|
||||
sysvec_table[sysvec - FIRST_SYSTEM_VECTOR] = handler;
|
||||
}
|
||||
|
||||
static noinstr void fred_extint(struct pt_regs *regs)
|
||||
{
|
||||
unsigned int vector = regs->fred_ss.vector;
|
||||
|
@ -402,8 +402,6 @@ static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit)
|
||||
desc->limit1 = (limit >> 16) & 0xf;
|
||||
}
|
||||
|
||||
void alloc_intr_gate(unsigned int n, const void *addr);
|
||||
|
||||
static inline void init_idt_data(struct idt_data *data, unsigned int n,
|
||||
const void *addr)
|
||||
{
|
||||
|
@ -459,6 +459,21 @@ __visible noinstr void func(struct pt_regs *regs, \
|
||||
#define DEFINE_FREDENTRY_DEBUG DEFINE_FREDENTRY_RAW
|
||||
#endif
|
||||
|
||||
void idt_install_sysvec(unsigned int n, const void *function);
|
||||
|
||||
#ifdef CONFIG_X86_FRED
|
||||
void fred_install_sysvec(unsigned int vector, const idtentry_t function);
|
||||
#else
|
||||
static inline void fred_install_sysvec(unsigned int vector, const idtentry_t function) { }
|
||||
#endif
|
||||
|
||||
#define sysvec_install(vector, function) { \
|
||||
if (cpu_feature_enabled(X86_FEATURE_FRED)) \
|
||||
fred_install_sysvec(vector, function); \
|
||||
else \
|
||||
idt_install_sysvec(vector, asm_##function); \
|
||||
}
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
|
@ -26,8 +26,8 @@ static u32 __init acrn_detect(void)
|
||||
|
||||
static void __init acrn_init_platform(void)
|
||||
{
|
||||
/* Setup the IDT for ACRN hypervisor callback */
|
||||
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_acrn_hv_callback);
|
||||
/* Install system interrupt handler for ACRN hypervisor callback */
|
||||
sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_acrn_hv_callback);
|
||||
|
||||
x86_platform.calibrate_tsc = acrn_get_tsc_khz;
|
||||
x86_platform.calibrate_cpu = acrn_get_tsc_khz;
|
||||
|
@ -539,19 +539,18 @@ static void __init ms_hyperv_init_platform(void)
|
||||
*/
|
||||
x86_platform.apic_post_init = hyperv_init;
|
||||
hyperv_setup_mmu_ops();
|
||||
/* Setup the IDT for hypervisor callback */
|
||||
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_hyperv_callback);
|
||||
|
||||
/* Setup the IDT for reenlightenment notifications */
|
||||
/* Install system interrupt handler for hypervisor callback */
|
||||
sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_hyperv_callback);
|
||||
|
||||
/* Install system interrupt handler for reenlightenment notifications */
|
||||
if (ms_hyperv.features & HV_ACCESS_REENLIGHTENMENT) {
|
||||
alloc_intr_gate(HYPERV_REENLIGHTENMENT_VECTOR,
|
||||
asm_sysvec_hyperv_reenlightenment);
|
||||
sysvec_install(HYPERV_REENLIGHTENMENT_VECTOR, sysvec_hyperv_reenlightenment);
|
||||
}
|
||||
|
||||
/* Setup the IDT for stimer0 */
|
||||
/* Install system interrupt handler for stimer0 */
|
||||
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE) {
|
||||
alloc_intr_gate(HYPERV_STIMER0_VECTOR,
|
||||
asm_sysvec_hyperv_stimer0);
|
||||
sysvec_install(HYPERV_STIMER0_VECTOR, sysvec_hyperv_stimer0);
|
||||
}
|
||||
|
||||
# ifdef CONFIG_SMP
|
||||
|
@ -337,7 +337,7 @@ void idt_invalidate(void)
|
||||
load_idt(&idt);
|
||||
}
|
||||
|
||||
void __init alloc_intr_gate(unsigned int n, const void *addr)
|
||||
void __init idt_install_sysvec(unsigned int n, const void *function)
|
||||
{
|
||||
if (WARN_ON(n < FIRST_SYSTEM_VECTOR))
|
||||
return;
|
||||
@ -346,5 +346,5 @@ void __init alloc_intr_gate(unsigned int n, const void *addr)
|
||||
return;
|
||||
|
||||
if (!WARN_ON(test_and_set_bit(n, system_vectors)))
|
||||
set_intr_gate(n, addr);
|
||||
set_intr_gate(n, function);
|
||||
}
|
||||
|
@ -829,7 +829,7 @@ static void __init kvm_guest_init(void)
|
||||
|
||||
if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_INT) && kvmapf) {
|
||||
static_branch_enable(&kvm_async_pf_enabled);
|
||||
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_kvm_asyncpf_interrupt);
|
||||
sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_kvm_asyncpf_interrupt);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -2216,7 +2216,7 @@ static __init void xen_alloc_callback_vector(void)
|
||||
return;
|
||||
|
||||
pr_info("Xen HVM callback vector for event delivery is enabled\n");
|
||||
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_xen_hvm_callback);
|
||||
sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_xen_hvm_callback);
|
||||
}
|
||||
#else
|
||||
void xen_setup_callback_vector(void) {}
|
||||
|
Loading…
Reference in New Issue
Block a user