Skip to contentSkip to conversation

Ucontrol patchset V2

PATCH In review Carsten Otte 4 participants 21 messages Dec 8, 2011

Subsystems (9)
Documentation x86 KVM PowerPC +5 more subsystems
lore
Share & tools
lore
#0 lore raw

cover Ucontrol patchset V2

Hi Avi, Hi Marcelo,

I think I've integrated all feedback from last round. The race between KVM_S390_ENABLE_UCONTROL and creation of vcpus has been resolved by adding a parameter to KVM_CREATE_VM. The default KVM_VM_REGULAR (==0) is backward compatible to KVM_CREATE_VM without parameters, and KVM_VM_S390_UCONTROL enables user controlled virtual machines for CECSIM. The extra ioctl is gone.
The page table walk in the storage key patch has moved to arch/s390/mm, and I think this patch should go with the rest of this series via your tree after Martin reviewed it.

so long,
Carsten

#1 lore raw

PATCH 1/12 kvm-s390: ioctl to switch to user controlled virtual machines

This patch introduces a new config option for user controlled kernel virtual machines. It introduces an optional parameter to KVM_CREATE_VM in order to create a user controlled virtual machine. The parameter is passed to kvm_arch_init_vm for all architectures. Valid values for the new parameter are KVM_VM_REGULAR (defined to 0 for backward compatibility to old KVM_CREATE_VM) and KVM_VM_S390_UCONTROL for s390 only.
Note that the user controlled virtual machines require CAP_SYS_ADMIN privileges.

---

---
 Documentation/virtual/kvm/api.txt |    7 ++++++-
 arch/ia64/kvm/kvm-ia64.c          |    5 ++++-
 arch/powerpc/kvm/powerpc.c        |    5 ++++-
 arch/s390/kvm/Kconfig             |    9 +++++++++
 arch/s390/kvm/kvm-s390.c          |   30 +++++++++++++++++++++++++-----
 arch/s390/kvm/kvm-s390.h          |   10 ++++++++++
 arch/x86/kvm/x86.c                |    5 ++++-
 include/linux/kvm.h               |    3 +++
 include/linux/kvm_host.h          |    2 +-
 virt/kvm/kvm_main.c               |   19 +++++++++++++------
 10 files changed, 79 insertions(+), 16 deletions(-)
Documentation/virtual/kvm/api.txt +6 -1
@@ -95,7 +95,7 @@ described as 'basic' will be available.
 Capability: basic
 Architectures: all
 Type: system ioctl
-Parameters: none
+Parameters: machine type identifier (KVM_VM_*)
 Returns: a VM fd that can be used to control the new virtual machine.
 
 The new VM has no virtual cpus and no memory.  An mmap() of a VM fd
@@ -103,6 +103,11 @@ will access the virtual machine's physic
 corresponds to guest physical address zero.  Use of mmap() on a VM fd
 is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is
 available.
+You most certainly want to use KVM_VM_REGULAR as machine type.
+
+In order to create user controlled virtual machines on S390, check
+KVM_CAP_S390_UCONTROL and use KVM_VM_S390_UCONTROL as machine type as
+privileged user (CAP_SYS_ADMIN).
 
 4.3 KVM_GET_MSR_INDEX_LIST
 
