All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6 v2] Lazy fpu for svm/npt
@ 2010-01-10 10:31 Avi Kivity
  2010-01-10 10:31 ` [PATCH 1/6] KVM: Set cr0.et when the guest writes cr0 Avi Kivity
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

This patchset (on top of the previous cr0 patchset) brings lazy fpu to npt.
For the cases where guest and host cr0 match (the majority) it will disable
intercepts for cr0.ts once the guest fpu is loaded, so the guest can to its
own lazy fpu without trapping.

v2:
	Refactored last patch into three independent patches; no code changes.

Avi Kivity (6):
  KVM: Set cr0.et when the guest writes cr0
  KVM: SVM: Fix SVM_CR0_SELECTIVE_MASK
  KVM: SVM: Initialize fpu_active in init_vmcb()
  KVM: SVM: Restore unconditional cr0 intercept under npt
  KVM: SVM: Selective cr0 intercept
  KVM: SVM: Lazy fpu with npt

 arch/x86/include/asm/svm.h |    2 +-
 arch/x86/kvm/svm.c         |   73 +++++++++++++++++++++----------------------
 arch/x86/kvm/x86.c         |    2 +
 3 files changed, 39 insertions(+), 38 deletions(-)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] KVM: Set cr0.et when the guest writes cr0
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
@ 2010-01-10 10:31 ` Avi Kivity
  2010-01-10 10:31 ` [PATCH 2/6] KVM: SVM: Fix SVM_CR0_SELECTIVE_MASK Avi Kivity
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

Follow the hardware.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/x86.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6e6f188..ca42ae3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -428,6 +428,8 @@ out:
 
 void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
+	cr0 |= X86_CR0_ET;
+
 	if (cr0 & CR0_RESERVED_BITS) {
 		printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
 		       cr0, kvm_read_cr0(vcpu));
-- 
1.6.5.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/6] KVM: SVM: Fix SVM_CR0_SELECTIVE_MASK
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
  2010-01-10 10:31 ` [PATCH 1/6] KVM: Set cr0.et when the guest writes cr0 Avi Kivity
@ 2010-01-10 10:31 ` Avi Kivity
  2010-01-10 10:31 ` [PATCH 3/6] KVM: SVM: Initialize fpu_active in init_vmcb() Avi Kivity
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

Instead of selecting TS and MP as the comments say, the macro included TS and
PE.  Luckily the macro is unused now, but fix in order to save a few hours of
debugging from anyone who attempts to use it.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/include/asm/svm.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 1fecb7e..38638cd 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -313,7 +313,7 @@ struct __attribute__ ((__packed__)) vmcb {
 
 #define SVM_EXIT_ERR		-1
 
-#define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */
+#define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
 
 #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
 #define SVM_VMRUN  ".byte 0x0f, 0x01, 0xd8"
-- 
1.6.5.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/6] KVM: SVM: Initialize fpu_active in init_vmcb()
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
  2010-01-10 10:31 ` [PATCH 1/6] KVM: Set cr0.et when the guest writes cr0 Avi Kivity
  2010-01-10 10:31 ` [PATCH 2/6] KVM: SVM: Fix SVM_CR0_SELECTIVE_MASK Avi Kivity
@ 2010-01-10 10:31 ` Avi Kivity
  2010-01-10 10:31 ` [PATCH 4/6] KVM: SVM: Restore unconditional cr0 intercept under npt Avi Kivity
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

init_vmcb() sets up the intercepts as if the fpu is active, so initialize it
there.  This avoids an INIT from setting up intercepts inconsistent with
fpu_active.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/svm.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 4ad8e2e..92f5574 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -540,6 +540,8 @@ static void init_vmcb(struct vcpu_svm *svm)
 	struct vmcb_control_area *control = &svm->vmcb->control;
 	struct vmcb_save_area *save = &svm->vmcb->save;
 
+	svm->vcpu.fpu_active = 1;
+
 	control->intercept_cr_read = 	INTERCEPT_CR0_MASK |
 					INTERCEPT_CR3_MASK |
 					INTERCEPT_CR4_MASK;
@@ -730,7 +732,6 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
 	init_vmcb(svm);
 
 	fx_init(&svm->vcpu);
-	svm->vcpu.fpu_active = 1;
 	svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
 	if (kvm_vcpu_is_bsp(&svm->vcpu))
 		svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
-- 
1.6.5.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/6] KVM: SVM: Restore unconditional cr0 intercept under npt
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
                   ` (2 preceding siblings ...)
  2010-01-10 10:31 ` [PATCH 3/6] KVM: SVM: Initialize fpu_active in init_vmcb() Avi Kivity
@ 2010-01-10 10:31 ` Avi Kivity
  2010-01-10 10:31 ` [PATCH 5/6] KVM: SVM: Selective cr0 intercept Avi Kivity
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

Currently we don't intercept cr0 at all when npt is enabled.  This improves
performance but requires us to activate the fpu at all times.

