aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2014-05-26 05:48:38 -0400
committerAlexander Graf <agraf@suse.de>2014-05-30 08:26:29 -0400
commit687414bebe30d59c766b682cf86b1c5fa92d7af9 (patch)
treea3c77dd1e86e4bb94e503c5dc74b5eb96f231234 /arch/powerpc/kvm
parent1066f7724c73fca9ddb978c7f5b7411c54032047 (diff)
KVM: PPC: Book3S HV: Fix dirty map for hugepages
The dirty map that we construct for the KVM_GET_DIRTY_LOG ioctl has one bit per system page (4K/64K). Currently, we only set one bit in the map for each HPT entry with the Change bit set, even if the HPT is for a large page (e.g., 16MB). Userspace then considers only the first system page dirty, though in fact the guest may have modified anywhere in the large page. To fix this, we make kvm_test_clear_dirty() return the actual number of pages that are dirty (and rename it to kvm_test_clear_dirty_npages() to emphasize that that's what it returns). In kvmppc_hv_get_dirty_log() we then set that many bits in the dirty map. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 4e22ecbcf93f..96c90447d4bf 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -1060,22 +1060,27 @@ void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte)
1060 kvm_handle_hva(kvm, hva, kvm_unmap_rmapp); 1060 kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
1061} 1061}
1062 1062
1063static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp) 1063/*
1064 * Returns the number of system pages that are dirty.
1065 * This can be more than 1 if we find a huge-page HPTE.
1066 */
1067static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
1064{ 1068{
1065 struct revmap_entry *rev = kvm->arch.revmap; 1069 struct revmap_entry *rev = kvm->arch.revmap;
1066 unsigned long head, i, j; 1070 unsigned long head, i, j;
1071 unsigned long n;
1067 unsigned long *hptep; 1072 unsigned long *hptep;
1068 int ret = 0; 1073 int npages_dirty = 0;
1069 1074
1070 retry: 1075 retry:
1071 lock_rmap(rmapp); 1076 lock_rmap(rmapp);
1072 if (*rmapp & KVMPPC_RMAP_CHANGED) { 1077 if (*rmapp & KVMPPC_RMAP_CHANGED) {
1073 *rmapp &= ~KVMPPC_RMAP_CHANGED; 1078 *rmapp &= ~KVMPPC_RMAP_CHANGED;
1074 ret = 1; 1079 npages_dirty = 1;
1075 } 1080 }
1076 if (!(*rmapp & KVMPPC_RMAP_PRESENT)) { 1081 if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
1077 unlock_rmap(rmapp); 1082 unlock_rmap(rmapp);
1078 return ret; 1083 return npages_dirty;
1079 } 1084 }
1080 1085
1081 i = head = *rmapp & KVMPPC_RMAP_INDEX; 1086 i = head = *rmapp & KVMPPC_RMAP_INDEX;
@@ -1106,13 +1111,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
1106 rev[i].guest_rpte |= HPTE_R_C; 1111 rev[i].guest_rpte |= HPTE_R_C;
1107 note_hpte_modification(kvm, &rev[i]); 1112 note_hpte_modification(kvm, &rev[i]);
1108 } 1113 }
1109 ret = 1; 1114 n = hpte_page_size(hptep[0], hptep[1]);
1115 n = (n + PAGE_SIZE - 1) >> PAGE_SHIFT;
1116 if (n > npages_dirty)
1117 npages_dirty = n;
1110 } 1118 }
1111 hptep[0] &= ~HPTE_V_HVLOCK; 1119 hptep[0] &= ~HPTE_V_HVLOCK;
1112 } while ((i = j) != head); 1120 } while ((i = j) != head);
1113 1121
1114 unlock_rmap(rmapp); 1122 unlock_rmap(rmapp);
1115 return ret; 1123 return npages_dirty;
1116} 1124}
1117 1125
1118static void harvest_vpa_dirty(struct kvmppc_vpa *vpa, 1126static void harvest_vpa_dirty(struct kvmppc_vpa *vpa,
@@ -1136,15 +1144,22 @@ static void harvest_vpa_dirty(struct kvmppc_vpa *vpa,
1136long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot, 1144long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
1137 unsigned long *map) 1145 unsigned long *map)
1138{ 1146{
1139 unsigned long i; 1147 unsigned long i, j;
1140 unsigned long *rmapp; 1148 unsigned long *rmapp;
1141 struct kvm_vcpu *vcpu; 1149 struct kvm_vcpu *vcpu;
1142 1150
1143 preempt_disable(); 1151 preempt_disable();
1144 rmapp = memslot->arch.rmap; 1152 rmapp = memslot->arch.rmap;
1145 for (i = 0; i < memslot->npages; ++i) { 1153 for (i = 0; i < memslot->npages; ++i) {
1146 if (kvm_test_clear_dirty(kvm, rmapp) && map) 1154 int npages = kvm_test_clear_dirty_npages(kvm, rmapp);
1147 __set_bit_le(i, map); 1155 /*
1156 * Note that if npages > 0 then i must be a multiple of npages,
1157 * since we always put huge-page HPTEs in the rmap chain
1158 * corresponding to their page base address.
1159 */
1160 if (npages && map)
1161 for (j = i; npages; ++j, --npages)
1162 __set_bit_le(j, map);
1148 ++rmapp; 1163 ++rmapp;
1149 } 1164 }
1150 1165