18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012,2013 - ARM Ltd 48c2ecf20Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef __ARM_KVM_ASM_H__ 88c2ecf20Sopenharmony_ci#define __ARM_KVM_ASM_H__ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <asm/hyp_image.h> 118c2ecf20Sopenharmony_ci#include <asm/virt.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define ARM_EXIT_WITH_SERROR_BIT 31 148c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT)) 158c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_IS_TRAP(x) (ARM_EXCEPTION_CODE((x)) == ARM_EXCEPTION_TRAP) 168c2ecf20Sopenharmony_ci#define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT)) 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_IRQ 0 198c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_EL1_SERROR 1 208c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_TRAP 2 218c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_IL 3 228c2ecf20Sopenharmony_ci/* The hyp-stub will return this for any kvm_call_hyp() call */ 238c2ecf20Sopenharmony_ci#define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define kvm_arm_exception_type \ 268c2ecf20Sopenharmony_ci {ARM_EXCEPTION_IRQ, "IRQ" }, \ 278c2ecf20Sopenharmony_ci {ARM_EXCEPTION_EL1_SERROR, "SERROR" }, \ 288c2ecf20Sopenharmony_ci {ARM_EXCEPTION_TRAP, "TRAP" }, \ 298c2ecf20Sopenharmony_ci {ARM_EXCEPTION_HYP_GONE, "HYP_GONE" } 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * Size of the HYP vectors preamble. kvm_patch_vector_branch() generates code 338c2ecf20Sopenharmony_ci * that jumps over this. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci#define KVM_VECTOR_PREAMBLE (2 * AARCH64_INSN_SIZE) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define __SMCCC_WORKAROUND_1_SMC_SZ 36 388c2ecf20Sopenharmony_ci#define __SMCCC_WORKAROUND_3_SMC_SZ 36 398c2ecf20Sopenharmony_ci#define __SPECTRE_BHB_LOOP_SZ 44 408c2ecf20Sopenharmony_ci#define __SPECTRE_BHB_CLEARBHB_SZ 12 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define KVM_HOST_SMCCC_ID(id) \ 438c2ecf20Sopenharmony_ci ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ 448c2ecf20Sopenharmony_ci ARM_SMCCC_SMC_64, \ 458c2ecf20Sopenharmony_ci ARM_SMCCC_OWNER_VENDOR_HYP, \ 468c2ecf20Sopenharmony_ci (id)) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define KVM_HOST_SMCCC_FUNC(name) KVM_HOST_SMCCC_ID(__KVM_HOST_SMCCC_FUNC_##name) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_hyp_init 0 518c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_vcpu_run 1 528c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context 2 538c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa 3 548c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid 4 558c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context 5 568c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff 6 578c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs 7 588c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___vgic_v3_get_ich_vtr_el2 8 598c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr 9 608c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___vgic_v3_write_vmcr 10 618c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs 11 628c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 12 638c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs 13 648c2ecf20Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs 14 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#include <linux/mm.h> 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define DECLARE_KVM_VHE_SYM(sym) extern char sym[] 718c2ecf20Sopenharmony_ci#define DECLARE_KVM_NVHE_SYM(sym) extern char kvm_nvhe_sym(sym)[] 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* 748c2ecf20Sopenharmony_ci * Define a pair of symbols sharing the same name but one defined in 758c2ecf20Sopenharmony_ci * VHE and the other in nVHE hyp implementations. 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci#define DECLARE_KVM_HYP_SYM(sym) \ 788c2ecf20Sopenharmony_ci DECLARE_KVM_VHE_SYM(sym); \ 798c2ecf20Sopenharmony_ci DECLARE_KVM_NVHE_SYM(sym) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define DECLARE_KVM_VHE_PER_CPU(type, sym) \ 828c2ecf20Sopenharmony_ci DECLARE_PER_CPU(type, sym) 838c2ecf20Sopenharmony_ci#define DECLARE_KVM_NVHE_PER_CPU(type, sym) \ 848c2ecf20Sopenharmony_ci DECLARE_PER_CPU(type, kvm_nvhe_sym(sym)) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define DECLARE_KVM_HYP_PER_CPU(type, sym) \ 878c2ecf20Sopenharmony_ci DECLARE_KVM_VHE_PER_CPU(type, sym); \ 888c2ecf20Sopenharmony_ci DECLARE_KVM_NVHE_PER_CPU(type, sym) 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* 918c2ecf20Sopenharmony_ci * Compute pointer to a symbol defined in nVHE percpu region. 928c2ecf20Sopenharmony_ci * Returns NULL if percpu memory has not been allocated yet. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci#define this_cpu_ptr_nvhe_sym(sym) per_cpu_ptr_nvhe_sym(sym, smp_processor_id()) 958c2ecf20Sopenharmony_ci#define per_cpu_ptr_nvhe_sym(sym, cpu) \ 968c2ecf20Sopenharmony_ci ({ \ 978c2ecf20Sopenharmony_ci unsigned long base, off; \ 988c2ecf20Sopenharmony_ci base = kvm_arm_hyp_percpu_base[cpu]; \ 998c2ecf20Sopenharmony_ci off = (unsigned long)&CHOOSE_NVHE_SYM(sym) - \ 1008c2ecf20Sopenharmony_ci (unsigned long)&CHOOSE_NVHE_SYM(__per_cpu_start); \ 1018c2ecf20Sopenharmony_ci base ? (typeof(CHOOSE_NVHE_SYM(sym))*)(base + off) : NULL; \ 1028c2ecf20Sopenharmony_ci }) 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci#if defined(__KVM_NVHE_HYPERVISOR__) 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define CHOOSE_NVHE_SYM(sym) sym 1078c2ecf20Sopenharmony_ci#define CHOOSE_HYP_SYM(sym) CHOOSE_NVHE_SYM(sym) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* The nVHE hypervisor shouldn't even try to access VHE symbols */ 1108c2ecf20Sopenharmony_ciextern void *__nvhe_undefined_symbol; 1118c2ecf20Sopenharmony_ci#define CHOOSE_VHE_SYM(sym) __nvhe_undefined_symbol 1128c2ecf20Sopenharmony_ci#define this_cpu_ptr_hyp_sym(sym) (&__nvhe_undefined_symbol) 1138c2ecf20Sopenharmony_ci#define per_cpu_ptr_hyp_sym(sym, cpu) (&__nvhe_undefined_symbol) 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#elif defined(__KVM_VHE_HYPERVISOR__) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define CHOOSE_VHE_SYM(sym) sym 1188c2ecf20Sopenharmony_ci#define CHOOSE_HYP_SYM(sym) CHOOSE_VHE_SYM(sym) 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* The VHE hypervisor shouldn't even try to access nVHE symbols */ 1218c2ecf20Sopenharmony_ciextern void *__vhe_undefined_symbol; 1228c2ecf20Sopenharmony_ci#define CHOOSE_NVHE_SYM(sym) __vhe_undefined_symbol 1238c2ecf20Sopenharmony_ci#define this_cpu_ptr_hyp_sym(sym) (&__vhe_undefined_symbol) 1248c2ecf20Sopenharmony_ci#define per_cpu_ptr_hyp_sym(sym, cpu) (&__vhe_undefined_symbol) 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#else 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* 1298c2ecf20Sopenharmony_ci * BIG FAT WARNINGS: 1308c2ecf20Sopenharmony_ci * 1318c2ecf20Sopenharmony_ci * - Don't be tempted to change the following is_kernel_in_hyp_mode() 1328c2ecf20Sopenharmony_ci * to has_vhe(). has_vhe() is implemented as a *final* capability, 1338c2ecf20Sopenharmony_ci * while this is used early at boot time, when the capabilities are 1348c2ecf20Sopenharmony_ci * not final yet.... 1358c2ecf20Sopenharmony_ci * 1368c2ecf20Sopenharmony_ci * - Don't let the nVHE hypervisor have access to this, as it will 1378c2ecf20Sopenharmony_ci * pick the *wrong* symbol (yes, it runs at EL2...). 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci#define CHOOSE_HYP_SYM(sym) (is_kernel_in_hyp_mode() \ 1408c2ecf20Sopenharmony_ci ? CHOOSE_VHE_SYM(sym) \ 1418c2ecf20Sopenharmony_ci : CHOOSE_NVHE_SYM(sym)) 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci#define this_cpu_ptr_hyp_sym(sym) (is_kernel_in_hyp_mode() \ 1448c2ecf20Sopenharmony_ci ? this_cpu_ptr(&sym) \ 1458c2ecf20Sopenharmony_ci : this_cpu_ptr_nvhe_sym(sym)) 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#define per_cpu_ptr_hyp_sym(sym, cpu) (is_kernel_in_hyp_mode() \ 1488c2ecf20Sopenharmony_ci ? per_cpu_ptr(&sym, cpu) \ 1498c2ecf20Sopenharmony_ci : per_cpu_ptr_nvhe_sym(sym, cpu)) 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci#define CHOOSE_VHE_SYM(sym) sym 1528c2ecf20Sopenharmony_ci#define CHOOSE_NVHE_SYM(sym) kvm_nvhe_sym(sym) 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#endif 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci/* Translate a kernel address @ptr into its equivalent linear mapping */ 1578c2ecf20Sopenharmony_ci#define kvm_ksym_ref(ptr) \ 1588c2ecf20Sopenharmony_ci ({ \ 1598c2ecf20Sopenharmony_ci void *val = (ptr); \ 1608c2ecf20Sopenharmony_ci if (!is_kernel_in_hyp_mode()) \ 1618c2ecf20Sopenharmony_ci val = lm_alias((ptr)); \ 1628c2ecf20Sopenharmony_ci val; \ 1638c2ecf20Sopenharmony_ci }) 1648c2ecf20Sopenharmony_ci#define kvm_ksym_ref_nvhe(sym) kvm_ksym_ref(kvm_nvhe_sym(sym)) 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistruct kvm; 1678c2ecf20Sopenharmony_cistruct kvm_vcpu; 1688c2ecf20Sopenharmony_cistruct kvm_s2_mmu; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__kvm_hyp_init); 1718c2ecf20Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__kvm_hyp_host_vector); 1728c2ecf20Sopenharmony_ciDECLARE_KVM_HYP_SYM(__kvm_hyp_vector); 1738c2ecf20Sopenharmony_ci#define __kvm_hyp_init CHOOSE_NVHE_SYM(__kvm_hyp_init) 1748c2ecf20Sopenharmony_ci#define __kvm_hyp_host_vector CHOOSE_NVHE_SYM(__kvm_hyp_host_vector) 1758c2ecf20Sopenharmony_ci#define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector) 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ciextern unsigned long kvm_arm_hyp_percpu_base[NR_CPUS]; 1788c2ecf20Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__per_cpu_start); 1798c2ecf20Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__per_cpu_end); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ciextern atomic_t arm64_el2_vector_last_slot; 1828c2ecf20Sopenharmony_ciDECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs); 1838c2ecf20Sopenharmony_ci#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs) 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciextern void __kvm_flush_vm_context(void); 1868c2ecf20Sopenharmony_ciextern void __kvm_flush_cpu_context(struct kvm_s2_mmu *mmu); 1878c2ecf20Sopenharmony_ciextern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa, 1888c2ecf20Sopenharmony_ci int level); 1898c2ecf20Sopenharmony_ciextern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ciextern void __kvm_timer_set_cntvoff(u64 cntvoff); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciextern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ciextern void __kvm_enable_ssbs(void); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ciextern u64 __vgic_v3_get_ich_vtr_el2(void); 1988c2ecf20Sopenharmony_ciextern u64 __vgic_v3_read_vmcr(void); 1998c2ecf20Sopenharmony_ciextern void __vgic_v3_write_vmcr(u32 vmcr); 2008c2ecf20Sopenharmony_ciextern void __vgic_v3_init_lrs(void); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciextern u32 __kvm_get_mdcr_el2(void); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ciextern char __smccc_workaround_1_smc[__SMCCC_WORKAROUND_1_SMC_SZ]; 2058c2ecf20Sopenharmony_ciextern char __smccc_workaround_3_smc[__SMCCC_WORKAROUND_3_SMC_SZ]; 2068c2ecf20Sopenharmony_ciextern char __spectre_bhb_loop_k8[__SPECTRE_BHB_LOOP_SZ]; 2078c2ecf20Sopenharmony_ciextern char __spectre_bhb_loop_k24[__SPECTRE_BHB_LOOP_SZ]; 2088c2ecf20Sopenharmony_ciextern char __spectre_bhb_loop_k32[__SPECTRE_BHB_LOOP_SZ]; 2098c2ecf20Sopenharmony_ciextern char __spectre_bhb_clearbhb[__SPECTRE_BHB_LOOP_SZ]; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* 2128c2ecf20Sopenharmony_ci * Obtain the PC-relative address of a kernel symbol 2138c2ecf20Sopenharmony_ci * s: symbol 2148c2ecf20Sopenharmony_ci * 2158c2ecf20Sopenharmony_ci * The goal of this macro is to return a symbol's address based on a 2168c2ecf20Sopenharmony_ci * PC-relative computation, as opposed to a loading the VA from a 2178c2ecf20Sopenharmony_ci * constant pool or something similar. This works well for HYP, as an 2188c2ecf20Sopenharmony_ci * absolute VA is guaranteed to be wrong. Only use this if trying to 2198c2ecf20Sopenharmony_ci * obtain the address of a symbol (i.e. not something you obtained by 2208c2ecf20Sopenharmony_ci * following a pointer). 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci#define hyp_symbol_addr(s) \ 2238c2ecf20Sopenharmony_ci ({ \ 2248c2ecf20Sopenharmony_ci typeof(s) *addr; \ 2258c2ecf20Sopenharmony_ci asm("adrp %0, %1\n" \ 2268c2ecf20Sopenharmony_ci "add %0, %0, :lo12:%1\n" \ 2278c2ecf20Sopenharmony_ci : "=r" (addr) : "S" (&s)); \ 2288c2ecf20Sopenharmony_ci addr; \ 2298c2ecf20Sopenharmony_ci }) 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#define __KVM_EXTABLE(from, to) \ 2328c2ecf20Sopenharmony_ci " .pushsection __kvm_ex_table, \"a\"\n" \ 2338c2ecf20Sopenharmony_ci " .align 3\n" \ 2348c2ecf20Sopenharmony_ci " .long (" #from " - .), (" #to " - .)\n" \ 2358c2ecf20Sopenharmony_ci " .popsection\n" 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci#define __kvm_at(at_op, addr) \ 2398c2ecf20Sopenharmony_ci( { \ 2408c2ecf20Sopenharmony_ci int __kvm_at_err = 0; \ 2418c2ecf20Sopenharmony_ci u64 spsr, elr; \ 2428c2ecf20Sopenharmony_ci asm volatile( \ 2438c2ecf20Sopenharmony_ci " mrs %1, spsr_el2\n" \ 2448c2ecf20Sopenharmony_ci " mrs %2, elr_el2\n" \ 2458c2ecf20Sopenharmony_ci "1: at "at_op", %3\n" \ 2468c2ecf20Sopenharmony_ci " isb\n" \ 2478c2ecf20Sopenharmony_ci " b 9f\n" \ 2488c2ecf20Sopenharmony_ci "2: msr spsr_el2, %1\n" \ 2498c2ecf20Sopenharmony_ci " msr elr_el2, %2\n" \ 2508c2ecf20Sopenharmony_ci " mov %w0, %4\n" \ 2518c2ecf20Sopenharmony_ci "9:\n" \ 2528c2ecf20Sopenharmony_ci __KVM_EXTABLE(1b, 2b) \ 2538c2ecf20Sopenharmony_ci : "+r" (__kvm_at_err), "=&r" (spsr), "=&r" (elr) \ 2548c2ecf20Sopenharmony_ci : "r" (addr), "i" (-EFAULT)); \ 2558c2ecf20Sopenharmony_ci __kvm_at_err; \ 2568c2ecf20Sopenharmony_ci} ) 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci#else /* __ASSEMBLY__ */ 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci.macro get_host_ctxt reg, tmp 2628c2ecf20Sopenharmony_ci adr_this_cpu \reg, kvm_host_data, \tmp 2638c2ecf20Sopenharmony_ci add \reg, \reg, #HOST_DATA_CONTEXT 2648c2ecf20Sopenharmony_ci.endm 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci.macro get_vcpu_ptr vcpu, ctxt 2678c2ecf20Sopenharmony_ci get_host_ctxt \ctxt, \vcpu 2688c2ecf20Sopenharmony_ci ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] 2698c2ecf20Sopenharmony_ci.endm 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci.macro get_loaded_vcpu vcpu, ctxt 2728c2ecf20Sopenharmony_ci adr_this_cpu \ctxt, kvm_hyp_ctxt, \vcpu 2738c2ecf20Sopenharmony_ci ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] 2748c2ecf20Sopenharmony_ci.endm 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci.macro set_loaded_vcpu vcpu, ctxt, tmp 2778c2ecf20Sopenharmony_ci adr_this_cpu \ctxt, kvm_hyp_ctxt, \tmp 2788c2ecf20Sopenharmony_ci str \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] 2798c2ecf20Sopenharmony_ci.endm 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/* 2828c2ecf20Sopenharmony_ci * KVM extable for unexpected exceptions. 2838c2ecf20Sopenharmony_ci * In the same format _asm_extable, but output to a different section so that 2848c2ecf20Sopenharmony_ci * it can be mapped to EL2. The KVM version is not sorted. The caller must 2858c2ecf20Sopenharmony_ci * ensure: 2868c2ecf20Sopenharmony_ci * x18 has the hypervisor value to allow any Shadow-Call-Stack instrumented 2878c2ecf20Sopenharmony_ci * code to write to it, and that SPSR_EL2 and ELR_EL2 are restored by the fixup. 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ci.macro _kvm_extable, from, to 2908c2ecf20Sopenharmony_ci .pushsection __kvm_ex_table, "a" 2918c2ecf20Sopenharmony_ci .align 3 2928c2ecf20Sopenharmony_ci .long (\from - .), (\to - .) 2938c2ecf20Sopenharmony_ci .popsection 2948c2ecf20Sopenharmony_ci.endm 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci#define CPU_XREG_OFFSET(x) (CPU_USER_PT_REGS + 8*x) 2978c2ecf20Sopenharmony_ci#define CPU_LR_OFFSET CPU_XREG_OFFSET(30) 2988c2ecf20Sopenharmony_ci#define CPU_SP_EL0_OFFSET (CPU_LR_OFFSET + 8) 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci/* 3018c2ecf20Sopenharmony_ci * We treat x18 as callee-saved as the host may use it as a platform 3028c2ecf20Sopenharmony_ci * register (e.g. for shadow call stack). 3038c2ecf20Sopenharmony_ci */ 3048c2ecf20Sopenharmony_ci.macro save_callee_saved_regs ctxt 3058c2ecf20Sopenharmony_ci str x18, [\ctxt, #CPU_XREG_OFFSET(18)] 3068c2ecf20Sopenharmony_ci stp x19, x20, [\ctxt, #CPU_XREG_OFFSET(19)] 3078c2ecf20Sopenharmony_ci stp x21, x22, [\ctxt, #CPU_XREG_OFFSET(21)] 3088c2ecf20Sopenharmony_ci stp x23, x24, [\ctxt, #CPU_XREG_OFFSET(23)] 3098c2ecf20Sopenharmony_ci stp x25, x26, [\ctxt, #CPU_XREG_OFFSET(25)] 3108c2ecf20Sopenharmony_ci stp x27, x28, [\ctxt, #CPU_XREG_OFFSET(27)] 3118c2ecf20Sopenharmony_ci stp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)] 3128c2ecf20Sopenharmony_ci.endm 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci.macro restore_callee_saved_regs ctxt 3158c2ecf20Sopenharmony_ci // We require \ctxt is not x18-x28 3168c2ecf20Sopenharmony_ci ldr x18, [\ctxt, #CPU_XREG_OFFSET(18)] 3178c2ecf20Sopenharmony_ci ldp x19, x20, [\ctxt, #CPU_XREG_OFFSET(19)] 3188c2ecf20Sopenharmony_ci ldp x21, x22, [\ctxt, #CPU_XREG_OFFSET(21)] 3198c2ecf20Sopenharmony_ci ldp x23, x24, [\ctxt, #CPU_XREG_OFFSET(23)] 3208c2ecf20Sopenharmony_ci ldp x25, x26, [\ctxt, #CPU_XREG_OFFSET(25)] 3218c2ecf20Sopenharmony_ci ldp x27, x28, [\ctxt, #CPU_XREG_OFFSET(27)] 3228c2ecf20Sopenharmony_ci ldp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)] 3238c2ecf20Sopenharmony_ci.endm 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci.macro save_sp_el0 ctxt, tmp 3268c2ecf20Sopenharmony_ci mrs \tmp, sp_el0 3278c2ecf20Sopenharmony_ci str \tmp, [\ctxt, #CPU_SP_EL0_OFFSET] 3288c2ecf20Sopenharmony_ci.endm 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci.macro restore_sp_el0 ctxt, tmp 3318c2ecf20Sopenharmony_ci ldr \tmp, [\ctxt, #CPU_SP_EL0_OFFSET] 3328c2ecf20Sopenharmony_ci msr sp_el0, \tmp 3338c2ecf20Sopenharmony_ci.endm 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci#endif 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci#endif /* __ARM_KVM_ASM_H__ */ 338