aboutsummaryrefslogtreecommitdiff
path: root/target-s390x
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2013-12-17 14:22:09 +0100
committerAlexander Graf <agraf@suse.de>2013-12-18 14:24:10 +0100
commit3796f0e1cda41eacf4fc915e7edaf54f2279466c (patch)
tree85420c34f3efc16b367965b40ad1b9b0343ec3ca /target-s390x
parentb8031adba791325907d8a9e19af8d483996974fd (diff)
s390x/kvm: Fixed condition code for unknown SIGP orders
If SIGP is called with an unknown order code, it has to return CC1 instead of CC3 and set the "invalid order" bit in the return status. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-s390x')
-rw-r--r--target-s390x/kvm.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 0bf3d1f49e..f7b772668c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -633,8 +633,9 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
CPUS390XState *env = &cpu->env;
uint8_t order_code;
uint16_t cpu_addr;
- int r = -1;
S390CPU *target_cpu;
+ uint64_t *statusreg = &env->regs[ipa1 >> 4];
+ int cc;
cpu_synchronize_state(CPU(cpu));
@@ -644,29 +645,33 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
cpu_addr = env->regs[ipa1 & 0x0f];
target_cpu = s390_cpu_addr2state(cpu_addr);
if (target_cpu == NULL) {
+ cc = 3; /* not operational */
goto out;
}
switch (order_code) {
case SIGP_START:
- r = kvm_s390_cpu_start(target_cpu);
+ cc = kvm_s390_cpu_start(target_cpu);
break;
case SIGP_RESTART:
- r = kvm_s390_cpu_restart(target_cpu);
+ cc = kvm_s390_cpu_restart(target_cpu);
break;
case SIGP_SET_ARCH:
/* make the caller panic */
return -1;
case SIGP_INITIAL_CPU_RESET:
- r = s390_cpu_initial_reset(target_cpu);
+ cc = s390_cpu_initial_reset(target_cpu);
break;
default:
- fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", order_code);
+ DPRINTF("KVM: unknown SIGP: 0x%x\n", order_code);
+ *statusreg &= 0xffffffff00000000UL;
+ *statusreg |= SIGP_STAT_INVALID_ORDER;
+ cc = 1; /* status stored */
break;
}
out:
- setcc(cpu, r ? 3 : 0);
+ setcc(cpu, cc);
return 0;
}