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),
|
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)
|
|||||||
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, \
|
|||||||
#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)
|
|||||||
|
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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) {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user