lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1421012793-30106-10-git-send-email-riel@redhat.com>
Date:	Sun, 11 Jan 2015 16:46:31 -0500
From:	riel@...hat.com
To:	linux-kernel@...r.kernel.org
Cc:	mingo@...hat.com, hpa@...or.com, matt.fleming@...el.com,
	bp@...e.de, oleg@...hat.com, pbonzini@...hat.com,
	tglx@...utronix.de, luto@...capital.net
Subject: [RFC PATCH 09/11] x86,fpu,kvm: keep vcpu FPU active as long as it is resident

From: Rik van Riel <riel@...hat.com>

Currently KVM always deactivates the FPU on VCPU unload, only to
reactivate it next time the guest uses it. This can make using the
FPU inside a KVM guest fairly expensive.

On the other hand, restoring the FPU state for a KVM guest is also
significantly more involved (and expensive) than restoring the FPU
state on bare metal, so it is unlikely we will want to do this all
the time for every single guest.

This patch strikes a fairly conservative balance, where the FPU
state is re-used as long as nothing else used the FPU registers
on the same CPU. This means the guest FPU will stay active across
KVM event handling in the host, and even periods where the guest
VCPU went idle, or got interrupted by a kernel thread, but no
userspace tasks ran on the CPU.

Smarter, and more aggressive policies may make sense.

Signed-off-by: Rik van Riel <riel@...hat.com>
---
 arch/x86/kvm/x86.c       | 26 +++++++++++++++++++-------
 include/linux/kvm_host.h |  2 +-
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0033df3..a5b01e6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6128,10 +6128,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			r = 0;
 			goto out;
 		}
-		if (kvm_check_request(KVM_REQ_DEACTIVATE_FPU, vcpu)) {
-			vcpu->fpu_active = 0;
-			kvm_x86_ops->fpu_deactivate(vcpu);
-		}
 		if (kvm_check_request(KVM_REQ_APF_HALT, vcpu)) {
 			/* Page is swapped out. Do synthetic halt */
 			vcpu->arch.apf.halted = true;
@@ -6188,8 +6184,23 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	preempt_disable();
 
 	kvm_x86_ops->prepare_guest_switch(vcpu);
-	if (vcpu->fpu_active)
-		kvm_load_guest_fpu(vcpu);
+
+	if (vcpu->fpu_active) {
+		if (this_cpu_read(fpu_owner) == &vcpu->arch.guest_fpu) {
+			/*
+			 * The FPU is all ours. Still restore the FPU state
+			 * from memory, just in case the emulator touched it.
+			 */
+			kvm_load_guest_fpu(vcpu);
+		} else {
+			/*
+			 * Something else is using the FPU. The guest will
+			 * re-activate it on demand, if needed.
+			 */
+			vcpu->fpu_active = 0;
+			kvm_x86_ops->fpu_deactivate(vcpu);
+		}
+	}
 	kvm_load_guest_xcr0(vcpu);
 
 	vcpu->mode = IN_GUEST_MODE;
@@ -6903,6 +6914,7 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
 	kvm_put_guest_xcr0(vcpu);
 	vcpu->guest_fpu_loaded = 1;
 	__kernel_fpu_begin();
+	this_cpu_write(fpu_owner, &vcpu->arch.guest_fpu);
 	fpu_restore_checking(&vcpu->arch.guest_fpu);
 	trace_kvm_fpu(1);
 }
@@ -6917,8 +6929,8 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 	vcpu->guest_fpu_loaded = 0;
 	fpu_save_init(&vcpu->arch.guest_fpu);
 	__kernel_fpu_end();
+	/* but keep fpu_owner pointed at &vcpu->arch.guest_fpu */
 	++vcpu->stat.fpu_reload;
-	kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
 	trace_kvm_fpu(0);
 }
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a6059bd..503259f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -121,7 +121,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_MMU_SYNC           7
 #define KVM_REQ_CLOCK_UPDATE       8
 #define KVM_REQ_KICK               9
-#define KVM_REQ_DEACTIVATE_FPU    10
+
 #define KVM_REQ_EVENT             11
 #define KVM_REQ_APF_HALT          12
 #define KVM_REQ_STEAL_UPDATE      13
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