Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 71d7b52

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini: "This is dominated by a couple large series for ARM and x86 respectively, but apart from that things are calm. ARM: - Large set of FP/SVE fixes for pKVM, addressing the fallout from the per-CPU data rework and making sure that the host is not involved in the FP/SVE switching any more - Allow FEAT_BTI to be enabled with NV now that FEAT_PAUTH is completely supported - Fix for the respective priorities of Failed PAC, Illegal Execution state and Instruction Abort exceptions - Fix the handling of AArch32 instruction traps failing their condition code, which was broken by the introduction of ESR_EL2.ISS2 - Allow vcpus running in AArch32 state to be restored in System mode - Fix AArch32 GPR restore that would lose the 64 bit state under some conditions RISC-V: - No need to use mask when hart-index-bits is 0 - Fix incorrect reg_subtype labels in kvm_riscv_vcpu_set_reg_isa_ext() x86: - Fixes and debugging help for the #VE sanity check. Also disable it by default, even for CONFIG_DEBUG_KERNEL, because it was found to trigger spuriously (most likely a processor erratum as the exact symptoms vary by generation). - Avoid WARN() when two NMIs arrive simultaneously during an NMI-disabled situation (GIF=0 or interrupt shadow) when the processor supports virtual NMI. While generally KVM will not request an NMI window when virtual NMIs are supported, in this case it *does* have to single-step over the interrupt shadow or enable the STGI intercept, in order to deliver the latched second NMI. - Drop support for hand tuning APIC timer advancement from userspace. Since we have adaptive tuning, and it has proved to work well, drop the module parameter for manual configuration and with it a few stupid bugs that it had" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (32 commits) KVM: x86/mmu: Don't save mmu_invalidate_seq after checking private attr KVM: arm64: Ensure that SME controls are disabled in protected mode KVM: arm64: Refactor CPACR trap bit setting/clearing to use ELx format KVM: arm64: Consolidate initializing the host data's fpsimd_state/sve in pKVM KVM: arm64: Eagerly restore host fpsimd/sve state in pKVM KVM: arm64: Allocate memory mapped at hyp for host sve state in pKVM KVM: arm64: Specialize handling of host fpsimd state on trap KVM: arm64: Abstract set/clear of CPTR_EL2 bits behind helper KVM: arm64: Fix prototype for __sve_save_state/__sve_restore_state KVM: arm64: Reintroduce __sve_save_state KVM: x86: Drop support for hand tuning APIC timer advancement from userspace KVM: SEV-ES: Delegate LBR virtualization to the processor KVM: SEV-ES: Disallow SEV-ES guests when X86_FEATURE_LBRV is absent KVM: SEV-ES: Prevent MSR access post VMSA encryption RISC-V: KVM: Fix incorrect reg_subtype labels in kvm_riscv_vcpu_set_reg_isa_ext function RISC-V: KVM: No need to use mask when hart-index-bit is 0 KVM: arm64: nv: Expose BTI and CSV_frac to a guest hypervisor KVM: arm64: nv: Fix relative priorities of exceptions generated by ERETAx KVM: arm64: AArch32: Fix spurious trapping of conditional instructions KVM: arm64: Allow AArch32 PSTATE.M to be restored as System mode ...
2 parents 5121452 + db574f2 commit 71d7b52

38 files changed

+558
-150
lines changed

arch/arm64/include/asm/el2_setup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
/* Coprocessor traps */
147147
.macro __init_el2_cptr
148148
__check_hvhe .LnVHE_\@, x1
149-
mov x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN)
149+
mov x0, #CPACR_ELx_FPEN
150150
msr cpacr_el1, x0
151151
b .Lskip_set_cptr_\@
152152
.LnVHE_\@:
@@ -277,7 +277,7 @@
277277

278278
// (h)VHE case
279279
mrs x0, cpacr_el1 // Disable SVE traps
280-
orr x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN)
280+
orr x0, x0, #CPACR_ELx_ZEN
281281
msr cpacr_el1, x0
282282
b .Lskip_set_cptr_\@
283283

