|
@@ -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,
|
|
|
|
- &vcpu->run->s.regs.gprs[r1]);
|
|
|
|
|
|
+ rc = __sigp_sense(vcpu, cpu_addr, status_reg);
|
|
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]);
|
|
|
|
- break;
|
|
|
|
- case SIGP_SET_ARCHITECTURE:
|
|
|
|
- vcpu->stat.instruction_sigp_arch++;
|
|
|
|
- rc = __sigp_set_arch(vcpu, parameter);
|
|
|
|
|
|
+ status_reg);
|
|
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,
|
|
|
|
- &vcpu->run->s.regs.gprs[r1]);
|
|
|
|
|
|
+ rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, status_reg);
|
|
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,
|
|
|
|
- &vcpu->run->s.regs.gprs[r1]);
|
|
|
|
|
|
+ rc = __sigp_sense_running(vcpu, cpu_addr, status_reg);
|
|
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)
|