Skip to content

Commit 2d761db

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/fpsimd-tracking into kvmarm-master/next
* kvm-arm64/fpsimd-tracking: : . : Simplify the handling of both the FP/SIMD and SVE state by : removing the need for mapping the thread at EL2, and by : dropping the tracking of the host's SVE state which is : always invalid by construction. : . arm64/fpsimd: Document the use of TIF_FOREIGN_FPSTATE by KVM KVM: arm64: Stop mapping current thread_info at EL2 KVM: arm64: Introduce flag shadowing TIF_FOREIGN_FPSTATE KVM: arm64: Remove unused __sve_save_state KVM: arm64: Get rid of host SVE tracking/saving KVM: arm64: Reorder vcpu flag definitions Signed-off-by: Marc Zyngier <[email protected]>
2 parents e525523 + 31aa126 commit 2d761db

File tree

9 files changed

+40
-81
lines changed

9 files changed

+40
-81
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <asm/fpsimd.h>
2727
#include <asm/kvm.h>
2828
#include <asm/kvm_asm.h>
29-
#include <asm/thread_info.h>
3029

3130
#define __KVM_HAVE_ARCH_INTC_INITIALIZED
3231

@@ -321,7 +320,6 @@ struct kvm_vcpu_arch {
321320
struct kvm_guest_debug_arch vcpu_debug_state;
322321
struct kvm_guest_debug_arch external_debug_state;
323322

324-
struct thread_info *host_thread_info; /* hyp VA */
325323
struct user_fpsimd_state *host_fpsimd_state; /* hyp VA */
326324

327325
struct {
@@ -408,20 +406,17 @@ struct kvm_vcpu_arch {
408406
#define KVM_ARM64_DEBUG_DIRTY (1 << 0)
409407
#define KVM_ARM64_FP_ENABLED (1 << 1) /* guest FP regs loaded */
410408
#define KVM_ARM64_FP_HOST (1 << 2) /* host FP regs loaded */
411-
#define KVM_ARM64_HOST_SVE_IN_USE (1 << 3) /* backup for host TIF_SVE */
412409
#define KVM_ARM64_HOST_SVE_ENABLED (1 << 4) /* SVE enabled for EL0 */
413410
#define KVM_ARM64_GUEST_HAS_SVE (1 << 5) /* SVE exposed to guest */
414411
#define KVM_ARM64_VCPU_SVE_FINALIZED (1 << 6) /* SVE config completed */
415412
#define KVM_ARM64_GUEST_HAS_PTRAUTH (1 << 7) /* PTRAUTH exposed to guest */
416413
#define KVM_ARM64_PENDING_EXCEPTION (1 << 8) /* Exception pending */
414+
/*
415+
* Overlaps with KVM_ARM64_EXCEPT_MASK on purpose so that it can't be
416+
* set together with an exception...
417+
*/
418+
#define KVM_ARM64_INCREMENT_PC (1 << 9) /* Increment PC */
417419
#define KVM_ARM64_EXCEPT_MASK (7 << 9) /* Target EL/MODE */
418-
#define KVM_ARM64_DEBUG_STATE_SAVE_SPE (1 << 12) /* Save SPE context if active */
419-
#define KVM_ARM64_DEBUG_STATE_SAVE_TRBE (1 << 13) /* Save TRBE context if active */
420-
421-
#define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \
422-
KVM_GUESTDBG_USE_SW_BP | \
423-
KVM_GUESTDBG_USE_HW | \
424-
KVM_GUESTDBG_SINGLESTEP)
425420
/*
426421
* When KVM_ARM64_PENDING_EXCEPTION is set, KVM_ARM64_EXCEPT_MASK can
427422
* take the following values:
@@ -439,11 +434,14 @@ struct kvm_vcpu_arch {
439434
#define KVM_ARM64_EXCEPT_AA64_EL1 (0 << 11)
440435
#define KVM_ARM64_EXCEPT_AA64_EL2 (1 << 11)
441436

442-
/*
443-
* Overlaps with KVM_ARM64_EXCEPT_MASK on purpose so that it can't be
444-
* set together with an exception...
445-
*/
446-
#define KVM_ARM64_INCREMENT_PC (1 << 9) /* Increment PC */
437+
#define KVM_ARM64_DEBUG_STATE_SAVE_SPE (1 << 12) /* Save SPE context if active */
438+
#define KVM_ARM64_DEBUG_STATE_SAVE_TRBE (1 << 13) /* Save TRBE context if active */
439+
#define KVM_ARM64_FP_FOREIGN_FPSTATE (1 << 14)
440+
441+
#define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \
442+
KVM_GUESTDBG_USE_SW_BP | \
443+
KVM_GUESTDBG_USE_HW | \
444+
KVM_GUESTDBG_SINGLESTEP)
447445

448446
#define vcpu_has_sve(vcpu) (system_supports_sve() && \
449447
((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
@@ -736,6 +734,7 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
736734
/* Guest/host FPSIMD coordination helpers */
737735
int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
738736
void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
737+
void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu *vcpu);
739738
void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu);
740739
void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu);
741740

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu);
9090

