A set of patches add support for vector registers on s390x.

Notable: Floating point registers and vector registers overlap,
 so extra care is needed so that we end up with a consistent state
 in all cases.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJVZtPHAAoJEN7Pa5PG8C+vsTwP/RMv8R5l//hREjmTPXqMcnrE
 8Z2GQgkTJWxBSyqzCjGOpzS3F4mX3gI10bArTVVaGIOJKGbtuiiqWeF1Fkc193Pm
 RqlyWYjWHTY4fJvl+xYP5dIGTH2C8WeLkfhGc4QvFnnCBPHMGzVs3sw9LFq8xJ/p
 kC64/VQDZraSSsNx9uQ0IeYy5qI4ZzUnSWMerr27AAXpBOdp3FD8jpRyVzN1VPWD
 dlyUugYq1E7y3AR/hnANYr3uCTXNlQ4f1aa8y6GYHzED5UnMnFEVE0InCYWGYyql
 xb2cusdA8ZyMNtvs3r0FyjVlAvHGLNNeJncspJCvmUImcZHwXcFttpQCnK4OJD6t
 CTDmd3b4Wz9ljzYWPz/KgxygkqZyLZ7Fmn3DfTY+Zrq+18dasqSnsj/SMtywlGpB
 pKchNlD0oGLS3xKtDaHQhhpJD4tIw0CxT9MsYcLp0uwCB8zkUnuSXtIPhpVubg9F
 4DYnQG538LtJM4g4qUQYmMxE6IQSAxvKE+2GjyZa4JVL/Nv1oYkWwDY/6cWYekIQ
 u1aRZ1b1px9MrpaO/NfU2+7Ict0uKQrrzf64amqnBy1JmV5uie/JIrIcn26dpFeL
 KN4blfG5oZXRAkoY3PxeLYGCAPle4Lp0BHI6WXh2STCyYsYBsq/IAs66qt1Q/VQZ
 S+mJISMu6bqSuI1EQb99
 =y7nj
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20150528' into staging

A set of patches add support for vector registers on s390x.
Notable: Floating point registers and vector registers overlap,
so extra care is needed so that we end up with a consistent state
in all cases.

# gpg: Signature made Thu May 28 09:37:27 2015 BST using RSA key ID C6F02FAF
# gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"

* remotes/cohuck/tags/s390x-20150528:
  s390x: Enable vector processing capability
  s390x: Migrate vector registers
  s390x: Add vector registers to ELF dump
  linux/elf.h update
  s390x: Add vector registers to HMP output
  s390x: gdb updates for vector registers
  gdb-xml: Include XML for s390 vector registers
  s390x: Store Additional Status SIGP order
  s390x: Vector Register IOCTLs
  s390x: Common access to floating point registers

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-05-28 14:57:34 +01:00
commit a849047372
11 changed files with 357 additions and 43 deletions

2
configure vendored
View file

@ -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)
;;

59
gdb-xml/s390-vx.xml Normal file
View file

@ -0,0 +1,59 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.s390.vx">
<vector id="v4f" type="ieee_single" count="4"/>
<vector id="v2d" type="ieee_double" count="2"/>
<vector id="v16i8" type="int8" count="16"/>
<vector id="v8i16" type="int16" count="8"/>
<vector id="v4i32" type="int32" count="4"/>
<vector id="v2i64" type="int64" count="2"/>
<union id="vec128">
<field name="v4_float" type="v4f"/>
<field name="v2_double" type="v2d"/>
<field name="v16_int8" type="v16i8"/>
<field name="v8_int16" type="v8i16"/>
<field name="v4_int32" type="v4i32"/>
<field name="v2_int64" type="v2i64"/>
<field name="uint128" type="uint128"/>
</union>
<reg name="v0l" bitsize="64" type="uint64"/>
<reg name="v1l" bitsize="64" type="uint64"/>
<reg name="v2l" bitsize="64" type="uint64"/>
<reg name="v3l" bitsize="64" type="uint64"/>
<reg name="v4l" bitsize="64" type="uint64"/>
<reg name="v5l" bitsize="64" type="uint64"/>
<reg name="v6l" bitsize="64" type="uint64"/>
<reg name="v7l" bitsize="64" type="uint64"/>
<reg name="v8l" bitsize="64" type="uint64"/>
<reg name="v9l" bitsize="64" type="uint64"/>
<reg name="v10l" bitsize="64" type="uint64"/>
<reg name="v11l" bitsize="64" type="uint64"/>
<reg name="v12l" bitsize="64" type="uint64"/>
<reg name="v13l" bitsize="64" type="uint64"/>
<reg name="v14l" bitsize="64" type="uint64"/>
<reg name="v15l" bitsize="64" type="uint64"/>
<reg name="v16" bitsize="128" type="vec128"/>
<reg name="v17" bitsize="128" type="vec128"/>
<reg name="v18" bitsize="128" type="vec128"/>
<reg name="v19" bitsize="128" type="vec128"/>
<reg name="v20" bitsize="128" type="vec128"/>
<reg name="v21" bitsize="128" type="vec128"/>
<reg name="v22" bitsize="128" type="vec128"/>
<reg name="v23" bitsize="128" type="vec128"/>
<reg name="v24" bitsize="128" type="vec128"/>
<reg name="v25" bitsize="128" type="vec128"/>
<reg name="v26" bitsize="128" type="vec128"/>
<reg name="v27" bitsize="128" type="vec128"/>
<reg name="v28" bitsize="128" type="vec128"/>
<reg name="v29" bitsize="128" type="vec128"/>
<reg name="v30" bitsize="128" type="vec128"/>
<reg name="v31" bitsize="128" type="vec128"/>
</feature>

View file

@ -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 */

View file

@ -4098,7 +4098,7 @@ static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
*/
//save_fp_regs(&current->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;

View file

@ -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;
@ -78,14 +92,38 @@ 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);
}
}
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 = &note->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)
{
@ -134,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}
};

View file

@ -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 */
@ -162,6 +166,11 @@ typedef struct CPUS390XState {
} CPUS390XState;
static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr)
{
return &cs->vregs[nr][0];
}
#include "cpu-qom.h"
#include <sysemu/kvm.h>
@ -936,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
@ -1180,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

View file

@ -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,13 +124,55 @@ 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;
}
}
/* 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);
}

View file

@ -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]);

View file

@ -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;
@ -337,15 +338,24 @@ 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.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 +478,23 @@ int kvm_arch_get_registers(CPUState *cs)
}
}
/* Floating point */
r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
if (r < 0) {
return r;
/* 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;
}
for (i = 0; i < 16; i++) {
env->fregs[i].ll = fpu.fprs[i];
}
env->fpc = fpu.fpc;
/* The prefix */
if (can_sync_regs(cs, KVM_SYNC_PREFIX)) {
@ -1356,6 +1374,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)
@ -1363,6 +1403,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 +1418,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);
@ -1441,6 +1484,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;
@ -1558,6 +1631,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;

View file

@ -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()
}
@ -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 */
}

View file

@ -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 {
@ -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]);
@ -187,7 +193,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]);
}
}