Clear the CMMA status for all guest pages, so any pages the guest marked
 as unused are again used any may not be reclaimed by the host.
+
+1.3. ATTRIBUTE KVM_S390_VM_MEM_LIMIT_SIZE
+Parameters: in attr->addr the address for the new limit of guest memory
+Returns: -EFAULT if the given address is not accessible
+         -EINVAL if the virtual machine is of type UCONTROL
+         -E2BIG if the given guest memory is to big for that machine
+         -EBUSY if a vcpu is already defined
+         -ENOMEM if not enough memory is available for a new shadow guest mapping
+          0 otherwise
+
+Allows userspace to query the actual limit and set a new limit for
+the maximum guest memory size. The limit will be rounded up to
+2048 MB, 4096 GB, 8192 TB respectively, as this limit is governed by
+the number of page table levels.
 
        return r;
 }
 
-static int kvm_s390_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
+static int kvm_s390_get_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
+{
+       int ret;
+
+       switch (attr->attr) {
+       case KVM_S390_VM_MEM_LIMIT_SIZE:
+               ret = 0;
+               if (put_user(kvm->arch.gmap->asce_end, (u64 __user *)attr->addr))
+                       ret = -EFAULT;
+               break;
+       default:
+               ret = -ENXIO;
+               break;
+       }
+       return ret;
+}
+
+static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
 {
        int ret;
        unsigned int idx;
                mutex_unlock(&kvm->lock);
                ret = 0;
                break;
+       case KVM_S390_VM_MEM_LIMIT_SIZE: {
+               unsigned long new_limit;
+
+               if (kvm_is_ucontrol(kvm))
+                       return -EINVAL;
+
+               if (get_user(new_limit, (u64 __user *)attr->addr))
+                       return -EFAULT;
+
+               if (new_limit > kvm->arch.gmap->asce_end)
+                       return -E2BIG;
+
+               ret = -EBUSY;
+               mutex_lock(&kvm->lock);
+               if (atomic_read(&kvm->online_vcpus) == 0) {
+                       /* gmap_alloc will round the limit up */
+                       struct gmap *new = gmap_alloc(current->mm, new_limit);
+
+                       if (!new) {
+                               ret = -ENOMEM;
+                       } else {
+                               gmap_free(kvm->arch.gmap);
+                               new->private = kvm;
+                               kvm->arch.gmap = new;
+                               ret = 0;
+                       }
+               }
+               mutex_unlock(&kvm->lock);
+               break;
+       }
        default:
                ret = -ENXIO;
                break;
 
        switch (attr->group) {
        case KVM_S390_VM_MEM_CTRL:
-               ret = kvm_s390_mem_control(kvm, attr);
+               ret = kvm_s390_set_mem_control(kvm, attr);
                break;
        default:
                ret = -ENXIO;
 
 static int kvm_s390_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr)
 {
-       return -ENXIO;
+       int ret;
+
+       switch (attr->group) {
+       case KVM_S390_VM_MEM_CTRL:
+               ret = kvm_s390_get_mem_control(kvm, attr);
+               break;
+       default:
+               ret = -ENXIO;
+               break;
+       }
+
+       return ret;
 }
 
 static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
                switch (attr->attr) {
                case KVM_S390_VM_MEM_ENABLE_CMMA:
                case KVM_S390_VM_MEM_CLR_CMMA:
+               case KVM_S390_VM_MEM_LIMIT_SIZE:
                        ret = 0;
                        break;
                default: