public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] kvm: cleanup CR8 handling
@ 2010-12-08 11:27 Andre Przywara
  2010-12-13 12:08 ` Avi Kivity
  0 siblings, 1 reply; 4+ messages in thread
From: Andre Przywara @ 2010-12-08 11:27 UTC (permalink / raw)
  To: avi; +Cc: kvm, mtosatti, Andre Przywara

The handling of CR8 writes in KVM is currently somewhat cumbersome.
This patch makes it look like the other CR register handlers
and fixes a possible issue in VMX, where the RIP would be incremented
despite an injected #GP.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +-
 arch/x86/kvm/svm.c              |    7 ++++---
 arch/x86/kvm/vmx.c              |    4 ++--
 arch/x86/kvm/x86.c              |   18 ++++++++----------
 4 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d968cc5..2b89195 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -659,7 +659,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
+int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
 int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val);
 int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val);
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index ae943bb..ed5950c 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2610,16 +2610,17 @@ static int cr0_write_interception(struct vcpu_svm *svm)
 static int cr8_write_interception(struct vcpu_svm *svm)
 {
 	struct kvm_run *kvm_run = svm->vcpu.run;
+	int r;
 
 	u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
 	/* instruction emulation calls kvm_set_cr8() */
-	emulate_instruction(&svm->vcpu, 0, 0, 0);
+	r = emulate_instruction(&svm->vcpu, 0, 0, 0);
 	if (irqchip_in_kernel(svm->vcpu.kvm)) {
 		clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
-		return 1;
+		return r == EMULATE_DONE;
 	}
 	if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
-		return 1;
+		return r == EMULATE_DONE;
 	kvm_run->exit_reason = KVM_EXIT_SET_TPR;
 	return 0;
 }
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 72cfdb7..e5ef924 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3164,8 +3164,8 @@ static int handle_cr(struct kvm_vcpu *vcpu)
 		case 8: {
 				u8 cr8_prev = kvm_get_cr8(vcpu);
 				u8 cr8 = kvm_register_read(vcpu, reg);
-				kvm_set_cr8(vcpu, cr8);
-				skip_emulated_instruction(vcpu);
+				err = kvm_set_cr8(vcpu, cr8);
+				complete_insn_gp(vcpu, err);
 				if (irqchip_in_kernel(vcpu->kvm))
 					return 1;
 				if (cr8_prev <= cr8)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ed373ba..63b8877 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -667,7 +667,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr3);
 
-int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	if (cr8 & CR8_RESERVED_BITS)
 		return 1;
@@ -677,12 +677,6 @@ int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 		vcpu->arch.cr8 = cr8;
 	return 0;
 }
-
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
-{
-	if (__kvm_set_cr8(vcpu, cr8))
-		kvm_inject_gp(vcpu, 0);
-}
 EXPORT_SYMBOL_GPL(kvm_set_cr8);
 
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
@@ -4104,7 +4098,7 @@ static int emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu)
 		res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
 		break;
 	case 8:
-		res = __kvm_set_cr8(vcpu, val & 0xfUL);
+		res = kvm_set_cr8(vcpu, val);
 		break;
 	default:
 		vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
@@ -5379,8 +5373,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 	}
 
 	/* re-sync apic's tpr */
-	if (!irqchip_in_kernel(vcpu->kvm))
-		kvm_set_cr8(vcpu, kvm_run->cr8);
+	if (!irqchip_in_kernel(vcpu->kvm)) {
+		if (kvm_set_cr8(vcpu, kvm_run->cr8) != 0) {
+			r = -EINVAL;
+			goto out;
+		}
+	}
 
 	if (vcpu->arch.pio.count || vcpu->mmio_needed) {
 		if (vcpu->mmio_needed) {
-- 
1.6.4



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

* Re: [PATCH] kvm: cleanup CR8 handling
  2010-12-08 11:27 [PATCH] kvm: cleanup CR8 handling Andre Przywara
@ 2010-12-13 12:08 ` Avi Kivity
  2010-12-21 10:07   ` Andre Przywara
  0 siblings, 1 reply; 4+ messages in thread
From: Avi Kivity @ 2010-12-13 12:08 UTC (permalink / raw)
  To: Andre Przywara; +Cc: kvm, mtosatti

On 12/08/2010 01:27 PM, Andre Przywara wrote:
> The handling of CR8 writes in KVM is currently somewhat cumbersome.
> This patch makes it look like the other CR register handlers
> and fixes a possible issue in VMX, where the RIP would be incremented
> despite an injected #GP.
>
>   unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
> @@ -4104,7 +4098,7 @@ static int emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu)
>   		res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
>   		break;
>   	case 8:
> -		res = __kvm_set_cr8(vcpu, val&  0xfUL);
> +		res = kvm_set_cr8(vcpu, val);
>   		break;
>   	default:
>   		vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);

Why drop the mask?

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


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

* Re: [PATCH] kvm: cleanup CR8 handling
  2010-12-13 12:08 ` Avi Kivity
