mirror of
https://github.com/torvalds/linux.git
synced 2024-12-13 22:53:20 +00:00
830dcc9f9a
We expect all CPUs to be running at the same EL inside the kernel with or without VHE enabled and we have strict checks to ensure that any mismatch triggers a kernel panic. If VHE is enabled, we use the feature based on the boot CPU and all other CPUs should follow. This makes it a perfect candidate for a capability based on the boot CPU, which should be matched by all the CPUs (both when is ON and OFF). This saves us some not-so-pretty hooks and special code, just for verifying the conflict. The patch also makes the VHE capability entry depend on CONFIG_ARM64_VHE. Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Will Deacon <will.deacon@arm.com> Reviewed-by: Dave Martin <dave.martin@arm.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
108 lines
3.0 KiB
C
108 lines
3.0 KiB
C
/*
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __ASM__VIRT_H
|
|
#define __ASM__VIRT_H
|
|
|
|
/*
|
|
* The arm64 hcall implementation uses x0 to specify the hcall
|
|
* number. A value less than HVC_STUB_HCALL_NR indicates a special
|
|
* hcall, such as set vector. Any other value is handled in a
|
|
* hypervisor specific way.
|
|
*
|
|
* The hypercall is allowed to clobber any of the caller-saved
|
|
* registers (x0-x18), so it is advisable to use it through the
|
|
* indirection of a function call (as implemented in hyp-stub.S).
|
|
*/
|
|
|
|
/*
|
|
* HVC_SET_VECTORS - Set the value of the vbar_el2 register.
|
|
*
|
|
* @x1: Physical address of the new vector table.
|
|
*/
|
|
#define HVC_SET_VECTORS 0
|
|
|
|
/*
|
|
* HVC_SOFT_RESTART - CPU soft reset, used by the cpu_soft_restart routine.
|
|
*/
|
|
#define HVC_SOFT_RESTART 1
|
|
|
|
/*
|
|
* HVC_RESET_VECTORS - Restore the vectors to the original HYP stubs
|
|
*/
|
|
#define HVC_RESET_VECTORS 2
|
|
|
|
/* Max number of HYP stub hypercalls */
|
|
#define HVC_STUB_HCALL_NR 3
|
|
|
|
/* Error returned when an invalid stub number is passed into x0 */
|
|
#define HVC_STUB_ERR 0xbadca11
|
|
|
|
#define BOOT_CPU_MODE_EL1 (0xe11)
|
|
#define BOOT_CPU_MODE_EL2 (0xe12)
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <asm/ptrace.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/sysreg.h>
|
|
#include <asm/cpufeature.h>
|
|
|
|
/*
|
|
* __boot_cpu_mode records what mode CPUs were booted in.
|
|
* A correctly-implemented bootloader must start all CPUs in the same mode:
|
|
* In this case, both 32bit halves of __boot_cpu_mode will contain the
|
|
* same value (either 0 if booted in EL1, BOOT_CPU_MODE_EL2 if booted in EL2).
|
|
*
|
|
* Should the bootloader fail to do this, the two values will be different.
|
|
* This allows the kernel to flag an error when the secondaries have come up.
|
|
*/
|
|
extern u32 __boot_cpu_mode[2];
|
|
|
|
void __hyp_set_vectors(phys_addr_t phys_vector_base);
|
|
void __hyp_reset_vectors(void);
|
|
|
|
/* Reports the availability of HYP mode */
|
|
static inline bool is_hyp_mode_available(void)
|
|
{
|
|
return (__boot_cpu_mode[0] == BOOT_CPU_MODE_EL2 &&
|
|
__boot_cpu_mode[1] == BOOT_CPU_MODE_EL2);
|
|
}
|
|
|
|
/* Check if the bootloader has booted CPUs in different modes */
|
|
static inline bool is_hyp_mode_mismatched(void)
|
|
{
|
|
return __boot_cpu_mode[0] != __boot_cpu_mode[1];
|
|
}
|
|
|
|
static inline bool is_kernel_in_hyp_mode(void)
|
|
{
|
|
return read_sysreg(CurrentEL) == CurrentEL_EL2;
|
|
}
|
|
|
|
static inline bool has_vhe(void)
|
|
{
|
|
if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif /* ! __ASM__VIRT_H */
|