KVM: s390: protvirt: Secure memory is not mergeable
authorJanosch Frank <frankja@linux.ibm.com>
Tue, 16 Jul 2019 11:08:37 +0000 (13:08 +0200)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Thu, 27 Feb 2020 18:47:11 +0000 (19:47 +0100)
KSM will not work on secure pages, because when the kernel reads a
secure page, it will be encrypted and hence no two pages will look the
same.

Let's mark the guest pages as unmergeable when we transition to secure
mode.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
[borntraeger@de.ibm.com: patch merging, splitting, fixing]
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/include/asm/gmap.h
arch/s390/kvm/kvm-s390.c
arch/s390/mm/gmap.c

index 3c4926a..6f9ff7a 100644 (file)
@@ -148,4 +148,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,
 
 void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4],
                             unsigned long gaddr, unsigned long vmaddr);
+int gmap_mark_unmergeable(void);
 #endif /* _ASM_S390_GMAP_H */
index 87258be..bf61f48 100644 (file)
@@ -2234,6 +2234,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
                if (r)
                        break;
 
+               down_write(&current->mm->mmap_sem);
+               r = gmap_mark_unmergeable();
+               up_write(&current->mm->mmap_sem);
+               if (r)
+                       break;
+
                r = kvm_s390_pv_init_vm(kvm, &cmd->rc, &cmd->rrc);
                if (r)
                        break;
index edcdca9..7291452 100644 (file)
@@ -2548,6 +2548,22 @@ int s390_enable_sie(void)
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
 
+int gmap_mark_unmergeable(void)
+{
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
+                               MADV_UNMERGEABLE, &vma->vm_flags)) {
+                       return -ENOMEM;
+               }
+       }
+       mm->def_flags &= ~VM_MERGEABLE;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(gmap_mark_unmergeable);
+
 /*
  * Enable storage key handling from now on and initialize the storage
  * keys with the default key.
@@ -2593,7 +2609,6 @@ static const struct mm_walk_ops enable_skey_walk_ops = {
 int s390_enable_skey(void)
 {
        struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
        int rc = 0;
 
        down_write(&mm->mmap_sem);
@@ -2601,16 +2616,11 @@ int s390_enable_skey(void)
                goto out_up;
 
        mm->context.uses_skeys = 1;
-       for (vma = mm->mmap; vma; vma = vma->vm_next) {
-               if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
-                               MADV_UNMERGEABLE, &vma->vm_flags)) {
-                       mm->context.uses_skeys = 0;
-                       rc = -ENOMEM;
-                       goto out_up;
-               }
+       rc = gmap_mark_unmergeable();
+       if (rc) {
+               mm->context.uses_skeys = 0;
+               goto out_up;
        }
-       mm->def_flags &= ~VM_MERGEABLE;
-
        walk_page_range(mm, 0, TASK_SIZE, &enable_skey_walk_ops, NULL);
 
 out_up: