Skip to content

Commit c199a00

Browse files
author
Marc Zyngier
committed
Merge branch 'kvm-arm64/el2-obj-v4.1' into kvmarm-master/next-WIP
Signed-off-by: Marc Zyngier <[email protected]>
2 parents 9ebcfad + 6de7dd3 commit c199a00

35 files changed

+1793
-1398
lines changed

arch/arm64/include/asm/kvm_asm.h

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,70 @@
4242

4343
#include <linux/mm.h>
4444

45-
/* Translate a kernel address of @sym into its equivalent linear mapping */
46-
#define kvm_ksym_ref(sym) \
45+
/*
46+
* Translate name of a symbol defined in nVHE hyp to the name seen
47+
* by kernel proper. All nVHE symbols are prefixed by the build system
48+
* to avoid clashes with the VHE variants.
49+
*/
50+
#define kvm_nvhe_sym(sym) __kvm_nvhe_##sym
51+
52+
#define DECLARE_KVM_VHE_SYM(sym) extern char sym[]
53+
#define DECLARE_KVM_NVHE_SYM(sym) extern char kvm_nvhe_sym(sym)[]
54+
55+
/*
56+
* Define a pair of symbols sharing the same name but one defined in
57+
* VHE and the other in nVHE hyp implementations.
58+
*/
59+
#define DECLARE_KVM_HYP_SYM(sym) \
60+
DECLARE_KVM_VHE_SYM(sym); \
61+
DECLARE_KVM_NVHE_SYM(sym)
62+
63+
#define CHOOSE_VHE_SYM(sym) sym
64+
#define CHOOSE_NVHE_SYM(sym) kvm_nvhe_sym(sym)
65+
66+
#ifndef __KVM_NVHE_HYPERVISOR__
67+
/*
68+
* BIG FAT WARNINGS:
69+
*
70+
* - Don't be tempted to change the following is_kernel_in_hyp_mode()
71+
* to has_vhe(). has_vhe() is implemented as a *final* capability,
72+
* while this is used early at boot time, when the capabilities are
73+
* not final yet....
74+
*
75+
* - Don't let the nVHE hypervisor have access to this, as it will
76+
* pick the *wrong* symbol (yes, it runs at EL2...).
77+
*/
78+
#define CHOOSE_HYP_SYM(sym) (is_kernel_in_hyp_mode() ? CHOOSE_VHE_SYM(sym) \
79+
: CHOOSE_NVHE_SYM(sym))
80+
#else
81+
/* The nVHE hypervisor shouldn't even try to access anything */
82+
extern void *__nvhe_undefined_symbol;
83+
#define CHOOSE_HYP_SYM(sym) __nvhe_undefined_symbol
84+
#endif
85+
86+
/* Translate a kernel address @ptr into its equivalent linear mapping */
87+
#define kvm_ksym_ref(ptr) \
4788
({ \
48-
void *val = &sym; \
89+
void *val = (ptr); \
4990
if (!is_kernel_in_hyp_mode()) \
50-
val = lm_alias(&sym); \
91+
val = lm_alias((ptr)); \
5192
val; \
5293
})
94+
#define kvm_ksym_ref_nvhe(sym) kvm_ksym_ref(kvm_nvhe_sym(sym))
5395

5496
struct kvm;
5597
struct kvm_vcpu;
5698

57-
extern char __kvm_hyp_init[];
58-
extern char __kvm_hyp_init_end[];
99+
DECLARE_KVM_NVHE_SYM(__kvm_hyp_init);
100+
DECLARE_KVM_HYP_SYM(__kvm_hyp_vector);
101+
#define __kvm_hyp_init CHOOSE_NVHE_SYM(__kvm_hyp_init)
102+
#define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector)
59103

60-
extern char __kvm_hyp_vector[];
104+
#ifdef CONFIG_KVM_INDIRECT_VECTORS
105+
extern atomic_t arm64_el2_vector_last_slot;
106+
DECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs);
107+
#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs)
108+
#endif
61109

62110
extern void __kvm_flush_vm_context(void);
63111
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
@@ -66,9 +114,7 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
66114

67115
extern void __kvm_timer_set_cntvoff(u64 cntvoff);
68116

69-
extern int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu);
70-
71-
extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
117+
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
72118

