diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 14:41:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 14:41:11 -0500 |
commit | 597b0d21626da4e6f09f132442caf0cc2b0eb47c (patch) | |
tree | 13c0074bb20f7b05a471e78d4ff52c665a10266a /arch/x86/kvm/mmu.c | |
parent | 2640c9a90fa596871e142f42052608864335f102 (diff) | |
parent | 87917239204d67a316cb89751750f86c9ed3640b (diff) |
Merge branch 'kvm-updates/2.6.29' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
* 'kvm-updates/2.6.29' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm: (140 commits)
KVM: MMU: handle large host sptes on invlpg/resync
KVM: Add locking to virtual i8259 interrupt controller
KVM: MMU: Don't treat a global pte as such if cr4.pge is cleared
MAINTAINERS: Maintainership changes for kvm/ia64
KVM: ia64: Fix kvm_arch_vcpu_ioctl_[gs]et_regs()
KVM: x86: Rework user space NMI injection as KVM_CAP_USER_NMI
KVM: VMX: Fix pending NMI-vs.-IRQ race for user space irqchip
KVM: fix handling of ACK from shared guest IRQ
KVM: MMU: check for present pdptr shadow page in walk_shadow
KVM: Consolidate userspace memory capability reporting into common code
KVM: Advertise the bug in memory region destruction as fixed
KVM: use cpumask_var_t for cpus_hardware_enabled
KVM: use modern cpumask primitives, no cpumask_t on stack
KVM: Extract core of kvm_flush_remote_tlbs/kvm_reload_remote_mmus
KVM: set owner of cpu and vm file operations
anon_inodes: use fops->owner for module refcount
x86: KVM guest: kvm_get_tsc_khz: return khz, not lpj
KVM: MMU: prepopulate the shadow on invlpg
KVM: MMU: skip global pgtables on sync due to cr3 switch
KVM: MMU: collapse remote TLB flushes on root sync
...
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r-- | arch/x86/kvm/mmu.c | 444 |
1 files changed, 356 insertions, 88 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 410ddbc1aa2e..83f11c7474a1 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "vmx.h" | ||
21 | #include "mmu.h" | 20 | #include "mmu.h" |
22 | 21 | ||
23 | #include <linux/kvm_host.h> | 22 | #include <linux/kvm_host.h> |
@@ -33,6 +32,7 @@ | |||
33 | #include <asm/page.h> | 32 | #include <asm/page.h> |
34 | #include <asm/cmpxchg.h> | 33 | #include <asm/cmpxchg.h> |
35 | #include <asm/io.h> | 34 | #include <asm/io.h> |
35 | #include <asm/vmx.h> | ||
36 | 36 | ||
37 | /* | 37 | /* |
38 | * When setting this variable to true it enables Two-Dimensional-Paging | 38 | * When setting this variable to true it enables Two-Dimensional-Paging |
@@ -168,6 +168,7 @@ static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */ | |||
168 | static u64 __read_mostly shadow_user_mask; | 168 | static u64 __read_mostly shadow_user_mask; |
169 | static u64 __read_mostly shadow_accessed_mask; | 169 | static u64 __read_mostly shadow_accessed_mask; |
170 | static u64 __read_mostly shadow_dirty_mask; | 170 | static u64 __read_mostly shadow_dirty_mask; |
171 | static u64 __read_mostly shadow_mt_mask; | ||
171 | 172 | ||
172 | void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte) | 173 | void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte) |
173 | { | 174 | { |
@@ -183,13 +184,14 @@ void kvm_mmu_set_base_ptes(u64 base_pte) | |||
183 | EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes); | 184 | EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes); |
184 | 185 | ||
185 | void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, | 186 | void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, |
186 | u64 dirty_mask, u64 nx_mask, u64 x_mask) | 187 | u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask) |
187 | { | 188 | { |
188 | shadow_user_mask = user_mask; | 189 | shadow_user_mask = user_mask; |
189 | shadow_accessed_mask = accessed_mask; | 190 | shadow_accessed_mask = accessed_mask; |
190 | shadow_dirty_mask = dirty_mask; | 191 | shadow_dirty_mask = dirty_mask; |
191 | shadow_nx_mask = nx_mask; | 192 | shadow_nx_mask = nx_mask; |
192 | shadow_x_mask = x_mask; | 193 | shadow_x_mask = x_mask; |
194 | shadow_mt_mask = mt_mask; | ||
193 | } | 195 | } |
194 | EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); | 196 | EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); |
195 | 197 | ||
@@ -384,7 +386,9 @@ static void account_shadowed(struct kvm *kvm, gfn_t gfn) | |||
384 | { | 386 | { |
385 | int *write_count; | 387 | int *write_count; |
386 | 388 | ||
387 | write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn)); | 389 | gfn = unalias_gfn(kvm, gfn); |
390 | write_count = slot_largepage_idx(gfn, | ||
391 | gfn_to_memslot_unaliased(kvm, gfn)); | ||
388 | *write_count += 1; | 392 | *write_count += 1; |
389 | } | 393 | } |
390 | 394 | ||
@@ -392,16 +396,20 @@ static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn) | |||
392 | { | 396 | { |
393 | int *write_count; | 397 | int *write_count; |
394 | 398 | ||
395 | write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn)); | 399 | gfn = unalias_gfn(kvm, gfn); |
400 | write_count = slot_largepage_idx(gfn, | ||
401 | gfn_to_memslot_unaliased(kvm, gfn)); | ||
396 | *write_count -= 1; | 402 | *write_count -= 1; |
397 | WARN_ON(*write_count < 0); | 403 | WARN_ON(*write_count < 0); |
398 | } | 404 | } |
399 | 405 | ||
400 | static int has_wrprotected_page(struct kvm *kvm, gfn_t gfn) | 406 | static int has_wrprotected_page(struct kvm *kvm, gfn_t gfn) |
401 | { | 407 | { |
402 | struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn); | 408 | struct kvm_memory_slot *slot; |
403 | int *largepage_idx; | 409 | int *largepage_idx; |
404 | 410 | ||
411 | gfn = unalias_gfn(kvm, gfn); | ||
412 | slot = gfn_to_memslot_unaliased(kvm, gfn); | ||
405 | if (slot) { | 413 | if (slot) { |
406 | largepage_idx = slot_largepage_idx(gfn, slot); | 414 | largepage_idx = slot_largepage_idx(gfn, slot); |
407 | return *largepage_idx; | 415 | return *largepage_idx; |
@@ -613,7 +621,7 @@ static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte) | |||
613 | return NULL; | 621 | return NULL; |
614 | } | 622 | } |
615 | 623 | ||
616 | static void rmap_write_protect(struct kvm *kvm, u64 gfn) | 624 | static int rmap_write_protect(struct kvm *kvm, u64 gfn) |
617 | { | 625 | { |
618 | unsigned long *rmapp; | 626 | unsigned long *rmapp; |
619 | u64 *spte; | 627 | u64 *spte; |
@@ -659,8 +667,7 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn) | |||
659 | spte = rmap_next(kvm, rmapp, spte); | 667 | spte = rmap_next(kvm, rmapp, spte); |
660 | } | 668 | } |
661 | 669 | ||
662 | if (write_protected) | 670 | return write_protected; |
663 | kvm_flush_remote_tlbs(kvm); | ||
664 | } | 671 | } |
665 | 672 | ||
666 | static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp) | 673 | static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp) |
@@ -786,9 +793,11 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, | |||
786 | sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE); | 793 | sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE); |
787 | set_page_private(virt_to_page(sp->spt), (unsigned long)sp); | 794 | set_page_private(virt_to_page(sp->spt), (unsigned long)sp); |
788 | list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages); | 795 | list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages); |
796 | INIT_LIST_HEAD(&sp->oos_link); | ||
789 | ASSERT(is_empty_shadow_page(sp->spt)); | 797 | ASSERT(is_empty_shadow_page(sp->spt)); |
790 | sp->slot_bitmap = 0; | 798 | bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS); |
791 | sp->multimapped = 0; | 799 | sp->multimapped = 0; |
800 | sp->global = 1; | ||
792 | sp->parent_pte = parent_pte; | 801 | sp->parent_pte = parent_pte; |
793 | --vcpu->kvm->arch.n_free_mmu_pages; | 802 | --vcpu->kvm->arch.n_free_mmu_pages; |
794 | return sp; | 803 | return sp; |
@@ -900,8 +909,9 @@ static void kvm_mmu_update_unsync_bitmap(u64 *spte) | |||
900 | struct kvm_mmu_page *sp = page_header(__pa(spte)); | 909 | struct kvm_mmu_page *sp = page_header(__pa(spte)); |
901 | 910 | ||
902 | index = spte - sp->spt; | 911 | index = spte - sp->spt; |
903 | __set_bit(index, sp->unsync_child_bitmap); | 912 | if (!__test_and_set_bit(index, sp->unsync_child_bitmap)) |
904 | sp->unsync_children = 1; | 913 | sp->unsync_children++; |
914 | WARN_ON(!sp->unsync_children); | ||
905 | } | 915 | } |
906 | 916 | ||
907 | static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp) | 917 | static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp) |
@@ -928,7 +938,6 @@ static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp) | |||
928 | 938 | ||
929 | static int unsync_walk_fn(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | 939 | static int unsync_walk_fn(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) |
930 | { | 940 | { |
931 | sp->unsync_children = 1; | ||
932 | kvm_mmu_update_parents_unsync(sp); | 941 | kvm_mmu_update_parents_unsync(sp); |
933 | return 1; | 942 | return 1; |
934 | } | 943 | } |
@@ -959,38 +968,66 @@ static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva) | |||
959 | { | 968 | { |
960 | } | 969 | } |
961 | 970 | ||
971 | #define KVM_PAGE_ARRAY_NR 16 | ||
972 | |||
973 | struct kvm_mmu_pages { | ||
974 | struct mmu_page_and_offset { | ||
975 | struct kvm_mmu_page *sp; | ||
976 | unsigned int idx; | ||
977 | } page[KVM_PAGE_ARRAY_NR]; | ||
978 | unsigned int nr; | ||
979 | }; | ||
980 | |||
962 | #define for_each_unsync_children(bitmap, idx) \ | 981 | #define for_each_unsync_children(bitmap, idx) \ |
963 | for (idx = find_first_bit(bitmap, 512); \ | 982 | for (idx = find_first_bit(bitmap, 512); \ |
964 | idx < 512; \ | 983 | idx < 512; \ |
965 | idx = find_next_bit(bitmap, 512, idx+1)) | 984 | idx = find_next_bit(bitmap, 512, idx+1)) |
966 | 985 | ||
967 | static int mmu_unsync_walk(struct kvm_mmu_page *sp, | 986 | int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp, |
968 | struct kvm_unsync_walk *walker) | 987 | int idx) |
969 | { | 988 | { |
970 | int i, ret; | 989 | int i; |
971 | 990 | ||
972 | if (!sp->unsync_children) | 991 | if (sp->unsync) |
973 | return 0; | 992 | for (i=0; i < pvec->nr; i++) |
993 | if (pvec->page[i].sp == sp) | ||
994 | return 0; | ||
995 | |||
996 | pvec->page[pvec->nr].sp = sp; | ||
997 | pvec->page[pvec->nr].idx = idx; | ||
998 | pvec->nr++; | ||
999 | return (pvec->nr == KVM_PAGE_ARRAY_NR); | ||
1000 | } | ||
1001 | |||
1002 | static int __mmu_unsync_walk(struct kvm_mmu_page *sp, | ||
1003 | struct kvm_mmu_pages *pvec) | ||
1004 | { | ||
1005 | int i, ret, nr_unsync_leaf = 0; | ||
974 | 1006 | ||
975 | for_each_unsync_children(sp->unsync_child_bitmap, i) { | 1007 | for_each_unsync_children(sp->unsync_child_bitmap, i) { |
976 | u64 ent = sp->spt[i]; | 1008 | u64 ent = sp->spt[i]; |
977 | 1009 | ||
978 | if (is_shadow_present_pte(ent)) { | 1010 | if (is_shadow_present_pte(ent) && !is_large_pte(ent)) { |
979 | struct kvm_mmu_page *child; | 1011 | struct kvm_mmu_page *child; |
980 | child = page_header(ent & PT64_BASE_ADDR_MASK); | 1012 | child = page_header(ent & PT64_BASE_ADDR_MASK); |
981 | 1013 | ||
982 | if (child->unsync_children) { | 1014 | if (child->unsync_children) { |
983 | ret = mmu_unsync_walk(child, walker); | 1015 | if (mmu_pages_add(pvec, child, i)) |
984 | if (ret) | 1016 | return -ENOSPC; |
1017 | |||
1018 | ret = __mmu_unsync_walk(child, pvec); | ||
1019 | if (!ret) | ||
1020 | __clear_bit(i, sp->unsync_child_bitmap); | ||
1021 | else if (ret > 0) | ||
1022 | nr_unsync_leaf += ret; | ||
1023 | else | ||
985 | return ret; | 1024 | return ret; |
986 | __clear_bit(i, sp->unsync_child_bitmap); | ||
987 | } | 1025 | } |
988 | 1026 | ||
989 | if (child->unsync) { | 1027 | if (child->unsync) { |
990 | ret = walker->entry(child, walker); | 1028 | nr_unsync_leaf++; |
991 | __clear_bit(i, sp->unsync_child_bitmap); | 1029 | if (mmu_pages_add(pvec, child, i)) |
992 | if (ret) | 1030 | return -ENOSPC; |
993 | return ret; | ||
994 | } | 1031 | } |
995 | } | 1032 | } |
996 | } | 1033 | } |
@@ -998,7 +1035,17 @@ static int mmu_unsync_walk(struct kvm_mmu_page *sp, | |||
998 | if (find_first_bit(sp->unsync_child_bitmap, 512) == 512) | 1035 | if (find_first_bit(sp->unsync_child_bitmap, 512) == 512) |
999 | sp->unsync_children = 0; | 1036 | sp->unsync_children = 0; |
1000 | 1037 | ||
1001 | return 0; | 1038 | return nr_unsync_leaf; |
1039 | } | ||
1040 | |||
1041 | static int mmu_unsync_walk(struct kvm_mmu_page *sp, | ||
1042 | struct kvm_mmu_pages *pvec) | ||
1043 | { | ||
1044 | if (!sp->unsync_children) | ||
1045 | return 0; | ||
1046 | |||
1047 | mmu_pages_add(pvec, sp, 0); | ||
1048 | return __mmu_unsync_walk(sp, pvec); | ||
1002 | } | 1049 | } |
1003 | 1050 | ||
1004 | static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) | 1051 | static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) |
@@ -1021,10 +1068,18 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) | |||
1021 | return NULL; | 1068 | return NULL; |
1022 | } | 1069 | } |
1023 | 1070 | ||
1071 | static void kvm_unlink_unsync_global(struct kvm *kvm, struct kvm_mmu_page *sp) | ||
1072 | { | ||
1073 | list_del(&sp->oos_link); | ||
1074 | --kvm->stat.mmu_unsync_global; | ||
1075 | } | ||
1076 | |||
1024 | static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp) | 1077 | static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp) |
1025 | { | 1078 | { |
1026 | WARN_ON(!sp->unsync); | 1079 | WARN_ON(!sp->unsync); |
1027 | sp->unsync = 0; | 1080 | sp->unsync = 0; |
1081 | if (sp->global) | ||
1082 | kvm_unlink_unsync_global(kvm, sp); | ||
1028 | --kvm->stat.mmu_unsync; | 1083 | --kvm->stat.mmu_unsync; |
1029 | } | 1084 | } |
1030 | 1085 | ||
@@ -1037,7 +1092,8 @@ static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | |||
1037 | return 1; | 1092 | return 1; |
1038 | } | 1093 | } |
1039 | 1094 | ||
1040 | rmap_write_protect(vcpu->kvm, sp->gfn); | 1095 | if (rmap_write_protect(vcpu->kvm, sp->gfn)) |
1096 | kvm_flush_remote_tlbs(vcpu->kvm); | ||
1041 | kvm_unlink_unsync_page(vcpu->kvm, sp); | 1097 | kvm_unlink_unsync_page(vcpu->kvm, sp); |
1042 | if (vcpu->arch.mmu.sync_page(vcpu, sp)) { | 1098 | if (vcpu->arch.mmu.sync_page(vcpu, sp)) { |
1043 | kvm_mmu_zap_page(vcpu->kvm, sp); | 1099 | kvm_mmu_zap_page(vcpu->kvm, sp); |
@@ -1048,30 +1104,89 @@ static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | |||
1048 | return 0; | 1104 | return 0; |
1049 | } | 1105 | } |
1050 | 1106 | ||
1051 | struct sync_walker { | 1107 | struct mmu_page_path { |
1052 | struct kvm_vcpu *vcpu; | 1108 | struct kvm_mmu_page *parent[PT64_ROOT_LEVEL-1]; |
1053 | struct kvm_unsync_walk walker; | 1109 | unsigned int idx[PT64_ROOT_LEVEL-1]; |
1054 | }; | 1110 | }; |
1055 | 1111 | ||
1056 | static int mmu_sync_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk) | 1112 | #define for_each_sp(pvec, sp, parents, i) \ |
1113 | for (i = mmu_pages_next(&pvec, &parents, -1), \ | ||
1114 | sp = pvec.page[i].sp; \ | ||
1115 | i < pvec.nr && ({ sp = pvec.page[i].sp; 1;}); \ | ||
1116 | i = mmu_pages_next(&pvec, &parents, i)) | ||
1117 | |||
1118 | int mmu_pages_next(struct kvm_mmu_pages *pvec, struct mmu_page_path *parents, | ||
1119 | int i) | ||
1057 | { | 1120 | { |
1058 | struct sync_walker *sync_walk = container_of(walk, struct sync_walker, | 1121 | int n; |
1059 | walker); | ||
1060 | struct kvm_vcpu *vcpu = sync_walk->vcpu; | ||
1061 | 1122 | ||
1062 | kvm_sync_page(vcpu, sp); | 1123 | for (n = i+1; n < pvec->nr; n++) { |
1063 | return (need_resched() || spin_needbreak(&vcpu->kvm->mmu_lock)); | 1124 | struct kvm_mmu_page *sp = pvec->page[n].sp; |
1125 | |||
1126 | if (sp->role.level == PT_PAGE_TABLE_LEVEL) { | ||
1127 | parents->idx[0] = pvec->page[n].idx; | ||
1128 | return n; | ||
1129 | } | ||
1130 | |||
1131 | parents->parent[sp->role.level-2] = sp; | ||
1132 | parents->idx[sp->role.level-1] = pvec->page[n].idx; | ||
1133 | } | ||
1134 | |||
1135 | return n; | ||
1064 | } | 1136 | } |
1065 | 1137 | ||
1066 | static void mmu_sync_children(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | 1138 | void mmu_pages_clear_parents(struct mmu_page_path *parents) |
1067 | { | 1139 | { |
1068 | struct sync_walker walker = { | 1140 | struct kvm_mmu_page *sp; |
1069 | .walker = { .entry = mmu_sync_fn, }, | 1141 | unsigned int level = 0; |
1070 | .vcpu = vcpu, | 1142 | |
1071 | }; | 1143 | do { |
1144 | unsigned int idx = parents->idx[level]; | ||
1145 | |||
1146 | sp = parents->parent[level]; | ||
1147 | if (!sp) | ||
1148 | return; | ||
1149 | |||
1150 | --sp->unsync_children; | ||
1151 | WARN_ON((int)sp->unsync_children < 0); | ||
1152 | __clear_bit(idx, sp->unsync_child_bitmap); | ||
1153 | level++; | ||
1154 | } while (level < PT64_ROOT_LEVEL-1 && !sp->unsync_children); | ||
1155 | } | ||
1156 | |||
1157 | static void kvm_mmu_pages_init(struct kvm_mmu_page *parent, | ||
1158 | struct mmu_page_path *parents, | ||
1159 | struct kvm_mmu_pages *pvec) | ||
1160 | { | ||
1161 | parents->parent[parent->role.level-1] = NULL; | ||
1162 | pvec->nr = 0; | ||
1163 | } | ||
1164 | |||
1165 | static void mmu_sync_children(struct kvm_vcpu *vcpu, | ||
1166 | struct kvm_mmu_page *parent) | ||
1167 | { | ||
1168 | int i; | ||
1169 | struct kvm_mmu_page *sp; | ||
1170 | struct mmu_page_path parents; | ||
1171 | struct kvm_mmu_pages pages; | ||
1172 | |||
1173 | kvm_mmu_pages_init(parent, &parents, &pages); | ||
1174 | while (mmu_unsync_walk(parent, &pages)) { | ||
1175 | int protected = 0; | ||
1072 | 1176 | ||
1073 | while (mmu_unsync_walk(sp, &walker.walker)) | 1177 | for_each_sp(pages, sp, parents, i) |
1178 | protected |= rmap_write_protect(vcpu->kvm, sp->gfn); | ||
1179 | |||
1180 | if (protected) | ||
1181 | kvm_flush_remote_tlbs(vcpu->kvm); | ||
1182 | |||
1183 | for_each_sp(pages, sp, parents, i) { | ||
1184 | kvm_sync_page(vcpu, sp); | ||
1185 | mmu_pages_clear_parents(&parents); | ||
1186 | } | ||
1074 | cond_resched_lock(&vcpu->kvm->mmu_lock); | 1187 | cond_resched_lock(&vcpu->kvm->mmu_lock); |
1188 | kvm_mmu_pages_init(parent, &parents, &pages); | ||
1189 | } | ||
1075 | } | 1190 | } |
1076 | 1191 | ||
1077 | static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | 1192 | static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, |
@@ -1129,7 +1244,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | |||
1129 | sp->role = role; | 1244 | sp->role = role; |
1130 | hlist_add_head(&sp->hash_link, bucket); | 1245 | hlist_add_head(&sp->hash_link, bucket); |
1131 | if (!metaphysical) { | 1246 | if (!metaphysical) { |
1132 | rmap_write_protect(vcpu->kvm, gfn); | 1247 | if (rmap_write_protect(vcpu->kvm, gfn)) |
1248 | kvm_flush_remote_tlbs(vcpu->kvm); | ||
1133 | account_shadowed(vcpu->kvm, gfn); | 1249 | account_shadowed(vcpu->kvm, gfn); |
1134 | } | 1250 | } |
1135 | if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte) | 1251 | if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte) |
@@ -1153,6 +1269,8 @@ static int walk_shadow(struct kvm_shadow_walk *walker, | |||
1153 | if (level == PT32E_ROOT_LEVEL) { | 1269 | if (level == PT32E_ROOT_LEVEL) { |
1154 | shadow_addr = vcpu->arch.mmu.pae_root[(addr >> 30) & 3]; | 1270 | shadow_addr = vcpu->arch.mmu.pae_root[(addr >> 30) & 3]; |
1155 | shadow_addr &= PT64_BASE_ADDR_MASK; | 1271 | shadow_addr &= PT64_BASE_ADDR_MASK; |
1272 | if (!shadow_addr) | ||
1273 | return 1; | ||
1156 | --level; | 1274 | --level; |
1157 | } | 1275 | } |
1158 | 1276 | ||
@@ -1237,33 +1355,29 @@ static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp) | |||
1237 | } | 1355 | } |
1238 | } | 1356 | } |
1239 | 1357 | ||
1240 | struct zap_walker { | 1358 | static int mmu_zap_unsync_children(struct kvm *kvm, |
1241 | struct kvm_unsync_walk walker; | 1359 | struct kvm_mmu_page *parent) |
1242 | struct kvm *kvm; | ||
1243 | int zapped; | ||
1244 | }; | ||
1245 | |||
1246 | static int mmu_zap_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk) | ||
1247 | { | 1360 | { |
1248 | struct zap_walker *zap_walk = container_of(walk, struct zap_walker, | 1361 | int i, zapped = 0; |
1249 | walker); | 1362 | struct mmu_page_path parents; |
1250 | kvm_mmu_zap_page(zap_walk->kvm, sp); | 1363 | struct kvm_mmu_pages pages; |
1251 | zap_walk->zapped = 1; | ||
1252 | return 0; | ||
1253 | } | ||
1254 | 1364 | ||
1255 | static int mmu_zap_unsync_children(struct kvm *kvm, struct kvm_mmu_page *sp) | 1365 | if (parent->role.level == PT_PAGE_TABLE_LEVEL) |
1256 | { | ||
1257 | struct zap_walker walker = { | ||
1258 | .walker = { .entry = mmu_zap_fn, }, | ||
1259 | .kvm = kvm, | ||
1260 | .zapped = 0, | ||
1261 | }; | ||
1262 | |||
1263 | if (sp->role.level == PT_PAGE_TABLE_LEVEL) | ||
1264 | return 0; | 1366 | return 0; |
1265 | mmu_unsync_walk(sp, &walker.walker); | 1367 | |
1266 | return walker.zapped; | 1368 | kvm_mmu_pages_init(parent, &parents, &pages); |
1369 | while (mmu_unsync_walk(parent, &pages)) { | ||
1370 | struct kvm_mmu_page *sp; | ||
1371 | |||
1372 | for_each_sp(pages, sp, parents, i) { | ||
1373 | kvm_mmu_zap_page(kvm, sp); | ||
1374 | mmu_pages_clear_parents(&parents); | ||
1375 | } | ||
1376 | zapped += pages.nr; | ||
1377 | kvm_mmu_pages_init(parent, &parents, &pages); | ||
1378 | } | ||
1379 | |||
1380 | return zapped; | ||
1267 | } | 1381 | } |
1268 | 1382 | ||
1269 | static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) | 1383 | static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) |
@@ -1362,7 +1476,7 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn) | |||
1362 | int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn)); | 1476 | int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn)); |
1363 | struct kvm_mmu_page *sp = page_header(__pa(pte)); | 1477 | struct kvm_mmu_page *sp = page_header(__pa(pte)); |
1364 | 1478 | ||
1365 | __set_bit(slot, &sp->slot_bitmap); | 1479 | __set_bit(slot, sp->slot_bitmap); |
1366 | } | 1480 | } |
1367 | 1481 | ||
1368 | static void mmu_convert_notrap(struct kvm_mmu_page *sp) | 1482 | static void mmu_convert_notrap(struct kvm_mmu_page *sp) |
@@ -1393,6 +1507,110 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva) | |||
1393 | return page; | 1507 | return page; |
1394 | } | 1508 | } |
1395 | 1509 | ||
1510 | /* | ||
1511 | * The function is based on mtrr_type_lookup() in | ||
1512 | * arch/x86/kernel/cpu/mtrr/generic.c | ||
1513 | */ | ||
1514 | static int get_mtrr_type(struct mtrr_state_type *mtrr_state, | ||
1515 | u64 start, u64 end) | ||
1516 | { | ||
1517 | int i; | ||
1518 | u64 base, mask; | ||
1519 | u8 prev_match, curr_match; | ||
1520 | int num_var_ranges = KVM_NR_VAR_MTRR; | ||
1521 | |||
1522 | if (!mtrr_state->enabled) | ||
1523 | return 0xFF; | ||
1524 | |||
1525 | /* Make end inclusive end, instead of exclusive */ | ||
1526 | end--; | ||
1527 | |||
1528 | /* Look in fixed ranges. Just return the type as per start */ | ||
1529 | if (mtrr_state->have_fixed && (start < 0x100000)) { | ||
1530 | int idx; | ||
1531 | |||
1532 | if (start < 0x80000) { | ||
1533 | idx = 0; | ||
1534 | idx += (start >> 16); | ||
1535 | return mtrr_state->fixed_ranges[idx]; | ||
1536 | } else if (start < 0xC0000) { | ||
1537 | idx = 1 * 8; | ||
1538 | idx += ((start - 0x80000) >> 14); | ||
1539 | return mtrr_state->fixed_ranges[idx]; | ||
1540 | } else if (start < 0x1000000) { | ||
1541 | idx = 3 * 8; | ||
1542 | idx += ((start - 0xC0000) >> 12); | ||
1543 | return mtrr_state->fixed_ranges[idx]; | ||
1544 | } | ||
1545 | } | ||
1546 | |||
1547 | /* | ||
1548 | * Look in variable ranges | ||
1549 | * Look of multiple ranges matching this address and pick type | ||
1550 | * as per MTRR precedence | ||
1551 | */ | ||
1552 | if (!(mtrr_state->enabled & 2)) | ||
1553 | return mtrr_state->def_type; | ||
1554 | |||
1555 | prev_match = 0xFF; | ||
1556 | for (i = 0; i < num_var_ranges; ++i) { | ||
1557 | unsigned short start_state, end_state; | ||
1558 | |||
1559 | if (!(mtrr_state->var_ranges[i].mask_lo & (1 << 11))) | ||
1560 | continue; | ||
1561 | |||
1562 | base = (((u64)mtrr_state->var_ranges[i].base_hi) << 32) + | ||
1563 | (mtrr_state->var_ranges[i].base_lo & PAGE_MASK); | ||
1564 | mask = (((u64)mtrr_state->var_ranges[i].mask_hi) << 32) + | ||
1565 | (mtrr_state->var_ranges[i].mask_lo & PAGE_MASK); | ||
1566 | |||
1567 | start_state = ((start & mask) == (base & mask)); | ||
1568 | end_state = ((end & mask) == (base & mask)); | ||
1569 | if (start_state != end_state) | ||
1570 | return 0xFE; | ||
1571 | |||
1572 | if ((start & mask) != (base & mask)) | ||
1573 | continue; | ||
1574 | |||
1575 | curr_match = mtrr_state->var_ranges[i].base_lo & 0xff; | ||
1576 | if (prev_match == 0xFF) { | ||
1577 | prev_match = curr_match; | ||
1578 | continue; | ||
1579 | } | ||
1580 | |||
1581 | if (prev_match == MTRR_TYPE_UNCACHABLE || | ||
1582 | curr_match == MTRR_TYPE_UNCACHABLE) | ||
1583 | return MTRR_TYPE_UNCACHABLE; | ||
1584 | |||
1585 | if ((prev_match == MTRR_TYPE_WRBACK && | ||
1586 | curr_match == MTRR_TYPE_WRTHROUGH) || | ||
1587 | (prev_match == MTRR_TYPE_WRTHROUGH && | ||
1588 | curr_match == MTRR_TYPE_WRBACK)) { | ||
1589 | prev_match = MTRR_TYPE_WRTHROUGH; | ||
1590 | curr_match = MTRR_TYPE_WRTHROUGH; | ||
1591 | } | ||
1592 | |||
1593 | if (prev_match != curr_match) | ||
1594 | return MTRR_TYPE_UNCACHABLE; | ||
1595 | } | ||
1596 | |||
1597 | if (prev_match != 0xFF) | ||
1598 | return prev_match; | ||
1599 | |||
1600 | return mtrr_state->def_type; | ||
1601 | } | ||
1602 | |||
1603 | static u8 get_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) | ||
1604 | { | ||
1605 | u8 mtrr; | ||
1606 | |||
1607 | mtrr = get_mtrr_type(&vcpu->arch.mtrr_state, gfn << PAGE_SHIFT, | ||
1608 | (gfn << PAGE_SHIFT) + PAGE_SIZE); | ||
1609 | if (mtrr == 0xfe || mtrr == 0xff) | ||
1610 | mtrr = MTRR_TYPE_WRBACK; | ||
1611 | return mtrr; | ||
1612 | } | ||
1613 | |||
1396 | static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | 1614 | static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) |
1397 | { | 1615 | { |
1398 | unsigned index; | 1616 | unsigned index; |
@@ -1409,9 +1627,15 @@ static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | |||
1409 | if (s->role.word != sp->role.word) | 1627 | if (s->role.word != sp->role.word) |
1410 | return 1; | 1628 | return 1; |
1411 | } | 1629 | } |
1412 | kvm_mmu_mark_parents_unsync(vcpu, sp); | ||
1413 | ++vcpu->kvm->stat.mmu_unsync; | 1630 | ++vcpu->kvm->stat.mmu_unsync; |
1414 | sp->unsync = 1; | 1631 | sp->unsync = 1; |
1632 | |||
1633 | if (sp->global) { | ||
1634 | list_add(&sp->oos_link, &vcpu->kvm->arch.oos_global_pages); | ||
1635 | ++vcpu->kvm->stat.mmu_unsync_global; | ||
1636 | } else | ||
1637 | kvm_mmu_mark_parents_unsync(vcpu, sp); | ||
1638 | |||
1415 | mmu_convert_notrap(sp); | 1639 | mmu_convert_notrap(sp); |
1416 | return 0; | 1640 | return 0; |
1417 | } | 1641 | } |
@@ -1437,11 +1661,24 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn, | |||
1437 | static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | 1661 | static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, |
1438 | unsigned pte_access, int user_fault, | 1662 | unsigned pte_access, int user_fault, |
1439 | int write_fault, int dirty, int largepage, | 1663 | int write_fault, int dirty, int largepage, |
1440 | gfn_t gfn, pfn_t pfn, bool speculative, | 1664 | int global, gfn_t gfn, pfn_t pfn, bool speculative, |
1441 | bool can_unsync) | 1665 | bool can_unsync) |
1442 | { | 1666 | { |
1443 | u64 spte; | 1667 | u64 spte; |
1444 | int ret = 0; | 1668 | int ret = 0; |
1669 | u64 mt_mask = shadow_mt_mask; | ||
1670 | struct kvm_mmu_page *sp = page_header(__pa(shadow_pte)); | ||
1671 | |||
1672 | if (!(vcpu->arch.cr4 & X86_CR4_PGE)) | ||
1673 | global = 0; | ||
1674 | if (!global && sp->global) { | ||
1675 | sp->global = 0; | ||
1676 | if (sp->unsync) { | ||
1677 | kvm_unlink_unsync_global(vcpu->kvm, sp); | ||
1678 | kvm_mmu_mark_parents_unsync(vcpu, sp); | ||
1679 | } | ||
1680 | } | ||
1681 | |||
1445 | /* | 1682 | /* |
1446 | * We don't set the accessed bit, since we sometimes want to see | 1683 | * We don't set the accessed bit, since we sometimes want to see |
1447 | * whether the guest actually used the pte (in order to detect | 1684 | * whether the guest actually used the pte (in order to detect |
@@ -1460,6 +1697,11 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
1460 | spte |= shadow_user_mask; | 1697 | spte |= shadow_user_mask; |
1461 | if (largepage) | 1698 | if (largepage) |
1462 | spte |= PT_PAGE_SIZE_MASK; | 1699 | spte |= PT_PAGE_SIZE_MASK; |
1700 | if (mt_mask) { | ||
1701 | mt_mask = get_memory_type(vcpu, gfn) << | ||
1702 | kvm_x86_ops->get_mt_mask_shift(); | ||
1703 | spte |= mt_mask; | ||
1704 | } | ||
1463 | 1705 | ||
1464 | spte |= (u64)pfn << PAGE_SHIFT; | 1706 | spte |= (u64)pfn << PAGE_SHIFT; |
1465 | 1707 | ||
@@ -1474,6 +1716,15 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
1474 | 1716 | ||
1475 | spte |= PT_WRITABLE_MASK; | 1717 | spte |= PT_WRITABLE_MASK; |
1476 | 1718 | ||
1719 | /* | ||
1720 | * Optimization: for pte sync, if spte was writable the hash | ||
1721 | * lookup is unnecessary (and expensive). Write protection | ||
1722 | * is responsibility of mmu_get_page / kvm_sync_page. | ||
1723 | * Same reasoning can be applied to dirty page accounting. | ||
1724 | */ | ||
1725 | if (!can_unsync && is_writeble_pte(*shadow_pte)) | ||
1726 | goto set_pte; | ||
1727 | |||
1477 | if (mmu_need_write_protect(vcpu, gfn, can_unsync)) { | 1728 | if (mmu_need_write_protect(vcpu, gfn, can_unsync)) { |
1478 | pgprintk("%s: found shadow page for %lx, marking ro\n", | 1729 | pgprintk("%s: found shadow page for %lx, marking ro\n", |
1479 | __func__, gfn); | 1730 | __func__, gfn); |
@@ -1495,8 +1746,8 @@ set_pte: | |||
1495 | static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | 1746 | static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, |
1496 | unsigned pt_access, unsigned pte_access, | 1747 | unsigned pt_access, unsigned pte_access, |
1497 | int user_fault, int write_fault, int dirty, | 1748 | int user_fault, int write_fault, int dirty, |
1498 | int *ptwrite, int largepage, gfn_t gfn, | 1749 | int *ptwrite, int largepage, int global, |
1499 | pfn_t pfn, bool speculative) | 1750 | gfn_t gfn, pfn_t pfn, bool speculative) |
1500 | { | 1751 | { |
1501 | int was_rmapped = 0; | 1752 | int was_rmapped = 0; |
1502 | int was_writeble = is_writeble_pte(*shadow_pte); | 1753 | int was_writeble = is_writeble_pte(*shadow_pte); |
@@ -1529,7 +1780,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
1529 | } | 1780 | } |
1530 | } | 1781 | } |
1531 | if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault, | 1782 | if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault, |
1532 | dirty, largepage, gfn, pfn, speculative, true)) { | 1783 | dirty, largepage, global, gfn, pfn, speculative, true)) { |
1533 | if (write_fault) | 1784 | if (write_fault) |
1534 | *ptwrite = 1; | 1785 | *ptwrite = 1; |
1535 | kvm_x86_ops->tlb_flush(vcpu); | 1786 | kvm_x86_ops->tlb_flush(vcpu); |
@@ -1586,7 +1837,7 @@ static int direct_map_entry(struct kvm_shadow_walk *_walk, | |||
1586 | || (walk->largepage && level == PT_DIRECTORY_LEVEL)) { | 1837 | || (walk->largepage && level == PT_DIRECTORY_LEVEL)) { |
1587 | mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL, | 1838 | mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL, |
1588 | 0, walk->write, 1, &walk->pt_write, | 1839 | 0, walk->write, 1, &walk->pt_write, |
1589 | walk->largepage, gfn, walk->pfn, false); | 1840 | walk->largepage, 0, gfn, walk->pfn, false); |
1590 | ++vcpu->stat.pf_fixed; | 1841 | ++vcpu->stat.pf_fixed; |
1591 | return 1; | 1842 | return 1; |
1592 | } | 1843 | } |
@@ -1773,6 +2024,15 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu) | |||
1773 | } | 2024 | } |
1774 | } | 2025 | } |
1775 | 2026 | ||
2027 | static void mmu_sync_global(struct kvm_vcpu *vcpu) | ||
2028 | { | ||
2029 | struct kvm *kvm = vcpu->kvm; | ||
2030 | struct kvm_mmu_page *sp, *n; | ||
2031 | |||
2032 | list_for_each_entry_safe(sp, n, &kvm->arch.oos_global_pages, oos_link) | ||
2033 | kvm_sync_page(vcpu, sp); | ||
2034 | } | ||
2035 | |||
1776 | void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) | 2036 | void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) |
1777 | { | 2037 | { |
1778 | spin_lock(&vcpu->kvm->mmu_lock); | 2038 | spin_lock(&vcpu->kvm->mmu_lock); |
@@ -1780,6 +2040,13 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) | |||
1780 | spin_unlock(&vcpu->kvm->mmu_lock); | 2040 | spin_unlock(&vcpu->kvm->mmu_lock); |
1781 | } | 2041 | } |
1782 | 2042 | ||
2043 | void kvm_mmu_sync_global(struct kvm_vcpu *vcpu) | ||
2044 | { | ||
2045 | spin_lock(&vcpu->kvm->mmu_lock); | ||
2046 | mmu_sync_global(vcpu); | ||
2047 | spin_unlock(&vcpu->kvm->mmu_lock); | ||
2048 | } | ||
2049 | |||
1783 | static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr) | 2050 | static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr) |
1784 | { | 2051 | { |
1785 | return vaddr; | 2052 | return vaddr; |
@@ -2178,7 +2445,8 @@ static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn) | |||
2178 | } | 2445 | } |
2179 | 2446 | ||
2180 | void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | 2447 | void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, |
2181 | const u8 *new, int bytes) | 2448 | const u8 *new, int bytes, |
2449 | bool guest_initiated) | ||
2182 | { | 2450 | { |
2183 | gfn_t gfn = gpa >> PAGE_SHIFT; | 2451 | gfn_t gfn = gpa >> PAGE_SHIFT; |
2184 | struct kvm_mmu_page *sp; | 2452 | struct kvm_mmu_page *sp; |
@@ -2204,15 +2472,17 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
2204 | kvm_mmu_free_some_pages(vcpu); | 2472 | kvm_mmu_free_some_pages(vcpu); |
2205 | ++vcpu->kvm->stat.mmu_pte_write; | 2473 | ++vcpu->kvm->stat.mmu_pte_write; |
2206 | kvm_mmu_audit(vcpu, "pre pte write"); | 2474 | kvm_mmu_audit(vcpu, "pre pte write"); |
2207 | if (gfn == vcpu->arch.last_pt_write_gfn | 2475 | if (guest_initiated) { |
2208 | && !last_updated_pte_accessed(vcpu)) { | 2476 | if (gfn == vcpu->arch.last_pt_write_gfn |
2209 | ++vcpu->arch.last_pt_write_count; | 2477 | && !last_updated_pte_accessed(vcpu)) { |
2210 | if (vcpu->arch.last_pt_write_count >= 3) | 2478 | ++vcpu->arch.last_pt_write_count; |
2211 | flooded = 1; | 2479 | if (vcpu->arch.last_pt_write_count >= 3) |
2212 | } else { | 2480 | flooded = 1; |
2213 | vcpu->arch.last_pt_write_gfn = gfn; | 2481 | } else { |
2214 | vcpu->arch.last_pt_write_count = 1; | 2482 | vcpu->arch.last_pt_write_gfn = gfn; |
2215 | vcpu->arch.last_pte_updated = NULL; | 2483 | vcpu->arch.last_pt_write_count = 1; |
2484 | vcpu->arch.last_pte_updated = NULL; | ||
2485 | } | ||
2216 | } | 2486 | } |
2217 | index = kvm_page_table_hashfn(gfn); | 2487 | index = kvm_page_table_hashfn(gfn); |
2218 | bucket = &vcpu->kvm->arch.mmu_page_hash[index]; | 2488 | bucket = &vcpu->kvm->arch.mmu_page_hash[index]; |
@@ -2352,9 +2622,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_page_fault); | |||
2352 | 2622 | ||
2353 | void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva) | 2623 | void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva) |
2354 | { | 2624 | { |
2355 | spin_lock(&vcpu->kvm->mmu_lock); | ||
2356 | vcpu->arch.mmu.invlpg(vcpu, gva); | 2625 | vcpu->arch.mmu.invlpg(vcpu, gva); |
2357 | spin_unlock(&vcpu->kvm->mmu_lock); | ||
2358 | kvm_mmu_flush_tlb(vcpu); | 2626 | kvm_mmu_flush_tlb(vcpu); |
2359 | ++vcpu->stat.invlpg; | 2627 | ++vcpu->stat.invlpg; |
2360 | } | 2628 | } |
@@ -2451,7 +2719,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot) | |||
2451 | int i; | 2719 | int i; |
2452 | u64 *pt; | 2720 | u64 *pt; |
2453 | 2721 | ||
2454 | if (!test_bit(slot, &sp->slot_bitmap)) | 2722 | if (!test_bit(slot, sp->slot_bitmap)) |
2455 | continue; | 2723 | continue; |
2456 | 2724 | ||
2457 | pt = sp->spt; | 2725 | pt = sp->spt; |
@@ -2860,8 +3128,8 @@ static void audit_write_protection(struct kvm_vcpu *vcpu) | |||
2860 | if (sp->role.metaphysical) | 3128 | if (sp->role.metaphysical) |
2861 | continue; | 3129 | continue; |
2862 | 3130 | ||
2863 | slot = gfn_to_memslot(vcpu->kvm, sp->gfn); | ||
2864 | gfn = unalias_gfn(vcpu->kvm, sp->gfn); | 3131 | gfn = unalias_gfn(vcpu->kvm, sp->gfn); |
3132 | slot = gfn_to_memslot_unaliased(vcpu->kvm, sp->gfn); | ||
2865 | rmapp = &slot->rmap[gfn - slot->base_gfn]; | 3133 | rmapp = &slot->rmap[gfn - slot->base_gfn]; |
2866 | if (*rmapp) | 3134 | if (*rmapp) |
2867 | printk(KERN_ERR "%s: (%s) shadow page has writable" | 3135 | printk(KERN_ERR "%s: (%s) shadow page has writable" |