@@ -298,7 +298,7 @@
298298

299299
// (h)VHE case
300300
mrs x0, cpacr_el1 // Disable SME traps
301-
orr x0, x0, #(CPACR_EL1_SMEN_EL0EN | CPACR_EL1_SMEN_EL1EN)
301+
orr x0, x0, #CPACR_ELx_SMEN
302302
msr cpacr_el1, x0
303303
b .Lskip_set_cptr_sme_\@
304304

arch/arm64/include/asm/kvm_arm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,12 @@
305305
GENMASK(19, 14) | \
306306
BIT(11))
307307

308+
#define CPTR_VHE_EL2_RES0 (GENMASK(63, 32) | \
309+
GENMASK(27, 26) | \
310+
GENMASK(23, 22) | \
311+
GENMASK(19, 18) | \
312+
GENMASK(15, 0))
313+
308314
/* Hyp Debug Configuration Register bits */
309315
#define MDCR_EL2_E2TB_MASK (UL(0x3))
310316
#define MDCR_EL2_E2TB_SHIFT (UL(24))

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,68 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
557557
vcpu_set_flag((v), e); \
558558
} while (0)
559559

560+
#define __build_check_all_or_none(r, bits) \
561+
BUILD_BUG_ON(((r) & (bits)) && ((r) & (bits)) != (bits))
562+
563+
#define __cpacr_to_cptr_clr(clr, set) \
564+
({ \
565+
u64 cptr = 0; \
566+
\
567+
if ((set) & CPACR_ELx_FPEN) \
568+
cptr |= CPTR_EL2_TFP; \
569+
if ((set) & CPACR_ELx_ZEN) \
570+
cptr |= CPTR_EL2_TZ; \
571+
if ((set) & CPACR_ELx_SMEN) \
572+
cptr |= CPTR_EL2_TSM; \
573+
if ((clr) & CPACR_ELx_TTA) \
574+
cptr |= CPTR_EL2_TTA; \
575+
if ((clr) & CPTR_EL2_TAM) \
576+
cptr |= CPTR_EL2_TAM; \
577+
if ((clr) & CPTR_EL2_TCPAC) \
578+
cptr |= CPTR_EL2_TCPAC; \
579+
\
580+
cptr; \
581+
})
582+
583+
#define __cpacr_to_cptr_set(clr, set) \
584+
({ \
585+
u64 cptr = 0; \
586+
\
587+
if ((clr) & CPACR_ELx_FPEN) \
588+
cptr |= CPTR_EL2_TFP; \
589+
if ((clr) & CPACR_ELx_ZEN) \
590+
cptr |= CPTR_EL2_TZ; \
591+
if ((clr) & CPACR_ELx_SMEN) \
592+
cptr |= CPTR_EL2_TSM; \
593+
if ((set) & CPACR_ELx_TTA) \
594+
cptr |= CPTR_EL2_TTA; \
595+
if ((set) & CPTR_EL2_TAM) \
596+
cptr |= CPTR_EL2_TAM; \
597+
if ((set) & CPTR_EL2_TCPAC) \
598+
cptr |= CPTR_EL2_TCPAC; \
599+
\
600+
cptr; \
601+
})
602+
603+
#define cpacr_clear_set(clr, set) \
604+
do { \
605+
BUILD_BUG_ON((set) & CPTR_VHE_EL2_RES0); \
606+
BUILD_BUG_ON((clr) & CPACR_ELx_E0POE); \
607+
__build_check_all_or_none((clr), CPACR_ELx_FPEN); \
608+
__build_check_all_or_none((set), CPACR_ELx_FPEN); \
609+
__build_check_all_or_none((clr), CPACR_ELx_ZEN); \
610+
__build_check_all_or_none((set), CPACR_ELx_ZEN); \
611+
__build_check_all_or_none((clr), CPACR_ELx_SMEN); \
612+
__build_check_all_or_none((set), CPACR_ELx_SMEN); \
613+
\
614+
if (has_vhe() || has_hvhe()) \
615+
sysreg_clear_set(cpacr_el1, clr, set); \
616+
else \
617+
sysreg_clear_set(cptr_el2, \
618+
__cpacr_to_cptr_clr(clr, set), \
619+
__cpacr_to_cptr_set(clr, set));\
620+
} while (0)
621+
560622
static __always_inline void kvm_write_cptr_el2(u64 val)
561623
{
562624
if (has_vhe() || has_hvhe())
@@ -570,17 +632,16 @@ static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu)
570632
u64 val;
571633