73119
extern void __kvm_enable_ssbs(void);
74120

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_i
516516
* Skip an instruction which has been emulated at hyp while most guest sysregs
517517
* are live.
518518
*/
519-
static __always_inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
519+
static __always_inline void __kvm_skip_instr(struct kvm_vcpu *vcpu)
520520
{
521521
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
522522
vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR);

arch/arm64/include/asm/kvm_host.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ struct kvm_vcpu_arch {
338338
struct vcpu_reset_state reset_state;
339339

340340
/* True when deferrable sysregs are loaded on the physical CPU,
341-
* see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
341+
* see kvm_vcpu_load_sysregs_vhe and kvm_vcpu_put_sysregs_vhe. */
342342
bool sysregs_loaded_on_cpu;
343343

344344
/* Guest PV state */
@@ -448,6 +448,18 @@ void kvm_arm_resume_guest(struct kvm *kvm);
448448

449449
u64 __kvm_call_hyp(void *hypfn, ...);
450450

451+
#define kvm_call_hyp_nvhe(f, ...) \
452+
do { \
453+
DECLARE_KVM_NVHE_SYM(f); \
454+
__kvm_call_hyp(kvm_ksym_ref_nvhe(f), ##__VA_ARGS__); \
455+
} while(0)
456+
457+
#define kvm_call_hyp_nvhe_ret(f, ...) \
458+
({ \
459+
DECLARE_KVM_NVHE_SYM(f); \
460+
__kvm_call_hyp(kvm_ksym_ref_nvhe(f), ##__VA_ARGS__); \
461+
})
462+
451463
/*
452464
* The couple of isb() below are there to guarantee the same behaviour
453465
* on VHE as on !VHE, where the eret to EL1 acts as a context
@@ -459,7 +471,7 @@ u64 __kvm_call_hyp(void *hypfn, ...);
459471
f(__VA_ARGS__); \
460472
isb(); \
461473
} else { \
462-
__kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__); \
474+
kvm_call_hyp_nvhe(f, ##__VA_ARGS__); \
463475
} \
464476
} while(0)
465477

@@ -471,8 +483,7 @@ u64 __kvm_call_hyp(void *hypfn, ...);
471483
ret = f(__VA_ARGS__); \
472484
isb(); \
473485
} else { \
474-
ret = __kvm_call_hyp(kvm_ksym_ref(f), \
475-
##__VA_ARGS__); \
486+
ret = kvm_call_hyp_nvhe_ret(f, ##__VA_ARGS__); \
476487
} \
477488
\
478489
ret; \
@@ -628,8 +639,8 @@ static inline int kvm_arm_have_ssbd(void)
628639
}
629640
}
630641

631-
void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu);
632-
void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu);
642+
void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu);
643+
void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu);
633644

634645
int kvm_set_ipa_limit(void);
635646

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
#include <asm/alternative.h>
1313
#include <asm/sysreg.h>
1414

15-
#define __hyp_text __section(.hyp.text) notrace __noscs
16-
1715
#define read_sysreg_elx(r,nvh,vh) \
1816
({ \
1917
u64 reg; \
@@ -63,29 +61,38 @@ void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if);
6361
void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if);
6462
int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
6563

64+
#ifdef __KVM_NVHE_HYPERVISOR__
6665
void __timer_enable_traps(struct kvm_vcpu *vcpu);
6766
void __timer_disable_traps(struct kvm_vcpu *vcpu);
67+
#endif
6868

69+
#ifdef __KVM_NVHE_HYPERVISOR__
6970
void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
7071
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
72+
#else
7173
void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
7274
void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
7375
void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
7476
void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt);
75-
void __sysreg32_save_state(struct kvm_vcpu *vcpu);
76-
void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
77+
#endif
7778

7879
void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
7980
void __debug_switch_to_host(struct kvm_vcpu *vcpu);
8081

8182
void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
8283
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
8384

85+
#ifndef __KVM_NVHE_HYPERVISOR__
8486
void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
8587
void deactivate_traps_vhe_put(void);
88+
#endif
8689

8790
u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
91+
92+
void __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt);
93+
#ifdef __KVM_NVHE_HYPERVISOR__
8894
void __noreturn __hyp_do_panic(unsigned long, ...);
95+
#endif
8996

9097
#endif /* __ARM64_KVM_HYP_H__ */
9198

arch/arm64/include/asm/mmu.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ struct bp_hardening_data {
4545
bp_hardening_cb_t fn;
4646
};
4747

48-
#if (defined(CONFIG_HARDEN_BRANCH_PREDICTOR) || \
49-
defined(CONFIG_HARDEN_EL2_VECTORS))
50-
51-
extern char __bp_harden_hyp_vecs[];
52-
extern atomic_t arm64_el2_vector_last_slot;
53-
#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR || CONFIG_HARDEN_EL2_VECTORS */
54-
5548
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
5649
DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
5750

arch/arm64/include/asm/virt.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,17 @@ static inline bool is_kernel_in_hyp_mode(void)
8585

8686
static __always_inline bool has_vhe(void)
8787
{
88-
if (cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN))
88+
/*
89+
* The following macros are defined for code specic to VHE/nVHE.
90+
* If has_vhe() is inlined into those compilation units, it can
91+
* be determined statically. Otherwise fall back to caps.
92+
*/
93+
if (__is_defined(__KVM_VHE_HYPERVISOR__))
8994
return true;
90-
91-
return false;
95+
else if (__is_defined(__KVM_NVHE_HYPERVISOR__))
96+
return false;
97+
else
98+
return cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN);
9299
}
93100