Remove this behaviour in preparation for adding selective cr0 intercepts.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/svm.c |   30 ++++++++----------------------
 1 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 92f5574..e922605 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -643,10 +643,8 @@ static void init_vmcb(struct vcpu_svm *svm)
 		control->intercept &= ~((1ULL << INTERCEPT_TASK_SWITCH) |
 					(1ULL << INTERCEPT_INVLPG));
 		control->intercept_exceptions &= ~(1 << PF_VECTOR);
-		control->intercept_cr_read &= ~(INTERCEPT_CR0_MASK|
-						INTERCEPT_CR3_MASK);
-		control->intercept_cr_write &= ~(INTERCEPT_CR0_MASK|
-						 INTERCEPT_CR3_MASK);
+		control->intercept_cr_read &= ~INTERCEPT_CR3_MASK;
+		control->intercept_cr_write &= ~INTERCEPT_CR3_MASK;
 		save->g_pat = 0x0007040600070406ULL;
 		save->cr3 = 0;
 		save->cr4 = 0;
@@ -982,12 +980,11 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 		}
 	}
 #endif
-	if (npt_enabled)
-		goto set;
-
 	vcpu->arch.cr0 = cr0;
-	cr0 |= X86_CR0_PG | X86_CR0_WP;
-set:
+
+	if (!npt_enabled)
+		cr0 |= X86_CR0_PG | X86_CR0_WP;
+
 	/*
 	 * re-enable caching here because the QEMU bios
 	 * does not do it - this results in some delay at
@@ -2383,21 +2380,10 @@ static int handle_exit(struct kvm_vcpu *vcpu)
 
 	svm_complete_interrupts(svm);
 
-	if (npt_enabled) {
-		int mmu_reload = 0;
-		if ((kvm_read_cr0_bits(vcpu, X86_CR0_PG) ^ svm->vmcb->save.cr0)
-		    & X86_CR0_PG) {
-			svm_set_cr0(vcpu, svm->vmcb->save.cr0);
-			mmu_reload = 1;
-		}
+	if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR0_MASK))
 		vcpu->arch.cr0 = svm->vmcb->save.cr0;
+	if (npt_enabled)
 		vcpu->arch.cr3 = svm->vmcb->save.cr3;
-		if (mmu_reload) {
-			kvm_mmu_reset_context(vcpu);
-			kvm_mmu_load(vcpu);
-		}
-	}
-
 
 	if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
 		kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
-- 
1.6.5.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/6] KVM: SVM: Selective cr0 intercept
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
                   ` (3 preceding siblings ...)
  2010-01-10 10:31 ` [PATCH 4/6] KVM: SVM: Restore unconditional cr0 intercept under npt Avi Kivity
@ 2010-01-10 10:31 ` Avi Kivity
  2010-01-10 10:31 ` [PATCH 6/6] KVM: SVM: Lazy fpu with npt Avi Kivity
  2010-01-11 10:32 ` [PATCH 0/6 v2] Lazy fpu for svm/npt Joerg Roedel
  6 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

If two conditions apply:
 - no bits outside TS and EM differ between the host and guest cr0
 - the fpu is active

then we can activate the selective cr0 write intercept and drop the
unconditional cr0 read and write intercept, and allow the guest to run
with the host fpu state.  This reduces cr0 exits due to guest fpu management
while the guest fpu is loaded.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/svm.c |   32 ++++++++++++++++++++++++++------
 1 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index e922605..d969ad2 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -571,6 +571,7 @@ static void init_vmcb(struct vcpu_svm *svm)
 	control->intercept = 	(1ULL << INTERCEPT_INTR) |
 				(1ULL << INTERCEPT_NMI) |
 				(1ULL << INTERCEPT_SMI) |
+				(1ULL << INTERCEPT_SELECTIVE_CR0) |
 				(1ULL << INTERCEPT_CPUID) |
 				(1ULL << INTERCEPT_INVD) |
 				(1ULL << INTERCEPT_HLT) |
@@ -963,6 +964,27 @@ static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
 }
 
+static void update_cr0_intercept(struct vcpu_svm *svm)
+{
+	ulong gcr0 = svm->vcpu.arch.cr0;
+	u64 *hcr0 = &svm->vmcb->save.cr0;
+
+	if (!svm->vcpu.fpu_active)
+		*hcr0 |= SVM_CR0_SELECTIVE_MASK;
+	else
+		*hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
+			| (gcr0 & SVM_CR0_SELECTIVE_MASK);
+
+
+	if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
+		svm->vmcb->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK;
+		svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
+	} else {
+		svm->vmcb->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
+		svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
+	}
+}
+
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -992,6 +1014,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 	 */
 	cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
 	svm->vmcb->save.cr0 = cr0;
+	update_cr0_intercept(svm);
 }
 
 static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -1237,11 +1260,8 @@ static int ud_interception(struct vcpu_svm *svm)
 static int nm_interception(struct vcpu_svm *svm)
 {
 	svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
-	if (!kvm_read_cr0_bits(&svm->vcpu, X86_CR0_TS))
-		svm->vmcb->save.cr0 &= ~X86_CR0_TS;
-	else
-		svm->vmcb->save.cr0 |= X86_CR0_TS;
 	svm->vcpu.fpu_active = 1;
+	update_cr0_intercept(svm);
 
 	return 1;
 }