9191
void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
9292
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
93-
void __sve_save_state(void *sve_pffr, u32 *fpsr);
9493
void __sve_restore_state(void *sve_pffr, u32 *fpsr);
9594

9695
#ifndef __KVM_NVHE_HYPERVISOR__

arch/arm64/kernel/fpsimd.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@
7878
* indicate whether or not the userland FPSIMD state of the current task is
7979
* present in the registers. The flag is set unless the FPSIMD registers of this
8080
* CPU currently contain the most recent userland FPSIMD state of the current
81-
* task.
81+
* task. If the task is behaving as a VMM, then this is will be managed by
82+
* KVM which will clear it to indicate that the vcpu FPSIMD state is currently
83+
* loaded on the CPU, allowing the state to be saved if a FPSIMD-aware
84+
* softirq kicks in. Upon vcpu_put(), KVM will save the vcpu FP state and
85+
* flag the register state as invalid.
8286
*
8387
* In order to allow softirq handlers to use FPSIMD, kernel_neon_begin() may
8488
* save the task's FPSIMD context back to task_struct from softirq context.

arch/arm64/kvm/arm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
856856
}
857857

858858
kvm_arm_setup_debug(vcpu);
859+
kvm_arch_vcpu_ctxflush_fp(vcpu);
859860

860861
/**************************************************************
861862
* Enter the guest

arch/arm64/kvm/fpsimd.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88
#include <linux/irqflags.h>
99
#include <linux/sched.h>
10-
#include <linux/thread_info.h>
1110
#include <linux/kvm_host.h>
1211
#include <asm/fpsimd.h>
1312
#include <asm/kvm_asm.h>
@@ -28,24 +27,13 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
2827
{
2928
int ret;
3029

31-
struct thread_info *ti = &current->thread_info;
3230
struct user_fpsimd_state *fpsimd = &current->thread.uw.fpsimd_state;
3331

34-
/*
35-
* Make sure the host task thread flags and fpsimd state are
36-
* visible to hyp:
37-
*/
38-
ret = create_hyp_mappings(ti, ti + 1, PAGE_HYP);
39-
if (ret)
40-
goto error;
41-
32+
/* Make sure the host task fpsimd state is visible to hyp: */
4233
ret = create_hyp_mappings(fpsimd, fpsimd + 1, PAGE_HYP);
43-
if (ret)
44-
goto error;
34+
if (!ret)
35+
vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
4536

46-
vcpu->arch.host_thread_info = kern_hyp_va(ti);
47-
vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
48-
error:
4937
return ret;
5038
}
5139

@@ -55,26 +43,27 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
5543
*
5644
* Here, we just set the correct metadata to indicate that the FPSIMD
5745
* state in the cpu regs (if any) belongs to current on the host.
58-
*
59-
* TIF_SVE is backed up here, since it may get clobbered with guest state.
60-
* This flag is restored by kvm_arch_vcpu_put_fp(vcpu).
6146
*/
6247
void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
6348
{
6449
BUG_ON(!current->mm);
50+
BUG_ON(test_thread_flag(TIF_SVE));
6551

66-
vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
67-
KVM_ARM64_HOST_SVE_IN_USE |
68-
KVM_ARM64_HOST_SVE_ENABLED);
52+
vcpu->arch.flags &= ~KVM_ARM64_FP_ENABLED;
6953
vcpu->arch.flags |= KVM_ARM64_FP_HOST;
7054

71-
if (test_thread_flag(TIF_SVE))
72-
vcpu->arch.flags |= KVM_ARM64_HOST_SVE_IN_USE;
73-
7455
if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
7556
vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
7657
}
7758

