Commit 413c98f2 authored by Claudio Imbrenda's avatar Claudio Imbrenda
Browse files

KVM: s390: fake memslot for ucontrol VMs



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: default avatarSean Christopherson <seanjc@google.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Link: https://lore.kernel.org/r/20250123144627.312456-4-imbrenda@linux.ibm.com


Signed-off-by: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
Message-ID: <20250123144627.312456-4-imbrenda@linux.ibm.com>
parent decff09a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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
+16 −1
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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);