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

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
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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;
+0 −2
Original line number Diff line number Diff line
@@ -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)
{
+15 −0
Original line number Diff line number Diff line
@@ -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__ */

/*
+2 −2
Original line number Diff line number Diff line
@@ -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;
+7 −8
Original line number Diff line number Diff line
@@ -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
Loading