arch/ia64/kvm/kvm-ia64.c +4 -1
@@ -809,10 +809,13 @@ static void kvm_build_io_pmt(struct kvm
 #define GUEST_PHYSICAL_RR4	0x2739
 #define VMM_INIT_RR		0x1660
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
 	BUG_ON(!kvm);
 
+	if (type != KVM_VM_REGULAR)
+		return -EINVAL;
+
 	kvm->arch.is_sn2 = ia64_platform_is("sn2");
 
 	kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
arch/powerpc/kvm/powerpc.c +4 -1
@@ -171,8 +171,11 @@ void kvm_arch_check_processor_compat(voi
 	*(int *)rtn = kvmppc_core_check_processor_compat();
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
+	if (type != KVM_VM_REGULAR)
+		return -EINVAL;
+
 	return kvmppc_core_init_vm(kvm);
 }
 
arch/s390/kvm/Kconfig +9 -0
@@ -34,6 +34,15 @@ config KVM
 
 	  If unsure, say N.
 
+config KVM_UCONTROL
+	bool "Userspace controlled virtual machines"
+	depends on KVM
+	---help---
+	  Allow CAP_SYS_ADMIN users to create KVM virtual machines that are
+	  controlled by userspace.
+
+	  If unsure, say N.
+
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
 source drivers/vhost/Kconfig
arch/s390/kvm/kvm-s390.c +25 -5
@@ -171,11 +171,28 @@ long kvm_arch_vm_ioctl(struct file *filp
 	return r;
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
 	int rc;
 	char debug_name[16];
 
+	rc = -EINVAL;
+#ifdef CONFIG_KVM_UCONTROL
+	switch (type) {
+	case KVM_VM_REGULAR:
+		break;
+	case KVM_VM_S390_UCONTROL:
+		if (!capable(CAP_SYS_ADMIN))
+			goto out_err;
+		break;
+	default:
+		goto out_err;
+	}
+#else
+	if (type != KVM_VM_REGULAR)
+		goto out_err;
+#endif
+
 	rc = s390_enable_sie();
 	if (rc)
 		goto out_err;
@@ -198,10 +215,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
 	debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
 	VM_EVENT(kvm, 3, "%s", "vm created");
 
-	kvm->arch.gmap = gmap_alloc(current->mm);
-	if (!kvm->arch.gmap)
-		goto out_nogmap;
-
+	if (type == KVM_VM_REGULAR) {
+		kvm->arch.gmap = gmap_alloc(current->mm);
+		if (!kvm->arch.gmap)
+			goto out_nogmap;
+	} else {
+		kvm->arch.gmap = NULL;
+	}
 	return 0;
 out_nogmap:
 	debug_unregister(kvm->arch.dbf);
arch/s390/kvm/kvm-s390.h +10 -0
@@ -47,6 +47,16 @@ static inline int __cpu_is_stopped(struc
 	return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
 }
 
+static inline int kvm_is_ucontrol(struct kvm *kvm)
+{
+#ifdef CONFIG_KVM_UCONTROL
+	if (kvm->arch.gmap)
+		return 0;
+	return 1;
+#else
+	return 0;
+#endif
+}
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
 void kvm_s390_tasklet(unsigned long parm);
arch/x86/kvm/x86.c +4 -1
@@ -5969,8 +5969,11 @@ void kvm_arch_vcpu_uninit(struct kvm_vcp
 	free_page((unsigned long)vcpu->arch.pio_data);
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
+	if (type != KVM_VM_REGULAR)
+		return -EINVAL;
+
 	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
 	INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
include/linux/kvm.h +3 -0
@@ -431,6 +431,9 @@ struct kvm_ppc_pvinfo {
 
 #define KVMIO 0xAE
 
+#define KVM_VM_REGULAR       0
+#define KVM_VM_S390_UCONTROL 1
+
 /*
  * ioctls for /dev/kvm fds:
  */
include/linux/kvm_host.h +1 -1
@@ -519,7 +519,7 @@ static inline void kvm_arch_free_vm(stru
 }
 #endif
 
-int kvm_arch_init_vm(struct kvm *kvm);
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
 void kvm_arch_destroy_vm(struct kvm *kvm);
 void kvm_free_all_assigned_devices(struct kvm *kvm);
 void kvm_arch_sync_events(struct kvm *kvm);
virt/kvm/kvm_main.c +13 -6
@@ -449,7 +449,7 @@ static void kvm_init_memslots_id(struct
 		slots->id_to_index[i] = slots->memslots[i].id = i;
 }
 
-static struct kvm *kvm_create_vm(void)
+static struct kvm *kvm_create_vm(unsigned long type)
 {
 	int r, i;
 	struct kvm *kvm = kvm_arch_alloc_vm();
@@ -457,7 +457,7 @@ static struct kvm *kvm_create_vm(void)
 	if (!kvm)
 		return ERR_PTR(-ENOMEM);
 
-	r = kvm_arch_init_vm(kvm);
+	r = kvm_arch_init_vm(kvm, type);
 	if (r)
 		goto out_err_nodisable;
 
@@ -2207,12 +2207,12 @@ static struct file_operations kvm_vm_fop
 	.llseek		= noop_llseek,
 };
 
-static int kvm_dev_ioctl_create_vm(void)
+static int kvm_dev_ioctl_create_vm(unsigned long type)
 {
 	int r;
 	struct kvm *kvm;
 
-	kvm = kvm_create_vm();
+	kvm = kvm_create_vm(type);
 	if (IS_ERR(kvm))
 		return PTR_ERR(kvm);
 #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
@@ -2264,9 +2264,16 @@ static long kvm_dev_ioctl(struct file *f
 		break;
 	case KVM_CREATE_VM:
 		r = -EINVAL;
-		if (arg)
+		switch (arg) {
+		case KVM_VM_REGULAR:
+#ifdef CONFIG_KVM_UCONTROL
+		case KVM_VM_S390_UCONTROL:
+#endif
+			r = kvm_dev_ioctl_create_vm(arg);
+			break;
+		default:
 			goto out;
-		r = kvm_dev_ioctl_create_vm();
+		}
 		break;
 	case KVM_CHECK_EXTENSION:
 		r = kvm_dev_ioctl_check_extension_generic(arg);
#2 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 8 lines · Carsten Otte

plain text document attachment (enable-ucontrol.patch) This patch introduces a new config option for user controlled kernel virtual machines. It introduces an optional parameter to KVM_CREATE_VM in order to create a user controlled virtual machine. The parameter is passed to kvm_arch_init_vm for all architectures. Valid values for the new parameter are KVM_VM_REGULAR (defined to 0 for backward compatibility to old KVM_CREATE_VM) and KVM_VM_S390_UCONTROL for s390 only.

Why is it s390 specific? why isn't it KVM_VM_UCONTROL which is currently only implemented on s390?

Signature · 1 line
Sasha.
#3 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 2 lines · Sasha Levin

Why is it s390 specific? why isn't it KVM_VM_UCONTROL which is currently only implemented on s390?

Good point. Maybe the subject line for the patch should be fixed along with that ;-)

#4 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

In reply to Sasha Levin
Quoted 10 lines · Sasha Levin
Quoted 8 lines · Carsten Otte

plain text document attachment (enable-ucontrol.patch) This patch introduces a new config option for user controlled kernel virtual machines. It introduces an optional parameter to KVM_CREATE_VM in order to create a user controlled virtual machine. The parameter is passed to kvm_arch_init_vm for all architectures. Valid values for the new parameter are KVM_VM_REGULAR (defined to 0 for backward compatibility to old KVM_CREATE_VM) and KVM_VM_S390_UCONTROL for s390 only.

Quoted 2 lines

Why is it s390 specific? why isn't it KVM_VM_UCONTROL which is currently only implemented on s390?

It's not possible (or at least very difficult) to implement ucontrol on x86. For example, to update VMCSs you need privileged instructions. It might be doable on svm, but there's no point, really.

Signature · 1 line
error compiling committee.c: too many arguments to function
#5 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 11 lines · Avi Kivity
Quoted 10 lines · Sasha Levin
Quoted 8 lines · Carsten Otte

plain text document attachment (enable-ucontrol.patch) This patch introduces a new config option for user controlled kernel virtual machines. It introduces an optional parameter to KVM_CREATE_VM in order to create a user controlled virtual machine. The parameter is passed to kvm_arch_init_vm for all architectures. Valid values for the new parameter are KVM_VM_REGULAR (defined to 0 for backward compatibility to old KVM_CREATE_VM) and KVM_VM_S390_UCONTROL for s390 only.

Quoted 6 lines
Quoted 2 lines

Why is it s390 specific? why isn't it KVM_VM_UCONTROL which is currently only implemented on s390?

It's not possible (or at least very difficult) to implement ucontrol on x86. For example, to update VMCSs you need privileged instructions. It might be doable on svm, but there's no point, really.

Might not work for x86, but maybe on arm? ppc? or some other random arch that will be added in the future?

No point in limiting it to s390 from day one.

It also makes code a bit cleaner (kvm_main.c shouldn't have arch names in the code).

Signature · 1 line
Sasha.
#6 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 15 lines · Sasha Levin
Quoted 14 lines · Avi Kivity
Quoted 12 lines · Sasha Levin
Quoted 8 lines · Carsten Otte

plain text document attachment (enable-ucontrol.patch) This patch introduces a new config option for user controlled kernel virtual machines. It introduces an optional parameter to KVM_CREATE_VM in order to create a user controlled virtual machine. The parameter is passed to kvm_arch_init_vm for all architectures. Valid values for the new parameter are KVM_VM_REGULAR (defined to 0 for backward compatibility to old KVM_CREATE_VM) and KVM_VM_S390_UCONTROL for s390 only.

Why is it s390 specific? why isn't it KVM_VM_UCONTROL which is currently only implemented on s390?

Quoted 8 lines
Quoted 3 lines

It's not possible (or at least very difficult) to implement ucontrol on x86. For example, to update VMCSs you need privileged instructions. It might be doable on svm, but there's no point, really.

Might not work for x86, but maybe on arm? ppc? or some other random arch that will be added in the future?

No point in limiting it to s390 from day one.

Agree.

Quoted 2 lines

It also makes code a bit cleaner (kvm_main.c shouldn't have arch names in the code).

That doesn't bother me.

Signature · 1 line
error compiling committee.c: too many arguments to function
#7 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 20 lines · Avi Kivity
Quoted 19 lines · Sasha Levin
Quoted 17 lines · Avi Kivity
Quoted 10 lines · Sasha Levin
Quoted 8 lines · Carsten Otte

plain text document attachment (enable-ucontrol.patch) This patch introduces a new config option for user controlled kernel virtual machines. It introduces an optional parameter to KVM_CREATE_VM in order to create a user controlled virtual machine. The parameter is passed to kvm_arch_init_vm for all architectures. Valid values for the new parameter are KVM_VM_REGULAR (defined to 0 for backward compatibility to old KVM_CREATE_VM) and KVM_VM_S390_UCONTROL for s390 only.

Quoted 2 lines

Why is it s390 specific? why isn't it KVM_VM_UCONTROL which is currently only implemented on s390?

It's not possible (or at least very difficult) to implement ucontrol on x86. For example, to update VMCSs you need privileged instructions. It might be doable on svm, but there's no point, really.

Quoted 6 lines
Quoted 4 lines

Might not work for x86, but maybe on arm? ppc? or some other random arch that will be added in the future?

No point in limiting it to s390 from day one.

Agree.

I don't think I would want to see full exposure of the vm control block to user space on any architecture really.

If the 390 folks like to shoot themselves in the security foot, I'm ok with that, but the whole idea of kvm is to abstract these hw details. By giving user space direct access to the vm control block, you essentially give user space a mkcpl(0) ioctl.

The vm control block in memory is also pretty specific to s390. The only other thing that comes close, where mmap'ing something actually gives you control over the full vm description is SVM's VMCB. All other archs (not 100% sure on arm) need to modify registers from cpl0 code.

So overall I dislike the idea of exposing the SIE block to user space. Imagine a system with containers on it where container vms should still be able to run kvm vms. From a security pov, this would break it, as you essentially give the user full access over the host. Unless CAP_ADMIN is not set in such a scenario of course. Then it's only as bad as /dev/mem which any random trojan or virus could use to inject itself into the kernel.

If you really have to do this, please

1) make it s390 only. I don't even want to have to see this uglyness in other archs
2) make it a config option, so sane people can disable it. (which you already do, good)

Thanks,

Alex

#8 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 3 lines · Alexander Graf

If you really have to do this, please

1) make it s390 only. I don't even want to have to see this uglyness in other archs

It pretty much is. The only interference is a) checking the machine type in arch_init_vm now that I've introduced that parameter to CREATE_VM on Avi's request and b) a dummy arch_vcpu_fault function that I've introduced on Avi's request. Both changes make sense for future enhancements independent of ucontrol.

so long,
Carsten

#9 lore raw

Re: [patch 01/12] [PATCH] kvm-s390: ioctl to switch to user controlled virtual machines

Quoted 10 lines · Carsten Otte
Quoted 4 lines · Alexander Graf

If you really have to do this, please

1) make it s390 only. I don't even want to have to see this
uglyness in other archs

It pretty much is. The only interference is a) checking the machine type in arch_init_vm now that I've introduced that parameter to CREATE_VM on Avi's request and b) a dummy arch_vcpu_fault function that I've introduced on Avi's request. Both changes make sense for future enhancements independent of ucontrol.

