diff mbox

[08/12] kvm/svm: cache nested intercepts

Message ID 1248872192-30881-9-git-send-email-joerg.roedel@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Joerg Roedel July 29, 2009, 12:56 p.m. UTC
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kvm/svm.c |   30 +++++++++++++++++++++++-------
 1 files changed, 23 insertions(+), 7 deletions(-)

Comments

Joerg Roedel July 29, 2009, 1:13 p.m. UTC | #1
On Wed, Jul 29, 2009 at 04:13:35PM +0300, Avi Kivity wrote:
> 
> I don't see the benefit of this patch.  Accessing the cache is just
> as expensive as accessing the real vmcb.

The benefit is that we don't have to gup and map the nested vmcb just
for checking who will take the intercept. Another reason is that with
this patch the behavior of nested SVM is more aligned to real hardware.

	Joerg


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avi Kivity July 29, 2009, 1:13 p.m. UTC | #2
On 07/29/2009 03:56 PM, Joerg Roedel wrote:
> Signed-off-by: Joerg Roedel<joerg.roedel@amd.com>
> ---
>   arch/x86/kvm/svm.c |   30 +++++++++++++++++++++++-------
>   1 files changed, 23 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 31467b1..9192c9a 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -86,6 +86,15 @@ struct nested_state {
>
>   	/* gpa pointers to the real vectors */
>   	u64 vmcb_msrpm;
> +
> +	/* cache for intercepts of the guest */
> +	u16 intercept_cr_read;
> +	u16 intercept_cr_write;
> +	u16 intercept_dr_read;
> +	u16 intercept_dr_write;
> +	u32 intercept_exceptions;
> +	u64 intercept;
> +
>   };
>
>   struct vcpu_svm {
> @@ -1459,7 +1468,6 @@ static int nested_svm_exit_handled_real(struct vcpu_svm *svm,
>   					void *arg2,
>   					void *opaque)
>   {
> -	struct vmcb *nested_vmcb = (struct vmcb *)arg1;
>   	bool kvm_overrides = *(bool *)opaque;
>   	u32 exit_code = svm->vmcb->control.exit_code;
>
> @@ -1486,38 +1494,38 @@ static int nested_svm_exit_handled_real(struct vcpu_svm *svm,
>   	switch (exit_code) {
>   	case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: {
>   		u32 cr_bits = 1<<  (exit_code - SVM_EXIT_READ_CR0);
> -		if (nested_vmcb->control.intercept_cr_read&  cr_bits)
> +		if (svm->nested.intercept_cr_read&  cr_bits)
>   			return 1;
>   		break;
>   	}
>   	case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: {
>   		u32 cr_bits = 1<<  (exit_code - SVM_EXIT_WRITE_CR0);
> -		if (nested_vmcb->control.intercept_cr_write&  cr_bits)
> +		if (svm->nested.intercept_cr_write&  cr_bits)
>   			return 1;
>   		break;
>   	}
>   	case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: {
>   		u32 dr_bits = 1<<  (exit_code - SVM_EXIT_READ_DR0);
> -		if (nested_vmcb->control.intercept_dr_read&  dr_bits)
> +		if (svm->nested.intercept_dr_read&  dr_bits)
>   			return 1;
>   		break;
>   	}
>   	case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: {
>   		u32 dr_bits = 1<<  (exit_code - SVM_EXIT_WRITE_DR0);
> -		if (nested_vmcb->control.intercept_dr_write&  dr_bits)
> +		if (svm->nested.intercept_dr_write&  dr_bits)
>   			return 1;
>   		break;
>   	}
>   	case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
>   		u32 excp_bits = 1<<  (exit_code - SVM_EXIT_EXCP_BASE);
> -		if (nested_vmcb->control.intercept_exceptions&  excp_bits)
> +		if (svm->nested.intercept_exceptions&  excp_bits)
>   			return 1;
>   		break;
>   	}
>   	default: {
>   		u64 exit_bits = 1ULL<<  (exit_code - SVM_EXIT_INTR);
>   		nsvm_printk("exit code: 0x%x\n", exit_code);
> -		if (nested_vmcb->control.intercept&  exit_bits)
> +		if (svm->nested.intercept&  exit_bits)
>   			return 1;
>   	}
>   	}
> @@ -1808,6 +1816,14 @@ static int nested_svm_vmrun(struct vcpu_svm *svm, void *arg1,
>
>   	svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa;
>
> +	/* cache intercepts */
> +	svm->nested.intercept_cr_read    = nested_vmcb->control.intercept_cr_read;
> +	svm->nested.intercept_cr_write   = nested_vmcb->control.intercept_cr_write;
> +	svm->nested.intercept_dr_read    = nested_vmcb->control.intercept_dr_read;
> +	svm->nested.intercept_dr_write   = nested_vmcb->control.intercept_dr_write;
> +	svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions;
> +	svm->nested.intercept            = nested_vmcb->control.intercept;
> +
>   	force_new_asid(&svm->vcpu);
>   	svm->vmcb->control.exit_int_info = nested_vmcb->control.exit_int_info;
>   	svm->vmcb->control.exit_int_info_err = nested_vmcb->control.exit_int_info_err;
>    

I don't see the benefit of this patch.  Accessing the cache is just as 
expensive as accessing the real vmcb.
Avi Kivity July 29, 2009, 1:26 p.m. UTC | #3
On 07/29/2009 04:13 PM, Joerg Roedel wrote:
> On Wed, Jul 29, 2009 at 04:13:35PM +0300, Avi Kivity wrote:
>    
>> I don't see the benefit of this patch.  Accessing the cache is just
>> as expensive as accessing the real vmcb.
>>      
>
> The benefit is that we don't have to gup and map the nested vmcb just
> for checking who will take the intercept.

Makes sense.

> Another reason is that with
> this patch the behavior of nested SVM is more aligned to real hardware.
>    

Even more important, please put this in the commit log.
Joerg Roedel July 29, 2009, 1:47 p.m. UTC | #4
On Wed, Jul 29, 2009 at 04:26:02PM +0300, Avi Kivity wrote:
> On 07/29/2009 04:13 PM, Joerg Roedel wrote:
> >On Wed, Jul 29, 2009 at 04:13:35PM +0300, Avi Kivity wrote:
> >>I don't see the benefit of this patch.  Accessing the cache is just
> >>as expensive as accessing the real vmcb.
> >
> >The benefit is that we don't have to gup and map the nested vmcb just
> >for checking who will take the intercept.
> 
> Makes sense.
> 
> >Another reason is that with
> >this patch the behavior of nested SVM is more aligned to real hardware.
> 
> Even more important, please put this in the commit log.

Ok, will do.


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Graf July 29, 2009, 1:50 p.m. UTC | #5
Joerg Roedel wrote:
> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
> ---
>  arch/x86/kvm/svm.c |   30 +++++++++++++++++++++++-------
>  1 files changed, 23 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 31467b1..9192c9a 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -86,6 +86,15 @@ struct nested_state {
>  
>  	/* gpa pointers to the real vectors */
>  	u64 vmcb_msrpm;
> +
> +	/* cache for intercepts of the guest */
> +	u16 intercept_cr_read;
> +	u16 intercept_cr_write;
> +	u16 intercept_dr_read;
> +	u16 intercept_dr_write;
> +	u32 intercept_exceptions;
> +	u64 intercept;
> +
>  };
>  
>  struct vcpu_svm {
> @@ -1459,7 +1468,6 @@ static int nested_svm_exit_handled_real(struct vcpu_svm *svm,
>  					void *arg2,
>  					void *opaque)
>  {
> -	struct vmcb *nested_vmcb = (struct vmcb *)arg1;
>   

That's not enough. You actually have to make the caller not pass it as
argument too. Otherwise a good idea.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Joerg Roedel July 29, 2009, 1:52 p.m. UTC | #6
On Wed, Jul 29, 2009 at 03:50:39PM +0200, Alexander Graf wrote:
> Joerg Roedel wrote:
> > Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
> > ---
> >  arch/x86/kvm/svm.c |   30 +++++++++++++++++++++++-------
> >  1 files changed, 23 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> > index 31467b1..9192c9a 100644
> > --- a/arch/x86/kvm/svm.c
> > +++ b/arch/x86/kvm/svm.c
> > @@ -86,6 +86,15 @@ struct nested_state {
> >  
> >  	/* gpa pointers to the real vectors */
> >  	u64 vmcb_msrpm;
> > +
> > +	/* cache for intercepts of the guest */
> > +	u16 intercept_cr_read;
> > +	u16 intercept_cr_write;
> > +	u16 intercept_dr_read;
> > +	u16 intercept_dr_write;
> > +	u32 intercept_exceptions;
> > +	u64 intercept;
> > +
> >  };
> >  
> >  struct vcpu_svm {
> > @@ -1459,7 +1468,6 @@ static int nested_svm_exit_handled_real(struct vcpu_svm *svm,
> >  					void *arg2,
> >  					void *opaque)
> >  {
> > -	struct vmcb *nested_vmcb = (struct vmcb *)arg1;
> >   
> 
> That's not enough. You actually have to make the caller not pass it as
> argument too. Otherwise a good idea.

Yeah, true. Thats planned but not yet done. Today I just sent out what I have
so far :) This will surely be part of the second cleanup round.

	Joerg


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 31467b1..9192c9a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -86,6 +86,15 @@  struct nested_state {
 
 	/* gpa pointers to the real vectors */
 	u64 vmcb_msrpm;
+
+	/* cache for intercepts of the guest */
+	u16 intercept_cr_read;
+	u16 intercept_cr_write;
+	u16 intercept_dr_read;
+	u16 intercept_dr_write;
+	u32 intercept_exceptions;
+	u64 intercept;
+
 };
 
 struct vcpu_svm {
@@ -1459,7 +1468,6 @@  static int nested_svm_exit_handled_real(struct vcpu_svm *svm,
 					void *arg2,
 					void *opaque)
 {
-	struct vmcb *nested_vmcb = (struct vmcb *)arg1;
 	bool kvm_overrides = *(bool *)opaque;
 	u32 exit_code = svm->vmcb->control.exit_code;
 
@@ -1486,38 +1494,38 @@  static int nested_svm_exit_handled_real(struct vcpu_svm *svm,
 	switch (exit_code) {
 	case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: {
 		u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0);
-		if (nested_vmcb->control.intercept_cr_read & cr_bits)
+		if (svm->nested.intercept_cr_read & cr_bits)
 			return 1;
 		break;
 	}
 	case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: {
 		u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0);
-		if (nested_vmcb->control.intercept_cr_write & cr_bits)
+		if (svm->nested.intercept_cr_write & cr_bits)
 			return 1;
 		break;
 	}
 	case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: {
 		u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0);
-		if (nested_vmcb->control.intercept_dr_read & dr_bits)
+		if (svm->nested.intercept_dr_read & dr_bits)
 			return 1;
 		break;
 	}
 	case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: {
 		u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0);
-		if (nested_vmcb->control.intercept_dr_write & dr_bits)
+		if (svm->nested.intercept_dr_write & dr_bits)
 			return 1;
 		break;
 	}
 	case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
 		u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE);
-		if (nested_vmcb->control.intercept_exceptions & excp_bits)
+		if (svm->nested.intercept_exceptions & excp_bits)
 			return 1;
 		break;
 	}
 	default: {
 		u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR);
 		nsvm_printk("exit code: 0x%x\n", exit_code);
-		if (nested_vmcb->control.intercept & exit_bits)
+		if (svm->nested.intercept & exit_bits)
 			return 1;
 	}
 	}
@@ -1808,6 +1816,14 @@  static int nested_svm_vmrun(struct vcpu_svm *svm, void *arg1,
 
 	svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa;
 
+	/* cache intercepts */
+	svm->nested.intercept_cr_read    = nested_vmcb->control.intercept_cr_read;
+	svm->nested.intercept_cr_write   = nested_vmcb->control.intercept_cr_write;
+	svm->nested.intercept_dr_read    = nested_vmcb->control.intercept_dr_read;
+	svm->nested.intercept_dr_write   = nested_vmcb->control.intercept_dr_write;
+	svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions;
+	svm->nested.intercept            = nested_vmcb->control.intercept;
+
 	force_new_asid(&svm->vcpu);
 	svm->vmcb->control.exit_int_info = nested_vmcb->control.exit_int_info;
 	svm->vmcb->control.exit_int_info_err = nested_vmcb->control.exit_int_info_err;