94101
#endif /* __ASSEMBLY__ */

arch/arm64/kernel/image-vars.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,58 @@ __efistub__ctype = _ctype;
5151

5252
#endif
5353

54+
#ifdef CONFIG_KVM
55+
56+
/*
57+
* KVM nVHE code has its own symbol namespace prefixed with __kvm_nvhe_, to
58+
* separate it from the kernel proper. The following symbols are legally
59+
* accessed by it, therefore provide aliases to make them linkable.
60+
* Do not include symbols which may not be safely accessed under hypervisor
61+
* memory mappings.
62+
*/
63+
64+
#define KVM_NVHE_ALIAS(sym) __kvm_nvhe_##sym = sym;
65+
66+
/* Alternative callbacks for init-time patching of nVHE hyp code. */
67+
KVM_NVHE_ALIAS(arm64_enable_wa2_handling);
68+
KVM_NVHE_ALIAS(kvm_patch_vector_branch);
69+
KVM_NVHE_ALIAS(kvm_update_va_mask);
70+
71+
/* Global kernel state accessed by nVHE hyp code. */
72+
KVM_NVHE_ALIAS(arm64_ssbd_callback_required);
73+
KVM_NVHE_ALIAS(kvm_host_data);
74+
KVM_NVHE_ALIAS(kvm_vgic_global_state);
75+
76+
/* Kernel constant needed to compute idmap addresses. */
77+
KVM_NVHE_ALIAS(kimage_voffset);
78+
79+
/* Kernel symbols used to call panic() from nVHE hyp code (via ERET). */
80+
KVM_NVHE_ALIAS(__hyp_panic_string);
81+
KVM_NVHE_ALIAS(panic);
82+
83+
/* Vectors installed by hyp-init on reset HVC. */
84+
KVM_NVHE_ALIAS(__hyp_stub_vectors);
85+
86+
/* IDMAP TCR_EL1.T0SZ as computed by the EL1 init code */
87+
KVM_NVHE_ALIAS(idmap_t0sz);
88+
89+
/* Kernel symbol used by icache_is_vpipt(). */
90+
KVM_NVHE_ALIAS(__icache_flags);
91+
92+
/* Kernel symbols needed for cpus_have_final/const_caps checks. */
93+
KVM_NVHE_ALIAS(arm64_const_caps_ready);
94+
KVM_NVHE_ALIAS(cpu_hwcap_keys);
95+
KVM_NVHE_ALIAS(cpu_hwcaps);
96+
97+
/* Static keys which are set if a vGIC trap should be handled in hyp. */
98+
KVM_NVHE_ALIAS(vgic_v2_cpuif_trap);
99+
KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
100+
101+
/* Static key checked in pmr_sync(). */
102+
#ifdef CONFIG_ARM64_PSEUDO_NMI
103+
KVM_NVHE_ALIAS(gic_pmr_sync);
104+
#endif
105+
106+
#endif /* CONFIG_KVM */
107+
54108
#endif /* __ARM64_KERNEL_IMAGE_VARS_H */

