162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2015 - ARM Ltd 462306a36Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef __ARM64_KVM_HYP_H__ 862306a36Sopenharmony_ci#define __ARM64_KVM_HYP_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/compiler.h> 1162306a36Sopenharmony_ci#include <linux/kvm_host.h> 1262306a36Sopenharmony_ci#include <asm/alternative.h> 1362306a36Sopenharmony_ci#include <asm/sysreg.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciDECLARE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); 1662306a36Sopenharmony_ciDECLARE_PER_CPU(unsigned long, kvm_hyp_vector); 1762306a36Sopenharmony_ciDECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Unified accessors for registers that have a different encoding 2162306a36Sopenharmony_ci * between VHE and non-VHE. They must be specified without their "ELx" 2262306a36Sopenharmony_ci * encoding, but with the SYS_ prefix, as defined in asm/sysreg.h. 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#if defined(__KVM_VHE_HYPERVISOR__) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define read_sysreg_el0(r) read_sysreg_s(r##_EL02) 2862306a36Sopenharmony_ci#define write_sysreg_el0(v,r) write_sysreg_s(v, r##_EL02) 2962306a36Sopenharmony_ci#define read_sysreg_el1(r) read_sysreg_s(r##_EL12) 3062306a36Sopenharmony_ci#define write_sysreg_el1(v,r) write_sysreg_s(v, r##_EL12) 3162306a36Sopenharmony_ci#define read_sysreg_el2(r) read_sysreg_s(r##_EL1) 3262306a36Sopenharmony_ci#define write_sysreg_el2(v,r) write_sysreg_s(v, r##_EL1) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#else // !__KVM_VHE_HYPERVISOR__ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#if defined(__KVM_NVHE_HYPERVISOR__) 3762306a36Sopenharmony_ci#define VHE_ALT_KEY ARM64_KVM_HVHE 3862306a36Sopenharmony_ci#else 3962306a36Sopenharmony_ci#define VHE_ALT_KEY ARM64_HAS_VIRT_HOST_EXTN 4062306a36Sopenharmony_ci#endif 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define read_sysreg_elx(r,nvh,vh) \ 4362306a36Sopenharmony_ci ({ \ 4462306a36Sopenharmony_ci u64 reg; \ 4562306a36Sopenharmony_ci asm volatile(ALTERNATIVE(__mrs_s("%0", r##nvh), \ 4662306a36Sopenharmony_ci __mrs_s("%0", r##vh), \ 4762306a36Sopenharmony_ci VHE_ALT_KEY) \ 4862306a36Sopenharmony_ci : "=r" (reg)); \ 4962306a36Sopenharmony_ci reg; \ 5062306a36Sopenharmony_ci }) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define write_sysreg_elx(v,r,nvh,vh) \ 5362306a36Sopenharmony_ci do { \ 5462306a36Sopenharmony_ci u64 __val = (u64)(v); \ 5562306a36Sopenharmony_ci asm volatile(ALTERNATIVE(__msr_s(r##nvh, "%x0"), \ 5662306a36Sopenharmony_ci __msr_s(r##vh, "%x0"), \ 5762306a36Sopenharmony_ci VHE_ALT_KEY) \ 5862306a36Sopenharmony_ci : : "rZ" (__val)); \ 5962306a36Sopenharmony_ci } while (0) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define read_sysreg_el0(r) read_sysreg_elx(r, _EL0, _EL02) 6262306a36Sopenharmony_ci#define write_sysreg_el0(v,r) write_sysreg_elx(v, r, _EL0, _EL02) 6362306a36Sopenharmony_ci#define read_sysreg_el1(r) read_sysreg_elx(r, _EL1, _EL12) 6462306a36Sopenharmony_ci#define write_sysreg_el1(v,r) write_sysreg_elx(v, r, _EL1, _EL12) 6562306a36Sopenharmony_ci#define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1) 6662306a36Sopenharmony_ci#define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#endif // __KVM_VHE_HYPERVISOR__ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 7162306a36Sopenharmony_ci * Without an __arch_swab32(), we fall back to ___constant_swab32(), but the 7262306a36Sopenharmony_ci * static inline can allow the compiler to out-of-line this. KVM always wants 7362306a36Sopenharmony_ci * the macro version as its always inlined. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci#define __kvm_swab32(x) ___constant_swab32(x) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciint __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_civoid __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if); 8062306a36Sopenharmony_civoid __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if); 8162306a36Sopenharmony_civoid __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if); 8262306a36Sopenharmony_civoid __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if); 8362306a36Sopenharmony_civoid __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if); 8462306a36Sopenharmony_civoid __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if); 8562306a36Sopenharmony_ciint __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#ifdef __KVM_NVHE_HYPERVISOR__ 8862306a36Sopenharmony_civoid __timer_enable_traps(struct kvm_vcpu *vcpu); 8962306a36Sopenharmony_civoid __timer_disable_traps(struct kvm_vcpu *vcpu); 9062306a36Sopenharmony_ci#endif 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#ifdef __KVM_NVHE_HYPERVISOR__ 9362306a36Sopenharmony_civoid __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt); 9462306a36Sopenharmony_civoid __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt); 9562306a36Sopenharmony_ci#else 9662306a36Sopenharmony_civoid sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt); 9762306a36Sopenharmony_civoid sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt); 9862306a36Sopenharmony_civoid sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt); 9962306a36Sopenharmony_civoid sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt); 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_civoid __debug_switch_to_guest(struct kvm_vcpu *vcpu); 10362306a36Sopenharmony_civoid __debug_switch_to_host(struct kvm_vcpu *vcpu); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#ifdef __KVM_NVHE_HYPERVISOR__ 10662306a36Sopenharmony_civoid __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu); 10762306a36Sopenharmony_civoid __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu); 10862306a36Sopenharmony_ci#endif 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_civoid __fpsimd_save_state(struct user_fpsimd_state *fp_regs); 11162306a36Sopenharmony_civoid __fpsimd_restore_state(struct user_fpsimd_state *fp_regs); 11262306a36Sopenharmony_civoid __sve_restore_state(void *sve_pffr, u32 *fpsr); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci#ifndef __KVM_NVHE_HYPERVISOR__ 11562306a36Sopenharmony_civoid activate_traps_vhe_load(struct kvm_vcpu *vcpu); 11662306a36Sopenharmony_civoid deactivate_traps_vhe_put(struct kvm_vcpu *vcpu); 11762306a36Sopenharmony_ci#endif 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciu64 __guest_enter(struct kvm_vcpu *vcpu); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cibool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#ifdef __KVM_NVHE_HYPERVISOR__ 12462306a36Sopenharmony_civoid __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr, 12562306a36Sopenharmony_ci u64 elr, u64 par); 12662306a36Sopenharmony_ci#endif 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#ifdef __KVM_NVHE_HYPERVISOR__ 12962306a36Sopenharmony_civoid __pkvm_init_switch_pgd(phys_addr_t phys, unsigned long size, 13062306a36Sopenharmony_ci phys_addr_t pgd, void *sp, void *cont_fn); 13162306a36Sopenharmony_ciint __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus, 13262306a36Sopenharmony_ci unsigned long *per_cpu_base, u32 hyp_va_bits); 13362306a36Sopenharmony_civoid __noreturn __host_enter(struct kvm_cpu_context *host_ctxt); 13462306a36Sopenharmony_ci#endif 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64pfr0_el1_sys_val); 13762306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64pfr1_el1_sys_val); 13862306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64isar0_el1_sys_val); 13962306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64isar1_el1_sys_val); 14062306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64isar2_el1_sys_val); 14162306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64mmfr0_el1_sys_val); 14262306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64mmfr1_el1_sys_val); 14362306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64mmfr2_el1_sys_val); 14462306a36Sopenharmony_ciextern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciextern unsigned long kvm_nvhe_sym(__icache_flags); 14762306a36Sopenharmony_ciextern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#endif /* __ARM64_KVM_HYP_H__ */ 150