From c498d8e36e2998fb67de21a34ece633d356a4834 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Thu, 7 May 2015 14:35:44 -0400 Subject: s390x: Common access to floating point registers Provide a routine to access the correct floating point register, to simplify future expansion. Suggested-by: David Hildenbrand Signed-off-by: Eric Farman Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- linux-user/signal.c | 4 ++-- target-s390x/arch_dump.c | 3 ++- target-s390x/cpu.h | 5 +++++ target-s390x/gdbstub.c | 4 ++-- target-s390x/helper.c | 2 +- target-s390x/kvm.c | 9 ++++++--- target-s390x/translate.c | 2 +- 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 5bb399e16b..1166f2fdb2 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4098,7 +4098,7 @@ static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) */ //save_fp_regs(¤t->thread.fp_regs); FIXME for (i = 0; i < 16; i++) { - __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]); + __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]); } } @@ -4239,7 +4239,7 @@ restore_sigregs(CPUS390XState *env, target_sigregs *sc) __get_user(env->aregs[i], &sc->regs.acrs[i]); } for (i = 0; i < 16; i++) { - __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]); + __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]); } return err; diff --git a/target-s390x/arch_dump.c b/target-s390x/arch_dump.c index a1554f5754..36e8407283 100644 --- a/target-s390x/arch_dump.c +++ b/target-s390x/arch_dump.c @@ -78,11 +78,12 @@ static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu) static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu) { int i; + CPUS390XState *cs = &cpu->env; note->hdr.n_type = cpu_to_be32(NT_FPREGSET); note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc); for (i = 0; i <= 15; i++) { - note->contents.fpregset.fprs[i] = cpu_to_be64(cpu->env.fregs[i].ll); + note->contents.fpregset.fprs[i] = cpu_to_be64(get_freg(cs, i)->ll); } } diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index c55721114e..e968769e8e 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -162,6 +162,11 @@ typedef struct CPUS390XState { } CPUS390XState; +static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr) +{ + return &cs->fregs[nr]; +} + #include "cpu-qom.h" #include diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c index 8945f0271d..40bdfe7c65 100644 --- a/target-s390x/gdbstub.c +++ b/target-s390x/gdbstub.c @@ -111,7 +111,7 @@ static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) case S390_FPC_REGNUM: return gdb_get_reg32(mem_buf, env->fpc); case S390_F0_REGNUM ... S390_F15_REGNUM: - return gdb_get_reg64(mem_buf, env->fregs[n - S390_F0_REGNUM].ll); + return gdb_get_reg64(mem_buf, get_freg(env, n - S390_F0_REGNUM)->ll); default: return 0; } @@ -124,7 +124,7 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) env->fpc = ldl_p(mem_buf); return 4; case S390_F0_REGNUM ... S390_F15_REGNUM: - env->fregs[n - S390_F0_REGNUM].ll = ldtul_p(mem_buf); + get_freg(env, n - S390_F0_REGNUM)->ll = ldtul_p(mem_buf); return 8; default: return 0; diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 041c9c7429..6b47766494 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -445,7 +445,7 @@ static void do_mchk_interrupt(CPUS390XState *env) lowcore = cpu_map_lowcore(env); for (i = 0; i < 16; i++) { - lowcore->floating_pt_save_area[i] = cpu_to_be64(env->fregs[i].ll); + lowcore->floating_pt_save_area[i] = cpu_to_be64(get_freg(env, i)->ll); lowcore->gpregs_save_area[i] = cpu_to_be64(env->regs[i]); lowcore->access_regs_save_area[i] = cpu_to_be32(env->aregs[i]); lowcore->cregs_save_area[i] = cpu_to_be64(env->cregs[i]); diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index ea18015793..1a40a94a51 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -339,7 +339,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) /* Floating point */ for (i = 0; i < 16; i++) { - fpu.fprs[i] = env->fregs[i].ll; + fpu.fprs[i] = get_freg(env, i)->ll; } fpu.fpc = env->fpc; @@ -474,7 +474,7 @@ int kvm_arch_get_registers(CPUState *cs) return r; } for (i = 0; i < 16; i++) { - env->fregs[i].ll = fpu.fprs[i]; + get_freg(env, i)->ll = fpu.fprs[i]; } env->fpc = fpu.fpc; @@ -1363,6 +1363,7 @@ static int kvm_s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) static const uint8_t ar_id = 1; uint64_t ckc = cpu->env.ckc >> 8; void *mem; + int i; hwaddr len = SAVE_AREA_SIZE; mem = cpu_physical_memory_map(addr, &len, 1); @@ -1377,7 +1378,9 @@ static int kvm_s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) if (store_arch) { cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1); } - memcpy(mem, &cpu->env.fregs, 128); + for (i = 0; i < 16; ++i) { + *((uint64 *)mem + i) = get_freg(&cpu->env, i)->ll; + } memcpy(mem + 128, &cpu->env.regs, 128); memcpy(mem + 256, &cpu->env.psw, 16); memcpy(mem + 280, &cpu->env.psa, 4); diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 80e3a545e4..96b43b3b6e 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -113,7 +113,7 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, } for (i = 0; i < 16; i++) { - cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll); + cpu_fprintf(f, "F%02d=%016" PRIx64, i, get_freg(env, i)->ll); if ((i % 4) == 3) { cpu_fprintf(f, "\n"); } else { -- cgit v1.2.3 From fcb79802e07fe06fe24ba97a027d8a1c3a714fa7 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Mon, 18 Aug 2014 15:33:39 -0400 Subject: s390x: Vector Register IOCTLs Handle the actual syncing of the vector registers with kernel space, via the get/put register IOCTLs. The vector registers that were introduced with the z13 overlay the existing floating point registers. FP registers 0-15 are the high-halves of vector registers 0-15. Thus, remove the freg fields and replace them with the equivalent vector field to avoid errors in duplication. Moreover, synchronize either the vector registers via kvm_sync_regs, or floating point registers via the GET/SET FPU IOCTLs. Signed-off-by: Eric Farman Signed-off-by: Cornelia Huck --- target-s390x/cpu.h | 8 ++++++-- target-s390x/kvm.c | 49 ++++++++++++++++++++++++++++++++---------------- target-s390x/machine.c | 32 +++++++++++++++---------------- target-s390x/translate.c | 2 +- 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index e968769e8e..708349ca04 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -81,7 +81,11 @@ typedef struct MchkQueue { typedef struct CPUS390XState { uint64_t regs[16]; /* GP registers */ - CPU_DoubleU fregs[16]; /* FP registers */ + /* + * The floating point registers are part of the vector registers. + * vregs[0][0] -> vregs[15][0] are 16 floating point registers + */ + CPU_DoubleU vregs[32][2]; /* vector registers */ uint32_t aregs[16]; /* access registers */ uint32_t fpc; /* floating-point control register */ @@ -164,7 +168,7 @@ typedef struct CPUS390XState { static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr) { - return &cs->fregs[nr]; + return &cs->vregs[nr][0]; } #include "cpu-qom.h" diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 1a40a94a51..ca8ffcc2a9 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -337,15 +337,24 @@ int kvm_arch_put_registers(CPUState *cs, int level) } } - /* Floating point */ - for (i = 0; i < 16; i++) { - fpu.fprs[i] = get_freg(env, i)->ll; - } - fpu.fpc = env->fpc; + if (can_sync_regs(cs, KVM_SYNC_VRS)) { + for (i = 0; i < 32; i++) { + cs->kvm_run->s.regs.vrs[i][0] = env->vregs[i][0].ll; + cs->kvm_run->s.regs.vrs[i][1] = env->vregs[i][1].ll; + } + cs->kvm_run->s.regs.fpc = env->fpc; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS; + } else { + /* Floating point */ + for (i = 0; i < 16; i++) { + fpu.fprs[i] = get_freg(env, i)->ll; + } + fpu.fpc = env->fpc; - r = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu); - if (r < 0) { - return r; + r = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu); + if (r < 0) { + return r; + } } /* Do we need to save more than that? */ @@ -468,15 +477,23 @@ int kvm_arch_get_registers(CPUState *cs) } } - /* Floating point */ - r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); - if (r < 0) { - return r; - } - for (i = 0; i < 16; i++) { - get_freg(env, i)->ll = fpu.fprs[i]; + /* Floating point and vector registers */ + if (can_sync_regs(cs, KVM_SYNC_VRS)) { + for (i = 0; i < 32; i++) { + env->vregs[i][0].ll = cs->kvm_run->s.regs.vrs[i][0]; + env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1]; + } + env->fpc = cs->kvm_run->s.regs.fpc; + } else { + r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); + if (r < 0) { + return r; + } + for (i = 0; i < 16; i++) { + get_freg(env, i)->ll = fpu.fprs[i]; + } + env->fpc = fpu.fpc; } - env->fpc = fpu.fpc; /* The prefix */ if (can_sync_regs(cs, KVM_SYNC_PREFIX)) { diff --git a/target-s390x/machine.c b/target-s390x/machine.c index 7853e3c989..1a9390b6cd 100644 --- a/target-s390x/machine.c +++ b/target-s390x/machine.c @@ -47,22 +47,22 @@ const VMStateDescription vmstate_fpu = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_UINT64(env.fregs[0].ll, S390CPU), - VMSTATE_UINT64(env.fregs[1].ll, S390CPU), - VMSTATE_UINT64(env.fregs[2].ll, S390CPU), - VMSTATE_UINT64(env.fregs[3].ll, S390CPU), - VMSTATE_UINT64(env.fregs[4].ll, S390CPU), - VMSTATE_UINT64(env.fregs[5].ll, S390CPU), - VMSTATE_UINT64(env.fregs[6].ll, S390CPU), - VMSTATE_UINT64(env.fregs[7].ll, S390CPU), - VMSTATE_UINT64(env.fregs[8].ll, S390CPU), - VMSTATE_UINT64(env.fregs[9].ll, S390CPU), - VMSTATE_UINT64(env.fregs[10].ll, S390CPU), - VMSTATE_UINT64(env.fregs[11].ll, S390CPU), - VMSTATE_UINT64(env.fregs[12].ll, S390CPU), - VMSTATE_UINT64(env.fregs[13].ll, S390CPU), - VMSTATE_UINT64(env.fregs[14].ll, S390CPU), - VMSTATE_UINT64(env.fregs[15].ll, S390CPU), + VMSTATE_UINT64(env.vregs[0][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[1][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[2][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[3][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[4][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[5][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[6][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[7][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[8][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[9][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[10][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[11][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[12][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[13][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[14][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[15][0].ll, S390CPU), VMSTATE_UINT32(env.fpc, S390CPU), VMSTATE_END_OF_LIST() } diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 96b43b3b6e..06fc1923eb 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -187,7 +187,7 @@ void s390x_translate_init(void) for (i = 0; i < 16; i++) { snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i); fregs[i] = tcg_global_mem_new(TCG_AREG0, - offsetof(CPUS390XState, fregs[i].d), + offsetof(CPUS390XState, vregs[i][0].d), cpu_reg_names[i + 16]); } } -- cgit v1.2.3 From abec53565dce5ed56bff4968d3bed88f6cf68c3c Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Wed, 14 Jan 2015 09:57:16 -0500 Subject: s390x: Store Additional Status SIGP order Add handling for the Store Additional Status at Address order that exists for the Signal Processor (SIGP) instruction. Signed-off-by: Eric Farman Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- target-s390x/cpu.h | 1 + target-s390x/kvm.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 708349ca04..031f94dc40 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -945,6 +945,7 @@ struct sysib_322 { #define SIGP_SET_PREFIX 0x0d #define SIGP_STORE_STATUS_ADDR 0x0e #define SIGP_SET_ARCH 0x12 +#define SIGP_STORE_ADTL_STATUS 0x17 /* SIGP condition codes */ #define SIGP_CC_ORDER_CODE_ACCEPTED 0 diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index ca8ffcc2a9..61e1321a4b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -1373,6 +1373,28 @@ static void sigp_stop(void *arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +#define ADTL_SAVE_AREA_SIZE 1024 +static int kvm_s390_store_adtl_status(S390CPU *cpu, hwaddr addr) +{ + void *mem; + hwaddr len = ADTL_SAVE_AREA_SIZE; + + mem = cpu_physical_memory_map(addr, &len, 1); + if (!mem) { + return -EFAULT; + } + if (len != ADTL_SAVE_AREA_SIZE) { + cpu_physical_memory_unmap(mem, len, 1, 0); + return -EFAULT; + } + + memcpy(mem, &cpu->env.vregs, 512); + + cpu_physical_memory_unmap(mem, len, 1, len); + + return 0; +} + #define KVM_S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) #define SAVE_AREA_SIZE 512 static int kvm_s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) @@ -1461,6 +1483,36 @@ static void sigp_store_status_at_address(void *arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +static void sigp_store_adtl_status(void *arg) +{ + SigpInfo *si = arg; + + if (!kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS)) { + set_sigp_status(si, SIGP_STAT_INVALID_ORDER); + return; + } + + /* cpu has to be stopped */ + if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) { + set_sigp_status(si, SIGP_STAT_INCORRECT_STATE); + return; + } + + /* parameter must be aligned to 1024-byte boundary */ + if (si->param & 0x3ff) { + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); + return; + } + + cpu_synchronize_state(CPU(si->cpu)); + + if (kvm_s390_store_adtl_status(si->cpu, si->param)) { + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); + return; + } + si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; +} + static void sigp_restart(void *arg) { SigpInfo *si = arg; @@ -1578,6 +1630,9 @@ static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order, case SIGP_STORE_STATUS_ADDR: run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, &si); break; + case SIGP_STORE_ADTL_STATUS: + run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, &si); + break; case SIGP_SET_PREFIX: run_on_cpu(CPU(dst_cpu), sigp_set_prefix, &si); break; -- cgit v1.2.3 From 773d4ebc9a31a5e0efbaf83f76715ab40c355384 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Tue, 18 Nov 2014 17:03:02 -0500 Subject: gdb-xml: Include XML for s390 vector registers Include the vector registers XML file that is provided by gdb, and can be used by the qemu gdbserver interface. Signed-off-by: Eric Farman Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- gdb-xml/s390-vx.xml | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 gdb-xml/s390-vx.xml diff --git a/gdb-xml/s390-vx.xml b/gdb-xml/s390-vx.xml new file mode 100644 index 0000000000..8239c116c2 --- /dev/null +++ b/gdb-xml/s390-vx.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From ca343c7a84fbe457dd442d26d5a01f31e8a8d308 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Tue, 3 Jun 2014 08:42:18 -0400 Subject: s390x: gdb updates for vector registers gdb allows registers to be displayed/modified, and is being updated to account for the new vector registers. Mirror these changes in the gdb stub in qemu so that this can be performed when gdb is attached to the qemu gdbserver. Signed-off-by: Eric Farman Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- configure | 2 +- target-s390x/gdbstub.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 9852aef526..b707429625 100755 --- a/configure +++ b/configure @@ -5292,7 +5292,7 @@ case "$target_name" in echo "TARGET_ABI32=y" >> $config_target_mak ;; s390x) - gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml" + gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml" ;; tricore) ;; diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c index 40bdfe7c65..ddc14a6cd4 100644 --- a/target-s390x/gdbstub.c +++ b/target-s390x/gdbstub.c @@ -131,6 +131,48 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) } } +/* the values represent the positions in s390-vx.xml */ +#define S390_V0L_REGNUM 0 +#define S390_V15L_REGNUM 15 +#define S390_V16_REGNUM 16 +#define S390_V31_REGNUM 31 +/* total number of registers in s390-vx.xml */ +#define S390_NUM_VREGS 32 + +static int cpu_read_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + int ret; + + switch (n) { + case S390_V0L_REGNUM ... S390_V15L_REGNUM: + ret = gdb_get_reg64(mem_buf, env->vregs[n][1].ll); + break; + case S390_V16_REGNUM ... S390_V31_REGNUM: + ret = gdb_get_reg64(mem_buf, env->vregs[n][0].ll); + ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1].ll); + break; + default: + ret = 0; + } + + return ret; +} + +static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_V0L_REGNUM ... S390_V15L_REGNUM: + env->vregs[n][1].ll = ldtul_p(mem_buf + 8); + return 8; + case S390_V16_REGNUM ... S390_V31_REGNUM: + env->vregs[n][0].ll = ldtul_p(mem_buf); + env->vregs[n][1].ll = ldtul_p(mem_buf + 8); + return 16; + default: + return 0; + } +} + void s390_cpu_gdb_init(CPUState *cs) { gdb_register_coprocessor(cs, cpu_read_ac_reg, @@ -140,4 +182,8 @@ void s390_cpu_gdb_init(CPUState *cs) gdb_register_coprocessor(cs, cpu_read_fp_reg, cpu_write_fp_reg, S390_NUM_FP_REGS, "s390-fpr.xml", 0); + + gdb_register_coprocessor(cs, cpu_read_vreg, + cpu_write_vreg, + S390_NUM_VREGS, "s390-vx.xml", 0); } -- cgit v1.2.3 From 56c42271495fc5f6c5bd70c4309a74b425c5cbda Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Thu, 29 May 2014 13:50:37 -0400 Subject: s390x: Add vector registers to HMP output There are mechanisms to dump registers via the qemu HMP interface, such as the "info registers" command. Expand this output to dump the new vector registers. Signed-off-by: Eric Farman Reviewed-by: David Hildenbrand Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- target-s390x/translate.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 06fc1923eb..fbffd3066d 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -121,6 +121,12 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, } } + for (i = 0; i < 32; i++) { + cpu_fprintf(f, "V%02d=%016" PRIx64 "%016" PRIx64, i, + env->vregs[i][0].ll, env->vregs[i][1].ll); + cpu_fprintf(f, (i % 2) ? " " : "\n"); + } + #ifndef CONFIG_USER_ONLY for (i = 0; i < 16; i++) { cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]); -- cgit v1.2.3 From eeef559ab4a80753b7bf31728780692a3a4e3ec1 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Wed, 12 Nov 2014 14:22:55 -0500 Subject: linux/elf.h update Sync with kernel elf.h updates to get s390x vector register definitions. Signed-off-by: Eric Farman Signed-off-by: Cornelia Huck --- include/elf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/elf.h b/include/elf.h index 3e75f05afd..4afd474d5a 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1456,6 +1456,8 @@ typedef struct elf64_shdr { #define NT_TASKSTRUCT 4 #define NT_AUXV 6 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */ +#define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 (lower half) */ #define NT_S390_PREFIX 0x305 /* s390 prefix register */ #define NT_S390_CTRS 0x304 /* s390 control registers */ #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ -- cgit v1.2.3 From 3ceeb2930faf1116ee4bb22c8a7794bb2337e8a9 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Thu, 29 May 2014 14:54:26 -0400 Subject: s390x: Add vector registers to ELF dump Create ELF notes for the vector registers where applicable, so that their contents can be examined by utilities such as crash or readelf. Signed-off-by: Eric Farman Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- target-s390x/arch_dump.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/target-s390x/arch_dump.c b/target-s390x/arch_dump.c index 36e8407283..dab63eb44f 100644 --- a/target-s390x/arch_dump.c +++ b/target-s390x/arch_dump.c @@ -44,6 +44,18 @@ struct S390xElfFpregsetStruct { typedef struct S390xElfFpregsetStruct S390xElfFpregset; +struct S390xElfVregsLoStruct { + uint64_t vregs[16]; +} QEMU_PACKED; + +typedef struct S390xElfVregsLoStruct S390xElfVregsLo; + +struct S390xElfVregsHiStruct { + uint64_t vregs[16][2]; +} QEMU_PACKED; + +typedef struct S390xElfVregsHiStruct S390xElfVregsHi; + typedef struct noteStruct { Elf64_Nhdr hdr; char name[5]; @@ -51,6 +63,8 @@ typedef struct noteStruct { union { S390xElfPrstatus prstatus; S390xElfFpregset fpregset; + S390xElfVregsLo vregslo; + S390xElfVregsHi vregshi; uint32_t prefix; uint64_t timer; uint64_t todcmp; @@ -87,6 +101,29 @@ static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu) } } +static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu) +{ + int i; + + note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_LOW); + for (i = 0; i <= 15; i++) { + note->contents.vregslo.vregs[i] = cpu_to_be64(cpu->env.vregs[i][1].ll); + } +} + +static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu) +{ + int i; + S390xElfVregsHi *temp_vregshi; + + temp_vregshi = ¬e->contents.vregshi; + + note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_HIGH); + for (i = 0; i <= 15; i++) { + temp_vregshi->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i + 16][0].ll); + temp_vregshi->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i + 16][1].ll); + } +} static void s390x_write_elf64_timer(Note *note, S390CPU *cpu) { @@ -135,6 +172,8 @@ static const struct NoteFuncDescStruct { {sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer}, {sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp}, {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg}, + {sizeof(((Note *)0)->contents.vregslo), s390x_write_elf64_vregslo}, + {sizeof(((Note *)0)->contents.vregshi), s390x_write_elf64_vregshi}, { 0, NULL} }; -- cgit v1.2.3 From b2ac0ff5d9478907cfd5b204c9179f77d0cb943f Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Thu, 7 May 2015 10:52:16 -0400 Subject: s390x: Migrate vector registers When migrating a guest, be sure to include the vector registers. The vector registers are defined in a subsection, similar to the existing subsection for floating point registers. Since the floating point registers are always present (and thus migrated), we can skip them when performing the migration of the vector registers which may or may not be present. Suggested-by: David Hildenbrand Signed-off-by: Eric Farman Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- target-s390x/cpu.h | 14 ++++++++++++ target-s390x/machine.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 031f94dc40..a71abaeef7 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1190,4 +1190,18 @@ static inline int s390_assign_subch_ioeventfd(EventNotifier *notifier, } } +#ifdef CONFIG_KVM +static inline bool vregs_needed(void *opaque) +{ + if (kvm_enabled()) { + return kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS); + } + return 0; +} +#else +static inline bool vregs_needed(void *opaque) +{ + return 0; +} +#endif #endif diff --git a/target-s390x/machine.c b/target-s390x/machine.c index 1a9390b6cd..e52d76032e 100644 --- a/target-s390x/machine.c +++ b/target-s390x/machine.c @@ -73,6 +73,64 @@ static inline bool fpu_needed(void *opaque) return true; } +const VMStateDescription vmstate_vregs = { + .name = "cpu/vregs", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + /* vregs[0][0] -> vregs[15][0] and fregs are overlays */ + VMSTATE_UINT64(env.vregs[16][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[17][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[18][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[19][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[20][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[21][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[22][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[23][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[24][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[25][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[26][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[27][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[28][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[29][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[30][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[31][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[0][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[1][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[2][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[3][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[4][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[5][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[6][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[7][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[8][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[9][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[10][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[11][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[12][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[13][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[14][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[15][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[16][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[17][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[18][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[19][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[20][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[21][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[22][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[23][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[24][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[25][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[26][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[27][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[28][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[29][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[30][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[31][1].ll, S390CPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -105,6 +163,9 @@ const VMStateDescription vmstate_s390_cpu = { { .vmsd = &vmstate_fpu, .needed = fpu_needed, + } , { + .vmsd = &vmstate_vregs, + .needed = vregs_needed, } , { /* empty */ } -- cgit v1.2.3 From 46ca6b3bc99ebf9205e28ed14c023ebf84d39bb7 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Thu, 30 Oct 2014 09:23:06 -0400 Subject: s390x: Enable vector processing capability Everything is finally in place, inform the kernel that user space supports vector registers. Signed-off-by: Eric Farman Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- target-s390x/kvm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 61e1321a4b..6de7759b67 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -269,6 +269,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0); + kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0); return 0; -- cgit v1.2.3