arch/arm64/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ obj-$(CONFIG_KVM) += hyp/
1313
kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
1414
$(KVM)/vfio.o $(KVM)/irqchip.o \
1515
arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
16-
inject_fault.o regmap.o va_layout.o hyp.o hyp-init.o handle_exit.o \
16+
inject_fault.o regmap.o va_layout.o hyp.o handle_exit.o \
1717
guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o \
1818
vgic-sys-reg-v3.o fpsimd.o pmu.o \
1919
aarch32.o arch_timer.o \

arch/arm64/kvm/arm.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
351351

352352
kvm_vgic_load(vcpu);
353353
kvm_timer_vcpu_load(vcpu);
354-
kvm_vcpu_load_sysregs(vcpu);
354+
if (has_vhe())
355+
kvm_vcpu_load_sysregs_vhe(vcpu);
355356
kvm_arch_vcpu_load_fp(vcpu);
356357
kvm_vcpu_pmu_restore_guest(vcpu);
357358
if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
@@ -369,7 +370,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
369370
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
370371
{
371372
kvm_arch_vcpu_put_fp(vcpu);
372-
kvm_vcpu_put_sysregs(vcpu);
373+
if (has_vhe())
374+
kvm_vcpu_put_sysregs_vhe(vcpu);
373375
kvm_timer_vcpu_put(vcpu);
374376
kvm_vgic_put(vcpu);
375377
kvm_vcpu_pmu_restore_host(vcpu);
@@ -748,11 +750,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
748750
trace_kvm_entry(*vcpu_pc(vcpu));
749751
guest_enter_irqoff();
750752

751-
if (has_vhe()) {
752-
ret = kvm_vcpu_run_vhe(vcpu);
753-
} else {
754-
ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
755-
}
753+
ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu);
756754

757755
vcpu->mode = OUTSIDE_GUEST_MODE;
758756
vcpu->stat.exits++;
@@ -1285,7 +1283,7 @@ static void cpu_init_hyp_mode(void)
12851283
* so that we can use adr_l to access per-cpu variables in EL2.
12861284
*/
12871285
tpidr_el2 = ((unsigned long)this_cpu_ptr(&kvm_host_data) -
1288-
(unsigned long)kvm_ksym_ref(kvm_host_data));
1286+
(unsigned long)kvm_ksym_ref(&kvm_host_data));
12891287

12901288
pgd_ptr = kvm_mmu_get_httbr();
12911289
hyp_stack_ptr = __this_cpu_read(kvm_arm_hyp_stack_page) + PAGE_SIZE;
@@ -1306,7 +1304,7 @@ static void cpu_init_hyp_mode(void)
13061304
*/
13071305
if (this_cpu_has_cap(ARM64_SSBS) &&
13081306
arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) {
1309-
kvm_call_hyp(__kvm_enable_ssbs);
1307+
kvm_call_hyp_nvhe(__kvm_enable_ssbs);
13101308
}
13111309
}
13121310

arch/arm64/kvm/hyp/Makefile

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,12 @@
33
# Makefile for Kernel-based Virtual Machine module, HYP part
44
#
55

6-
ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
7-
$(DISABLE_STACKLEAK_PLUGIN)
8-
9-
obj-$(CONFIG_KVM) += hyp.o
10-
11-
hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \
12-
debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o
13-
14-
# KVM code is run at a different exception code with a different map, so
15-
# compiler instrumentation that inserts callbacks or checks into the code may
16-
# cause crashes. Just disable it.
17-
GCOV_PROFILE := n
18-
KASAN_SANITIZE := n
19-
UBSAN_SANITIZE := n
20-
KCOV_INSTRUMENT := n
6+
incdir := $(srctree)/$(src)/include
7+
subdir-asflags-y := -I$(incdir)
8+
subdir-ccflags-y := -I$(incdir) \
9+
-fno-stack-protector \
10+
-DDISABLE_BRANCH_PROFILING \
11+
$(DISABLE_STACKLEAK_PLUGIN)
12+
13+
obj-$(CONFIG_KVM) += vhe/ nvhe/
14+
obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o

0 commit comments

Comments
 (0)