572634
if (has_vhe()) {
573-
val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN |
574-
CPACR_EL1_ZEN_EL1EN);
635+
val = (CPACR_ELx_FPEN | CPACR_EL1_ZEN_EL1EN);
575636
if (cpus_have_final_cap(ARM64_SME))
576637
val |= CPACR_EL1_SMEN_EL1EN;
577638
} else if (has_hvhe()) {
578-
val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN);
639+
val = CPACR_ELx_FPEN;
579640

580641
if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
581-
val |= CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN;
642+
val |= CPACR_ELx_ZEN;
582643
if (cpus_have_final_cap(ARM64_SME))
583-
val |= CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN;
644+
val |= CPACR_ELx_SMEN;
584645
} else {
585646
val = CPTR_NVHE_EL2_RES1;
586647

arch/arm64/include/asm/kvm_host.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ static inline enum kvm_mode kvm_get_mode(void) { return KVM_MODE_NONE; };
7676
DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
7777

7878
extern unsigned int __ro_after_init kvm_sve_max_vl;
79+
extern unsigned int __ro_after_init kvm_host_sve_max_vl;
7980
int __init kvm_arm_init_sve(void);
8081

8182
u32 __attribute_const__ kvm_target_cpu(void);
@@ -521,6 +522,20 @@ struct kvm_cpu_context {
521522
u64 *vncr_array;
522523
};
523524

525+
struct cpu_sve_state {
526+
__u64 zcr_el1;
527+
528+
/*
529+
* Ordering is important since __sve_save_state/__sve_restore_state
530+
* relies on it.
531+
*/
532+
__u32 fpsr;
533+
__u32 fpcr;
534+
535+
/* Must be SVE_VQ_BYTES (128 bit) aligned. */
536+
__u8 sve_regs[];
537+
};
538+
524539
/*
525540
* This structure is instantiated on a per-CPU basis, and contains
526541
* data that is:
@@ -534,7 +549,15 @@ struct kvm_cpu_context {
534549
*/
535550
struct kvm_host_data {
536551
struct kvm_cpu_context host_ctxt;
537-
struct user_fpsimd_state *fpsimd_state; /* hyp VA */
552+
553+
/*
554+
* All pointers in this union are hyp VA.
555+
* sve_state is only used in pKVM and if system_supports_sve().
556+
*/
557+
union {
558+
struct user_fpsimd_state *fpsimd_state;
559+
struct cpu_sve_state *sve_state;
560+
};
538561

539562
/* Ownership of the FP regs */
540563
enum {

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu);
111111

112112
void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
113113
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
114-
void __sve_restore_state(void *sve_pffr, u32 *fpsr);
114+
void __sve_save_state(void *sve_pffr, u32 *fpsr, int save_ffr);
115+
void __sve_restore_state(void *sve_pffr, u32 *fpsr, int restore_ffr);
115116

116117
u64 __guest_enter(struct kvm_vcpu *vcpu);
117118

@@ -142,5 +143,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val);
142143

143144
extern unsigned long kvm_nvhe_sym(__icache_flags);
144145
extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
146+
extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
145147

146148
#endif /* __ARM64_KVM_HYP_H__ */

arch/arm64/include/asm/kvm_pkvm.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,13 @@ static inline unsigned long hyp_ffa_proxy_pages(void)
128128
return (2 * KVM_FFA_MBOX_NR_PAGES) + DIV_ROUND_UP(desc_max, PAGE_SIZE);
129129
}
130130

