162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2012,2013 - ARM Ltd 462306a36Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef __ARM_KVM_ASM_H__ 862306a36Sopenharmony_ci#define __ARM_KVM_ASM_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <asm/hyp_image.h> 1162306a36Sopenharmony_ci#include <asm/insn.h> 1262306a36Sopenharmony_ci#include <asm/virt.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define ARM_EXIT_WITH_SERROR_BIT 31 1562306a36Sopenharmony_ci#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT)) 1662306a36Sopenharmony_ci#define ARM_EXCEPTION_IS_TRAP(x) (ARM_EXCEPTION_CODE((x)) == ARM_EXCEPTION_TRAP) 1762306a36Sopenharmony_ci#define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT)) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define ARM_EXCEPTION_IRQ 0 2062306a36Sopenharmony_ci#define ARM_EXCEPTION_EL1_SERROR 1 2162306a36Sopenharmony_ci#define ARM_EXCEPTION_TRAP 2 2262306a36Sopenharmony_ci#define ARM_EXCEPTION_IL 3 2362306a36Sopenharmony_ci/* The hyp-stub will return this for any kvm_call_hyp() call */ 2462306a36Sopenharmony_ci#define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define kvm_arm_exception_type \ 2762306a36Sopenharmony_ci {ARM_EXCEPTION_IRQ, "IRQ" }, \ 2862306a36Sopenharmony_ci {ARM_EXCEPTION_EL1_SERROR, "SERROR" }, \ 2962306a36Sopenharmony_ci {ARM_EXCEPTION_TRAP, "TRAP" }, \ 3062306a36Sopenharmony_ci {ARM_EXCEPTION_HYP_GONE, "HYP_GONE" } 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * Size of the HYP vectors preamble. kvm_patch_vector_branch() generates code 3462306a36Sopenharmony_ci * that jumps over this. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci#define KVM_VECTOR_PREAMBLE (2 * AARCH64_INSN_SIZE) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define KVM_HOST_SMCCC_ID(id) \ 3962306a36Sopenharmony_ci ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ 4062306a36Sopenharmony_ci ARM_SMCCC_SMC_64, \ 4162306a36Sopenharmony_ci ARM_SMCCC_OWNER_VENDOR_HYP, \ 4262306a36Sopenharmony_ci (id)) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define KVM_HOST_SMCCC_FUNC(name) KVM_HOST_SMCCC_ID(__KVM_HOST_SMCCC_FUNC_##name) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define __KVM_HOST_SMCCC_FUNC___kvm_hyp_init 0 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#include <linux/mm.h> 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cienum __kvm_host_smccc_func { 5362306a36Sopenharmony_ci /* Hypercalls available only prior to pKVM finalisation */ 5462306a36Sopenharmony_ci /* __KVM_HOST_SMCCC_FUNC___kvm_hyp_init */ 5562306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 = __KVM_HOST_SMCCC_FUNC___kvm_hyp_init + 1, 5662306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_init, 5762306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_create_private_mapping, 5862306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector, 5962306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs, 6062306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs, 6162306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config, 6262306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize, 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* Hypercalls available after pKVM finalisation */ 6562306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp, 6662306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_host_unshare_hyp, 6762306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc, 6862306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_vcpu_run, 6962306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context, 7062306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa, 7162306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa_nsh, 7262306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid, 7362306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_range, 7462306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context, 7562306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff, 7662306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr, 7762306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___vgic_v3_write_vmcr, 7862306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs, 7962306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs, 8062306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_init_traps, 8162306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_init_vm, 8262306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_init_vcpu, 8362306a36Sopenharmony_ci __KVM_HOST_SMCCC_FUNC___pkvm_teardown_vm, 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define DECLARE_KVM_VHE_SYM(sym) extern char sym[] 8762306a36Sopenharmony_ci#define DECLARE_KVM_NVHE_SYM(sym) extern char kvm_nvhe_sym(sym)[] 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * Define a pair of symbols sharing the same name but one defined in 9162306a36Sopenharmony_ci * VHE and the other in nVHE hyp implementations. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci#define DECLARE_KVM_HYP_SYM(sym) \ 9462306a36Sopenharmony_ci DECLARE_KVM_VHE_SYM(sym); \ 9562306a36Sopenharmony_ci DECLARE_KVM_NVHE_SYM(sym) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define DECLARE_KVM_VHE_PER_CPU(type, sym) \ 9862306a36Sopenharmony_ci DECLARE_PER_CPU(type, sym) 9962306a36Sopenharmony_ci#define DECLARE_KVM_NVHE_PER_CPU(type, sym) \ 10062306a36Sopenharmony_ci DECLARE_PER_CPU(type, kvm_nvhe_sym(sym)) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define DECLARE_KVM_HYP_PER_CPU(type, sym) \ 10362306a36Sopenharmony_ci DECLARE_KVM_VHE_PER_CPU(type, sym); \ 10462306a36Sopenharmony_ci DECLARE_KVM_NVHE_PER_CPU(type, sym) 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* 10762306a36Sopenharmony_ci * Compute pointer to a symbol defined in nVHE percpu region. 10862306a36Sopenharmony_ci * Returns NULL if percpu memory has not been allocated yet. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ci#define this_cpu_ptr_nvhe_sym(sym) per_cpu_ptr_nvhe_sym(sym, smp_processor_id()) 11162306a36Sopenharmony_ci#define per_cpu_ptr_nvhe_sym(sym, cpu) \ 11262306a36Sopenharmony_ci ({ \ 11362306a36Sopenharmony_ci unsigned long base, off; \ 11462306a36Sopenharmony_ci base = kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[cpu]; \ 11562306a36Sopenharmony_ci off = (unsigned long)&CHOOSE_NVHE_SYM(sym) - \ 11662306a36Sopenharmony_ci (unsigned long)&CHOOSE_NVHE_SYM(__per_cpu_start); \ 11762306a36Sopenharmony_ci base ? (typeof(CHOOSE_NVHE_SYM(sym))*)(base + off) : NULL; \ 11862306a36Sopenharmony_ci }) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#if defined(__KVM_NVHE_HYPERVISOR__) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define CHOOSE_NVHE_SYM(sym) sym 12362306a36Sopenharmony_ci#define CHOOSE_HYP_SYM(sym) CHOOSE_NVHE_SYM(sym) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* The nVHE hypervisor shouldn't even try to access VHE symbols */ 12662306a36Sopenharmony_ciextern void *__nvhe_undefined_symbol; 12762306a36Sopenharmony_ci#define CHOOSE_VHE_SYM(sym) __nvhe_undefined_symbol 12862306a36Sopenharmony_ci#define this_cpu_ptr_hyp_sym(sym) (&__nvhe_undefined_symbol) 12962306a36Sopenharmony_ci#define per_cpu_ptr_hyp_sym(sym, cpu) (&__nvhe_undefined_symbol) 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#elif defined(__KVM_VHE_HYPERVISOR__) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#define CHOOSE_VHE_SYM(sym) sym 13462306a36Sopenharmony_ci#define CHOOSE_HYP_SYM(sym) CHOOSE_VHE_SYM(sym) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* The VHE hypervisor shouldn't even try to access nVHE symbols */ 13762306a36Sopenharmony_ciextern void *__vhe_undefined_symbol; 13862306a36Sopenharmony_ci#define CHOOSE_NVHE_SYM(sym) __vhe_undefined_symbol 13962306a36Sopenharmony_ci#define this_cpu_ptr_hyp_sym(sym) (&__vhe_undefined_symbol) 14062306a36Sopenharmony_ci#define per_cpu_ptr_hyp_sym(sym, cpu) (&__vhe_undefined_symbol) 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#else 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci/* 14562306a36Sopenharmony_ci * BIG FAT WARNINGS: 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * - Don't be tempted to change the following is_kernel_in_hyp_mode() 14862306a36Sopenharmony_ci * to has_vhe(). has_vhe() is implemented as a *final* capability, 14962306a36Sopenharmony_ci * while this is used early at boot time, when the capabilities are 15062306a36Sopenharmony_ci * not final yet.... 15162306a36Sopenharmony_ci * 15262306a36Sopenharmony_ci * - Don't let the nVHE hypervisor have access to this, as it will 15362306a36Sopenharmony_ci * pick the *wrong* symbol (yes, it runs at EL2...). 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci#define CHOOSE_HYP_SYM(sym) (is_kernel_in_hyp_mode() \ 15662306a36Sopenharmony_ci ? CHOOSE_VHE_SYM(sym) \ 15762306a36Sopenharmony_ci : CHOOSE_NVHE_SYM(sym)) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci#define this_cpu_ptr_hyp_sym(sym) (is_kernel_in_hyp_mode() \ 16062306a36Sopenharmony_ci ? this_cpu_ptr(&sym) \ 16162306a36Sopenharmony_ci : this_cpu_ptr_nvhe_sym(sym)) 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#define per_cpu_ptr_hyp_sym(sym, cpu) (is_kernel_in_hyp_mode() \ 16462306a36Sopenharmony_ci ? per_cpu_ptr(&sym, cpu) \ 16562306a36Sopenharmony_ci : per_cpu_ptr_nvhe_sym(sym, cpu)) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#define CHOOSE_VHE_SYM(sym) sym 16862306a36Sopenharmony_ci#define CHOOSE_NVHE_SYM(sym) kvm_nvhe_sym(sym) 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#endif 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistruct kvm_nvhe_init_params { 17362306a36Sopenharmony_ci unsigned long mair_el2; 17462306a36Sopenharmony_ci unsigned long tcr_el2; 17562306a36Sopenharmony_ci unsigned long tpidr_el2; 17662306a36Sopenharmony_ci unsigned long stack_hyp_va; 17762306a36Sopenharmony_ci unsigned long stack_pa; 17862306a36Sopenharmony_ci phys_addr_t pgd_pa; 17962306a36Sopenharmony_ci unsigned long hcr_el2; 18062306a36Sopenharmony_ci unsigned long vttbr; 18162306a36Sopenharmony_ci unsigned long vtcr; 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/* 18562306a36Sopenharmony_ci * Used by the host in EL1 to dump the nVHE hypervisor backtrace on 18662306a36Sopenharmony_ci * hyp_panic() in non-protected mode. 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * @stack_base: hyp VA of the hyp_stack base. 18962306a36Sopenharmony_ci * @overflow_stack_base: hyp VA of the hyp_overflow_stack base. 19062306a36Sopenharmony_ci * @fp: hyp FP where the backtrace begins. 19162306a36Sopenharmony_ci * @pc: hyp PC where the backtrace begins. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_cistruct kvm_nvhe_stacktrace_info { 19462306a36Sopenharmony_ci unsigned long stack_base; 19562306a36Sopenharmony_ci unsigned long overflow_stack_base; 19662306a36Sopenharmony_ci unsigned long fp; 19762306a36Sopenharmony_ci unsigned long pc; 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/* Translate a kernel address @ptr into its equivalent linear mapping */ 20162306a36Sopenharmony_ci#define kvm_ksym_ref(ptr) \ 20262306a36Sopenharmony_ci ({ \ 20362306a36Sopenharmony_ci void *val = (ptr); \ 20462306a36Sopenharmony_ci if (!is_kernel_in_hyp_mode()) \ 20562306a36Sopenharmony_ci val = lm_alias((ptr)); \ 20662306a36Sopenharmony_ci val; \ 20762306a36Sopenharmony_ci }) 20862306a36Sopenharmony_ci#define kvm_ksym_ref_nvhe(sym) kvm_ksym_ref(kvm_nvhe_sym(sym)) 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistruct kvm; 21162306a36Sopenharmony_cistruct kvm_vcpu; 21262306a36Sopenharmony_cistruct kvm_s2_mmu; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__kvm_hyp_init); 21562306a36Sopenharmony_ciDECLARE_KVM_HYP_SYM(__kvm_hyp_vector); 21662306a36Sopenharmony_ci#define __kvm_hyp_init CHOOSE_NVHE_SYM(__kvm_hyp_init) 21762306a36Sopenharmony_ci#define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector) 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ciextern unsigned long kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[]; 22062306a36Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__per_cpu_start); 22162306a36Sopenharmony_ciDECLARE_KVM_NVHE_SYM(__per_cpu_end); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciDECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs); 22462306a36Sopenharmony_ci#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs) 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ciextern void __kvm_flush_vm_context(void); 22762306a36Sopenharmony_ciextern void __kvm_flush_cpu_context(struct kvm_s2_mmu *mmu); 22862306a36Sopenharmony_ciextern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa, 22962306a36Sopenharmony_ci int level); 23062306a36Sopenharmony_ciextern void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, 23162306a36Sopenharmony_ci phys_addr_t ipa, 23262306a36Sopenharmony_ci int level); 23362306a36Sopenharmony_ciextern void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu, 23462306a36Sopenharmony_ci phys_addr_t start, unsigned long pages); 23562306a36Sopenharmony_ciextern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ciextern void __kvm_timer_set_cntvoff(u64 cntvoff); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciextern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ciextern void __kvm_adjust_pc(struct kvm_vcpu *vcpu); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ciextern u64 __vgic_v3_get_gic_config(void); 24462306a36Sopenharmony_ciextern u64 __vgic_v3_read_vmcr(void); 24562306a36Sopenharmony_ciextern void __vgic_v3_write_vmcr(u32 vmcr); 24662306a36Sopenharmony_ciextern void __vgic_v3_init_lrs(void); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ciextern u64 __kvm_get_mdcr_el2(void); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci#define __KVM_EXTABLE(from, to) \ 25162306a36Sopenharmony_ci " .pushsection __kvm_ex_table, \"a\"\n" \ 25262306a36Sopenharmony_ci " .align 3\n" \ 25362306a36Sopenharmony_ci " .long (" #from " - .), (" #to " - .)\n" \ 25462306a36Sopenharmony_ci " .popsection\n" 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci#define __kvm_at(at_op, addr) \ 25862306a36Sopenharmony_ci( { \ 25962306a36Sopenharmony_ci int __kvm_at_err = 0; \ 26062306a36Sopenharmony_ci u64 spsr, elr; \ 26162306a36Sopenharmony_ci asm volatile( \ 26262306a36Sopenharmony_ci " mrs %1, spsr_el2\n" \ 26362306a36Sopenharmony_ci " mrs %2, elr_el2\n" \ 26462306a36Sopenharmony_ci "1: at "at_op", %3\n" \ 26562306a36Sopenharmony_ci " isb\n" \ 26662306a36Sopenharmony_ci " b 9f\n" \ 26762306a36Sopenharmony_ci "2: msr spsr_el2, %1\n" \ 26862306a36Sopenharmony_ci " msr elr_el2, %2\n" \ 26962306a36Sopenharmony_ci " mov %w0, %4\n" \ 27062306a36Sopenharmony_ci "9:\n" \ 27162306a36Sopenharmony_ci __KVM_EXTABLE(1b, 2b) \ 27262306a36Sopenharmony_ci : "+r" (__kvm_at_err), "=&r" (spsr), "=&r" (elr) \ 27362306a36Sopenharmony_ci : "r" (addr), "i" (-EFAULT)); \ 27462306a36Sopenharmony_ci __kvm_at_err; \ 27562306a36Sopenharmony_ci} ) 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_civoid __noreturn hyp_panic(void); 27862306a36Sopenharmony_ciasmlinkage void kvm_unexpected_el2_exception(void); 27962306a36Sopenharmony_ciasmlinkage void __noreturn hyp_panic(void); 28062306a36Sopenharmony_ciasmlinkage void __noreturn hyp_panic_bad_stack(void); 28162306a36Sopenharmony_ciasmlinkage void kvm_unexpected_el2_exception(void); 28262306a36Sopenharmony_cistruct kvm_cpu_context; 28362306a36Sopenharmony_civoid handle_trap(struct kvm_cpu_context *host_ctxt); 28462306a36Sopenharmony_ciasmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on); 28562306a36Sopenharmony_civoid __noreturn __pkvm_init_finalise(void); 28662306a36Sopenharmony_civoid kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); 28762306a36Sopenharmony_civoid kvm_patch_vector_branch(struct alt_instr *alt, 28862306a36Sopenharmony_ci __le32 *origptr, __le32 *updptr, int nr_inst); 28962306a36Sopenharmony_civoid kvm_get_kimage_voffset(struct alt_instr *alt, 29062306a36Sopenharmony_ci __le32 *origptr, __le32 *updptr, int nr_inst); 29162306a36Sopenharmony_civoid kvm_compute_final_ctr_el0(struct alt_instr *alt, 29262306a36Sopenharmony_ci __le32 *origptr, __le32 *updptr, int nr_inst); 29362306a36Sopenharmony_civoid __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr_virt, 29462306a36Sopenharmony_ci u64 elr_phys, u64 par, uintptr_t vcpu, u64 far, u64 hpfar); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci#else /* __ASSEMBLY__ */ 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci.macro get_host_ctxt reg, tmp 29962306a36Sopenharmony_ci adr_this_cpu \reg, kvm_host_data, \tmp 30062306a36Sopenharmony_ci add \reg, \reg, #HOST_DATA_CONTEXT 30162306a36Sopenharmony_ci.endm 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci.macro get_vcpu_ptr vcpu, ctxt 30462306a36Sopenharmony_ci get_host_ctxt \ctxt, \vcpu 30562306a36Sopenharmony_ci ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] 30662306a36Sopenharmony_ci.endm 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci.macro get_loaded_vcpu vcpu, ctxt 30962306a36Sopenharmony_ci adr_this_cpu \ctxt, kvm_hyp_ctxt, \vcpu 31062306a36Sopenharmony_ci ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] 31162306a36Sopenharmony_ci.endm 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci.macro set_loaded_vcpu vcpu, ctxt, tmp 31462306a36Sopenharmony_ci adr_this_cpu \ctxt, kvm_hyp_ctxt, \tmp 31562306a36Sopenharmony_ci str \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] 31662306a36Sopenharmony_ci.endm 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/* 31962306a36Sopenharmony_ci * KVM extable for unexpected exceptions. 32062306a36Sopenharmony_ci * Create a struct kvm_exception_table_entry output to a section that can be 32162306a36Sopenharmony_ci * mapped by EL2. The table is not sorted. 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * The caller must ensure: 32462306a36Sopenharmony_ci * x18 has the hypervisor value to allow any Shadow-Call-Stack instrumented 32562306a36Sopenharmony_ci * code to write to it, and that SPSR_EL2 and ELR_EL2 are restored by the fixup. 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci.macro _kvm_extable, from, to 32862306a36Sopenharmony_ci .pushsection __kvm_ex_table, "a" 32962306a36Sopenharmony_ci .align 3 33062306a36Sopenharmony_ci .long (\from - .), (\to - .) 33162306a36Sopenharmony_ci .popsection 33262306a36Sopenharmony_ci.endm 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci#define CPU_XREG_OFFSET(x) (CPU_USER_PT_REGS + 8*x) 33562306a36Sopenharmony_ci#define CPU_LR_OFFSET CPU_XREG_OFFSET(30) 33662306a36Sopenharmony_ci#define CPU_SP_EL0_OFFSET (CPU_LR_OFFSET + 8) 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci/* 33962306a36Sopenharmony_ci * We treat x18 as callee-saved as the host may use it as a platform 34062306a36Sopenharmony_ci * register (e.g. for shadow call stack). 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_ci.macro save_callee_saved_regs ctxt 34362306a36Sopenharmony_ci str x18, [\ctxt, #CPU_XREG_OFFSET(18)] 34462306a36Sopenharmony_ci stp x19, x20, [\ctxt, #CPU_XREG_OFFSET(19)] 34562306a36Sopenharmony_ci stp x21, x22, [\ctxt, #CPU_XREG_OFFSET(21)] 34662306a36Sopenharmony_ci stp x23, x24, [\ctxt, #CPU_XREG_OFFSET(23)] 34762306a36Sopenharmony_ci stp x25, x26, [\ctxt, #CPU_XREG_OFFSET(25)] 34862306a36Sopenharmony_ci stp x27, x28, [\ctxt, #CPU_XREG_OFFSET(27)] 34962306a36Sopenharmony_ci stp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)] 35062306a36Sopenharmony_ci.endm 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci.macro restore_callee_saved_regs ctxt 35362306a36Sopenharmony_ci // We require \ctxt is not x18-x28 35462306a36Sopenharmony_ci ldr x18, [\ctxt, #CPU_XREG_OFFSET(18)] 35562306a36Sopenharmony_ci ldp x19, x20, [\ctxt, #CPU_XREG_OFFSET(19)] 35662306a36Sopenharmony_ci ldp x21, x22, [\ctxt, #CPU_XREG_OFFSET(21)] 35762306a36Sopenharmony_ci ldp x23, x24, [\ctxt, #CPU_XREG_OFFSET(23)] 35862306a36Sopenharmony_ci ldp x25, x26, [\ctxt, #CPU_XREG_OFFSET(25)] 35962306a36Sopenharmony_ci ldp x27, x28, [\ctxt, #CPU_XREG_OFFSET(27)] 36062306a36Sopenharmony_ci ldp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)] 36162306a36Sopenharmony_ci.endm 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci.macro save_sp_el0 ctxt, tmp 36462306a36Sopenharmony_ci mrs \tmp, sp_el0 36562306a36Sopenharmony_ci str \tmp, [\ctxt, #CPU_SP_EL0_OFFSET] 36662306a36Sopenharmony_ci.endm 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci.macro restore_sp_el0 ctxt, tmp 36962306a36Sopenharmony_ci ldr \tmp, [\ctxt, #CPU_SP_EL0_OFFSET] 37062306a36Sopenharmony_ci msr sp_el0, \tmp 37162306a36Sopenharmony_ci.endm 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci#endif 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci#endif /* __ARM_KVM_ASM_H__ */ 376