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:
commit
a849047372
2
configure
vendored
2
configure
vendored
@ -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
59
gdb-xml/s390-vx.xml
Normal 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>
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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 = ¬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)
|
||||
{
|
||||
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user