public inbox for kvmarm@lists.cs.columbia.edu
 help / color / mirror / Atom feed
From: Andrew Scull <ascull@google.com>
To: kvmarm@lists.cs.columbia.edu
Cc: kernel-team@android.com, maz@kernel.org, catalin.marinas@arm.com,
	will@kernel.org, Dave.Martin@arm.com
Subject: [PATCH 06/10] KVM: arm64: Avoid needlessly reloading guest FP state
Date: Thu,  4 Mar 2021 11:54:49 +0000	[thread overview]
Message-ID: <20210304115454.3597879-7-ascull@google.com> (raw)
In-Reply-To: <20210304115454.3597879-1-ascull@google.com>

When returning to a user task from a vcpu, keep track of the vcpu state
being in registers so that the state can be reinstated on the next entry
if the registers still contain the vcpu's latest state.

This avoids the need to trap and restore in the case that the vcpu's
registers are still in place. The state must still be saved when
switching away from the vcpu to allow movement to another core or the
task to load its own state.

Signed-off-by: Andrew Scull <ascull@google.com>
Cc: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/include/asm/fpsimd.h |  1 +
 arch/arm64/kernel/fpsimd.c      | 11 +++++++++--
 arch/arm64/kvm/fpsimd.c         | 18 ++++++++++++++++--
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index bec5f14b622a..fc0b932211f0 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -48,6 +48,7 @@ extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
 extern void fpsimd_bind_task_to_cpu(void);
 extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
 				     void *sve_state, unsigned int sve_vl);
+extern bool fpsimd_is_bound_to_cpu(struct user_fpsimd_state *state);
 
 extern void fpsimd_flush_task_state(struct task_struct *target);
 extern void fpsimd_save_and_flush_cpu_state(void);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 062b21f30f94..683675b5d198 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1009,8 +1009,7 @@ void fpsimd_thread_switch(struct task_struct *next)
 	 * state.  For kernel threads, FPSIMD registers are never loaded
 	 * and wrong_task and wrong_cpu will always be true.
 	 */
-	wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
-					&next->thread.uw.fpsimd_state;
+	wrong_task = !fpsimd_is_bound_to_cpu(&next->thread.uw.fpsimd_state);
 	wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
 
 	update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
@@ -1137,6 +1136,14 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
 	last->sve_vl = sve_vl;
 }
 
+bool fpsimd_is_bound_to_cpu(struct user_fpsimd_state *st)
+{
+	WARN_ON(!system_supports_fpsimd());
+	WARN_ON(!in_softirq() && !irqs_disabled());
+
+	return __this_cpu_read(fpsimd_last_state.st) == st;
+}
+
 /*
  * Load the userland FPSIMD state of 'current' from memory, but only if the
  * FPSIMD state already held in the registers is /not/ the most recent FPSIMD
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 3e5a02137643..dcc5bfad5408 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -51,6 +51,8 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
  */
 void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 {
+	unsigned long flags;
+
 	BUG_ON(!current->mm);
 
 	vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
@@ -61,13 +63,25 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	if (!system_supports_fpsimd())
 		return;
 
-	vcpu->arch.flags |= KVM_ARM64_FP_HOST;
+	local_irq_save(flags);
+
+	if (fpsimd_is_bound_to_cpu(&vcpu->arch.ctxt.fp_regs) &&
+	    vcpu->arch.fpsimd_cpu == smp_processor_id()) {
+		clear_thread_flag(TIF_FOREIGN_FPSTATE);
+		update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu));
+
+		vcpu->arch.flags |= KVM_ARM64_FP_ENABLED;
+	} else {
+		vcpu->arch.flags |= KVM_ARM64_FP_HOST;
+	}
 
 	if (test_thread_flag(TIF_SVE))
 		vcpu->arch.flags |= KVM_ARM64_HOST_SVE_IN_USE;
 
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
 		vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
+
+	local_irq_restore(flags);
 }
 
 
@@ -124,7 +138,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 	local_irq_save(flags);
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
-		fpsimd_save_and_flush_cpu_state();
+		fpsimd_thread_switch(current);
 
 		if (guest_has_sve)
 			__vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_s(SYS_ZCR_EL12);
-- 
2.30.1.766.gb4fecdf3b7-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

  parent reply	other threads:[~2021-03-04 11:55 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-04 11:54 [PATCH 00/10] FPSIMD restore bypass and protecting Andrew Scull
2021-03-04 11:54 ` [PATCH 01/10] KVM: arm64: Leave KVM_ARM64_DEBUG_DIRTY updates to the host Andrew Scull
2021-03-04 11:54 ` [PATCH 02/10] KVM: arm64: Synchronize vcpu FPSIMD in " Andrew Scull
2021-03-04 11:54 ` [PATCH 03/10] KVM: arm64: Unmap host task thread flags from hyp Andrew Scull
2021-03-04 11:54 ` [PATCH 04/10] KVM: arm64: Support smp_processor_id() in nVHE hyp Andrew Scull
2021-03-11 10:35   ` Quentin Perret
2021-03-12 11:20     ` Andrew Scull
2021-03-12 11:27       ` Andrew Scull
2021-03-04 11:54 ` [PATCH 05/10] KVM: arm64: Track where vcpu FP state was last loaded Andrew Scull
2021-03-11 10:37   ` Quentin Perret
2021-03-11 10:40     ` Quentin Perret
2021-03-04 11:54 ` Andrew Scull [this message]
2021-03-04 11:54 ` [PATCH 07/10] KVM: arm64: Separate host and hyp vcpu FP flags Andrew Scull
2021-03-04 11:54 ` [PATCH 08/10] KVM: arm64: Pass the arch run struct explicitly Andrew Scull
2021-03-04 11:54 ` [PATCH 09/10] KVM: arm64: Use hyp-private run struct in protected mode Andrew Scull
2021-03-04 11:54 ` [PATCH 10/10] RFC: KVM: arm64: Manage FPSIMD state at EL2 for protected vCPUs Andrew Scull

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210304115454.3597879-7-ascull@google.com \
    --to=ascull@google.com \
    --cc=Dave.Martin@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=kernel-team@android.com \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=maz@kernel.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox