Commit 8f4a29b0 authored by Xin Li's avatar Xin Li Committed by Borislav Petkov (AMD)

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: default avatarXin Li <xin3.li@intel.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Tested-by: default avatarShan Kang <shan.kang@intel.com>
Link: https://lore.kernel.org/r/20231205105030.8698-28-xin3.li@intel.com
parent 14619d91
...@@ -119,6 +119,20 @@ static idtentry_t sysvec_table[NR_SYSTEM_VECTORS] __ro_after_init = { ...@@ -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), 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) static noinstr void fred_extint(struct pt_regs *regs)
{ {
unsigned int vector = regs->fred_ss.vector; unsigned int vector = regs->fred_ss.vector;
......
...@@ -402,8 +402,6 @@ static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) ...@@ -402,8 +402,6 @@ static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit)
desc->limit1 = (limit >> 16) & 0xf; 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, static inline void init_idt_data(struct idt_data *data, unsigned int n,
const void *addr) const void *addr)
{ {
......
...@@ -459,6 +459,21 @@ __visible noinstr void func(struct pt_regs *regs, \ ...@@ -459,6 +459,21 @@ __visible noinstr void func(struct pt_regs *regs, \
#define DEFINE_FREDENTRY_DEBUG DEFINE_FREDENTRY_RAW #define DEFINE_FREDENTRY_DEBUG DEFINE_FREDENTRY_RAW
#endif #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__ */ #else /* !__ASSEMBLY__ */
/* /*
......
...@@ -26,8 +26,8 @@ static u32 __init acrn_detect(void) ...@@ -26,8 +26,8 @@ static u32 __init acrn_detect(void)
static void __init acrn_init_platform(void) static void __init acrn_init_platform(void)
{ {
/* Setup the IDT for ACRN hypervisor callback */ /* Install system interrupt handler for ACRN hypervisor callback */
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_acrn_hv_callback); sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_acrn_hv_callback);
x86_platform.calibrate_tsc = acrn_get_tsc_khz; x86_platform.calibrate_tsc = acrn_get_tsc_khz;
x86_platform.calibrate_cpu = acrn_get_tsc_khz; x86_platform.calibrate_cpu = acrn_get_tsc_khz;
......
...@@ -539,19 +539,18 @@ static void __init ms_hyperv_init_platform(void) ...@@ -539,19 +539,18 @@ static void __init ms_hyperv_init_platform(void)
*/ */
x86_platform.apic_post_init = hyperv_init; x86_platform.apic_post_init = hyperv_init;
hyperv_setup_mmu_ops(); 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) { if (ms_hyperv.features & HV_ACCESS_REENLIGHTENMENT) {
alloc_intr_gate(HYPERV_REENLIGHTENMENT_VECTOR, sysvec_install(HYPERV_REENLIGHTENMENT_VECTOR, sysvec_hyperv_reenlightenment);
asm_sysvec_hyperv_reenlightenment);
} }
/* Setup the IDT for stimer0 */ /* Install system interrupt handler for stimer0 */
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE) { if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE) {
alloc_intr_gate(HYPERV_STIMER0_VECTOR, sysvec_install(HYPERV_STIMER0_VECTOR, sysvec_hyperv_stimer0);
asm_sysvec_hyperv_stimer0);
} }
# ifdef CONFIG_SMP # ifdef CONFIG_SMP
......
...@@ -337,7 +337,7 @@ void idt_invalidate(void) ...@@ -337,7 +337,7 @@ void idt_invalidate(void)
load_idt(&idt); 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)) if (WARN_ON(n < FIRST_SYSTEM_VECTOR))
return; return;
...@@ -346,5 +346,5 @@ void __init alloc_intr_gate(unsigned int n, const void *addr) ...@@ -346,5 +346,5 @@ void __init alloc_intr_gate(unsigned int n, const void *addr)
return; return;
if (!WARN_ON(test_and_set_bit(n, system_vectors))) 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) ...@@ -829,7 +829,7 @@ static void __init kvm_guest_init(void)
if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_INT) && kvmapf) { if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_INT) && kvmapf) {
static_branch_enable(&kvm_async_pf_enabled); 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 #ifdef CONFIG_SMP
......
...@@ -2216,7 +2216,7 @@ static __init void xen_alloc_callback_vector(void) ...@@ -2216,7 +2216,7 @@ static __init void xen_alloc_callback_vector(void)
return; return;
pr_info("Xen HVM callback vector for event delivery is enabled\n"); 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 #else
void xen_setup_callback_vector(void) {} void xen_setup_callback_vector(void) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment