18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 48c2ecf20Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef __ASM__VIRT_H 88c2ecf20Sopenharmony_ci#define __ASM__VIRT_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* 118c2ecf20Sopenharmony_ci * The arm64 hcall implementation uses x0 to specify the hcall 128c2ecf20Sopenharmony_ci * number. A value less than HVC_STUB_HCALL_NR indicates a special 138c2ecf20Sopenharmony_ci * hcall, such as set vector. Any other value is handled in a 148c2ecf20Sopenharmony_ci * hypervisor specific way. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * The hypercall is allowed to clobber any of the caller-saved 178c2ecf20Sopenharmony_ci * registers (x0-x18), so it is advisable to use it through the 188c2ecf20Sopenharmony_ci * indirection of a function call (as implemented in hyp-stub.S). 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * HVC_SET_VECTORS - Set the value of the vbar_el2 register. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * @x1: Physical address of the new vector table. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci#define HVC_SET_VECTORS 0 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * HVC_SOFT_RESTART - CPU soft reset, used by the cpu_soft_restart routine. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci#define HVC_SOFT_RESTART 1 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* 348c2ecf20Sopenharmony_ci * HVC_RESET_VECTORS - Restore the vectors to the original HYP stubs 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci#define HVC_RESET_VECTORS 2 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* Max number of HYP stub hypercalls */ 398c2ecf20Sopenharmony_ci#define HVC_STUB_HCALL_NR 3 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* Error returned when an invalid stub number is passed into x0 */ 428c2ecf20Sopenharmony_ci#define HVC_STUB_ERR 0xbadca11 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define BOOT_CPU_MODE_EL1 (0xe11) 458c2ecf20Sopenharmony_ci#define BOOT_CPU_MODE_EL2 (0xe12) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 508c2ecf20Sopenharmony_ci#include <asm/sections.h> 518c2ecf20Sopenharmony_ci#include <asm/sysreg.h> 528c2ecf20Sopenharmony_ci#include <asm/cpufeature.h> 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* 558c2ecf20Sopenharmony_ci * __boot_cpu_mode records what mode CPUs were booted in. 568c2ecf20Sopenharmony_ci * A correctly-implemented bootloader must start all CPUs in the same mode: 578c2ecf20Sopenharmony_ci * In this case, both 32bit halves of __boot_cpu_mode will contain the 588c2ecf20Sopenharmony_ci * same value (either 0 if booted in EL1, BOOT_CPU_MODE_EL2 if booted in EL2). 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * Should the bootloader fail to do this, the two values will be different. 618c2ecf20Sopenharmony_ci * This allows the kernel to flag an error when the secondaries have come up. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ciextern u32 __boot_cpu_mode[2]; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_civoid __hyp_set_vectors(phys_addr_t phys_vector_base); 668c2ecf20Sopenharmony_civoid __hyp_reset_vectors(void); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Reports the availability of HYP mode */ 698c2ecf20Sopenharmony_cistatic inline bool is_hyp_mode_available(void) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci return (__boot_cpu_mode[0] == BOOT_CPU_MODE_EL2 && 728c2ecf20Sopenharmony_ci __boot_cpu_mode[1] == BOOT_CPU_MODE_EL2); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* Check if the bootloader has booted CPUs in different modes */ 768c2ecf20Sopenharmony_cistatic inline bool is_hyp_mode_mismatched(void) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci return __boot_cpu_mode[0] != __boot_cpu_mode[1]; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic inline bool is_kernel_in_hyp_mode(void) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci return read_sysreg(CurrentEL) == CurrentEL_EL2; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic __always_inline bool has_vhe(void) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * Code only run in VHE/NVHE hyp context can assume VHE is present or 908c2ecf20Sopenharmony_ci * absent. Otherwise fall back to caps. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci if (is_vhe_hyp_code()) 938c2ecf20Sopenharmony_ci return true; 948c2ecf20Sopenharmony_ci else if (is_nvhe_hyp_code()) 958c2ecf20Sopenharmony_ci return false; 968c2ecf20Sopenharmony_ci else 978c2ecf20Sopenharmony_ci return cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci#endif /* ! __ASM__VIRT_H */ 103