[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v10 29/38] x86/traps: Add sysvec_install() to install a system interrupt handler



From: "H. Peter Anvin (Intel)" <hpa@xxxxxxxxx>

Add sysvec_install() to install a system interrupt handler into the IDT
or the FRED system interrupt handler table.

Tested-by: Shan Kang <shan.kang@xxxxxxxxx>
Signed-off-by: Xin Li <xin3.li@xxxxxxxxx>
---

Changes since v8:
* Introduce a macro sysvec_install() to derive the asm handler name from
  a C handler, which simplifies the code and avoids an ugly typecast
  (Thomas Gleixner).
---
 arch/x86/entry/entry_fred.c      | 14 ++++++++++++++
 arch/x86/include/asm/desc.h      |  2 --
 arch/x86/include/asm/idtentry.h  | 15 +++++++++++++++
 arch/x86/kernel/cpu/acrn.c       |  4 ++--
 arch/x86/kernel/cpu/mshyperv.c   | 15 +++++++--------
 arch/x86/kernel/idt.c            |  4 ++--
 arch/x86/kernel/kvm.c            |  2 +-
 drivers/xen/events/events_base.c |  2 +-
 8 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/arch/x86/entry/entry_fred.c b/arch/x86/entry/entry_fred.c
index dc645f5819a9..2fd3e421e066 100644
--- a/arch/x86/entry/entry_fred.c
+++ b/arch/x86/entry/entry_fred.c
@@ -126,6 +126,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;
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index ab97b22ac04a..ec95fe44fa3a 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -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)
 {
diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
index 4f26ee9b8b74..650c98160152 100644
--- a/arch/x86/include/asm/idtentry.h
+++ b/arch/x86/include/asm/idtentry.h
@@ -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__ */
 
 /*
diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
index bfeb18fad63f..2c5b51aad91a 100644
--- a/arch/x86/kernel/cpu/acrn.c
+++ b/arch/x86/kernel/cpu/acrn.c
@@ -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;
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index e6bba12c759c..3403880c3e09 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -536,19 +536,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
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c
index b786d48f5a0f..0db7d92de48a 100644
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -330,7 +330,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;
@@ -339,5 +339,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);
 }
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index b8ab9ee5896c..eabf03813a5c 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -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
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 3bdd5b59661d..c54123ca7b1a 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -2243,7 +2243,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) {}
-- 
2.34.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.