1ec7972c9SZhao Yakui // SPDX-License-Identifier: GPL-2.0 2ec7972c9SZhao Yakui /* 3ec7972c9SZhao Yakui * ACRN detection support 4ec7972c9SZhao Yakui * 5ec7972c9SZhao Yakui * Copyright (C) 2019 Intel Corporation. All rights reserved. 6ec7972c9SZhao Yakui * 7ec7972c9SZhao Yakui * Jason Chen CJ <jason.cj.chen@intel.com> 8ec7972c9SZhao Yakui * Zhao Yakui <yakui.zhao@intel.com> 9ec7972c9SZhao Yakui * 10ec7972c9SZhao Yakui */ 11ec7972c9SZhao Yakui 12498ad393SZhao Yakui #include <linux/interrupt.h> 137995700eSShuo Liu 147995700eSShuo Liu #include <asm/acrn.h> 15498ad393SZhao Yakui #include <asm/apic.h> 1686d709ceSShuo Liu #include <asm/cpufeatures.h> 17498ad393SZhao Yakui #include <asm/desc.h> 18ec7972c9SZhao Yakui #include <asm/hypervisor.h> 19a16be368SThomas Gleixner #include <asm/idtentry.h> 20498ad393SZhao Yakui #include <asm/irq_regs.h> 21ec7972c9SZhao Yakui acrn_detect(void)224c7bfa38SShuo Liustatic u32 __init acrn_detect(void) 23ec7972c9SZhao Yakui { 24ebbfc978SYin Fengwei return acrn_cpuid_base(); 25ec7972c9SZhao Yakui } 26ec7972c9SZhao Yakui acrn_init_platform(void)27ec7972c9SZhao Yakuistatic void __init acrn_init_platform(void) 28ec7972c9SZhao Yakui { 29498ad393SZhao Yakui /* Setup the IDT for ACRN hypervisor callback */ 30a16be368SThomas Gleixner alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_acrn_hv_callback); 3181a71f51SFei Li 3281a71f51SFei Li x86_platform.calibrate_tsc = acrn_get_tsc_khz; 3381a71f51SFei Li x86_platform.calibrate_cpu = acrn_get_tsc_khz; 34ec7972c9SZhao Yakui } 35ec7972c9SZhao Yakui acrn_x2apic_available(void)36ec7972c9SZhao Yakuistatic bool acrn_x2apic_available(void) 37ec7972c9SZhao Yakui { 3886d709ceSShuo Liu return boot_cpu_has(X86_FEATURE_X2APIC); 39ec7972c9SZhao Yakui } 40ec7972c9SZhao Yakui 41498ad393SZhao Yakui static void (*acrn_intr_handler)(void); 42498ad393SZhao Yakui DEFINE_IDTENTRY_SYSVEC(sysvec_acrn_hv_callback)43a16be368SThomas GleixnerDEFINE_IDTENTRY_SYSVEC(sysvec_acrn_hv_callback) 44498ad393SZhao Yakui { 45498ad393SZhao Yakui struct pt_regs *old_regs = set_irq_regs(regs); 46498ad393SZhao Yakui 47498ad393SZhao Yakui /* 48498ad393SZhao Yakui * The hypervisor requires that the APIC EOI should be acked. 49498ad393SZhao Yakui * If the APIC EOI is not acked, the APIC ISR bit for the 50498ad393SZhao Yakui * HYPERVISOR_CALLBACK_VECTOR will not be cleared and then it 51498ad393SZhao Yakui * will block the interrupt whose vector is lower than 52498ad393SZhao Yakui * HYPERVISOR_CALLBACK_VECTOR. 53498ad393SZhao Yakui */ 54*670c04adSDave Hansen apic_eoi(); 55498ad393SZhao Yakui inc_irq_stat(irq_hv_callback_count); 56498ad393SZhao Yakui 57498ad393SZhao Yakui if (acrn_intr_handler) 58498ad393SZhao Yakui acrn_intr_handler(); 59498ad393SZhao Yakui 60498ad393SZhao Yakui set_irq_regs(old_regs); 61498ad393SZhao Yakui } 62498ad393SZhao Yakui acrn_setup_intr_handler(void (* handler)(void))637995700eSShuo Liuvoid acrn_setup_intr_handler(void (*handler)(void)) 647995700eSShuo Liu { 657995700eSShuo Liu acrn_intr_handler = handler; 667995700eSShuo Liu } 677995700eSShuo Liu EXPORT_SYMBOL_GPL(acrn_setup_intr_handler); 687995700eSShuo Liu acrn_remove_intr_handler(void)697995700eSShuo Liuvoid acrn_remove_intr_handler(void) 707995700eSShuo Liu { 717995700eSShuo Liu acrn_intr_handler = NULL; 727995700eSShuo Liu } 737995700eSShuo Liu EXPORT_SYMBOL_GPL(acrn_remove_intr_handler); 747995700eSShuo Liu 75ec7972c9SZhao Yakui const __initconst struct hypervisor_x86 x86_hyper_acrn = { 76ec7972c9SZhao Yakui .name = "ACRN", 77ec7972c9SZhao Yakui .detect = acrn_detect, 78ec7972c9SZhao Yakui .type = X86_HYPER_ACRN, 79ec7972c9SZhao Yakui .init.init_platform = acrn_init_platform, 80ec7972c9SZhao Yakui .init.x2apic_available = acrn_x2apic_available, 81ec7972c9SZhao Yakui }; 82