Ah, so you're only introducing a generic framework for mmapping pages between user space and kernel space. That's arch-independent of course and a good idea :)

Alex

#10 lore raw

PATCH 2/12 kvm-s390-ucontrol: per vcpu address spaces

In reply to Carsten Otte

This patch introduces two ioctls for virtual cpus, that are only valid for kernel virtual machines that are controlled by userspace. Each virtual cpu has its individual address space in this mode of operation, and each address space is backed by the gmap implementation just like the address space for regular KVM guests. KVM_S390_UCAS_MAP allows to map a part of the user's virtual address space to the vcpu. Starting offset and length in both the user and the vcpu address space need to be aligned to 1M. KVM_S390_UCAS_UNMAP can be used to unmap a range of memory from a virtual cpu in a similar way.

---

---
 Documentation/virtual/kvm/api.txt |   38 ++++++++++++++++++++++++++++
 arch/s390/kvm/kvm-s390.c          |   50 +++++++++++++++++++++++++++++++++++++-
 include/linux/kvm.h               |   10 +++++++
 3 files changed, 97 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +38 -0
@@ -1455,6 +1455,44 @@ is supported; 2 if the processor require
 an RMA, or 1 if the processor can use an RMA but doesn't require it,
 because it supports the Virtual RMA (VRMA) facility.
 
