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

Commit d7b0b5eb authored by Carsten Otte's avatar Carsten Otte Committed by Avi Kivity
Browse files

KVM: s390: Make psw available on all exits, not just a subset



This patch moves s390 processor status word into the base kvm_run
struct and keeps it up-to date on all userspace exits.

The userspace ABI is broken by this, however there are no applications
in the wild using this.  A capability check is provided so users can
verify the updated API exists.

Cc: stable@kernel.org
Signed-off-by: default avatarCarsten Otte <cotte@de.ibm.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 3cfc3092
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
#ifndef __LINUX_KVM_S390_H
#ifndef __LINUX_KVM_S390_H
#define __LINUX_KVM_S390_H
#define __LINUX_KVM_S390_H

/*
/*
 * asm-s390/kvm.h - KVM s390 specific structures and definitions
 * asm-s390/kvm.h - KVM s390 specific structures and definitions
 *
 *
@@ -15,6 +14,8 @@
 */
 */
#include <linux/types.h>
#include <linux/types.h>


#define __KVM_S390

/* for KVM_GET_REGS and KVM_SET_REGS */
/* for KVM_GET_REGS and KVM_SET_REGS */
struct kvm_regs {
struct kvm_regs {
	/* general purpose regs for s390 */
	/* general purpose regs for s390 */
+17 −8
Original line number Original line Diff line number Diff line
@@ -117,10 +117,16 @@ long kvm_arch_dev_ioctl(struct file *filp,


int kvm_dev_ioctl_check_extension(long ext)
int kvm_dev_ioctl_check_extension(long ext)
{
{
	int r;

	switch (ext) {
	switch (ext) {
	case KVM_CAP_S390_PSW:
		r = 1;
		break;
	default:
	default:
		return 0;
		r = 0;
	}
	}
	return r;
}
}


/* Section: vm related */
/* Section: vm related */
@@ -420,8 +426,10 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
	vcpu_load(vcpu);
	vcpu_load(vcpu);
	if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
	if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
		rc = -EBUSY;
		rc = -EBUSY;
	else
	else {
		vcpu->arch.sie_block->gpsw = psw;
		vcpu->run->psw_mask = psw.mask;
		vcpu->run->psw_addr = psw.addr;
	}
	vcpu_put(vcpu);
	vcpu_put(vcpu);
	return rc;
	return rc;
}
}
@@ -509,9 +517,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)


	switch (kvm_run->exit_reason) {
	switch (kvm_run->exit_reason) {
	case KVM_EXIT_S390_SIEIC:
	case KVM_EXIT_S390_SIEIC:
		vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
		vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;
		break;
	case KVM_EXIT_UNKNOWN:
	case KVM_EXIT_UNKNOWN:
	case KVM_EXIT_INTR:
	case KVM_EXIT_INTR:
	case KVM_EXIT_S390_RESET:
	case KVM_EXIT_S390_RESET:
@@ -520,6 +525,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
		BUG();
		BUG();
	}
	}


	vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
	vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;

	might_fault();
	might_fault();


	do {
	do {
@@ -539,8 +547,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
		/* intercept cannot be handled in-kernel, prepare kvm-run */
		/* intercept cannot be handled in-kernel, prepare kvm-run */
		kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
		kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
		kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
		kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
		kvm_run->s390_sieic.mask     = vcpu->arch.sie_block->gpsw.mask;
		kvm_run->s390_sieic.addr     = vcpu->arch.sie_block->gpsw.addr;
		kvm_run->s390_sieic.ipa      = vcpu->arch.sie_block->ipa;
		kvm_run->s390_sieic.ipa      = vcpu->arch.sie_block->ipa;
		kvm_run->s390_sieic.ipb      = vcpu->arch.sie_block->ipb;
		kvm_run->s390_sieic.ipb      = vcpu->arch.sie_block->ipb;
		rc = 0;
		rc = 0;
@@ -552,6 +558,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
		rc = 0;
		rc = 0;
	}
	}


	kvm_run->psw_mask     = vcpu->arch.sie_block->gpsw.mask;
	kvm_run->psw_addr     = vcpu->arch.sie_block->gpsw.addr;

	if (vcpu->sigset_active)
	if (vcpu->sigset_active)
		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
		sigprocmask(SIG_SETMASK, &sigsaved, NULL);


+6 −2
Original line number Original line Diff line number Diff line
@@ -181,6 +181,11 @@ struct kvm_run {
	__u64 cr8;
	__u64 cr8;
	__u64 apic_base;
	__u64 apic_base;


#ifdef __KVM_S390
	/* the processor status word for s390 */
	__u64 psw_mask; /* psw upper half */
	__u64 psw_addr; /* psw lower half */
#endif
	union {
	union {
		/* KVM_EXIT_UNKNOWN */
		/* KVM_EXIT_UNKNOWN */
		struct {
		struct {
@@ -232,8 +237,6 @@ struct kvm_run {
		/* KVM_EXIT_S390_SIEIC */
		/* KVM_EXIT_S390_SIEIC */
		struct {
		struct {
			__u8 icptcode;
			__u8 icptcode;
			__u64 mask; /* psw upper half */
			__u64 addr; /* psw lower half */
			__u16 ipa;
			__u16 ipa;
			__u32 ipb;
			__u32 ipb;
		} s390_sieic;
		} s390_sieic;
@@ -492,6 +495,7 @@ struct kvm_ioeventfd {
#ifdef __KVM_HAVE_VCPU_EVENTS
#ifdef __KVM_HAVE_VCPU_EVENTS
#define KVM_CAP_VCPU_EVENTS 41
#define KVM_CAP_VCPU_EVENTS 41
#endif
#endif
#define KVM_CAP_S390_PSW 42


#ifdef KVM_CAP_IRQ_ROUTING
#ifdef KVM_CAP_IRQ_ROUTING