linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts
@ 2015-03-12 20:17 Joel Schopp
  2015-03-12 21:17 ` Bandan Das
  2015-03-12 21:20 ` Radim Krčmář
  0 siblings, 2 replies; 6+ messages in thread
From: Joel Schopp @ 2015-03-12 20:17 UTC (permalink / raw)
  To: Gleb Natapov, Paolo Bonzini, kvm
  Cc: Joerg Roedel, Borislav Petkov, linux-kernel, David Kaplan, rkrcmar

There isn't really a valid reason for kvm to intercept cr* reads
on svm hardware.  The current kvm code just ends up returning
the register

Signed-off-by: Joel Schopp <joel.schopp@amd.com>
---
 arch/x86/kvm/svm.c |   41 ++++-------------------------------------
 1 file changed, 4 insertions(+), 37 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index cc618c8..c3d10e6 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1090,9 +1090,6 @@ static void init_vmcb(struct vcpu_svm *svm)
 	svm->vcpu.fpu_active = 1;
 	svm->vcpu.arch.hflags = 0;
 
-	set_cr_intercept(svm, INTERCEPT_CR0_READ);
-	set_cr_intercept(svm, INTERCEPT_CR3_READ);
-	set_cr_intercept(svm, INTERCEPT_CR4_READ);
 	set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
 	set_cr_intercept(svm, INTERCEPT_CR3_WRITE);
 	set_cr_intercept(svm, INTERCEPT_CR4_WRITE);
@@ -1174,7 +1171,6 @@ static void init_vmcb(struct vcpu_svm *svm)
 		control->nested_ctl = 1;
 		clr_intercept(svm, INTERCEPT_INVLPG);
 		clr_exception_intercept(svm, PF_VECTOR);
-		clr_cr_intercept(svm, INTERCEPT_CR3_READ);
 		clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
 		save->g_pat = 0x0007040600070406ULL;
 		save->cr3 = 0;
@@ -2968,29 +2964,10 @@ static int cr_interception(struct vcpu_svm *svm)
 			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
 			return 1;
 		}
-	} else { /* mov from cr */
-		switch (cr) {
-		case 0:
-			val = kvm_read_cr0(&svm->vcpu);
-			break;
-		case 2:
-			val = svm->vcpu.arch.cr2;
-			break;
-		case 3:
-			val = kvm_read_cr3(&svm->vcpu);
-			break;
-		case 4:
-			val = kvm_read_cr4(&svm->vcpu);
-			break;
-		case 8:
-			val = kvm_get_cr8(&svm->vcpu);
-			break;
-		default:
-			WARN(1, "unhandled read from CR%d", cr);
-			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
-			return 1;
-		}
-		kvm_register_write(&svm->vcpu, reg, val);
+	} else { /* mov from cr, should never trap in svm */
+		WARN(1, "unhandled read from CR%d", cr);
+		kvm_queue_exception(&svm->vcpu, UD_VECTOR);
+		return 1;
 	}
 	kvm_complete_insn_gp(&svm->vcpu, err);
 
@@ -3321,10 +3298,6 @@ static int mwait_interception(struct vcpu_svm *svm)
 }
 
 static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
-	[SVM_EXIT_READ_CR0]			= cr_interception,
-	[SVM_EXIT_READ_CR3]			= cr_interception,
-	[SVM_EXIT_READ_CR4]			= cr_interception,
-	[SVM_EXIT_READ_CR8]			= cr_interception,
 	[SVM_EXIT_CR0_SEL_WRITE]		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR0]			= cr_interception,
 	[SVM_EXIT_WRITE_CR3]			= cr_interception,
