aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/kvm/kvm-s390.c51
-rw-r--r--virt/kvm/kvm_main.c2
2 files changed, 50 insertions, 3 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index b767ec97368a..346a3478dd00 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -11,6 +11,7 @@
11 * Christian Borntraeger <borntraeger@de.ibm.com> 11 * Christian Borntraeger <borntraeger@de.ibm.com>
12 * Heiko Carstens <heiko.carstens@de.ibm.com> 12 * Heiko Carstens <heiko.carstens@de.ibm.com>
13 * Christian Ehrhardt <ehrhardt@de.ibm.com> 13 * Christian Ehrhardt <ehrhardt@de.ibm.com>
14 * Jason J. Herne <jjherne@us.ibm.com>
14 */ 15 */
15 16
16#include <linux/compiler.h> 17#include <linux/compiler.h>
@@ -179,6 +180,25 @@ int kvm_dev_ioctl_check_extension(long ext)
179 return r; 180 return r;
180} 181}
181 182
183static void kvm_s390_sync_dirty_log(struct kvm *kvm,
184 struct kvm_memory_slot *memslot)
185{
186 gfn_t cur_gfn, last_gfn;
187 unsigned long address;
188 struct gmap *gmap = kvm->arch.gmap;
189
190 down_read(&gmap->mm->mmap_sem);
191 /* Loop over all guest pages */
192 last_gfn = memslot->base_gfn + memslot->npages;
193 for (cur_gfn = memslot->base_gfn; cur_gfn <= last_gfn; cur_gfn++) {
194 address = gfn_to_hva_memslot(memslot, cur_gfn);
195
196 if (gmap_test_and_clear_dirty(address, gmap))
197 mark_page_dirty(kvm, cur_gfn);
198 }
199 up_read(&gmap->mm->mmap_sem);
200}
201
182/* Section: vm related */ 202/* Section: vm related */
183/* 203/*
184 * Get (and clear) the dirty memory log for a memory slot. 204 * Get (and clear) the dirty memory log for a memory slot.
@@ -186,7 +206,36 @@ int kvm_dev_ioctl_check_extension(long ext)
186int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, 206int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
187 struct kvm_dirty_log *log) 207 struct kvm_dirty_log *log)
188{ 208{
189 return 0; 209 int r;
210 unsigned long n;
211 struct kvm_memory_slot *memslot;
212 int is_dirty = 0;
213
214 mutex_lock(&kvm->slots_lock);
215
216 r = -EINVAL;
217 if (log->slot >= KVM_USER_MEM_SLOTS)
218 goto out;
219
220 memslot = id_to_memslot(kvm->memslots, log->slot);
221 r = -ENOENT;
222 if (!memslot->dirty_bitmap)
223 goto out;
224
225 kvm_s390_sync_dirty_log(kvm, memslot);
226 r = kvm_get_dirty_log(kvm, log, &is_dirty);
227 if (r)
228 goto out;
229
230 /* Clear the dirty log */
231 if (is_dirty) {
232 n = kvm_dirty_bitmap_bytes(memslot);
233 memset(memslot->dirty_bitmap, 0, n);
234 }
235 r = 0;
236out:
237 mutex_unlock(&kvm->slots_lock);
238 return r;
190} 239}
191 240
192static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) 241static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 56baae8c2f56..7facdb1f1374 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -637,14 +637,12 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
637 */ 637 */
638static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) 638static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
639{ 639{
640#ifndef CONFIG_S390
641 unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot); 640 unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);
642 641
643 memslot->dirty_bitmap = kvm_kvzalloc(dirty_bytes); 642 memslot->dirty_bitmap = kvm_kvzalloc(dirty_bytes);
644 if (!memslot->dirty_bitmap) 643 if (!memslot->dirty_bitmap)
645 return -ENOMEM; 644 return -ENOMEM;
646 645
647#endif /* !CONFIG_S390 */
648 return 0; 646 return 0;
649} 647}
650 648