@@ -2294,7 +2314,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = {
 	[SVM_EXIT_READ_CR3]           		= emulate_on_interception,
 	[SVM_EXIT_READ_CR4]           		= emulate_on_interception,
 	[SVM_EXIT_READ_CR8]           		= emulate_on_interception,
-	/* for now: */
+	[SVM_EXIT_CR0_SEL_WRITE]		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR0]          		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR3]          		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR4]          		= emulate_on_interception,
@@ -2912,8 +2932,8 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
 		return;
 	}
 
+	update_cr0_intercept(svm);
 	svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
-	svm->vmcb->save.cr0 |= X86_CR0_TS;
 }
 
 static struct kvm_x86_ops svm_x86_ops = {
-- 
1.6.5.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/6] KVM: SVM: Lazy fpu with npt
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
                   ` (4 preceding siblings ...)
  2010-01-10 10:31 ` [PATCH 5/6] KVM: SVM: Selective cr0 intercept Avi Kivity
@ 2010-01-10 10:31 ` Avi Kivity
  2010-01-11 10:32 ` [PATCH 0/6 v2] Lazy fpu for svm/npt Joerg Roedel
  6 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-10 10:31 UTC (permalink / raw)
  To: Marcelo Tosatti, Joerg Roedel; +Cc: kvm

Now that we can allow the guest to play with cr0 when the fpu is loaded,
we can enable lazy fpu when npt is in use.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/svm.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index d969ad2..3ac48ee 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2586,8 +2586,6 @@ static void svm_flush_tlb(struct kvm_vcpu *vcpu)
 
 static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
 {
-	if (npt_enabled)
-		vcpu->fpu_active = 1;
 }
 
 static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
@@ -2926,12 +2924,6 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (npt_enabled) {
-		/* hack: npt requires active fpu at this time */
-		vcpu->fpu_active = 1;
-		return;
-	}
-
 	update_cr0_intercept(svm);
 	svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
 }
-- 
1.6.5.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/6 v2] Lazy fpu for svm/npt
  2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
                   ` (5 preceding siblings ...)
  2010-01-10 10:31 ` [PATCH 6/6] KVM: SVM: Lazy fpu with npt Avi Kivity
@ 2010-01-11 10:32 ` Joerg Roedel
  2010-01-11 10:39   ` Avi Kivity
  6 siblings, 1 reply; 9+ messages in thread
From: Joerg Roedel @ 2010-01-11 10:32 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Marcelo Tosatti, kvm

On Sun, Jan 10, 2010 at 12:31:23PM +0200, Avi Kivity wrote:
> This patchset (on top of the previous cr0 patchset) brings lazy fpu to npt.
> For the cases where guest and host cr0 match (the majority) it will disable
> intercepts for cr0.ts once the guest fpu is loaded, so the guest can to its
> own lazy fpu without trapping.

Looks good to me.

Acked-by: Joerg Roedel <joerg.roedel@amd.com>



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/6 v2] Lazy fpu for svm/npt
  2010-01-11 10:32 ` [PATCH 0/6 v2] Lazy fpu for svm/npt Joerg Roedel
@ 2010-01-11 10:39   ` Avi Kivity
  0 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2010-01-11 10:39 UTC (permalink / raw)
  To: Joerg Roedel; +Cc: Marcelo Tosatti, kvm

On 01/11/2010 12:32 PM, Joerg Roedel wrote:
> On Sun, Jan 10, 2010 at 12:31:23PM +0200, Avi Kivity wrote:
>    
>> This patchset (on top of the previous cr0 patchset) brings lazy fpu to npt.
>> For the cases where guest and host cr0 match (the majority) it will disable
>> intercepts for cr0.ts once the guest fpu is loaded, so the guest can to its
>> own lazy fpu without trapping.
>>      
> Looks good to me.
>
> Acked-by: Joerg Roedel<joerg.roedel@amd.com>
>    

Now merged, along with the earlier vmx-related bits.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-01-11 10:39 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-10 10:31 [PATCH 0/6 v2] Lazy fpu for svm/npt Avi Kivity
2010-01-10 10:31 ` [PATCH 1/6] KVM: Set cr0.et when the guest writes cr0 Avi Kivity
2010-01-10 10:31 ` [PATCH 2/6] KVM: SVM: Fix SVM_CR0_SELECTIVE_MASK Avi Kivity
2010-01-10 10:31 ` [PATCH 3/6] KVM: SVM: Initialize fpu_active in init_vmcb() Avi Kivity
2010-01-10 10:31 ` [PATCH 4/6] KVM: SVM: Restore unconditional cr0 intercept under npt Avi Kivity
2010-01-10 10:31 ` [PATCH 5/6] KVM: SVM: Selective cr0 intercept Avi Kivity
2010-01-10 10:31 ` [PATCH 6/6] KVM: SVM: Lazy fpu with npt Avi Kivity
2010-01-11 10:32 ` [PATCH 0/6 v2] Lazy fpu for svm/npt Joerg Roedel
2010-01-11 10:39   ` Avi Kivity

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.