@@ -4151,11 +4124,9 @@ static const struct __x86_intercept {
 	u32 exit_code;
 	enum x86_intercept_stage stage;
 } x86_intercept_map[] = {
-	[x86_intercept_cr_read]		= POST_EX(SVM_EXIT_READ_CR0),
 	[x86_intercept_cr_write]	= POST_EX(SVM_EXIT_WRITE_CR0),
 	[x86_intercept_clts]		= POST_EX(SVM_EXIT_WRITE_CR0),
 	[x86_intercept_lmsw]		= POST_EX(SVM_EXIT_WRITE_CR0),
-	[x86_intercept_smsw]		= POST_EX(SVM_EXIT_READ_CR0),
 	[x86_intercept_dr_read]		= POST_EX(SVM_EXIT_READ_DR0),
 	[x86_intercept_dr_write]	= POST_EX(SVM_EXIT_WRITE_DR0),
 	[x86_intercept_sldt]		= POST_EX(SVM_EXIT_LDTR_READ),
@@ -4221,10 +4192,6 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
 		goto out;
 
 	switch (icpt_info.exit_code) {
-	case SVM_EXIT_READ_CR0:
-		if (info->intercept == x86_intercept_cr_read)
-			icpt_info.exit_code += info->modrm_reg;
-		break;
 	case SVM_EXIT_WRITE_CR0: {
 		unsigned long cr0, val;
 		u64 intercept;


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

* Re: [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts
  2015-03-12 20:17 [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts Joel Schopp
@ 2015-03-12 21:17 ` Bandan Das
  2015-04-03 12:19   ` Radim Krčmář
  2015-03-12 21:20 ` Radim Krčmář
  1 sibling, 1 reply; 6+ messages in thread
From: Bandan Das @ 2015-03-12 21:17 UTC (permalink / raw)
  To: Joel Schopp
  Cc: Gleb Natapov, Paolo Bonzini, kvm, Joerg Roedel, Borislav Petkov,
	linux-kernel, David Kaplan, rkrcmar


Joel Schopp <joel.schopp@amd.com> writes:

> There isn't really a valid reason for kvm to intercept cr* reads
> on svm hardware.  The current kvm code just ends up returning
> the register
>
> Signed-off-by: Joel Schopp <joel.schopp@amd.com>
> ---
>  arch/x86/kvm/svm.c |   41 ++++-------------------------------------
>  1 file changed, 4 insertions(+), 37 deletions(-)
>
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index cc618c8..c3d10e6 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -1090,9 +1090,6 @@ static void init_vmcb(struct vcpu_svm *svm)
>  	svm->vcpu.fpu_active = 1;
>  	svm->vcpu.arch.hflags = 0;
>  
> -	set_cr_intercept(svm, INTERCEPT_CR0_READ);
> -	set_cr_intercept(svm, INTERCEPT_CR3_READ);
> -	set_cr_intercept(svm, INTERCEPT_CR4_READ);
>  	set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
>  	set_cr_intercept(svm, INTERCEPT_CR3_WRITE);
>  	set_cr_intercept(svm, INTERCEPT_CR4_WRITE);
> @@ -1174,7 +1171,6 @@ static void init_vmcb(struct vcpu_svm *svm)
>  		control->nested_ctl = 1;
>  		clr_intercept(svm, INTERCEPT_INVLPG);
>  		clr_exception_intercept(svm, PF_VECTOR);
> -		clr_cr_intercept(svm, INTERCEPT_CR3_READ);
>  		clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
>  		save->g_pat = 0x0007040600070406ULL;
>  		save->cr3 = 0;
> @@ -2968,29 +2964,10 @@ static int cr_interception(struct vcpu_svm *svm)
>  			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
>  			return 1;
>  		}
> -	} else { /* mov from cr */
> -		switch (cr) {
> -		case 0:
> -			val = kvm_read_cr0(&svm->vcpu);
> -			break;
> -		case 2:
> -			val = svm->vcpu.arch.cr2;
> -			break;
> -		case 3:
> -			val = kvm_read_cr3(&svm->vcpu);
> -			break;
> -		case 4:
> -			val = kvm_read_cr4(&svm->vcpu);
> -			break;
> -		case 8:
> -			val = kvm_get_cr8(&svm->vcpu);
> -			break;
> -		default:
> -			WARN(1, "unhandled read from CR%d", cr);
> -			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
> -			return 1;
> -		}
> -		kvm_register_write(&svm->vcpu, reg, val);
> +	} else { /* mov from cr, should never trap in svm */
> +		WARN(1, "unhandled read from CR%d", cr);
> +		kvm_queue_exception(&svm->vcpu, UD_VECTOR);
> +		return 1;

Can we end up here if a nested hypervisor sets cr read interception ?

Bandan

>  	}
>  	kvm_complete_insn_gp(&svm->vcpu, err);
>  
> @@ -3321,10 +3298,6 @@ static int mwait_interception(struct vcpu_svm *svm)
>  }
>  
>  static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
> -	[SVM_EXIT_READ_CR0]			= cr_interception,
> -	[SVM_EXIT_READ_CR3]			= cr_interception,
> -	[SVM_EXIT_READ_CR4]			= cr_interception,
> -	[SVM_EXIT_READ_CR8]			= cr_interception,
>  	[SVM_EXIT_CR0_SEL_WRITE]		= emulate_on_interception,
>  	[SVM_EXIT_WRITE_CR0]			= cr_interception,
>  	[SVM_EXIT_WRITE_CR3]			= cr_interception,
> @@ -4151,11 +4124,9 @@ static const struct __x86_intercept {
>  	u32 exit_code;
>  	enum x86_intercept_stage stage;
>  } x86_intercept_map[] = {
> -	[x86_intercept_cr_read]		= POST_EX(SVM_EXIT_READ_CR0),
>  	[x86_intercept_cr_write]	= POST_EX(SVM_EXIT_WRITE_CR0),
>  	[x86_intercept_clts]		= POST_EX(SVM_EXIT_WRITE_CR0),
>  	[x86_intercept_lmsw]		= POST_EX(SVM_EXIT_WRITE_CR0),
> -	[x86_intercept_smsw]		= POST_EX(SVM_EXIT_READ_CR0),
>  	[x86_intercept_dr_read]		= POST_EX(SVM_EXIT_READ_DR0),
>  	[x86_intercept_dr_write]	= POST_EX(SVM_EXIT_WRITE_DR0),
>  	[x86_intercept_sldt]		= POST_EX(SVM_EXIT_LDTR_READ),
> @@ -4221,10 +4192,6 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
>  		goto out;
>  
>  	switch (icpt_info.exit_code) {
> -	case SVM_EXIT_READ_CR0:
> -		if (info->intercept == x86_intercept_cr_read)
> -			icpt_info.exit_code += info->modrm_reg;
> -		break;
>  	case SVM_EXIT_WRITE_CR0: {
>  		unsigned long cr0, val;
>  		u64 intercept;
>
> --
> 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

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

* Re: [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts
  2015-03-12 20:17 [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts Joel Schopp
  2015-03-12 21:17 ` Bandan Das
@ 2015-03-12 21:20 ` Radim Krčmář
  2015-03-16 16:16   ` Joel Schopp
  1 sibling, 1 reply; 6+ messages in thread
From: Radim Krčmář @ 2015-03-12 21:20 UTC (permalink / raw)
  To: Joel Schopp
  Cc: Gleb Natapov, Paolo Bonzini, kvm, Joerg Roedel, Borislav Petkov,
	linux-kernel, David Kaplan

2015-03-12 15:17-0500, Joel Schopp:
> There isn't really a valid reason for kvm to intercept cr* reads
> on svm hardware.  The current kvm code just ends up returning
> the register

There is no need to intercept CR* if the value that the guest should see
is equal to what we set there, but that is not always the case:
- CR0 might differ from what the guest should see because of lazy fpu
- CR3 isn't intercepted with nested paging and it should differ
  otherwise
- CR4 contains PAE bit when run without nested paging

CR2 and CR8 already aren't intercepted, so it looks like only CR0 and
CR4 could use some optimizations.

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

* Re: [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts
  2015-03-12 21:20 ` Radim Krčmář
@ 2015-03-16 16:16   ` Joel Schopp
  2015-03-16 17:34     ` Radim Krčmář
  0 siblings, 1 reply; 6+ messages in thread
From: Joel Schopp @ 2015-03-16 16:16 UTC (permalink / raw)
  To: Radim Krčmář
  Cc: Gleb Natapov, Paolo Bonzini, kvm, Joerg Roedel, Borislav Petkov,
	linux-kernel, David Kaplan



On 03/12/2015 04:20 PM, Radim Krčmář wrote:
> 2015-03-12 15:17-0500, Joel Schopp:
>> There isn't really a valid reason for kvm to intercept cr* reads
>> on svm hardware.  The current kvm code just ends up returning
>> the register
> There is no need to intercept CR* if the value that the guest should see
> is equal to what we set there, but that is not always the case:
> - CR0 might differ from what the guest should see because of lazy fpu
Based on our previous conversations I understand why we have to trap the
write to the CR0 ts bit for lazy fpu, but don't understand why that
should affect a read.  I'll take another look at the code to see what
I'm missing.  You are probably correct in which case I'll modify the
patch to only turn off the read intercepts when lazy fpu isn't active.

> - CR3 isn't intercepted with nested paging and it should differ
>   otherwise
> - CR4 contains PAE bit when run without nested paging
>
> CR2 and CR8 already aren't intercepted, so it looks like only CR0 and
> CR4 could use some optimizations.
I'll send out a v2 with these less aggressive optimizations.

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

* Re: [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts
  2015-03-16 16:16   ` Joel Schopp
@ 2015-03-16 17:34     ` Radim Krčmář
  0 siblings, 0 replies; 6+ messages in thread
From: Radim Krčmář @ 2015-03-16 17:34 UTC (permalink / raw)
  To: Joel Schopp
  Cc: Gleb Natapov, Paolo Bonzini, kvm, Joerg Roedel, Borislav Petkov,
	linux-kernel, David Kaplan

2015-03-16 11:16-0500, Joel Schopp:
> On 03/12/2015 04:20 PM, Radim Krčmář wrote:
> > 2015-03-12 15:17-0500, Joel Schopp:
> >> There isn't really a valid reason for kvm to intercept cr* reads
> >> on svm hardware.  The current kvm code just ends up returning
> >> the register
> > There is no need to intercept CR* if the value that the guest should see
> > is equal to what we set there, but that is not always the case:
> > - CR0 might differ from what the guest should see because of lazy fpu
> Based on our previous conversations I understand why we have to trap the
> write to the CR0 ts bit for lazy fpu, but don't understand why that
> should affect a read.

KVM keeps one CR0 with guest's state (svm.vcpu.arch.cr0) and a second
one that is loaded to hardware CR0 on VMRUN (svm.vmcb->save.cr0);
these two might not match.
If we didn't intercept read, it would return hardware CR0, so the guest
could do CLTS (change svm.vcpu.arch.cr0) and read CR0.TS = 1, because of
lazy FPU.

Correct emulation is what we want.

> > CR2 and CR8 already aren't intercepted, so it looks like only CR0 and
> > CR4 could use some optimizations.
> I'll send out a v2 with these less aggressive optimizations.

Thanks.

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

* Re: [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts
  2015-03-12 21:17 ` Bandan Das
@ 2015-04-03 12:19   ` Radim Krčmář
  0 siblings, 0 replies; 6+ messages in thread
From: Radim Krčmář @ 2015-04-03 12:19 UTC (permalink / raw)
  To: Bandan Das
  Cc: Joel Schopp, Gleb Natapov, Paolo Bonzini, kvm, Joerg Roedel,
	Borislav Petkov, linux-kernel, David Kaplan

2015-03-12 17:17-0400, Bandan Das:
> Joel Schopp <joel.schopp@amd.com> writes:
> > @@ -2968,29 +2964,10 @@ static int cr_interception(struct vcpu_svm *svm)
> >  			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
> >  			return 1;
> >  		}
> > -	} else { /* mov from cr */
> > -		[reads of CR 0..8]
> > +	} else { /* mov from cr, should never trap in svm */
> > +		WARN(1, "unhandled read from CR%d", cr);
> > +		kvm_queue_exception(&svm->vcpu, UD_VECTOR);
> > +		return 1;
> 
> Can we end up here if a nested hypervisor sets cr read interception ?

No.  If the nested hypervisor sets intercept bits, we're going to detect
them in 'handle_exit -> nested_svm_exit_handled -> nested_svm_intercept'
and enter L1 before the cr_interception handler.

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

end of thread, other threads:[~2015-04-03 12:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-12 20:17 [PATCH] kvm: x86: svm: remove SVM_EXIT_READ_CR* intercepts Joel Schopp
2015-03-12 21:17 ` Bandan Das
2015-04-03 12:19   ` Radim Krčmář
2015-03-12 21:20 ` Radim Krčmář
2015-03-16 16:16   ` Joel Schopp
2015-03-16 17:34     ` Radim Krčmář

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).