All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christian Borntraeger <borntraeger@de.ibm.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: KVM <kvm@vger.kernel.org>,
	Janosch Frank <frankja@linux.vnet.ibm.com>,
	David Hildenbrand <david@redhat.com>,
	Claudio Imbrenda <imbrenda@linux.ibm.com>,
	Cornelia Huck <cohuck@redhat.com>,
	Michael Mueller <mimu@linux.ibm.com>,
	Vasily Gorbik <gor@linux.ibm.com>,
	Ulrich Weigand <uweigand@de.ibm.com>,
	linux-s390 <linux-s390@vger.kernel.org>,
	Heiko Carstens <heiko.carstens@de.ibm.com>
Subject: [GIT PULL 18/36] KVM: S390: protvirt: Introduce instruction data area bounce buffer
Date: Mon,  9 Mar 2020 09:51:08 +0100	[thread overview]
Message-ID: <20200309085126.3334302-19-borntraeger@de.ibm.com> (raw)
In-Reply-To: <20200309085126.3334302-1-borntraeger@de.ibm.com>

From: Janosch Frank <frankja@linux.ibm.com>

Now that we can't access guest memory anymore, we have a dedicated
satellite block that's a bounce buffer for instruction data.

We re-use the memop interface to copy the instruction data to / from
userspace. This lets us re-use a lot of QEMU code which used that
interface to make logical guest memory accesses which are not possible
anymore in protected mode anyway.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
[borntraeger@de.ibm.com: patch merging, splitting, fixing]
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 arch/s390/include/asm/kvm_host.h | 11 +++++-
 arch/s390/kvm/kvm-s390.c         | 66 ++++++++++++++++++++++++++++----
 arch/s390/kvm/pv.c               | 16 ++++++++
 include/uapi/linux/kvm.h         |  9 ++++-
 4 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 4fcbb055a565..aa945b101fff 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -127,6 +127,12 @@ struct mcck_volatile_info {
 #define CR14_INITIAL_MASK (CR14_UNUSED_32 | CR14_UNUSED_33 | \
 			   CR14_EXTERNAL_DAMAGE_SUBMASK)
 
+#define SIDAD_SIZE_MASK		0xff
+#define sida_origin(sie_block) \
+	((sie_block)->sidad & PAGE_MASK)
+#define sida_size(sie_block) \
+	((((sie_block)->sidad & SIDAD_SIZE_MASK) + 1) * PAGE_SIZE)
+
 #define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
@@ -315,7 +321,10 @@ struct kvm_s390_sie_block {
 #define CRYCB_FORMAT2 0x00000003
 	__u32	crycbd;			/* 0x00fc */
 	__u64	gcr[16];		/* 0x0100 */
-	__u64	gbea;			/* 0x0180 */
+	union {
+		__u64	gbea;		/* 0x0180 */
+		__u64	sidad;
+	};
 	__u8    reserved188[8];		/* 0x0188 */
 	__u64   sdnxo;			/* 0x0190 */
 	__u8    reserved198[8];		/* 0x0198 */
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index bd62312fdc0e..efbbcd2948a3 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -4495,12 +4495,40 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 	return r;
 }
 
+static long kvm_s390_guest_sida_op(struct kvm_vcpu *vcpu,
+				   struct kvm_s390_mem_op *mop)
+{
+	void __user *uaddr = (void __user *)mop->buf;
+	int r = 0;
+
+	if (mop->flags || !mop->size)
+		return -EINVAL;
+	if (mop->size + mop->sida_offset < mop->size)
+		return -EINVAL;
+	if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block))
+		return -E2BIG;
+
+	switch (mop->op) {
+	case KVM_S390_MEMOP_SIDA_READ:
+		if (copy_to_user(uaddr, (void *)(sida_origin(vcpu->arch.sie_block) +
+				 mop->sida_offset), mop->size))
+			r = -EFAULT;
+
+		break;
+	case KVM_S390_MEMOP_SIDA_WRITE:
+		if (copy_from_user((void *)(sida_origin(vcpu->arch.sie_block) +
+				   mop->sida_offset), uaddr, mop->size))
+			r = -EFAULT;
+		break;
+	}
+	return r;
+}
 static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
 				  struct kvm_s390_mem_op *mop)
 {
 	void __user *uaddr = (void __user *)mop->buf;
 	void *tmpbuf = NULL;
-	int r, srcu_idx;
+	int r = 0;
 	const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION
 				    | KVM_S390_MEMOP_F_CHECK_ONLY;
 
@@ -4510,14 +4538,15 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
 	if (mop->size > MEM_OP_MAX_SIZE)
 		return -E2BIG;
 
+	if (kvm_s390_pv_cpu_is_protected(vcpu))
+		return -EINVAL;
+
 	if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) {
 		tmpbuf = vmalloc(mop->size);
 		if (!tmpbuf)
 			return -ENOMEM;
 	}
 