131+
static inline size_t pkvm_host_sve_state_size(void)
132+
{
133+
if (!system_supports_sve())
134+
return 0;
135+
136+
return size_add(sizeof(struct cpu_sve_state),
137+
SVE_SIG_REGS_SIZE(sve_vq_from_vl(kvm_host_sve_max_vl)));
138+
}
139+
131140
#endif /* __ARM64_KVM_PKVM_H__ */

arch/arm64/kvm/arm.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,6 +1931,11 @@ static unsigned long nvhe_percpu_order(void)
19311931
return size ? get_order(size) : 0;
19321932
}
19331933

1934+
static size_t pkvm_host_sve_state_order(void)
1935+
{
1936+
return get_order(pkvm_host_sve_state_size());
1937+
}
1938+
19341939
/* A lookup table holding the hypervisor VA for each vector slot */
19351940
static void *hyp_spectre_vector_selector[BP_HARDEN_EL2_SLOTS];
19361941

@@ -2310,12 +2315,20 @@ static void __init teardown_subsystems(void)
23102315

23112316
static void __init teardown_hyp_mode(void)
23122317
{
2318+
bool free_sve = system_supports_sve() && is_protected_kvm_enabled();
23132319
int cpu;
23142320

23152321
free_hyp_pgds();
23162322
for_each_possible_cpu(cpu) {
23172323
free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
23182324
free_pages(kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[cpu], nvhe_percpu_order());
2325+
2326+
if (free_sve) {
2327+
struct cpu_sve_state *sve_state;
2328+
2329+
sve_state = per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state;
2330+
free_pages((unsigned long) sve_state, pkvm_host_sve_state_order());
2331+
}
23192332
}
23202333
}
23212334

@@ -2398,6 +2411,58 @@ static int __init kvm_hyp_init_protection(u32 hyp_va_bits)
23982411
return 0;
23992412
}
24002413

2414+
static int init_pkvm_host_sve_state(void)
2415+
{
2416+
int cpu;
2417+
2418+
if (!system_supports_sve())
2419+
return 0;
2420+
2421+
/* Allocate pages for host sve state in protected mode. */
2422+
for_each_possible_cpu(cpu) {
2423+
struct page *page = alloc_pages(GFP_KERNEL, pkvm_host_sve_state_order());
2424+
2425+
if (!page)
2426+
return -ENOMEM;
2427+
2428+
per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state = page_address(page);
2429+
}
2430+
2431+
/*
2432+
* Don't map the pages in hyp since these are only used in protected
2433+
* mode, which will (re)create its own mapping when initialized.
2434+
*/
2435+
2436+
return 0;
2437+
}
2438+
2439+
/*
2440+
* Finalizes the initialization of hyp mode, once everything else is initialized
2441+
* and the initialziation process cannot fail.
2442+
*/
2443+
static void finalize_init_hyp_mode(void)
2444+
{
2445+
int cpu;
2446+
2447+
if (system_supports_sve() && is_protected_kvm_enabled()) {
2448+
for_each_possible_cpu(cpu) {
2449+
struct cpu_sve_state *sve_state;
2450+
2451+
sve_state = per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state;
2452+
per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
2453+
kern_hyp_va(sve_state);
2454+
}
2455+
} else {
2456+
for_each_possible_cpu(cpu) {
2457+
struct user_fpsimd_state *fpsimd_state;
2458+
2459+
fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
2460+
per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
2461+
kern_hyp_va(fpsimd_state);
2462+
}
2463+
}
2464+
}
2465+
24012466
static void pkvm_hyp_init_ptrauth(void)
24022467
{
24032468
struct kvm_cpu_context *hyp_ctxt;
@@ -2566,6 +2631,10 @@ static int __init init_hyp_mode(void)
25662631
goto out_err;
25672632
}
25682633

