1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * ACRN detection support 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2019 Intel Corporation. All rights reserved. 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Jason Chen CJ <jason.cj.chen@intel.com> 8*4882a593Smuzhiyun * Zhao Yakui <yakui.zhao@intel.com> 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <linux/interrupt.h> 13*4882a593Smuzhiyun #include <asm/apic.h> 14*4882a593Smuzhiyun #include <asm/cpufeatures.h> 15*4882a593Smuzhiyun #include <asm/desc.h> 16*4882a593Smuzhiyun #include <asm/hypervisor.h> 17*4882a593Smuzhiyun #include <asm/idtentry.h> 18*4882a593Smuzhiyun #include <asm/irq_regs.h> 19*4882a593Smuzhiyun acrn_detect(void)20*4882a593Smuzhiyunstatic u32 __init acrn_detect(void) 21*4882a593Smuzhiyun { 22*4882a593Smuzhiyun return hypervisor_cpuid_base("ACRNACRNACRN", 0); 23*4882a593Smuzhiyun } 24*4882a593Smuzhiyun acrn_init_platform(void)25*4882a593Smuzhiyunstatic void __init acrn_init_platform(void) 26*4882a593Smuzhiyun { 27*4882a593Smuzhiyun /* Setup the IDT for ACRN hypervisor callback */ 28*4882a593Smuzhiyun alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_acrn_hv_callback); 29*4882a593Smuzhiyun } 30*4882a593Smuzhiyun acrn_x2apic_available(void)31*4882a593Smuzhiyunstatic bool acrn_x2apic_available(void) 32*4882a593Smuzhiyun { 33*4882a593Smuzhiyun return boot_cpu_has(X86_FEATURE_X2APIC); 34*4882a593Smuzhiyun } 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun static void (*acrn_intr_handler)(void); 37*4882a593Smuzhiyun DEFINE_IDTENTRY_SYSVEC(sysvec_acrn_hv_callback)38*4882a593SmuzhiyunDEFINE_IDTENTRY_SYSVEC(sysvec_acrn_hv_callback) 39*4882a593Smuzhiyun { 40*4882a593Smuzhiyun struct pt_regs *old_regs = set_irq_regs(regs); 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun /* 43*4882a593Smuzhiyun * The hypervisor requires that the APIC EOI should be acked. 44*4882a593Smuzhiyun * If the APIC EOI is not acked, the APIC ISR bit for the 45*4882a593Smuzhiyun * HYPERVISOR_CALLBACK_VECTOR will not be cleared and then it 46*4882a593Smuzhiyun * will block the interrupt whose vector is lower than 47*4882a593Smuzhiyun * HYPERVISOR_CALLBACK_VECTOR. 48*4882a593Smuzhiyun */ 49*4882a593Smuzhiyun ack_APIC_irq(); 50*4882a593Smuzhiyun inc_irq_stat(irq_hv_callback_count); 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun if (acrn_intr_handler) 53*4882a593Smuzhiyun acrn_intr_handler(); 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun set_irq_regs(old_regs); 56*4882a593Smuzhiyun } 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun const __initconst struct hypervisor_x86 x86_hyper_acrn = { 59*4882a593Smuzhiyun .name = "ACRN", 60*4882a593Smuzhiyun .detect = acrn_detect, 61*4882a593Smuzhiyun .type = X86_HYPER_ACRN, 62*4882a593Smuzhiyun .init.init_platform = acrn_init_platform, 63*4882a593Smuzhiyun .init.x2apic_available = acrn_x2apic_available, 64*4882a593Smuzhiyun }; 65