+4.64 KVM_S390_UCAS_MAP
+
+Capability: KVM_CAP_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+	struct kvm_s390_ucas_mapping {
+		__u64 user_addr;
+		__u64 vcpu_addr;
+		__u64 length;
+	};
+
+This ioctl maps the memory at "user_addr" with the length "length" to
+the vcpu's address space starting at "vcpu_addr". All parameters need to
+be alligned by 1 megabyte.
+
+4.65 KVM_S390_UCAS_UNMAP
+
+Capability: KVM_CAP_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+	struct kvm_s390_ucas_mapping {
+		__u64 user_addr;
+		__u64 vcpu_addr;
+		__u64 length;
+	};
+
+This ioctl unmaps the memory in the vcpu's address space starting at
+"vcpu_addr" with the length "length". The field "user_addr" is ignored.
+All parameters need to be alligned by 1 megabyte.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
arch/s390/kvm/kvm-s390.c +49 -1

73 lines not on this page · raw message

include/linux/kvm.h +10 -0
@@ -657,6 +657,16 @@ struct kvm_clock_data {
 					struct kvm_userspace_memory_region)
 #define KVM_SET_TSS_ADDR          _IO(KVMIO,   0x47)
 #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO,  0x48, __u64)
+
+/* enable ucontrol for s390 */
+struct kvm_s390_ucas_mapping {
+	__u64 user_addr;
+	__u64 vcpu_addr;
+	__u64 length;
+};
+#define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
+#define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
+
 /* Device model IOC */
 #define KVM_CREATE_IRQCHIP        _IO(KVMIO,   0x60)
 #define KVM_IRQ_LINE              _IOW(KVMIO,  0x61, struct kvm_irq_level)
#11 lore raw

PATCH 3/12 kvm-s390-ucontrol: export page faults to user

In reply to Carsten Otte

This patch introduces a new exit reason in the kvm_run structure named KVM_EXIT_UCONTROL. This exit indicates, that a virtual cpu has regognized a fault on the host page table. The idea is that userspace can handle this fault by mapping memory at the fault location into the cpu's address space and then continue to run the virtual cpu.

---

---
 Documentation/virtual/kvm/api.txt |   14 ++++++++++++++
 arch/s390/kvm/kvm-s390.c          |   32 +++++++++++++++++++++++++++-----
 arch/s390/kvm/kvm-s390.h          |    1 +
 include/linux/kvm.h               |    6 ++++++
 4 files changed, 48 insertions(+), 5 deletions(-)
Documentation/virtual/kvm/api.txt +14 -0
@@ -1653,6 +1653,20 @@ s390 specific.
 
 s390 specific.
 
