Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e0b1ab7 authored by Fan Zhang's avatar Fan Zhang Committed by Christian Borntraeger
Browse files

KVM: s390: gs support for kvm guests



This patch adds guarded storage support for KVM guest. We need to
setup the necessary control blocks, the kvm_run structure for the
new registers, the necessary wrappers for VSIE, as well as the
machine check save areas.
GS is enabled lazily and the register saving and reloading is done in
KVM code.  As this feature adds new content for migration, we provide
a new capability for enablement (KVM_CAP_S390_GS).

Signed-off-by: default avatarFan Zhang <zhangfan@linux.vnet.ibm.com>
Reviewed-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: default avatarJanosch Frank <frankja@linux.vnet.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent 7c2b3e0d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -4101,6 +4101,15 @@ to take care of that.
This capability can be enabled dynamically even if VCPUs were already
created and are running.

7.9 KVM_CAP_S390_GS

Architectures: s390
Parameters: none
Returns: 0 on success; -EINVAL if the machine does not support
	 guarded storage; -EBUSY if a VCPU has already been created.

Allows use of guarded storage for the KVM guest.

8. Other capabilities.
----------------------

+7 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <asm/cpu.h>
#include <asm/fpu/api.h>
#include <asm/isc.h>
#include <asm/guarded_storage.h>

#define KVM_S390_BSCA_CPU_SLOTS 64
#define KVM_S390_ESCA_CPU_SLOTS 248
@@ -192,6 +193,7 @@ struct kvm_s390_sie_block {
	__u32	ipb;			/* 0x0058 */
	__u32	scaoh;			/* 0x005c */
	__u8	reserved60;		/* 0x0060 */
#define ECB_GS		0x40
#define ECB_TE		0x10
#define ECB_SRSI	0x04
#define ECB_HOSTPROTINT	0x02
@@ -237,7 +239,9 @@ struct kvm_s390_sie_block {
	__u32	crycbd;			/* 0x00fc */
	__u64	gcr[16];		/* 0x0100 */
	__u64	gbea;			/* 0x0180 */
	__u8	reserved188[24];	/* 0x0188 */
	__u8    reserved188[8];		/* 0x0188 */
	__u64   sdnxo;			/* 0x0190 */
	__u8    reserved198[8];		/* 0x0198 */
	__u32	fac;			/* 0x01a0 */
	__u8	reserved1a4[20];	/* 0x01a4 */
	__u64	cbrlo;			/* 0x01b8 */
@@ -573,6 +577,7 @@ struct kvm_vcpu_arch {
	/* if vsie is active, currently executed shadow sie control block */
	struct kvm_s390_sie_block *vsie_block;
	unsigned int      host_acrs[NUM_ACRS];
	struct gs_cb      *host_gscb;
	struct fpu	  host_fpregs;
	struct kvm_s390_local_interrupt local_int;
	struct hrtimer    ckc_timer;
@@ -593,6 +598,7 @@ struct kvm_vcpu_arch {
	 */
	seqcount_t cputm_seqcount;
	__u64 cputm_start;
	bool gs_enabled;
};

struct kvm_vm_stat {
+13 −1
Original line number Diff line number Diff line
@@ -197,6 +197,10 @@ struct kvm_guest_debug_arch {
#define KVM_SYNC_VRS    (1UL << 6)
#define KVM_SYNC_RICCB  (1UL << 7)
#define KVM_SYNC_FPRS   (1UL << 8)
#define KVM_SYNC_GSCB   (1UL << 9)
/* length and alignment of the sdnx as a power of two */
#define SDNXC 8
#define SDNXL (1UL << SDNXC)
/* definition of registers in kvm_run */
struct kvm_sync_regs {
	__u64 prefix;	/* prefix register */
@@ -217,8 +221,16 @@ struct kvm_sync_regs {
	};
	__u8  reserved[512];	/* for future vector expansion */
	__u32 fpc;		/* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
	__u8 padding[52];	/* riccb needs to be 64byte aligned */
	__u8 padding1[52];	/* riccb needs to be 64byte aligned */
	__u8 riccb[64];		/* runtime instrumentation controls block */
	__u8 padding2[192];	/* sdnx needs to be 256byte aligned */
	union {
		__u8 sdnx[SDNXL];  /* state description annex */
		struct {
			__u64 reserved1[2];
			__u64 gscb[4];
		};
	};
};

#define KVM_REG_S390_TODPR	(KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ static const intercept_handler_t instruction_handlers[256] = {
	[0xb6] = kvm_s390_handle_stctl,
	[0xb7] = kvm_s390_handle_lctl,
	[0xb9] = kvm_s390_handle_b9,
	[0xe3] = kvm_s390_handle_e3,
	[0xe5] = kvm_s390_handle_e5,
	[0xeb] = kvm_s390_handle_eb,
};
+31 −2
Original line number Diff line number Diff line
@@ -410,6 +410,7 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,
				 struct kvm_s390_mchk_info *mchk)
{
	unsigned long ext_sa_addr;
	unsigned long lc;
	freg_t fprs[NUM_FPRS];
	union mci mci;
	int rc;
@@ -422,8 +423,28 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,
	/* Extended save area */
	rc = read_guest_lc(vcpu, __LC_MCESAD, &ext_sa_addr,
			   sizeof(unsigned long));
	/* Only bits 0-53 are used for address formation */
	/* Only bits 0 through 63-LC are used for address formation */
	lc = ext_sa_addr & MCESA_LC_MASK;
	if (test_kvm_facility(vcpu->kvm, 133)) {
		switch (lc) {
		case 0:
		case 10:
			ext_sa_addr &= ~0x3ffUL;
			break;
		case 11:
			ext_sa_addr &= ~0x7ffUL;
			break;
		case 12:
			ext_sa_addr &= ~0xfffUL;
			break;
		default:
			ext_sa_addr = 0;
			break;
		}
	} else {
		ext_sa_addr &= ~0x3ffUL;
	}

	if (!rc && mci.vr && ext_sa_addr && test_kvm_facility(vcpu->kvm, 129)) {
		if (write_guest_abs(vcpu, ext_sa_addr, vcpu->run->s.regs.vrs,
				    512))
@@ -431,6 +452,14 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,
	} else {
		mci.vr = 0;
	}
	if (!rc && mci.gs && ext_sa_addr && test_kvm_facility(vcpu->kvm, 133)
	    && (lc == 11 || lc == 12)) {
		if (write_guest_abs(vcpu, ext_sa_addr + 1024,
				    &vcpu->run->s.regs.gscb, 32))
			mci.gs = 0;
	} else {
		mci.gs = 0;
	}

	/* General interruption information */
	rc |= put_guest_lc(vcpu, 1, (u8 __user *) __LC_AR_MODE_ID);
Loading