-	srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
-
 	switch (mop->op) {
 	case KVM_S390_MEMOP_LOGICAL_READ:
 		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
@@ -4543,12 +4572,8 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
 		}
 		r = write_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
 		break;
-	default:
-		r = -EINVAL;
 	}
 
-	srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
-
 	if (r > 0 && (mop->flags & KVM_S390_MEMOP_F_INJECT_EXCEPTION) != 0)
 		kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
 
@@ -4556,6 +4581,31 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
 	return r;
 }
 
+static long kvm_s390_guest_memsida_op(struct kvm_vcpu *vcpu,
+				      struct kvm_s390_mem_op *mop)
+{
+	int r, srcu_idx;
+
+	srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+	switch (mop->op) {
+	case KVM_S390_MEMOP_LOGICAL_READ:
+	case KVM_S390_MEMOP_LOGICAL_WRITE:
+		r = kvm_s390_guest_mem_op(vcpu, mop);
+		break;
+	case KVM_S390_MEMOP_SIDA_READ:
+	case KVM_S390_MEMOP_SIDA_WRITE:
+		/* we are locked against sida going away by the vcpu->mutex */
+		r = kvm_s390_guest_sida_op(vcpu, mop);
+		break;
+	default:
+		r = -EINVAL;
+	}
+
+	srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
+	return r;
+}
+
 long kvm_arch_vcpu_async_ioctl(struct file *filp,
 			       unsigned int ioctl, unsigned long arg)
 {
@@ -4686,7 +4736,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		struct kvm_s390_mem_op mem_op;
 
 		if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0)
-			r = kvm_s390_guest_mem_op(vcpu, &mem_op);
+			r = kvm_s390_guest_memsida_op(vcpu, &mem_op);
 		else
 			r = -EFAULT;
 		break;
diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index 9840ee49e572..13a41533eacf 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -33,10 +33,18 @@ int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 	if (!cc)
 		free_pages(vcpu->arch.pv.stor_base,
 			   get_order(uv_info.guest_cpu_stor_len));
+
+	free_page(sida_origin(vcpu->arch.sie_block));
 	vcpu->arch.sie_block->pv_handle_cpu = 0;
 	vcpu->arch.sie_block->pv_handle_config = 0;
 	memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
 	vcpu->arch.sie_block->sdf = 0;
+	/*
+	 * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
+	 * Use the reset value of gbea to avoid leaking the kernel pointer of
+	 * the just freed sida.
+	 */
+	vcpu->arch.sie_block->gbea = 1;
 	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
 
 	return cc ? EIO : 0;
@@ -64,6 +72,14 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 	uvcb.state_origin = (u64)vcpu->arch.sie_block;
 	uvcb.stor_origin = (u64)vcpu->arch.pv.stor_base;
 
+	/* Alloc Secure Instruction Data Area Designation */
+	vcpu->arch.sie_block->sidad = __get_free_page(GFP_KERNEL | __GFP_ZERO);
+	if (!vcpu->arch.sie_block->sidad) {
+		free_pages(vcpu->arch.pv.stor_base,
+			   get_order(uv_info.guest_cpu_stor_len));
+		return -ENOMEM;
+	}
+
 	cc = uv_call(0, (u64)&uvcb);
 	*rc = uvcb.header.rc;
 	*rrc = uvcb.header.rrc;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index ad69817f7792..f4cac1c09e97 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -474,12 +474,17 @@ struct kvm_s390_mem_op {
 	__u32 size;		/* amount of bytes */
 	__u32 op;		/* type of operation */
 	__u64 buf;		/* buffer in userspace */
-	__u8 ar;		/* the access register number */
-	__u8 reserved[31];	/* should be set to 0 */
+	union {
+		__u8 ar;	/* the access register number */
+		__u32 sida_offset; /* offset into the sida */
+		__u8 reserved[32]; /* should be set to 0 */
+	};
 };
 /* types for kvm_s390_mem_op->op */
 #define KVM_S390_MEMOP_LOGICAL_READ	0
 #define KVM_S390_MEMOP_LOGICAL_WRITE	1
