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