+		/* KVM_EXIT_UCONTROL */
+		struct {
+			__u64 trans_exc_code;
+			__u32 pgm_code;
+		} s390_ucontrol;
+
+s390 specific. A page fault has occurred for a user controlled virtual
+machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
+resolved by the kernel.
+The program code and the translation exception code that were placed
+in the cpu's lowcore are presented here as defined by the z Architecture
+Principles of Operation Book in the Chapter for Dynamic Address Translation
+(DAT)
+
 		/* KVM_EXIT_DCR */
 		struct {
 			__u32 dcrn;
arch/s390/kvm/kvm-s390.c +27 -5
@@ -499,8 +499,10 @@ int kvm_arch_vcpu_ioctl_set_mpstate(stru
 	return -EINVAL; /* not implemented yet */
 }
 
-static void __vcpu_run(struct kvm_vcpu *vcpu)
+static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
+	int rc;
+
 	memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
 
 	if (need_resched())
@@ -517,9 +519,15 @@ static void __vcpu_run(struct kvm_vcpu *
 	local_irq_enable();
 	VCPU_EVENT(vcpu, 6, "entering sie flags %x",
 		   atomic_read(&vcpu->arch.sie_block->cpuflags));
-	if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
-		VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
-		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+	rc = sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
+	if (rc) {
+		if (kvm_is_ucontrol(vcpu->kvm)) {
+			rc = SIE_INTERCEPT_UCONTROL;
+		} else {
+			VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
+			kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+			rc = 0;
+		}
 	}
 	VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
 		   vcpu->arch.sie_block->icptcode);
@@ -528,6 +536,7 @@ static void __vcpu_run(struct kvm_vcpu *
 	local_irq_enable();
 
 	memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
+	return rc;
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -548,6 +557,7 @@ rerun_vcpu:
 	case KVM_EXIT_UNKNOWN:
 	case KVM_EXIT_INTR:
 	case KVM_EXIT_S390_RESET:
+	case KVM_EXIT_UCONTROL:
 		break;
 	default:
 		BUG();
@@ -559,7 +569,9 @@ rerun_vcpu:
 	might_fault();
 
 	do {
-		__vcpu_run(vcpu);
+		rc = __vcpu_run(vcpu);
+		if (rc)
+			break;
 		rc = kvm_handle_sie_intercept(vcpu);
 	} while (!signal_pending(current) && !rc);
 
@@ -571,6 +583,16 @@ rerun_vcpu:
 		rc = -EINTR;
 	}
 
+#ifdef CONFIG_KVM_UCONTROL
+	if (rc == SIE_INTERCEPT_UCONTROL) {
+		kvm_run->exit_reason = KVM_EXIT_UCONTROL;
+		kvm_run->s390_ucontrol.trans_exc_code =
+			current->thread.gmap_addr;
+		kvm_run->s390_ucontrol.pgm_code = 0x10;
+		rc = 0;
+	}
+#endif
+
 	if (rc == -EOPNOTSUPP) {
 		/* intercept cannot be handled in-kernel, prepare kvm-run */
 		kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
arch/s390/kvm/kvm-s390.h +1 -0
@@ -26,6 +26,7 @@ typedef int (*intercept_handler_t)(struc
 
 /* negativ values are error codes, positive values for internal conditions */
 #define SIE_INTERCEPT_RERUNVCPU		(1<<0)
+#define SIE_INTERCEPT_UCONTROL		(1<<1)
 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
 
 #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
include/linux/kvm.h +6 -0
@@ -162,6 +162,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_INTERNAL_ERROR   17
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL	  19
+#define KVM_EXIT_UCONTROL	  20
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -249,6 +250,11 @@ struct kvm_run {
 #define KVM_S390_RESET_CPU_INIT  8
 #define KVM_S390_RESET_IPL       16
 		__u64 s390_reset_flags;
+		/* KVM_EXIT_UCONTROL */
+		struct {
+			__u64 trans_exc_code;
+			__u32 pgm_code;
+		} s390_ucontrol;
 		/* KVM_EXIT_DCR */
 		struct {
 			__u32 dcrn;
#12 lore raw

PATCH 4/12 kvm-s390-ucontrol: export SIE control block to user

In reply to Carsten Otte

This patch exports the s390 SIE hardware control block to userspace via the mapping of the vcpu file descriptor. In order to do so, a new arch callback named kvm_arch_vcpu_fault is introduced for all architectures. It allows to map architecture specific pages.

---

---
 Documentation/virtual/kvm/api.txt |    5 +++++
 arch/ia64/kvm/kvm-ia64.c          |    5 +++++
 arch/powerpc/kvm/powerpc.c        |    5 +++++
 arch/s390/kvm/kvm-s390.c          |   13 +++++++++++++
 arch/x86/kvm/x86.c                |    5 +++++
 include/linux/kvm.h               |    1 +
 include/linux/kvm_host.h          |    1 +
 virt/kvm/kvm_main.c               |    2 +-
 8 files changed, 36 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +5 -0
@@ -218,6 +218,11 @@ allocation of vcpu ids.  For example, if
 single-threaded guest vcpus, it should make all vcpu ids be a multiple
 of the number of vcpus per vcore.
 
+For virtual cpus that have been created with S390 user controlled virtual
+machines, the resulting vcpu fd can be memory mapped at page offset
+KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
+cpu's hardware control block.
+
 4.8 KVM_GET_DIRTY_LOG (vm ioctl)
 
 Capability: basic
arch/ia64/kvm/kvm-ia64.c +5 -0
@@ -1566,6 +1566,11 @@ out:
 	return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 		struct kvm_memory_slot *memslot,
 		struct kvm_memory_slot old,
arch/powerpc/kvm/powerpc.c +5 -0
@@ -659,6 +659,11 @@ out:
 	return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
 	u32 inst_lis = 0x3c000000;
arch/s390/kvm/kvm-s390.c +13 -0
@@ -769,6 +769,19 @@ long kvm_arch_vcpu_ioctl(struct file *fi
 	return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+#ifdef CONFIG_KVM_UCONTROL
+	if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
+		 && (kvm_is_ucontrol(vcpu->kvm))) {
+		vmf->page = virt_to_page(vcpu->arch.sie_block);
+		get_page(vmf->page);
+		return 0;
+	}
+#endif
+	return VM_FAULT_SIGBUS;
+}
+
 /* Section: memory related */
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   struct kvm_memory_slot *memslot,
arch/x86/kvm/x86.c +5 -0
@@ -2790,6 +2790,11 @@ out:
 	return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
 static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
 {
 	int ret;
include/linux/kvm.h +1 -0
@@ -439,6 +439,7 @@ struct kvm_ppc_pvinfo {
 
 #define KVM_VM_REGULAR       0
 #define KVM_VM_S390_UCONTROL 1
+#define KVM_S390_SIE_PAGE_OFFSET 1
 
 /*
  * ioctls for /dev/kvm fds:
include/linux/kvm_host.h +1 -0
@@ -449,6 +449,7 @@ long kvm_arch_dev_ioctl(struct file *fil
 			unsigned int ioctl, unsigned long arg);
 long kvm_arch_vcpu_ioctl(struct file *filp,
 			 unsigned int ioctl, unsigned long arg);
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
 
 int kvm_dev_ioctl_check_extension(long ext);
 
virt/kvm/kvm_main.c +1 -1
@@ -1657,7 +1657,7 @@ static int kvm_vcpu_fault(struct vm_area
 		page = virt_to_page(vcpu->kvm->coalesced_mmio_ring);
 #endif
 	else
-		return VM_FAULT_SIGBUS;
+		return kvm_arch_vcpu_fault(vcpu, vmf);
 	get_page(page);
 	vmf->page = page;
 	return 0;
#13 lore raw

PATCH 5/12 kvm-s390-ucontrol: disable in-kernel handling of SIE intercepts

In reply to Carsten Otte

This patch disables in-kernel handling of SIE intercepts for user controlled virtual machines. All intercepts are passed to userspace via KVM_EXIT_SIE exit reason just like SIE intercepts that cannot be handled in-kernel for regular KVM guests.

---

arch/s390/kvm/kvm-s390.c +4 -1
Index: linux-2.5-cecsim/arch/s390/kvm/kvm-s390.c
===================================================================
@@ -572,7 +572,10 @@ rerun_vcpu:
 		rc = __vcpu_run(vcpu);
 		if (rc)
 			break;
-		rc = kvm_handle_sie_intercept(vcpu);
+		if (kvm_is_ucontrol(vcpu->kvm))
+			rc = -EOPNOTSUPP;
+		else
+			rc = kvm_handle_sie_intercept(vcpu);
 	} while (!signal_pending(current) && !rc);
 
 	if (rc == SIE_INTERCEPT_RERUNVCPU)
#14 lore raw

PATCH 6/12 kvm-s390-ucontrol: disable in-kernel irq stack

In reply to Carsten Otte

This patch disables the in-kernel interrupt stack for KVM virtual machines that are controlled by user. Userspace has to take care of handling interrupts on its own.

---

arch/s390/kvm/kvm-s390.c +2 -1
Index: linux-2.5-cecsim/arch/s390/kvm/kvm-s390.c
===================================================================
@@ -511,7 +511,8 @@ static int __vcpu_run(struct kvm_vcpu *v
 	if (test_thread_flag(TIF_MCCK_PENDING))
 		s390_handle_mcck();
 
-	kvm_s390_deliver_pending_interrupts(vcpu);
+	if (!kvm_is_ucontrol(vcpu->kvm))
+		kvm_s390_deliver_pending_interrupts(vcpu);
 
 	vcpu->arch.sie_block->icptcode = 0;
 	local_irq_disable();
#15 lore raw

PATCH 7/12 kvm-s390-ucontrol: interface to inject faults on a vcpu page table

In reply to Carsten Otte

This patch allows the user to fault in pages on a virtual cpus address space for user controlled virtual machines. Typically this is superfluous because userspace can just create a mapping and let the kernel's page fault logic take are of it. There is one
exception: SIE won't start if the lowcore is not present. Normally the kernel takes care of this [handle_validity() in arch/s390/kvm/intercept.c] but since the kernel does not handle intercepts for user controlled virtual machines, userspace needs to be able to handle this condition.

---

---
 Documentation/virtual/kvm/api.txt |   16 ++++++++++++++++
 arch/s390/kvm/kvm-s390.c          |    6 ++++++
 include/linux/kvm.h               |    1 +
 3 files changed, 23 insertions(+)
Documentation/virtual/kvm/api.txt +16 -0
@@ -1498,6 +1498,22 @@ This ioctl unmaps the memory in the vcpu
 "vcpu_addr" with the length "length". The field "user_addr" is ignored.
 All parameters need to be alligned by 1 megabyte.
 
+4.66 KVM_S390_VCPU_FAULT
+
+Capability: KVM_CAP_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: vcpu absolute address (in)
+Returns: 0 in case of success
+
+This call creates a page table entry on the virtual cpu's address space
+(for user controlled virtual machines) or the virtual machine's address
+space (for regular virtual machines). This only works for minor faults,
+thus it's recommended to access subject memory page via the user page
+table upfront. This is useful to handle validity intercepts for user
+controlled virtual machines to fault in the virtual cpu's lowcore pages
+prior to calling the KVM_RUN ioctl.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
arch/s390/kvm/kvm-s390.c +6 -0
@@ -767,6 +767,12 @@ long kvm_arch_vcpu_ioctl(struct file *fi
 		break;
 	}
 #endif
+	case KVM_S390_VCPU_FAULT: {
+		r = gmap_fault(arg, vcpu->arch.gmap);
+		if (!IS_ERR_VALUE(r))
+			r = 0;
+		break;
+	}
 	default:
 		r = -EINVAL;
 	}
include/linux/kvm.h +1 -0
@@ -673,6 +673,7 @@ struct kvm_s390_ucas_mapping {
 };
 #define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
 #define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
+#define KVM_S390_VCPU_FAULT	 _IOW(KVMIO, 0x52, unsigned long)
 
 /* Device model IOC */
 #define KVM_CREATE_IRQCHIP        _IO(KVMIO,   0x60)
#16 lore raw

PATCH 8/12 kvm-s390-ucontrol: disable sca

In reply to Carsten Otte

This patch makes sure user controlled virtual machines do not use a system control area (sca). This is needed in order to create virtual machines with more cpus than the size of the sca [64].

---

arch/s390/kvm/kvm-s390.c +20 -10
Index: linux-2.5-cecsim/arch/s390/kvm/kvm-s390.c
===================================================================
@@ -234,10 +234,13 @@ out_err:
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 3, "%s", "free cpu");
-	clear_bit(63 - vcpu->vcpu_id, (unsigned long *) &vcpu->kvm->arch.sca->mcn);
-	if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
-		(__u64) vcpu->arch.sie_block)
-		vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+	if (!kvm_is_ucontrol(vcpu->kvm)) {
+		clear_bit(63 - vcpu->vcpu_id,
+			  (unsigned long *) &vcpu->kvm->arch.sca->mcn);
+		if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
+		    (__u64) vcpu->arch.sie_block)
+			vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+	}
 	smp_mb();
 
 	if (kvm_is_ucontrol(vcpu->kvm))
@@ -374,12 +377,19 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
 		goto out_free_cpu;
 
 	vcpu->arch.sie_block->icpua = id;
-	BUG_ON(!kvm->arch.sca);
-	if (!kvm->arch.sca->cpu[id].sda)
-		kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
-	vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
-	vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
-	set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
+	if (!kvm_is_ucontrol(kvm)) {
+		if (!kvm->arch.sca) {
+			WARN_ON_ONCE(1);
+			goto out_free_cpu;
+		}
+		if (!kvm->arch.sca->cpu[id].sda)
+			kvm->arch.sca->cpu[id].sda =
+				(__u64) vcpu->arch.sie_block;
+		vcpu->arch.sie_block->scaoh =
+			(__u32)(((__u64)kvm->arch.sca) >> 32);
+		vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
+		set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
+	}
 
 	spin_lock_init(&vcpu->arch.local_int.lock);
 	INIT_LIST_HEAD(&vcpu->arch.local_int.list);
#17 lore raw

PATCH 9/12 kvm-s390: fix assumption for KVM_MAX_VCPUS

In reply to Carsten Otte

This patch fixes definition of the idle_mask and the local_int array in kvm_s390_float_interrupt. Previous definition had 64 cpus max hardcoded instead of using KVM_MAX_VCPUS.

---

arch/s390/include/asm/kvm_host.h +3 -2
Index: linux-2.5-cecsim/arch/s390/include/asm/kvm_host.h
===================================================================
@@ -220,8 +220,9 @@ struct kvm_s390_float_interrupt {
 	struct list_head list;
 	atomic_t active;
 	int next_rr_cpu;
-	unsigned long idle_mask [(64 + sizeof(long) - 1) / sizeof(long)];
-	struct kvm_s390_local_interrupt *local_int[64];
+	unsigned long idle_mask[(KVM_MAX_VCPUS + sizeof(long) - 1)
+				/ sizeof(long)];
+	struct kvm_s390_local_interrupt *local_int[KVM_MAX_VCPUS];
 };
 
 
#18 lore raw

PATCH 10/12 kvm-s390: storage key interface

In reply to Carsten Otte

This patch introduces an interface to access the guest visible storage keys. It supports three operations that model the behavior that SSKE/ISKE/RRBE instructions would have if they were issued by the guest. These instructions are all documented in the z architecture principles of operation book.

---

---
 Documentation/virtual/kvm/api.txt |   38 ++++++++++++++
 arch/s390/include/asm/kvm_host.h  |    4 +
 arch/s390/include/asm/pgtable.h   |    1 
 arch/s390/kvm/kvm-s390.c          |  103 ++++++++++++++++++++++++++++++++++++--
 arch/s390/mm/pgtable.c            |   70 +++++++++++++++++++------
 include/linux/kvm.h               |    7 ++
 6 files changed, 202 insertions(+), 21 deletions(-)
Documentation/virtual/kvm/api.txt +38 -0
@@ -1514,6 +1514,44 @@ table upfront. This is useful to handle
 controlled virtual machines to fault in the virtual cpu's lowcore pages
 prior to calling the KVM_RUN ioctl.
 
+4.67 KVM_S390_KEYOP
+
+Capability: KVM_CAP_UCONTROL
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_keyop (in+out)
+Returns: 0 in case of success
+
+The parameter looks like this:
+	struct kvm_s390_keyop {
+		__u64 user_addr;
+		__u8  key;
+		__u8  operation;
+	};
+
+user_addr	contains the userspace address of a memory page
+key		contains the guest visible storage key as defined by the
+		z Architecture Principles of Operation book, including key
+		value for key controlled storage protection, the fetch
+		protection bit, and the reference and change indicator bits
+operation	indicates the key operation that should be performed
+
+The following operations are supported:
+KVM_S390_KEYOP_SSKE:
+	This operation behaves just like the set storage key extended (SSKE)
+	instruction would, if it were issued by the guest. The storage key
+	provided in "key" is placed in the guest visible storage key.
+KVM_S390_KEYOP_ISKE:
+	This operation behaves just like the insert storage key extended (ISKE)
+	instruction would, if it were issued by the guest. After this call,
+	the guest visible storage key is presented in the "key" field.
+KVM_S390_KEYOP_RRBE:
+	This operation behaves just like the reset referenced bit extended
+	(RRBE) instruction would, if it were issued by the guest. The guest
+	visible reference bit is cleared, and the value presented in the "key"
+	field after this call has the reference bit set to 1 in case the
+	guest view of the reference bit was 1 prior to this call.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
arch/s390/include/asm/kvm_host.h +4 -0
@@ -24,6 +24,10 @@
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
 
+#define KVM_S390_KEYOP_SSKE 0x01
+#define KVM_S390_KEYOP_ISKE 0x02
+#define KVM_S390_KEYOP_RRBE 0x03
+
 struct sca_entry {
 	atomic_t scn;
 	__u32	reserved;
arch/s390/include/asm/pgtable.h +1 -0
@@ -1254,6 +1254,7 @@ static inline pte_t mk_swap_pte(unsigned
 extern int vmem_add_mapping(unsigned long start, unsigned long size);
 extern int vmem_remove_mapping(unsigned long start, unsigned long size);
 extern int s390_enable_sie(void);
+extern pte_t *ptep_for_addr(unsigned long addr);
 
 /*
  * No page table caches to initialise
arch/s390/kvm/kvm-s390.c +100 -3

113 lines not on this page · raw message

arch/s390/mm/pgtable.c +52 -18

95 lines not on this page · raw message

include/linux/kvm.h +7 -0
@@ -449,6 +449,13 @@ struct kvm_ppc_pvinfo {
 #define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 0x02, struct kvm_msr_list)
 
 #define KVM_S390_ENABLE_SIE       _IO(KVMIO,   0x06)
+
+struct kvm_s390_keyop {
+	__u64 user_addr;
+	__u8  key;
+	__u8  operation;
+};
+#define KVM_S390_KEYOP            _IOWR(KVMIO,   0x09, struct kvm_s390_keyop)
 /*
  * Check if a kvm extension is available.  Argument is extension number,
  * return is 1 (yes) or 0 (no, sorry).
#19 lore raw

PATCH 11/12 kvm-s390-ucontrol: announce capability for user controlled vms

In reply to Carsten Otte

This patch announces a new capability KVM_CAP_S390_UCONTROL that indicates that kvm can now support virtual machines that are controlled by userspace.

---

---
 arch/s390/kvm/kvm-s390.c |    3 +++
 include/linux/kvm.h      |    1 +
 2 files changed, 4 insertions(+)
arch/s390/kvm/kvm-s390.c +3 -0
@@ -226,6 +226,9 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_S390_PSW:
 	case KVM_CAP_S390_GMAP:
 	case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_UCONTROL
+	case KVM_CAP_S390_UCONTROL:
+#endif
 		r = 1;
 		break;
 	default:
include/linux/kvm.h +1 -0
@@ -574,6 +574,7 @@ struct kvm_s390_keyop {
 #define KVM_CAP_MAX_VCPUS 66       /* returns max vcpus per vm */
 #define KVM_CAP_PPC_PAPR 68
 #define KVM_CAP_S390_GMAP 71
+#define KVM_CAP_S390_UCONTROL 72
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
#20 lore raw

PATCH 12/12 kvm-s390: Fix return code for unknown ioctl numbers

In reply to Carsten Otte

This patch fixes the return code of kvm_arch_vcpu_ioctl in case of an unkown ioctl number.

---

---
 arch/s390/kvm/kvm-s390.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kvm/kvm-s390.c +1 -1
@@ -884,7 +884,7 @@ long kvm_arch_vcpu_ioctl(struct file *fi
 		break;
 	}
 	default:
-		r = -EINVAL;
+		r = -ENOTTY;
 	}
 	return r;
 }