]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: s390: fake memslot for ucontrol VMs
authorClaudio Imbrenda <imbrenda@linux.ibm.com>
Thu, 23 Jan 2025 14:46:15 +0000 (15:46 +0100)
committerClaudio Imbrenda <imbrenda@linux.ibm.com>
Fri, 31 Jan 2025 11:03:52 +0000 (12:03 +0100)
Create a fake memslot for ucontrol VMs. The fake memslot identity-maps
userspace.

Now memslots will always be present, and ucontrol is not a special case
anymore.

Suggested-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Link: https://lore.kernel.org/r/20250123144627.312456-4-imbrenda@linux.ibm.com
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Message-ID: <20250123144627.312456-4-imbrenda@linux.ibm.com>

Documentation/virt/kvm/api.rst
arch/s390/include/asm/kvm_host.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h

index 0d1c3a820ce6ea3c62e6341a0d1cc38b9ff9a75a..2b52eb77e29cba146b64489cfb1a267e7bb9b597 100644 (file)
@@ -1419,7 +1419,7 @@ fetch) is injected in the guest.
 S390:
 ^^^^^
 
-Returns -EINVAL if the VM has the KVM_VM_S390_UCONTROL flag set.
+Returns -EINVAL or -EEXIST if the VM has the KVM_VM_S390_UCONTROL flag set.
 Returns -EINVAL if called on a protected VM.
 
 4.36 KVM_SET_TSS_ADDR
index 4581388411b715cb11581bf9afd25512cb45531e..9a367866cab0eb5f24960aea9fd552e0a919cffa 100644 (file)
@@ -30,6 +30,8 @@
 #define KVM_S390_ESCA_CPU_SLOTS 248
 #define KVM_MAX_VCPUS 255
 
+#define KVM_INTERNAL_MEM_SLOTS 1
+
 /*
  * These seem to be used for allocating ->chip in the routing table, which we
  * don't use. 1 is as small as we can get to reduce the needed memory. If we
index ecbdd7d41230afc1e1d5f15e39c25bd8956a9e1e..fc44002a7b04c7a9c3bf1d24e59a782c21df3a0b 100644 (file)
@@ -3428,8 +3428,20 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        VM_EVENT(kvm, 3, "vm created with type %lu", type);
 
        if (type & KVM_VM_S390_UCONTROL) {
+               struct kvm_userspace_memory_region2 fake_memslot = {
+                       .slot = KVM_S390_UCONTROL_MEMSLOT,
+                       .guest_phys_addr = 0,
+                       .userspace_addr = 0,
+                       .memory_size = ALIGN_DOWN(TASK_SIZE, _SEGMENT_SIZE),
+                       .flags = 0,
+               };
+
                kvm->arch.gmap = NULL;
                kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT;
+               /* one flat fake memslot covering the whole address-space */
+               mutex_lock(&kvm->slots_lock);
+               KVM_BUG_ON(kvm_set_internal_memslot(kvm, &fake_memslot), kvm);
+               mutex_unlock(&kvm->slots_lock);
        } else {
                if (sclp.hamax == U64_MAX)
                        kvm->arch.mem_limit = TASK_SIZE_MAX;
@@ -5854,7 +5866,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 {
        gpa_t size;
 
-       if (kvm_is_ucontrol(kvm))
+       if (kvm_is_ucontrol(kvm) && new->id < KVM_USER_MEM_SLOTS)
                return -EINVAL;
 
        /* When we are protected, we should not change the memory slots */
@@ -5906,6 +5918,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 {
        int rc = 0;
 
+       if (kvm_is_ucontrol(kvm))
+               return;
+
        switch (change) {
        case KVM_MR_DELETE:
                rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
index 597d7a71deebe0917f88fc03bcb46c96c59eebab..30736ac16f848f2b3c2c98b45c97fdab59d3ac7a 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/processor.h>
 #include <asm/sclp.h>
 
+#define KVM_S390_UCONTROL_MEMSLOT (KVM_USER_MEM_SLOTS + 0)
+
 static inline void kvm_s390_fpu_store(struct kvm_run *run)
 {
        fpu_stfpc(&run->s.regs.fpc);