59+
void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu *vcpu)
60+
{
61+
if (test_thread_flag(TIF_FOREIGN_FPSTATE))
62+
vcpu->arch.flags |= KVM_ARM64_FP_FOREIGN_FPSTATE;
63+
else
64+
vcpu->arch.flags &= ~KVM_ARM64_FP_FOREIGN_FPSTATE;
65+
}
66+
7867
/*
7968
* If the guest FPSIMD state was loaded, update the host's context
8069
* tracking data mark the CPU FPSIMD regs as dirty and belonging to vcpu
@@ -104,13 +93,11 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
10493
void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
10594
{
10695
unsigned long flags;
107-
bool host_has_sve = system_supports_sve();
108-
bool guest_has_sve = vcpu_has_sve(vcpu);
10996

11097
local_irq_save(flags);
11198

11299
if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
113-
if (guest_has_sve) {
100+
if (vcpu_has_sve(vcpu)) {
114101
__vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR);
115102

116103
/* Restore the VL that was saved when bound to the CPU */
@@ -120,7 +107,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
120107
}
121108

122109
fpsimd_save_and_flush_cpu_state();
123-
} else if (has_vhe() && host_has_sve) {
110+
} else if (has_vhe() && system_supports_sve()) {
124111
/*
125112
* The FPSIMD/SVE state in the CPU has not been touched, and we
126113
* have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
@@ -134,8 +121,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
134121
sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
135122
}
136123

137-
update_thread_flag(TIF_SVE,
138-
vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE);
124+
update_thread_flag(TIF_SVE, 0);
139125

140126
local_irq_restore(flags);
141127
}

arch/arm64/kvm/hyp/fpsimd.S

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,3 @@ SYM_FUNC_START(__sve_restore_state)
2525
sve_load 0, x1, x2, 3
2626
ret
2727
SYM_FUNC_END(__sve_restore_state)
28-
29-
SYM_FUNC_START(__sve_save_state)
30-
mov x2, #1
31-
sve_save 0, x1, x2, 3
32-
ret
33-
SYM_FUNC_END(__sve_save_state)

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include <asm/fpsimd.h>
3030
#include <asm/debug-monitors.h>
3131
#include <asm/processor.h>
32-
#include <asm/thread_info.h>
3332

3433
struct kvm_exception_table_entry {
3534
int insn, fixup;
@@ -49,7 +48,7 @@ static inline bool update_fp_enabled(struct kvm_vcpu *vcpu)
4948
* trap the accesses.
5049
*/
5150
if (!system_supports_fpsimd() ||
52-
vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE)
51+
vcpu->arch.flags & KVM_ARM64_FP_FOREIGN_FPSTATE)
5352
vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
5453
KVM_ARM64_FP_HOST);
5554

@@ -143,16 +142,6 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
143142
return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
144143
}
145144

146-
static inline void __hyp_sve_save_host(struct kvm_vcpu *vcpu)
147-
{
148-
struct thread_struct *thread;
149-
150-
thread = container_of(vcpu->arch.host_fpsimd_state, struct thread_struct,
151-
uw.fpsimd_state);
152-
153-
__sve_save_state(sve_pffr(thread), &vcpu->arch.host_fpsimd_state->fpsr);
154-
}
155-
156145
static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
157146
{
158147
sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2);
@@ -169,21 +158,14 @@ static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
169158
*/
170159
static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
171160
{
172-
bool sve_guest, sve_host;
161+
bool sve_guest;
173162
u8 esr_ec;
174163
u64 reg;
175164

176165
if (!system_supports_fpsimd())
177166
return false;
178167

179-
if (system_supports_sve()) {
180-
sve_guest = vcpu_has_sve(vcpu);
181-
sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
182-
} else {
183-
sve_guest = false;
184-
sve_host = false;
185-
}
186-
168+
sve_guest = vcpu_has_sve(vcpu);
187169
esr_ec = kvm_vcpu_trap_get_class(vcpu);
188170

189171
/* Don't handle SVE traps for non-SVE vcpus here: */
@@ -207,11 +189,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
207189
isb();
208190

209191
if (vcpu->arch.flags & KVM_ARM64_FP_HOST) {
210-
if (sve_host)
211-
__hyp_sve_save_host(vcpu);
212-
else
213-
__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
214-
192+
__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
215193
vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
216194
}
217195

arch/arm64/kvm/hyp/nvhe/switch.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include <asm/fpsimd.h>
2626
#include <asm/debug-monitors.h>
2727
#include <asm/processor.h>
28-
#include <asm/thread_info.h>
2928

3029
#include <nvhe/fixed_config.h>
3130
#include <nvhe/mem_protect.h>

arch/arm64/kvm/hyp/vhe/switch.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include <asm/fpsimd.h>
2525
#include <asm/debug-monitors.h>
2626
#include <asm/processor.h>
27-
#include <asm/thread_info.h>
2827

2928
/* VHE specific context */
3029
DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);

0 commit comments

Comments
 (0)