[PATCH 3/5] KVM: Make the maximum number of user memslots configurable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The maximum number of user memslots is now a per-VM setting but there is
no way to change it. Intoduce KVM_CAP_MEMSLOTS_LIMIT per-VM capability to
set the limit.

When the limit is set, it becomes impossible to manage memslots whose id
is greater or equal so make sure there are no such slots.

Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
---
 Documentation/virt/kvm/api.rst | 16 ++++++++++++++++
 include/uapi/linux/kvm.h       |  1 +
 virt/kvm/kvm_main.c            | 30 ++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 99ceb978c8b0..551236fc1261 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -6038,6 +6038,22 @@ KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR exit notifications which user space
 can then handle to implement model specific MSR handling and/or user notifications
 to inform a user that an MSR was not handled.
 
+7.22 KVM_CAP_MEMSLOTS_LIMIT
+----------------------
+
+:Architectures: all
+:Target: VM
+:Parameters: args[0] is the maximum number of memory slots
+:Returns: 0 on success; E2BIG when set above global KVM_CAP_NR_MEMSLOTS; EINVAL
+          when there is an existing slot with id >= limit
+
+This capability overrides the default maximum number of memory slots, available
+per target VM. The limit can be changed at any time, however, when lowered, no
+memory slots with id ('slot' in 'struct kvm_userspace_memory_region') greater
+than the requested value should exist or EINVAL is returned. The maximum allowed
+value can be queried by checking system KVM_CAP_NR_MEMSLOTS capability. Per-VM
+KVM_CAP_NR_MEMSLOTS capability represents the currently set limit.
+
 8. Other capabilities.
 ======================
 
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 374c67875cdb..f68b0cde801a 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1058,6 +1058,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_ENFORCE_PV_FEATURE_CPUID 190
 #define KVM_CAP_SYS_HYPERV_CPUID 191
 #define KVM_CAP_DIRTY_LOG_RING 192
+#define KVM_CAP_MEMSLOTS_LIMIT 193
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5adb1b694304..da2cbfe9c9ee 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1412,6 +1412,31 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
 	return kvm_set_memory_region(kvm, mem);
 }
 
+static int kvm_set_memslots_max(struct kvm *kvm, u64 max)
+{
+	struct kvm_memory_slot *memslot;
+	int r = 0, as_id;
+
+	if (max > KVM_USER_MEM_SLOTS)
+		return -E2BIG;
+
+	mutex_lock(&kvm->slots_lock);
+	for (as_id = 0; as_id < KVM_ADDRESS_SPACE_NUM; as_id++) {
+		kvm_for_each_memslot(memslot, __kvm_memslots(kvm, as_id)) {
+			if (memslot->id >= max) {
+				r = -EINVAL;
+				break;
+			}
+		}
+	}
+	if (!r)
+		kvm->memslots_max = max;
+
+	mutex_unlock(&kvm->slots_lock);
+
+	return r;
+}
+
 #ifndef CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT
 /**
  * kvm_get_dirty_log - get a snapshot of dirty pages
@@ -3664,6 +3689,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
 	case KVM_CAP_CHECK_EXTENSION_VM:
 	case KVM_CAP_ENABLE_CAP_VM:
 	case KVM_CAP_HALT_POLL:
+	case KVM_CAP_MEMSLOTS_LIMIT:
 		return 1;
 #ifdef CONFIG_KVM_MMIO
 	case KVM_CAP_COALESCED_MMIO:
@@ -3789,6 +3815,10 @@ static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm,
 	}
 	case KVM_CAP_DIRTY_LOG_RING:
 		return kvm_vm_ioctl_enable_dirty_log_ring(kvm, cap->args[0]);
+	case KVM_CAP_MEMSLOTS_LIMIT:
+		if (cap->flags)
+			return -EINVAL;
+		return kvm_set_memslots_max(kvm, cap->args[0]);
 	default:
 		return kvm_vm_ioctl_enable_cap(kvm, cap);
 	}
-- 
2.29.2




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux