aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2010-07-15 23:19:51 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 23:40:56 -0400
commitfa1de2bfc0feb7245328ad25fb3e6d5cd2c903b4 (patch)
treebc993022b24c60c2ea2452ca6d7f5ed0faf0a322 /arch
parent6e3e243c3b6e0bbd18c6ce0fbc12bc3fe2d77b34 (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.c9
-rw-r--r--arch/x86/kvm/paging_tmpl.h5
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)