1*d487a240SSteffen Eiden // SPDX-License-Identifier: GPL-2.0 2*d487a240SSteffen Eiden 3*d487a240SSteffen Eiden #include <linux/kvm_types.h> 4*d487a240SSteffen Eiden #include <linux/kvm_host.h> 5*d487a240SSteffen Eiden 6*d487a240SSteffen Eiden #include "s390.h" 7*d487a240SSteffen Eiden #include "gmap.h" 8*d487a240SSteffen Eiden #include "dat.h" 9*d487a240SSteffen Eiden #include "kvm_mmu.h" 10*d487a240SSteffen Eiden 11*d487a240SSteffen Eiden /* 12*d487a240SSteffen Eiden * Get (and clear) the dirty memory log for a memory slot. 13*d487a240SSteffen Eiden */ 14*d487a240SSteffen Eiden int s390_kvm_mmu_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) 15*d487a240SSteffen Eiden { 16*d487a240SSteffen Eiden int r; 17*d487a240SSteffen Eiden unsigned long n; 18*d487a240SSteffen Eiden struct kvm_memory_slot *memslot; 19*d487a240SSteffen Eiden int is_dirty; 20*d487a240SSteffen Eiden 21*d487a240SSteffen Eiden if (kvm_is_ucontrol(kvm)) 22*d487a240SSteffen Eiden return -EINVAL; 23*d487a240SSteffen Eiden 24*d487a240SSteffen Eiden mutex_lock(&kvm->slots_lock); 25*d487a240SSteffen Eiden 26*d487a240SSteffen Eiden r = -EINVAL; 27*d487a240SSteffen Eiden if (log->slot >= KVM_USER_MEM_SLOTS) 28*d487a240SSteffen Eiden goto out; 29*d487a240SSteffen Eiden 30*d487a240SSteffen Eiden r = kvm_get_dirty_log(kvm, log, &is_dirty, &memslot); 31*d487a240SSteffen Eiden if (r) 32*d487a240SSteffen Eiden goto out; 33*d487a240SSteffen Eiden 34*d487a240SSteffen Eiden /* Clear the dirty log */ 35*d487a240SSteffen Eiden if (is_dirty) { 36*d487a240SSteffen Eiden n = kvm_dirty_bitmap_bytes(memslot); 37*d487a240SSteffen Eiden memset(memslot->dirty_bitmap, 0, n); 38*d487a240SSteffen Eiden } 39*d487a240SSteffen Eiden r = 0; 40*d487a240SSteffen Eiden out: 41*d487a240SSteffen Eiden mutex_unlock(&kvm->slots_lock); 42*d487a240SSteffen Eiden return r; 43*d487a240SSteffen Eiden } 44*d487a240SSteffen Eiden 45*d487a240SSteffen Eiden int s390_kvm_mmu_prepare_memory_region(struct kvm *kvm, 46*d487a240SSteffen Eiden const struct kvm_memory_slot *old, 47*d487a240SSteffen Eiden struct kvm_memory_slot *new, 48*d487a240SSteffen Eiden enum kvm_mr_change change) 49*d487a240SSteffen Eiden { 50*d487a240SSteffen Eiden if (kvm_is_ucontrol(kvm) && new && new->id < KVM_USER_MEM_SLOTS) 51*d487a240SSteffen Eiden return -EINVAL; 52*d487a240SSteffen Eiden 53*d487a240SSteffen Eiden /* When we are protected, we should not change the memory slots */ 54*d487a240SSteffen Eiden if (kvm_s390_pv_get_handle(kvm)) 55*d487a240SSteffen Eiden return -EINVAL; 56*d487a240SSteffen Eiden 57*d487a240SSteffen Eiden if (change != KVM_MR_DELETE && change != KVM_MR_FLAGS_ONLY) { 58*d487a240SSteffen Eiden /* 59*d487a240SSteffen Eiden * A few sanity checks. The memory in userland is ok to be 60*d487a240SSteffen Eiden * fragmented into various different vmas. It is okay to mmap() 61*d487a240SSteffen Eiden * and munmap() stuff in this slot after doing this call at any 62*d487a240SSteffen Eiden * time. 63*d487a240SSteffen Eiden */ 64*d487a240SSteffen Eiden if (new->userspace_addr & ~PAGE_MASK) 65*d487a240SSteffen Eiden return -EINVAL; 66*d487a240SSteffen Eiden if ((new->base_gfn + new->npages) * PAGE_SIZE > kvm->arch.mem_limit) 67*d487a240SSteffen Eiden return -EINVAL; 68*d487a240SSteffen Eiden if (!asce_contains_gfn(kvm->arch.gmap->asce, new->base_gfn + new->npages - 1)) 69*d487a240SSteffen Eiden return -EINVAL; 70*d487a240SSteffen Eiden } 71*d487a240SSteffen Eiden 72*d487a240SSteffen Eiden if (!kvm_s390_is_migration_mode(kvm)) 73*d487a240SSteffen Eiden return 0; 74*d487a240SSteffen Eiden 75*d487a240SSteffen Eiden /* 76*d487a240SSteffen Eiden * Turn off migration mode when: 77*d487a240SSteffen Eiden * - userspace creates a new memslot with dirty logging off, 78*d487a240SSteffen Eiden * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and 79*d487a240SSteffen Eiden * dirty logging is turned off. 80*d487a240SSteffen Eiden * Migration mode expects dirty page logging being enabled to store 81*d487a240SSteffen Eiden * its dirty bitmap. 82*d487a240SSteffen Eiden */ 83*d487a240SSteffen Eiden if (change != KVM_MR_DELETE && 84*d487a240SSteffen Eiden !(new->flags & KVM_MEM_LOG_DIRTY_PAGES)) 85*d487a240SSteffen Eiden WARN(kvm_s390_vm_stop_migration(kvm), 86*d487a240SSteffen Eiden "Failed to stop migration mode"); 87*d487a240SSteffen Eiden 88*d487a240SSteffen Eiden return 0; 89*d487a240SSteffen Eiden } 90*d487a240SSteffen Eiden 91*d487a240SSteffen Eiden void s390_kvm_mmu_commit_memory_region(struct kvm *kvm, 92*d487a240SSteffen Eiden struct kvm_memory_slot *old, 93*d487a240SSteffen Eiden const struct kvm_memory_slot *new, 94*d487a240SSteffen Eiden enum kvm_mr_change change) 95*d487a240SSteffen Eiden { 96*d487a240SSteffen Eiden struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL; 97*d487a240SSteffen Eiden int rc = 0; 98*d487a240SSteffen Eiden 99*d487a240SSteffen Eiden guard(mutex)(&kvm->slots_arch_lock); 100*d487a240SSteffen Eiden 101*d487a240SSteffen Eiden if (change == KVM_MR_FLAGS_ONLY) 102*d487a240SSteffen Eiden return; 103*d487a240SSteffen Eiden 104*d487a240SSteffen Eiden mc = kvm_s390_new_mmu_cache(); 105*d487a240SSteffen Eiden if (!mc) { 106*d487a240SSteffen Eiden rc = -ENOMEM; 107*d487a240SSteffen Eiden goto out; 108*d487a240SSteffen Eiden } 109*d487a240SSteffen Eiden 110*d487a240SSteffen Eiden scoped_guard(write_lock, &kvm->mmu_lock) { 111*d487a240SSteffen Eiden kvm_s390_update_cmma_dirty(kvm, old); 112*d487a240SSteffen Eiden switch (change) { 113*d487a240SSteffen Eiden case KVM_MR_DELETE: 114*d487a240SSteffen Eiden rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages); 115*d487a240SSteffen Eiden break; 116*d487a240SSteffen Eiden case KVM_MR_MOVE: 117*d487a240SSteffen Eiden rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages); 118*d487a240SSteffen Eiden if (rc) 119*d487a240SSteffen Eiden break; 120*d487a240SSteffen Eiden fallthrough; 121*d487a240SSteffen Eiden case KVM_MR_CREATE: 122*d487a240SSteffen Eiden rc = dat_create_slot(mc, kvm->arch.gmap->asce, new->base_gfn, new->npages); 123*d487a240SSteffen Eiden break; 124*d487a240SSteffen Eiden case KVM_MR_FLAGS_ONLY: 125*d487a240SSteffen Eiden break; 126*d487a240SSteffen Eiden default: 127*d487a240SSteffen Eiden WARN(1, "Unknown KVM MR CHANGE: %d\n", change); 128*d487a240SSteffen Eiden } 129*d487a240SSteffen Eiden } 130*d487a240SSteffen Eiden out: 131*d487a240SSteffen Eiden if (rc) 132*d487a240SSteffen Eiden pr_warn("failed to commit memory region\n"); 133*d487a240SSteffen Eiden } 134