2634+
err = init_pkvm_host_sve_state();
2635+
if (err)
2636+
goto out_err;
2637+
25692638
err = kvm_hyp_init_protection(hyp_va_bits);
25702639
if (err) {
25712640
kvm_err("Failed to init hyp memory protection\n");
@@ -2730,6 +2799,13 @@ static __init int kvm_arm_init(void)
27302799
if (err)
27312800
goto out_subs;
27322801

2802+
/*
2803+
* This should be called after initialization is done and failure isn't
2804+
* possible anymore.
2805+
*/
2806+
if (!in_hyp_mode)
2807+
finalize_init_hyp_mode();
2808+
27332809
kvm_arm_initialised = true;
27342810

27352811
return 0;

arch/arm64/kvm/emulate-nested.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,16 +2181,23 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
21812181
if (forward_traps(vcpu, HCR_NV))
21822182
return;
21832183

2184+
spsr = vcpu_read_sys_reg(vcpu, SPSR_EL2);
2185+
spsr = kvm_check_illegal_exception_return(vcpu, spsr);
2186+
21842187
/* Check for an ERETAx */
21852188
esr = kvm_vcpu_get_esr(vcpu);
21862189
if (esr_iss_is_eretax(esr) && !kvm_auth_eretax(vcpu, &elr)) {
21872190
/*
2188-
* Oh no, ERETAx failed to authenticate. If we have
2189-
* FPACCOMBINE, deliver an exception right away. If we
2190-
* don't, then let the mangled ELR value trickle down the
2191+
* Oh no, ERETAx failed to authenticate.
2192+
*
2193+
* If we have FPACCOMBINE and we don't have a pending
2194+
* Illegal Execution State exception (which has priority
2195+
* over FPAC), deliver an exception right away.
2196+
*
2197+
* Otherwise, let the mangled ELR value trickle down the
21912198
* ERET handling, and the guest will have a little surprise.
21922199
*/
2193-
if (kvm_has_pauth(vcpu->kvm, FPACCOMBINE)) {
2200+
if (kvm_has_pauth(vcpu->kvm, FPACCOMBINE) && !(spsr & PSR_IL_BIT)) {
21942201
esr &= ESR_ELx_ERET_ISS_ERETA;
21952202
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_FPAC);
21962203
kvm_inject_nested_sync(vcpu, esr);
@@ -2201,17 +2208,11 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
22012208
preempt_disable();
22022209
kvm_arch_vcpu_put(vcpu);
22032210

2204-
spsr = __vcpu_sys_reg(vcpu, SPSR_EL2);
2205-
spsr = kvm_check_illegal_exception_return(vcpu, spsr);
22062211
if (!esr_iss_is_eretax(esr))
22072212
elr = __vcpu_sys_reg(vcpu, ELR_EL2);
22082213

22092214
trace_kvm_nested_eret(vcpu, elr, spsr);
22102215

2211-
/*
2212-
* Note that the current exception level is always the virtual EL2,
2213-
* since we set HCR_EL2.NV bit only when entering the virtual EL2.
2214-
*/
22152216
*vcpu_pc(vcpu) = elr;
22162217
*vcpu_cpsr(vcpu) = spsr;
22172218

arch/arm64/kvm/fpsimd.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
9090
fpsimd_save_and_flush_cpu_state();
9191
}
9292
}
93+
94+
/*
95+
* If normal guests gain SME support, maintain this behavior for pKVM
96+
* guests, which don't support SME.
97+
*/
98+
WARN_ON(is_protected_kvm_enabled() && system_supports_sme() &&
99+
read_sysreg_s(SYS_SVCR));
93100
}
94101

95102
/*
@@ -161,9 +168,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
161168
if (has_vhe() && system_supports_sme()) {
162169
/* Also restore EL0 state seen on entry */
163170
if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
164-
sysreg_clear_set(CPACR_EL1, 0,
165-
CPACR_EL1_SMEN_EL0EN |
166-
CPACR_EL1_SMEN_EL1EN);
171+
sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
167172
else
168173
sysreg_clear_set(CPACR_EL1,
169174
CPACR_EL1_SMEN_EL0EN,

0 commit comments

Comments
 (0)