@ 2010-12-21 10:07   ` Andre Przywara
  2010-12-21 10:56     ` Avi Kivity
  0 siblings, 1 reply; 4+ messages in thread
From: Andre Przywara @ 2010-12-21 10:07 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm@vger.kernel.org, mtosatti@redhat.com

Avi Kivity wrote:
> On 12/08/2010 01:27 PM, Andre Przywara wrote:
>> The handling of CR8 writes in KVM is currently somewhat cumbersome.
>> This patch makes it look like the other CR register handlers
>> and fixes a possible issue in VMX, where the RIP would be incremented
>> despite an injected #GP.
>>
>>   unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
>> @@ -4104,7 +4098,7 @@ static int emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu)
>>   		res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
>>   		break;
>>   	case 8:
>> -		res = __kvm_set_cr8(vcpu, val&  0xfUL);
>> +		res = kvm_set_cr8(vcpu, val);
>>   		break;
>>   	default:
>>   		vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
> 
> Why drop the mask?
Because it is checked in kvm_set_cr8 itself. If it is wrong, the caller 
should get a #GP as described in the manual. By masking this out we 
would never deliver the #GP to the guest.

Regards,
Andre.

-- 
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany
Tel: +49 351 448-3567-12


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

* Re: [PATCH] kvm: cleanup CR8 handling
  2010-12-21 10:07   ` Andre Przywara
@ 2010-12-21 10:56     ` Avi Kivity
  0 siblings, 0 replies; 4+ messages in thread
From: Avi Kivity @ 2010-12-21 10:56 UTC (permalink / raw)
  To: Andre Przywara; +Cc: kvm@vger.kernel.org, mtosatti@redhat.com

On 12/21/2010 12:07 PM, Andre Przywara wrote:
> Avi Kivity wrote:
>> On 12/08/2010 01:27 PM, Andre Przywara wrote:
>>> The handling of CR8 writes in KVM is currently somewhat cumbersome.
>>> This patch makes it look like the other CR register handlers
>>> and fixes a possible issue in VMX, where the RIP would be incremented
>>> despite an injected #GP.
>>>
>>>   unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
>>> @@ -4104,7 +4098,7 @@ static int emulator_set_cr(int cr, unsigned 
>>> long val, struct kvm_vcpu *vcpu)
>>>           res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
>>>           break;
>>>       case 8:
>>> -        res = __kvm_set_cr8(vcpu, val&  0xfUL);
>>> +        res = kvm_set_cr8(vcpu, val);
>>>           break;
>>>       default:
>>>           vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
>>
>> Why drop the mask?
> Because it is checked in kvm_set_cr8 itself. If it is wrong, the 
> caller should get a #GP as described in the manual. By masking this 
> out we would never deliver the #GP to the guest.
>

Ok.  Strictly speaking, this should be in a separate patch, since it 
fixes a bug, but this is such a minor bug it doesn't matter.  I doubt 
any guest relies on #GP on invalid CR8.

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


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

end of thread, other threads:[~2010-12-21 10:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-08 11:27 [PATCH] kvm: cleanup CR8 handling Andre Przywara
2010-12-13 12:08 ` Avi Kivity
2010-12-21 10:07   ` Andre Przywara
2010-12-21 10:56     ` Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox