* [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