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

Commit bd59d3a4 authored by Cornelia Huck's avatar Cornelia Huck Committed by Avi Kivity
Browse files

KVM: s390: handle SIGP sense running intercepts



SIGP sense running may cause an intercept on higher level
virtualization, so handle it by checking the CPUSTAT_RUNNING flag.

Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarCarsten Otte <cotte@de.ibm.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 9e6dabef
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ struct kvm_vcpu_stat {
	u32 instruction_stfl;
	u32 instruction_tprot;
	u32 instruction_sigp_sense;
	u32 instruction_sigp_sense_running;
	u32 instruction_sigp_external_call;
	u32 instruction_sigp_emergency;
	u32 instruction_sigp_stop;
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
	{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
	{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
	{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
	{ "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
	{ "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
	{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
	{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
+39 −0
Original line number Diff line number Diff line
@@ -31,9 +31,11 @@
#define SIGP_SET_PREFIX        0x0d
#define SIGP_STORE_STATUS_ADDR 0x0e
#define SIGP_SET_ARCH          0x12
#define SIGP_SENSE_RUNNING     0x15

/* cpu status bits */
#define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
#define SIGP_STAT_NOT_RUNNING	    0x00000400UL
#define SIGP_STAT_INCORRECT_STATE   0x00000200UL
#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
#define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
@@ -275,6 +277,38 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
	return rc;
}

static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
				unsigned long *reg)
{
	int rc;
	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;

	if (cpu_addr >= KVM_MAX_VCPUS)
		return 3; /* not operational */

	spin_lock(&fi->lock);
	if (fi->local_int[cpu_addr] == NULL)
		rc = 3; /* not operational */
	else {
		if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
		    & CPUSTAT_RUNNING) {
			/* running */
			rc = 1;
		} else {
			/* not running */
			*reg &= 0xffffffff00000000UL;
			*reg |= SIGP_STAT_NOT_RUNNING;
			rc = 0;
		}
	}
	spin_unlock(&fi->lock);

	VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr,
		   rc);

	return rc;
}

int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
{
	int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -331,6 +365,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
		rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
				       &vcpu->arch.guest_gprs[r1]);
		break;
	case SIGP_SENSE_RUNNING:
		vcpu->stat.instruction_sigp_sense_running++;
		rc = __sigp_sense_running(vcpu, cpu_addr,
					  &vcpu->arch.guest_gprs[r1]);
		break;
	case SIGP_RESTART:
		vcpu->stat.instruction_sigp_restart++;
		/* user space must know about restart */