diff options
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/kvm_cache_regs.h | 12 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.h | 5 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 13 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 16 |
5 files changed, 30 insertions, 17 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index da6dee862763..e9f4f12ec3c4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -272,6 +272,7 @@ struct kvm_vcpu_arch { | |||
272 | unsigned long cr2; | 272 | unsigned long cr2; |
273 | unsigned long cr3; | 273 | unsigned long cr3; |
274 | unsigned long cr4; | 274 | unsigned long cr4; |
275 | unsigned long cr4_guest_owned_bits; | ||
275 | unsigned long cr8; | 276 | unsigned long cr8; |
276 | u32 hflags; | 277 | u32 hflags; |
277 | u64 pdptrs[4]; /* pae */ | 278 | u64 pdptrs[4]; /* pae */ |
diff --git a/arch/x86/kvm/kvm_cache_regs.h b/arch/x86/kvm/kvm_cache_regs.h index 7bcc5b6a4403..35acc36e1782 100644 --- a/arch/x86/kvm/kvm_cache_regs.h +++ b/arch/x86/kvm/kvm_cache_regs.h | |||
@@ -38,4 +38,16 @@ static inline u64 kvm_pdptr_read(struct kvm_vcpu *vcpu, int index) | |||
38 | return vcpu->arch.pdptrs[index]; | 38 | return vcpu->arch.pdptrs[index]; |
39 | } | 39 | } |
40 | 40 | ||
41 | static inline ulong kvm_read_cr4_bits(struct kvm_vcpu *vcpu, ulong mask) | ||
42 | { | ||
43 | if (mask & vcpu->arch.cr4_guest_owned_bits) | ||
44 | kvm_x86_ops->decache_cr4_guest_bits(vcpu); | ||
45 | return vcpu->arch.cr4 & mask; | ||
46 | } | ||
47 | |||
48 | static inline ulong kvm_read_cr4(struct kvm_vcpu *vcpu) | ||
49 | { | ||
50 | return kvm_read_cr4_bits(vcpu, ~0UL); | ||
51 | } | ||
52 | |||
41 | #endif | 53 | #endif |
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 61a1b3884b49..4567d8042b22 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __KVM_X86_MMU_H | 2 | #define __KVM_X86_MMU_H |
3 | 3 | ||
4 | #include <linux/kvm_host.h> | 4 | #include <linux/kvm_host.h> |
5 | #include "kvm_cache_regs.h" | ||
5 | 6 | ||
6 | #define PT64_PT_BITS 9 | 7 | #define PT64_PT_BITS 9 |
7 | #define PT64_ENT_PER_PAGE (1 << PT64_PT_BITS) | 8 | #define PT64_ENT_PER_PAGE (1 << PT64_PT_BITS) |
@@ -64,12 +65,12 @@ static inline int is_long_mode(struct kvm_vcpu *vcpu) | |||
64 | 65 | ||
65 | static inline int is_pae(struct kvm_vcpu *vcpu) | 66 | static inline int is_pae(struct kvm_vcpu *vcpu) |
66 | { | 67 | { |
67 | return vcpu->arch.cr4 & X86_CR4_PAE; | 68 | return kvm_read_cr4_bits(vcpu, X86_CR4_PAE); |
68 | } | 69 | } |
69 | 70 | ||
70 | static inline int is_pse(struct kvm_vcpu *vcpu) | 71 | static inline int is_pse(struct kvm_vcpu *vcpu) |
71 | { | 72 | { |
72 | return vcpu->arch.cr4 & X86_CR4_PSE; | 73 | return kvm_read_cr4_bits(vcpu, X86_CR4_PSE); |
73 | } | 74 | } |
74 | 75 | ||
75 | static inline int is_paging(struct kvm_vcpu *vcpu) | 76 | static inline int is_paging(struct kvm_vcpu *vcpu) |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index efbb614ccd36..284e905c59d3 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1615,8 +1615,10 @@ static void vmx_flush_tlb(struct kvm_vcpu *vcpu) | |||
1615 | 1615 | ||
1616 | static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu) | 1616 | static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu) |
1617 | { | 1617 | { |
1618 | vcpu->arch.cr4 &= KVM_GUEST_CR4_MASK; | 1618 | ulong cr4_guest_owned_bits = vcpu->arch.cr4_guest_owned_bits; |
1619 | vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & ~KVM_GUEST_CR4_MASK; | 1619 | |
1620 | vcpu->arch.cr4 &= ~cr4_guest_owned_bits; | ||
1621 | vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & cr4_guest_owned_bits; | ||
1620 | } | 1622 | } |
1621 | 1623 | ||
1622 | static void ept_load_pdptrs(struct kvm_vcpu *vcpu) | 1624 | static void ept_load_pdptrs(struct kvm_vcpu *vcpu) |
@@ -1661,7 +1663,7 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0, | |||
1661 | (CPU_BASED_CR3_LOAD_EXITING | | 1663 | (CPU_BASED_CR3_LOAD_EXITING | |
1662 | CPU_BASED_CR3_STORE_EXITING)); | 1664 | CPU_BASED_CR3_STORE_EXITING)); |
1663 | vcpu->arch.cr0 = cr0; | 1665 | vcpu->arch.cr0 = cr0; |
1664 | vmx_set_cr4(vcpu, vcpu->arch.cr4); | 1666 | vmx_set_cr4(vcpu, kvm_read_cr4(vcpu)); |
1665 | } else if (!is_paging(vcpu)) { | 1667 | } else if (!is_paging(vcpu)) { |
1666 | /* From nonpaging to paging */ | 1668 | /* From nonpaging to paging */ |
1667 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, | 1669 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, |
@@ -1669,7 +1671,7 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0, | |||
1669 | ~(CPU_BASED_CR3_LOAD_EXITING | | 1671 | ~(CPU_BASED_CR3_LOAD_EXITING | |
1670 | CPU_BASED_CR3_STORE_EXITING)); | 1672 | CPU_BASED_CR3_STORE_EXITING)); |
1671 | vcpu->arch.cr0 = cr0; | 1673 | vcpu->arch.cr0 = cr0; |
1672 | vmx_set_cr4(vcpu, vcpu->arch.cr4); | 1674 | vmx_set_cr4(vcpu, kvm_read_cr4(vcpu)); |
1673 | } | 1675 | } |
1674 | 1676 | ||
1675 | if (!(cr0 & X86_CR0_WP)) | 1677 | if (!(cr0 & X86_CR0_WP)) |
@@ -2420,6 +2422,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
2420 | 2422 | ||
2421 | vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); | 2423 | vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); |
2422 | vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); | 2424 | vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); |
2425 | vmx->vcpu.arch.cr4_guest_owned_bits = ~KVM_GUEST_CR4_MASK; | ||
2423 | 2426 | ||
2424 | tsc_base = vmx->vcpu.kvm->arch.vm_init_tsc; | 2427 | tsc_base = vmx->vcpu.kvm->arch.vm_init_tsc; |
2425 | rdtscll(tsc_this); | 2428 | rdtscll(tsc_this); |
@@ -3050,7 +3053,7 @@ static int handle_dr(struct kvm_vcpu *vcpu) | |||
3050 | vcpu->arch.eff_db[dr] = val; | 3053 | vcpu->arch.eff_db[dr] = val; |
3051 | break; | 3054 | break; |
3052 | case 4 ... 5: | 3055 | case 4 ... 5: |
3053 | if (vcpu->arch.cr4 & X86_CR4_DE) | 3056 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) |
3054 | kvm_queue_exception(vcpu, UD_VECTOR); | 3057 | kvm_queue_exception(vcpu, UD_VECTOR); |
3055 | break; | 3058 | break; |
3056 | case 6: | 3059 | case 6: |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 279318677911..84dd33e717fd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -482,7 +482,7 @@ EXPORT_SYMBOL_GPL(kvm_lmsw); | |||
482 | 482 | ||
483 | void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | 483 | void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) |
484 | { | 484 | { |
485 | unsigned long old_cr4 = vcpu->arch.cr4; | 485 | unsigned long old_cr4 = kvm_read_cr4(vcpu); |
486 | unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE; | 486 | unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE; |
487 | 487 | ||
488 | if (cr4 & CR4_RESERVED_BITS) { | 488 | if (cr4 & CR4_RESERVED_BITS) { |
@@ -1899,7 +1899,7 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu, | |||
1899 | return 0; | 1899 | return 0; |
1900 | if (mce->status & MCI_STATUS_UC) { | 1900 | if (mce->status & MCI_STATUS_UC) { |
1901 | if ((vcpu->arch.mcg_status & MCG_STATUS_MCIP) || | 1901 | if ((vcpu->arch.mcg_status & MCG_STATUS_MCIP) || |
1902 | !(vcpu->arch.cr4 & X86_CR4_MCE)) { | 1902 | !kvm_read_cr4_bits(vcpu, X86_CR4_MCE)) { |
1903 | printk(KERN_DEBUG "kvm: set_mce: " | 1903 | printk(KERN_DEBUG "kvm: set_mce: " |
1904 | "injects mce exception while " | 1904 | "injects mce exception while " |
1905 | "previous one is in progress!\n"); | 1905 | "previous one is in progress!\n"); |
@@ -3616,7 +3616,6 @@ unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr) | |||
3616 | { | 3616 | { |
3617 | unsigned long value; | 3617 | unsigned long value; |
3618 | 3618 | ||
3619 | kvm_x86_ops->decache_cr4_guest_bits(vcpu); | ||
3620 | switch (cr) { | 3619 | switch (cr) { |
3621 | case 0: | 3620 | case 0: |
3622 | value = vcpu->arch.cr0; | 3621 | value = vcpu->arch.cr0; |
@@ -3628,7 +3627,7 @@ unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr) | |||
3628 | value = vcpu->arch.cr3; | 3627 | value = vcpu->arch.cr3; |
3629 | break; | 3628 | break; |
3630 | case 4: | 3629 | case 4: |
3631 | value = vcpu->arch.cr4; | 3630 | value = kvm_read_cr4(vcpu); |
3632 | break; | 3631 | break; |
3633 | case 8: | 3632 | case 8: |
3634 | value = kvm_get_cr8(vcpu); | 3633 | value = kvm_get_cr8(vcpu); |
@@ -3656,7 +3655,7 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val, | |||
3656 | kvm_set_cr3(vcpu, val); | 3655 | kvm_set_cr3(vcpu, val); |
3657 | break; | 3656 | break; |
3658 | case 4: | 3657 | case 4: |
3659 | kvm_set_cr4(vcpu, mk_cr_64(vcpu->arch.cr4, val)); | 3658 | kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val)); |
3660 | break; | 3659 | break; |
3661 | case 8: | 3660 | case 8: |
3662 | kvm_set_cr8(vcpu, val & 0xfUL); | 3661 | kvm_set_cr8(vcpu, val & 0xfUL); |
@@ -4237,11 +4236,10 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
4237 | sregs->gdt.limit = dt.limit; | 4236 | sregs->gdt.limit = dt.limit; |
4238 | sregs->gdt.base = dt.base; | 4237 | sregs->gdt.base = dt.base; |
4239 | 4238 | ||
4240 | kvm_x86_ops->decache_cr4_guest_bits(vcpu); | ||
4241 | sregs->cr0 = vcpu->arch.cr0; | 4239 | sregs->cr0 = vcpu->arch.cr0; |
4242 | sregs->cr2 = vcpu->arch.cr2; | 4240 | sregs->cr2 = vcpu->arch.cr2; |
4243 | sregs->cr3 = vcpu->arch.cr3; | 4241 | sregs->cr3 = vcpu->arch.cr3; |
4244 | sregs->cr4 = vcpu->arch.cr4; | 4242 | sregs->cr4 = kvm_read_cr4(vcpu); |
4245 | sregs->cr8 = kvm_get_cr8(vcpu); | 4243 | sregs->cr8 = kvm_get_cr8(vcpu); |
4246 | sregs->efer = vcpu->arch.shadow_efer; | 4244 | sregs->efer = vcpu->arch.shadow_efer; |
4247 | sregs->apic_base = kvm_get_apic_base(vcpu); | 4245 | sregs->apic_base = kvm_get_apic_base(vcpu); |
@@ -4737,13 +4735,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
4737 | kvm_x86_ops->set_efer(vcpu, sregs->efer); | 4735 | kvm_x86_ops->set_efer(vcpu, sregs->efer); |
4738 | kvm_set_apic_base(vcpu, sregs->apic_base); | 4736 | kvm_set_apic_base(vcpu, sregs->apic_base); |
4739 | 4737 | ||
4740 | kvm_x86_ops->decache_cr4_guest_bits(vcpu); | ||
4741 | |||
4742 | mmu_reset_needed |= vcpu->arch.cr0 != sregs->cr0; | 4738 | mmu_reset_needed |= vcpu->arch.cr0 != sregs->cr0; |
4743 | kvm_x86_ops->set_cr0(vcpu, sregs->cr0); | 4739 | kvm_x86_ops->set_cr0(vcpu, sregs->cr0); |
4744 | vcpu->arch.cr0 = sregs->cr0; | 4740 | vcpu->arch.cr0 = sregs->cr0; |
4745 | 4741 | ||
4746 | mmu_reset_needed |= vcpu->arch.cr4 != sregs->cr4; | 4742 | mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; |
4747 | kvm_x86_ops->set_cr4(vcpu, sregs->cr4); | 4743 | kvm_x86_ops->set_cr4(vcpu, sregs->cr4); |
4748 | if (!is_long_mode(vcpu) && is_pae(vcpu)) { | 4744 | if (!is_long_mode(vcpu) && is_pae(vcpu)) { |
4749 | load_pdptrs(vcpu, vcpu->arch.cr3); | 4745 | load_pdptrs(vcpu, vcpu->arch.cr3); |