diff options
author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2010-07-15 23:19:51 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 23:40:56 -0400 |
commit | fa1de2bfc0feb7245328ad25fb3e6d5cd2c903b4 (patch) | |
tree | bc993022b24c60c2ea2452ca6d7f5ed0faf0a322 /arch | |
parent | 6e3e243c3b6e0bbd18c6ce0fbc12bc3fe2d77b34 (diff) |
KVM: MMU: add missing reserved bits check in speculative path
In the speculative path, we should check guest pte's reserved bits just as
the real processor does
Reported-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/mmu.c | 9 | ||||
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 5 |
2 files changed, 11 insertions, 3 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 812770cddc8d..d2ea9cabc066 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -2697,6 +2697,9 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, | |||
2697 | return; | 2697 | return; |
2698 | } | 2698 | } |
2699 | 2699 | ||
2700 | if (is_rsvd_bits_set(vcpu, *(u64 *)new, PT_PAGE_TABLE_LEVEL)) | ||
2701 | return; | ||
2702 | |||
2700 | ++vcpu->kvm->stat.mmu_pte_updated; | 2703 | ++vcpu->kvm->stat.mmu_pte_updated; |
2701 | if (!sp->role.cr4_pae) | 2704 | if (!sp->role.cr4_pae) |
2702 | paging32_update_pte(vcpu, sp, spte, new); | 2705 | paging32_update_pte(vcpu, sp, spte, new); |
@@ -2775,6 +2778,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
2775 | bool guest_initiated) | 2778 | bool guest_initiated) |
2776 | { | 2779 | { |
2777 | gfn_t gfn = gpa >> PAGE_SHIFT; | 2780 | gfn_t gfn = gpa >> PAGE_SHIFT; |
2781 | union kvm_mmu_page_role mask = { .word = 0 }; | ||
2778 | struct kvm_mmu_page *sp; | 2782 | struct kvm_mmu_page *sp; |
2779 | struct hlist_node *node; | 2783 | struct hlist_node *node; |
2780 | LIST_HEAD(invalid_list); | 2784 | LIST_HEAD(invalid_list); |
@@ -2849,6 +2853,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
2849 | } | 2853 | } |
2850 | } | 2854 | } |
2851 | 2855 | ||
2856 | mask.cr0_wp = mask.cr4_pae = mask.nxe = 1; | ||
2852 | for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn, node) { | 2857 | for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn, node) { |
2853 | pte_size = sp->role.cr4_pae ? 8 : 4; | 2858 | pte_size = sp->role.cr4_pae ? 8 : 4; |
2854 | misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1); | 2859 | misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1); |
@@ -2896,7 +2901,9 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
2896 | while (npte--) { | 2901 | while (npte--) { |
2897 | entry = *spte; | 2902 | entry = *spte; |
2898 | mmu_pte_write_zap_pte(vcpu, sp, spte); | 2903 | mmu_pte_write_zap_pte(vcpu, sp, spte); |
2899 | if (gentry) | 2904 | if (gentry && |
2905 | !((sp->role.word ^ vcpu->arch.mmu.base_role.word) | ||
2906 | & mask.word)) | ||
2900 | mmu_pte_write_new_pte(vcpu, sp, spte, &gentry); | 2907 | mmu_pte_write_new_pte(vcpu, sp, spte, &gentry); |
2901 | if (!remote_flush && need_remote_flush(entry, *spte)) | 2908 | if (!remote_flush && need_remote_flush(entry, *spte)) |
2902 | remote_flush = true; | 2909 | remote_flush = true; |
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index d9a2742014e3..51ef9097960d 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -638,8 +638,9 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, | |||
638 | return -EINVAL; | 638 | return -EINVAL; |
639 | 639 | ||
640 | gfn = gpte_to_gfn(gpte); | 640 | gfn = gpte_to_gfn(gpte); |
641 | if (gfn != sp->gfns[i] || | 641 | if (is_rsvd_bits_set(vcpu, gpte, PT_PAGE_TABLE_LEVEL) |
642 | !is_present_gpte(gpte) || !(gpte & PT_ACCESSED_MASK)) { | 642 | || gfn != sp->gfns[i] || !is_present_gpte(gpte) |
643 | || !(gpte & PT_ACCESSED_MASK)) { | ||
643 | u64 nonpresent; | 644 | u64 nonpresent; |
644 | 645 | ||
645 | if (is_present_gpte(gpte) || !clear_unsync) | 646 | if (is_present_gpte(gpte) || !clear_unsync) |