aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-01-05 19:36:38 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2007-01-06 02:55:23 -0500
commit399badf315bd4dd571b4b3b7cf666d9a2af40229 (patch)
tree5c84e0392454df650cb4ce25d6bfcb3bac843bc3 /drivers/kvm/kvm_main.c
parentcb26b572dc39467ba0969d1a76c2f723d2d6a2a6 (diff)
[PATCH] KVM: Prevent stale bits in cr0 and cr4
Hardware virtualization implementations allow the guests to freely change some of the bits in cr0 and cr4, but trap when changing the other bits. This is useful to avoid excessive exits due to changing, for example, the ts flag. It also means the kvm's copy of cr0 and cr4 may be stale with respect to these bits. most of the time this doesn't matter as these bits are not very interesting. Other times, however (for example when returning cr0 to userspace), they are, so get the fresh contents of these bits from the guest by means of a new arch operation. Signed-off-by: Avi Kivity <avi@qumranet.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index aca14139a680..bc88c334664b 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -390,6 +390,7 @@ EXPORT_SYMBOL_GPL(set_cr0);
390 390
391void lmsw(struct kvm_vcpu *vcpu, unsigned long msw) 391void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
392{ 392{
393 kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
393 set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f)); 394 set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f));
394} 395}
395EXPORT_SYMBOL_GPL(lmsw); 396EXPORT_SYMBOL_GPL(lmsw);
@@ -917,9 +918,10 @@ int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)
917 918
918int emulate_clts(struct kvm_vcpu *vcpu) 919int emulate_clts(struct kvm_vcpu *vcpu)
919{ 920{
920 unsigned long cr0 = vcpu->cr0; 921 unsigned long cr0;
921 922
922 cr0 &= ~CR0_TS_MASK; 923 kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
924 cr0 = vcpu->cr0 & ~CR0_TS_MASK;
923 kvm_arch_ops->set_cr0(vcpu, cr0); 925 kvm_arch_ops->set_cr0(vcpu, cr0);
924 return X86EMUL_CONTINUE; 926 return X86EMUL_CONTINUE;
925} 927}
@@ -1072,6 +1074,7 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
1072 1074
1073unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr) 1075unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
1074{ 1076{
1077 kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
1075 switch (cr) { 1078 switch (cr) {
1076 case 0: 1079 case 0:
1077 return vcpu->cr0; 1080 return vcpu->cr0;
@@ -1406,6 +1409,7 @@ static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
1406 sregs->gdt.limit = dt.limit; 1409 sregs->gdt.limit = dt.limit;
1407 sregs->gdt.base = dt.base; 1410 sregs->gdt.base = dt.base;
1408 1411
1412 kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
1409 sregs->cr0 = vcpu->cr0; 1413 sregs->cr0 = vcpu->cr0;
1410 sregs->cr2 = vcpu->cr2; 1414 sregs->cr2 = vcpu->cr2;
1411 sregs->cr3 = vcpu->cr3; 1415 sregs->cr3 = vcpu->cr3;
@@ -1470,6 +1474,8 @@ static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
1470#endif 1474#endif
1471 vcpu->apic_base = sregs->apic_base; 1475 vcpu->apic_base = sregs->apic_base;
1472 1476
1477 kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
1478
1473 mmu_reset_needed |= vcpu->cr0 != sregs->cr0; 1479 mmu_reset_needed |= vcpu->cr0 != sregs->cr0;
1474 kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0); 1480 kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0);
1475 1481