xref: /linux/arch/s390/kvm/gmap/kvm_mmu.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
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