Commit 3526a66b authored by David Hildenbrand's avatar David Hildenbrand Committed by Christian Borntraeger
Browse files

KVM: s390: sigp: dispatch orders with one target in a separate function



All sigp orders except SIGP SET ARCHITECTURE target exactly one vcpu.

Let's move the dispatch code for these orders into a separate function to
prepare for cleaner target availability checks.

Signed-off-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent a36c5393
Loading
Loading
Loading
Loading
+43 −31
Original line number Original line Diff line number Diff line
@@ -349,32 +349,15 @@ static int sigp_check_callable(struct kvm_vcpu *vcpu, u16 cpu_addr)
	return rc;
	return rc;
}
}


int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
			   u16 cpu_addr, u32 parameter, u64 *status_reg)
{
{
	int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
	int r3 = vcpu->arch.sie_block->ipa & 0x000f;
	u32 parameter;
	u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
	u8 order_code;
	int rc;
	int rc;


	/* sigp in userspace can exit */
	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);

	order_code = kvm_s390_get_base_disp_rs(vcpu);

	if (r1 % 2)
		parameter = vcpu->run->s.regs.gprs[r1];
	else
		parameter = vcpu->run->s.regs.gprs[r1 + 1];

	trace_kvm_s390_handle_sigp(vcpu, order_code, cpu_addr, parameter);
	switch (order_code) {
	switch (order_code) {
	case SIGP_SENSE:
	case SIGP_SENSE:
		vcpu->stat.instruction_sigp_sense++;
		vcpu->stat.instruction_sigp_sense++;
		rc = __sigp_sense(vcpu, cpu_addr,
		rc = __sigp_sense(vcpu, cpu_addr, status_reg);
				  &vcpu->run->s.regs.gprs[r1]);
		break;
		break;
	case SIGP_EXTERNAL_CALL:
	case SIGP_EXTERNAL_CALL:
		vcpu->stat.instruction_sigp_external_call++;
		vcpu->stat.instruction_sigp_external_call++;
@@ -395,25 +378,19 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
		break;
		break;
	case SIGP_STORE_STATUS_AT_ADDRESS:
	case SIGP_STORE_STATUS_AT_ADDRESS:
		rc = __sigp_store_status_at_addr(vcpu, cpu_addr, parameter,
		rc = __sigp_store_status_at_addr(vcpu, cpu_addr, parameter,
						 &vcpu->run->s.regs.gprs[r1]);
						 status_reg);
		break;
	case SIGP_SET_ARCHITECTURE:
		vcpu->stat.instruction_sigp_arch++;
		rc = __sigp_set_arch(vcpu, parameter);
		break;
		break;
	case SIGP_SET_PREFIX:
	case SIGP_SET_PREFIX:
		vcpu->stat.instruction_sigp_prefix++;
		vcpu->stat.instruction_sigp_prefix++;
		rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
		rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, status_reg);
				       &vcpu->run->s.regs.gprs[r1]);
		break;
		break;
	case SIGP_COND_EMERGENCY_SIGNAL:
	case SIGP_COND_EMERGENCY_SIGNAL:
		rc = __sigp_conditional_emergency(vcpu, cpu_addr, parameter,
		rc = __sigp_conditional_emergency(vcpu, cpu_addr, parameter,
						  &vcpu->run->s.regs.gprs[r1]);
						  status_reg);
		break;
		break;
	case SIGP_SENSE_RUNNING:
	case SIGP_SENSE_RUNNING:
		vcpu->stat.instruction_sigp_sense_running++;
		vcpu->stat.instruction_sigp_sense_running++;
		rc = __sigp_sense_running(vcpu, cpu_addr,
		rc = __sigp_sense_running(vcpu, cpu_addr, status_reg);
					  &vcpu->run->s.regs.gprs[r1]);
		break;
		break;
	case SIGP_START:
	case SIGP_START:
		rc = sigp_check_callable(vcpu, cpu_addr);
		rc = sigp_check_callable(vcpu, cpu_addr);
@@ -432,7 +409,42 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
		}
		}
		break;
		break;
	default:
	default:
		return -EOPNOTSUPP;
		rc = -EOPNOTSUPP;
	}

	return rc;
}

int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
{
	int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
	int r3 = vcpu->arch.sie_block->ipa & 0x000f;
	u32 parameter;
	u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
	u8 order_code;
	int rc;

	/* sigp in userspace can exit */
	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);

	order_code = kvm_s390_get_base_disp_rs(vcpu);

	if (r1 % 2)
		parameter = vcpu->run->s.regs.gprs[r1];
	else
		parameter = vcpu->run->s.regs.gprs[r1 + 1];

	trace_kvm_s390_handle_sigp(vcpu, order_code, cpu_addr, parameter);
	switch (order_code) {
	case SIGP_SET_ARCHITECTURE:
		vcpu->stat.instruction_sigp_arch++;
		rc = __sigp_set_arch(vcpu, parameter);
		break;
	default:
		rc = handle_sigp_dst(vcpu, order_code, cpu_addr,
				     parameter,
				     &vcpu->run->s.regs.gprs[r1]);
	}
	}


	if (rc < 0)
	if (rc < 0)