2019-06-03 05:44:50 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2015-10-21 09:09:49 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 - ARM Ltd
|
|
|
|
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __ARM64_KVM_HYP_H__
|
|
|
|
#define __ARM64_KVM_HYP_H__
|
|
|
|
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
#include <linux/kvm_host.h>
|
2018-12-06 17:31:24 +00:00
|
|
|
#include <asm/alternative.h>
|
2015-10-21 09:09:49 +00:00
|
|
|
#include <asm/sysreg.h>
|
|
|
|
|
2020-09-15 10:46:32 +00:00
|
|
|
DECLARE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
|
2020-09-15 10:46:29 +00:00
|
|
|
DECLARE_PER_CPU(unsigned long, kvm_hyp_vector);
|
2020-12-02 18:41:06 +00:00
|
|
|
DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
|
2020-09-15 10:46:29 +00:00
|
|
|
|
2015-10-28 12:00:00 +00:00
|
|
|
#define read_sysreg_elx(r,nvh,vh) \
|
|
|
|
({ \
|
|
|
|
u64 reg; \
|
KVM: arm64: Migrate _elx sysreg accessors to msr_s/mrs_s
Currently, the {read,write}_sysreg_el*() accessors for accessing
particular ELs' sysregs in the presence of VHE rely on some local
hacks and define their system register encodings in a way that is
inconsistent with the core definitions in <asm/sysreg.h>.
As a result, it is necessary to add duplicate definitions for any
system register that already needs a definition in sysreg.h for
other reasons.
This is a bit of a maintenance headache, and the reasons for the
_el*() accessors working the way they do is a bit historical.
This patch gets rid of the shadow sysreg definitions in
<asm/kvm_hyp.h>, converts the _el*() accessors to use the core
__msr_s/__mrs_s interface, and converts all call sites to use the
standard sysreg #define names (i.e., upper case, with SYS_ prefix).
This patch will conflict heavily anyway, so the opportunity
to clean up some bad whitespace in the context of the changes is
taken.
The change exposes a few system registers that have no sysreg.h
definition, due to msr_s/mrs_s being used in place of msr/mrs:
additions are made in order to fill in the gaps.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoffer Dall <christoffer.dall@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Link: https://www.spinics.net/lists/kvm-arm/msg31717.html
[Rebased to v4.21-rc1]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
[Rebased to v5.2-rc5, changelog updates]
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2019-04-06 10:29:40 +00:00
|
|
|
asm volatile(ALTERNATIVE(__mrs_s("%0", r##nvh), \
|
arm64: sysreg: Make mrs_s and msr_s macros work with Clang and LTO
Clang's integrated assembler does not allow assembly macros defined
in one inline asm block using the .macro directive to be used across
separate asm blocks. LLVM developers consider this a feature and not a
bug, recommending code refactoring:
https://bugs.llvm.org/show_bug.cgi?id=19749
As binutils doesn't allow macros to be redefined, this change uses
UNDEFINE_MRS_S and UNDEFINE_MSR_S to define corresponding macros
in-place and workaround gcc and clang limitations on redefining macros
across different assembler blocks.
Specifically, the current state after preprocessing looks like this:
asm volatile(".macro mXX_s ... .endm");
void f()
{
asm volatile("mXX_s a, b");
}
With GCC, it gives macro redefinition error because sysreg.h is included
in multiple source files, and assembler code for all of them is later
combined for LTO (I've seen an intermediate file with hundreds of
identical definitions).
With clang, it gives macro undefined error because clang doesn't allow
sharing macros between inline asm statements.
I also seem to remember catching another sort of undefined error with
GCC due to reordering of macro definition asm statement and generated
asm code for function that uses the macro.
The solution with defining and undefining for each use, while certainly
not elegant, satisfies both GCC and clang, LTO and non-LTO.
Co-developed-by: Alex Matveev <alxmtvv@gmail.com>
Co-developed-by: Yury Norov <ynorov@caviumnetworks.com>
Co-developed-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2019-04-24 16:55:37 +00:00
|
|
|
__mrs_s("%0", r##vh), \
|
2015-10-28 12:00:00 +00:00
|
|
|
ARM64_HAS_VIRT_HOST_EXTN) \
|
|
|
|
: "=r" (reg)); \
|
|
|
|
reg; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define write_sysreg_elx(v,r,nvh,vh) \
|
|
|
|
do { \
|
|
|
|
u64 __val = (u64)(v); \
|
KVM: arm64: Migrate _elx sysreg accessors to msr_s/mrs_s
Currently, the {read,write}_sysreg_el*() accessors for accessing
particular ELs' sysregs in the presence of VHE rely on some local
hacks and define their system register encodings in a way that is
inconsistent with the core definitions in <asm/sysreg.h>.
As a result, it is necessary to add duplicate definitions for any
system register that already needs a definition in sysreg.h for
other reasons.
This is a bit of a maintenance headache, and the reasons for the
_el*() accessors working the way they do is a bit historical.
This patch gets rid of the shadow sysreg definitions in
<asm/kvm_hyp.h>, converts the _el*() accessors to use the core
__msr_s/__mrs_s interface, and converts all call sites to use the
standard sysreg #define names (i.e., upper case, with SYS_ prefix).
This patch will conflict heavily anyway, so the opportunity
to clean up some bad whitespace in the context of the changes is
taken.
The change exposes a few system registers that have no sysreg.h
definition, due to msr_s/mrs_s being used in place of msr/mrs:
additions are made in order to fill in the gaps.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoffer Dall <christoffer.dall@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Link: https://www.spinics.net/lists/kvm-arm/msg31717.html
[Rebased to v4.21-rc1]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
[Rebased to v5.2-rc5, changelog updates]
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2019-04-06 10:29:40 +00:00
|
|
|
asm volatile(ALTERNATIVE(__msr_s(r##nvh, "%x0"), \
|
arm64: sysreg: Make mrs_s and msr_s macros work with Clang and LTO
Clang's integrated assembler does not allow assembly macros defined
in one inline asm block using the .macro directive to be used across
separate asm blocks. LLVM developers consider this a feature and not a
bug, recommending code refactoring:
https://bugs.llvm.org/show_bug.cgi?id=19749
As binutils doesn't allow macros to be redefined, this change uses
UNDEFINE_MRS_S and UNDEFINE_MSR_S to define corresponding macros
in-place and workaround gcc and clang limitations on redefining macros
across different assembler blocks.
Specifically, the current state after preprocessing looks like this:
asm volatile(".macro mXX_s ... .endm");
void f()
{
asm volatile("mXX_s a, b");
}
With GCC, it gives macro redefinition error because sysreg.h is included
in multiple source files, and assembler code for all of them is later
combined for LTO (I've seen an intermediate file with hundreds of
identical definitions).
With clang, it gives macro undefined error because clang doesn't allow
sharing macros between inline asm statements.
I also seem to remember catching another sort of undefined error with
GCC due to reordering of macro definition asm statement and generated
asm code for function that uses the macro.
The solution with defining and undefining for each use, while certainly
not elegant, satisfies both GCC and clang, LTO and non-LTO.
Co-developed-by: Alex Matveev <alxmtvv@gmail.com>
Co-developed-by: Yury Norov <ynorov@caviumnetworks.com>
Co-developed-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2019-04-24 16:55:37 +00:00
|
|
|
__msr_s(r##vh, "%x0"), \
|
2015-10-28 12:00:00 +00:00
|
|
|
ARM64_HAS_VIRT_HOST_EXTN) \
|
|
|
|
: : "rZ" (__val)); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unified accessors for registers that have a different encoding
|
|
|
|
* between VHE and non-VHE. They must be specified without their "ELx"
|
KVM: arm64: Migrate _elx sysreg accessors to msr_s/mrs_s
Currently, the {read,write}_sysreg_el*() accessors for accessing
particular ELs' sysregs in the presence of VHE rely on some local
hacks and define their system register encodings in a way that is
inconsistent with the core definitions in <asm/sysreg.h>.
As a result, it is necessary to add duplicate definitions for any
system register that already needs a definition in sysreg.h for
other reasons.
This is a bit of a maintenance headache, and the reasons for the
_el*() accessors working the way they do is a bit historical.
This patch gets rid of the shadow sysreg definitions in
<asm/kvm_hyp.h>, converts the _el*() accessors to use the core
__msr_s/__mrs_s interface, and converts all call sites to use the
standard sysreg #define names (i.e., upper case, with SYS_ prefix).
This patch will conflict heavily anyway, so the opportunity
to clean up some bad whitespace in the context of the changes is
taken.
The change exposes a few system registers that have no sysreg.h
definition, due to msr_s/mrs_s being used in place of msr/mrs:
additions are made in order to fill in the gaps.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoffer Dall <christoffer.dall@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Link: https://www.spinics.net/lists/kvm-arm/msg31717.html
[Rebased to v4.21-rc1]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
[Rebased to v5.2-rc5, changelog updates]
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2019-04-06 10:29:40 +00:00
|
|
|
* encoding, but with the SYS_ prefix, as defined in asm/sysreg.h.
|
2015-10-28 12:00:00 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define read_sysreg_el0(r) read_sysreg_elx(r, _EL0, _EL02)
|
|
|
|
#define write_sysreg_el0(v,r) write_sysreg_elx(v, r, _EL0, _EL02)
|
|
|
|
#define read_sysreg_el1(r) read_sysreg_elx(r, _EL1, _EL12)
|
|
|
|
#define write_sysreg_el1(v,r) write_sysreg_elx(v, r, _EL1, _EL12)
|
KVM: arm64: Migrate _elx sysreg accessors to msr_s/mrs_s
Currently, the {read,write}_sysreg_el*() accessors for accessing
particular ELs' sysregs in the presence of VHE rely on some local
hacks and define their system register encodings in a way that is
inconsistent with the core definitions in <asm/sysreg.h>.
As a result, it is necessary to add duplicate definitions for any
system register that already needs a definition in sysreg.h for
other reasons.
This is a bit of a maintenance headache, and the reasons for the
_el*() accessors working the way they do is a bit historical.
This patch gets rid of the shadow sysreg definitions in
<asm/kvm_hyp.h>, converts the _el*() accessors to use the core
__msr_s/__mrs_s interface, and converts all call sites to use the
standard sysreg #define names (i.e., upper case, with SYS_ prefix).
This patch will conflict heavily anyway, so the opportunity
to clean up some bad whitespace in the context of the changes is
taken.
The change exposes a few system registers that have no sysreg.h
definition, due to msr_s/mrs_s being used in place of msr/mrs:
additions are made in order to fill in the gaps.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoffer Dall <christoffer.dall@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Link: https://www.spinics.net/lists/kvm-arm/msg31717.html
[Rebased to v4.21-rc1]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
[Rebased to v5.2-rc5, changelog updates]
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2019-04-06 10:29:40 +00:00
|
|
|
#define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1)
|
|
|
|
#define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1)
|
2015-10-28 12:00:00 +00:00
|
|
|
|
2020-02-20 16:58:38 +00:00
|
|
|
/*
|
|
|
|
* Without an __arch_swab32(), we fall back to ___constant_swab32(), but the
|
|
|
|
* static inline can allow the compiler to out-of-line this. KVM always wants
|
|
|
|
* the macro version as its always inlined.
|
|
|
|
*/
|
|
|
|
#define __kvm_swab32(x) ___constant_swab32(x)
|
|
|
|
|
2016-09-06 13:02:17 +00:00
|
|
|
int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
|
2015-10-19 14:50:37 +00:00
|
|
|
|
2018-12-01 16:41:28 +00:00
|
|
|
void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if);
|
|
|
|
void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if);
|
|
|
|
void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if);
|
|
|
|
void __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if);
|
|
|
|
void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if);
|
|
|
|
void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if);
|
2017-06-09 11:49:33 +00:00
|
|
|
int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
|
2015-10-19 14:50:58 +00:00
|
|
|
|
2020-06-25 13:14:17 +00:00
|
|
|
#ifdef __KVM_NVHE_HYPERVISOR__
|
2017-01-04 15:10:28 +00:00
|
|
|
void __timer_enable_traps(struct kvm_vcpu *vcpu);
|
|
|
|
void __timer_disable_traps(struct kvm_vcpu *vcpu);
|
2020-06-25 13:14:17 +00:00
|
|
|
#endif
|
2015-10-19 15:32:20 +00:00
|
|
|
|
2020-06-25 13:14:16 +00:00
|
|
|
#ifdef __KVM_NVHE_HYPERVISOR__
|
2017-10-10 20:40:13 +00:00
|
|
|
void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
|
|
|
|
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
|
2020-06-25 13:14:16 +00:00
|
|
|
#else
|
2017-10-10 20:19:31 +00:00
|
|
|
void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
|
|
|
|
void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
|
|
|
|
void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
|
|
|
|
void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt);
|
2020-06-25 13:14:16 +00:00
|
|
|
#endif
|
2015-10-19 17:02:48 +00:00
|
|
|
|
2017-10-10 18:10:08 +00:00
|
|
|
void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
|
|
|
|
void __debug_switch_to_host(struct kvm_vcpu *vcpu);
|
2015-10-19 20:02:46 +00:00
|
|
|
|
2021-03-05 18:52:47 +00:00
|
|
|
#ifdef __KVM_NVHE_HYPERVISOR__
|
|
|
|
void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu);
|
|
|
|
void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu);
|
|
|
|
#endif
|
|
|
|
|
2015-10-26 08:34:09 +00:00
|
|
|
void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
|
|
|
|
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
|
2021-03-16 08:52:40 +00:00
|
|
|
void __sve_restore_state(void *sve_pffr, u32 *fpsr);
|
2015-10-26 08:34:09 +00:00
|
|
|
|
2020-06-25 13:14:14 +00:00
|
|
|
#ifndef __KVM_NVHE_HYPERVISOR__
|
2017-08-04 11:47:18 +00:00
|
|
|
void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
|
2021-08-17 08:11:25 +00:00
|
|
|
void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
|
2020-06-25 13:14:14 +00:00
|
|
|
#endif
|
2017-08-04 11:47:18 +00:00
|
|
|
|
2020-09-15 10:46:32 +00:00
|
|
|
u64 __guest_enter(struct kvm_vcpu *vcpu);
|
2020-06-25 13:14:14 +00:00
|
|
|
|
2020-12-02 18:41:12 +00:00
|
|
|
bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt);
|
|
|
|
|
2020-06-25 13:14:14 +00:00
|
|
|
#ifdef __KVM_NVHE_HYPERVISOR__
|
2021-03-05 18:52:49 +00:00
|
|
|
void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr,
|
|
|
|
u64 elr, u64 par);
|
2020-06-25 13:14:14 +00:00
|
|
|
#endif
|
2015-10-22 07:32:18 +00:00
|
|
|
|
KVM: arm64: Prepare the creation of s1 mappings at EL2
When memory protection is enabled, the EL2 code needs the ability to
create and manage its own page-table. To do so, introduce a new set of
hypercalls to bootstrap a memory management system at EL2.
This leads to the following boot flow in nVHE Protected mode:
1. the host allocates memory for the hypervisor very early on, using
the memblock API;
2. the host creates a set of stage 1 page-table for EL2, installs the
EL2 vectors, and issues the __pkvm_init hypercall;
3. during __pkvm_init, the hypervisor re-creates its stage 1 page-table
and stores it in the memory pool provided by the host;
4. the hypervisor then extends its stage 1 mappings to include a
vmemmap in the EL2 VA space, hence allowing to use the buddy
allocator introduced in a previous patch;
5. the hypervisor jumps back in the idmap page, switches from the
host-provided page-table to the new one, and wraps up its
initialization by enabling the new allocator, before returning to
the host.
6. the host can free the now unused page-table created for EL2, and
will now need to issue hypercalls to make changes to the EL2 stage 1
mappings instead of modifying them directly.
Note that for the sake of simplifying the review, this patch focuses on
the hypervisor side of things. In other words, this only implements the
new hypercalls, but does not make use of them from the host yet. The
host-side changes will follow in a subsequent patch.
Credits to Will for __pkvm_init_switch_pgd.
Acked-by: Will Deacon <will@kernel.org>
Co-authored-by: Will Deacon <will@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Quentin Perret <qperret@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210319100146.1149909-18-qperret@google.com
2021-03-19 10:01:25 +00:00
|
|
|
#ifdef __KVM_NVHE_HYPERVISOR__
|
|
|
|
void __pkvm_init_switch_pgd(phys_addr_t phys, unsigned long size,
|
|
|
|
phys_addr_t pgd, void *sp, void *cont_fn);
|
|
|
|
int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus,
|
|
|
|
unsigned long *per_cpu_base, u32 hyp_va_bits);
|
|
|
|
void __noreturn __host_enter(struct kvm_cpu_context *host_ctxt);
|
|
|
|
#endif
|
|
|
|
|
2021-10-10 14:56:32 +00:00
|
|
|
extern u64 kvm_nvhe_sym(id_aa64pfr0_el1_sys_val);
|
|
|
|
extern u64 kvm_nvhe_sym(id_aa64pfr1_el1_sys_val);
|
|
|
|
extern u64 kvm_nvhe_sym(id_aa64isar0_el1_sys_val);
|
|
|
|
extern u64 kvm_nvhe_sym(id_aa64isar1_el1_sys_val);
|
2021-03-22 13:32:34 +00:00
|
|
|
extern u64 kvm_nvhe_sym(id_aa64mmfr0_el1_sys_val);
|
|
|
|
extern u64 kvm_nvhe_sym(id_aa64mmfr1_el1_sys_val);
|
2021-10-10 14:56:32 +00:00
|
|
|
extern u64 kvm_nvhe_sym(id_aa64mmfr2_el1_sys_val);
|
2021-03-22 13:32:34 +00:00
|
|
|
|
2015-10-21 09:09:49 +00:00
|
|
|
#endif /* __ARM64_KVM_HYP_H__ */
|