+#define KVM_S390_MEMOP_SIDA_READ	2
+#define KVM_S390_MEMOP_SIDA_WRITE	3
 /* flags for kvm_s390_mem_op->flags */
 #define KVM_S390_MEMOP_F_CHECK_ONLY		(1ULL << 0)
 #define KVM_S390_MEMOP_F_INJECT_EXCEPTION	(1ULL << 1)
-- 
2.24.1

  parent reply	other threads:[~2020-03-09  8:51 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-09  8:50 [GIT PULL 00/36] KVM: s390: Features and Enhancements for 5.7 part1 Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 01/36] s390/protvirt: introduce host side setup Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 02/36] s390/protvirt: add ultravisor initialization Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 03/36] s390/mm: provide memory management functions for protected KVM guests Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 04/36] s390/mm: add (non)secure page access exceptions handlers Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 05/36] s390/protvirt: Add sysfs firmware interface for Ultravisor information Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 06/36] KVM: s390/interrupt: do not pin adapter interrupt pages Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 07/36] KVM: s390: protvirt: Add UV debug trace Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 08/36] KVM: s390: add new variants of UV CALL Christian Borntraeger
2020-03-09  8:50 ` [GIT PULL 09/36] KVM: s390: protvirt: Add initial vm and cpu lifecycle handling Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 10/36] KVM: s390: protvirt: Secure memory is not mergeable Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 11/36] KVM: s390/mm: Make pages accessible before destroying the guest Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 12/36] KVM: s390: protvirt: Handle SE notification interceptions Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 13/36] KVM: s390: protvirt: Instruction emulation Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 14/36] KVM: s390: protvirt: Implement interrupt injection Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 15/36] KVM: s390: protvirt: Add SCLP interrupt handling Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 16/36] KVM: s390: protvirt: Handle spec exception loops Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 17/36] KVM: s390: protvirt: Add new gprs location handling Christian Borntraeger
2020-03-09  8:51 ` Christian Borntraeger [this message]
2020-03-09  8:51 ` [GIT PULL 19/36] KVM: s390: protvirt: handle secure guest prefix pages Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 20/36] KVM: s390/mm: handle guest unpin events Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 21/36] KVM: s390: protvirt: Write sthyi data to instruction data area Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 22/36] KVM: s390: protvirt: STSI handling Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 23/36] KVM: s390: protvirt: disallow one_reg Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 24/36] KVM: s390: protvirt: Do only reset registers that are accessible Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 25/36] KVM: s390: protvirt: Only sync fmt4 registers Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 26/36] KVM: s390: protvirt: Add program exception injection Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 27/36] KVM: s390: protvirt: UV calls in support of diag308 0, 1 Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 28/36] KVM: s390: protvirt: Report CPU state to Ultravisor Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 29/36] KVM: s390: protvirt: Support cmd 5 operation state Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 30/36] KVM: s390: protvirt: Mask PSW interrupt bits for interception 104 and 112 Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 31/36] KVM: s390: protvirt: do not inject interrupts after start Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 32/36] KVM: s390: protvirt: Add UV cpu reset calls Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 33/36] DOCUMENTATION: Protected virtual machine introduction and IPL Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 34/36] KVM: s390: protvirt: introduce and enable KVM_CAP_S390_PROTECTED Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 35/36] KVM: s390: protvirt: Add KVM api documentation Christian Borntraeger
2020-03-09  8:51 ` [GIT PULL 36/36] KVM: s390: introduce module parameter kvm.use_gisa Christian Borntraeger
2020-03-10 16:21 ` [GIT PULL 00/36] KVM: s390: Features and Enhancements for 5.7 part1 Christian Borntraeger
2020-03-14 15:58 ` Christian Borntraeger
2020-03-15 18:15   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200309085126.3334302-19-borntraeger@de.ibm.com \
    --to=borntraeger@de.ibm.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=frankja@linux.vnet.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mimu@linux.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=uweigand@de.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.