summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2013-12-21 16:46:07 +0100
committerAurelien Jarno <aurelien@aurel32.net>2013-12-21 16:46:07 +0100
commite8092f7ae1c71419829879e18ce2dd7249a4d00f (patch)
tree84db2a3608997d2ffe766d4eaa21bffb6b47cfd9
parent3376f4151e4ce0534b35c49c56037cb347293c85 (diff)
parent10c8599a49f99180c2f79596325a5e856cdac59f (diff)
downloadqemu-e8092f7ae1c71419829879e18ce2dd7249a4d00f.tar.gz
Merge tag 'signed-s390-for-upstream' of git://github.com/agraf/qemu
Patch queue for s390 - 2013-12-18 This covers mostly minor bug fixes and implements the SIGP START hypercall which allows to start a remote CPU without changing its state. Cornelia Huck (1): s390x/kvm: Fix diagnose handling. Thomas Huth (7): s390x/kvm: Removed duplicated SIGP defines s390x/kvm: Removed s390_store_status stub s390x/kvm: Fix coding style in handle_sigp() s390x/kvm: Implemented SIGP START s390x/kvm: Simplified the calculation of the SIGP order code s390x/kvm: Fixed condition code for unknown SIGP orders s390x/ioinst: CHSC has to set a condition code * tag 'signed-s390-for-upstream' of git://github.com/agraf/qemu: s390x/ioinst: CHSC has to set a condition code s390x/kvm: Fixed condition code for unknown SIGP orders s390x/kvm: Simplified the calculation of the SIGP order code s390x/kvm: Implemented SIGP START s390x/kvm: Fix coding style in handle_sigp() s390x/kvm: Removed s390_store_status stub s390x/kvm: Removed duplicated SIGP defines s390x/kvm: Fix diagnose handling.
-rw-r--r--target-s390x/cpu.h3
-rw-r--r--target-s390x/ioinst.c1
-rw-r--r--target-s390x/kvm.c98
3 files changed, 50 insertions, 52 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index a2c077bdcd..68b5ab7056 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -352,6 +352,9 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb)
return addr;
}
+/* Base/displacement are at the same locations. */
+#define decode_basedisp_rs decode_basedisp_s
+
void s390x_tod_timer(void *opaque);
void s390x_cpu_timer(void *opaque);
diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 8d6363df4e..b8a6486f51 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -622,6 +622,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
break;
}
+ setcc(cpu, 0); /* Command execution complete */
out:
s390_cpu_physical_memory_unmap(env, req, map_size, 1);
}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 02ac4ba995..f7b772668c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -82,11 +82,6 @@
#define ICPT_CPU_STOP 0x28
#define ICPT_IO 0x40
-#define SIGP_RESTART 0x06
-#define SIGP_INITIAL_CPU_RESET 0x0b
-#define SIGP_STORE_STATUS_ADDR 0x0e
-#define SIGP_SET_ARCH 0x12
-
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
@@ -562,11 +557,19 @@ static void kvm_handle_diag_308(S390CPU *cpu, struct kvm_run *run)
handle_diag_308(&cpu->env, r1, r3);
}
-static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code)
+#define DIAG_KVM_CODE_MASK 0x000000000000ffff
+
+static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
{
int r = 0;
-
- switch (ipb_code) {
+ uint16_t func_code;
+
+ /*
+ * For any diagnose call we support, bits 48-63 of the resulting
+ * address specify the function code; the remainder is ignored.
+ */
+ func_code = decode_basedisp_rs(&cpu->env, ipb) & DIAG_KVM_CODE_MASK;
+ switch (func_code) {
case DIAG_IPL:
kvm_handle_diag_308(cpu, run);
break;
@@ -577,7 +580,7 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code)
sleep(10);
break;
default:
- DPRINTF("KVM: unknown DIAG: 0x%x\n", ipb_code);
+ DPRINTF("KVM: unknown DIAG: 0x%x\n", func_code);
r = -1;
break;
}
@@ -585,20 +588,21 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code)
return r;
}
-int kvm_s390_cpu_restart(S390CPU *cpu)
+static int kvm_s390_cpu_start(S390CPU *cpu)
{
- kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0);
s390_add_running_cpu(cpu);
qemu_cpu_kick(CPU(cpu));
- DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env);
+ DPRINTF("DONE: KVM cpu start: %p\n", &cpu->env);
return 0;
}
-static int s390_store_status(CPUS390XState *env, uint32_t parameter)
+int kvm_s390_cpu_restart(S390CPU *cpu)
{
- /* XXX */
- fprintf(stderr, "XXX SIGP store status\n");
- return -1;
+ kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0);
+ s390_add_running_cpu(cpu);
+ qemu_cpu_kick(CPU(cpu));
+ DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env);
+ return 0;
}
static int s390_cpu_initial_reset(S390CPU *cpu)
@@ -622,61 +626,52 @@ static int s390_cpu_initial_reset(S390CPU *cpu)
return 0;
}
+#define SIGP_ORDER_MASK 0x000000ff
+
static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
{
CPUS390XState *env = &cpu->env;
uint8_t order_code;
- uint32_t parameter;
uint16_t cpu_addr;
- uint8_t t;
- int r = -1;
S390CPU *target_cpu;
- CPUS390XState *target_env;
+ uint64_t *statusreg = &env->regs[ipa1 >> 4];
+ int cc;
cpu_synchronize_state(CPU(cpu));
/* get order code */
- order_code = run->s390_sieic.ipb >> 28;
- if (order_code > 0) {
- order_code = env->regs[order_code];
- }
- order_code += (run->s390_sieic.ipb & 0x0fff0000) >> 16;
+ order_code = decode_basedisp_rs(env, run->s390_sieic.ipb) & SIGP_ORDER_MASK;
- /* get parameters */
- t = (ipa1 & 0xf0) >> 4;
- if (!(t % 2)) {
- t++;
- }
-
- parameter = env->regs[t] & 0x7ffffe00;
cpu_addr = env->regs[ipa1 & 0x0f];
-
target_cpu = s390_cpu_addr2state(cpu_addr);
if (target_cpu == NULL) {
+ cc = 3; /* not operational */
goto out;
}
- target_env = &target_cpu->env;
switch (order_code) {
- case SIGP_RESTART:
- r = kvm_s390_cpu_restart(target_cpu);
- break;
- case SIGP_STORE_STATUS_ADDR:
- r = s390_store_status(target_env, parameter);
- break;
- case SIGP_SET_ARCH:
- /* make the caller panic */
- return -1;
- case SIGP_INITIAL_CPU_RESET:
- r = s390_cpu_initial_reset(target_cpu);
- break;
- default:
- fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", order_code);
- break;
+ case SIGP_START:
+ cc = kvm_s390_cpu_start(target_cpu);
+ break;
+ case SIGP_RESTART:
+ cc = kvm_s390_cpu_restart(target_cpu);
+ break;
+ case SIGP_SET_ARCH:
+ /* make the caller panic */
+ return -1;
+ case SIGP_INITIAL_CPU_RESET:
+ cc = s390_cpu_initial_reset(target_cpu);
+ break;
+ default:
+ 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;
}
@@ -684,7 +679,6 @@ static void handle_instruction(S390CPU *cpu, struct kvm_run *run)
{
unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
- int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
int r = -1;
DPRINTF("handle_instruction 0x%x 0x%x\n",
@@ -696,7 +690,7 @@ static void handle_instruction(S390CPU *cpu, struct kvm_run *run)
r = handle_priv(cpu, run, ipa0 >> 8, ipa1);
break;
case IPA0_DIAG:
- r = handle_diag(cpu, run, ipb_code);
+ r = handle_diag(cpu, run, run->s390_sieic.ipb);
break;
case IPA0_SIGP:
r = handle_sigp(cpu, run, ipa1);