Testing and gdbstub updates:

- docker updates for VirGL
   - re-factor gdbstub for static GDBState
   - re-factor gdbstub for dynamic arrays
   - add SVE support to arm gdbstub
   - add some guest debug tests to check-tcg
   - add aarch64 userspace register tests
   - remove packet size limit to gdbstub
   - simplify gdbstub monitor code
   - report vContSupported in gdbstub to use proper single-step
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl5xDUIACgkQ+9DbCVqe
 KkQwCwf/YtmUsNxxO+CgNctq2u3jV4FoOdQP3bejvmT2+cigKJhQuBlWPg1/YsqF
 RDNkmBQx2JaVVMuVmpnwVK1UD+kmYZqrtlOkPNcVrjPmLCq3BVI1LHe6Rjoerx8F
 QoZyH0IMNHbBgDo1I46lSFOWcxmOvo+Ow7NX5bPKwlRzf0dyEqSJahRaZLAgUscR
 taTtGfk9uQsnxoRsvH/efiQ4bZtUvrEQuhEX3WW/yVE1jTpcb2llwX4xONJb2It3
 /0WREGEEIT8PpnWw2S3FH4THY/BjWgz/FPDwNNZYCKBMWDjuG/8KHryd738T9rzo
 lkGP9YcXmiyxMMyFFwS8RD3SHr8LvQ==
 =Wm+a
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-gdbstub-170320-1' into staging

Testing and gdbstub updates:

  - docker updates for VirGL
  - re-factor gdbstub for static GDBState
  - re-factor gdbstub for dynamic arrays
  - add SVE support to arm gdbstub
  - add some guest debug tests to check-tcg
  - add aarch64 userspace register tests
  - remove packet size limit to gdbstub
  - simplify gdbstub monitor code
  - report vContSupported in gdbstub to use proper single-step

# gpg: Signature made Tue 17 Mar 2020 17:47:46 GMT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* remotes/stsquad/tags/pull-testing-and-gdbstub-170320-1: (28 commits)
  gdbstub: Fix single-step issue by confirming 'vContSupported+' feature to gdb
  gdbstub: do not split gdb_monitor_write payload
  gdbstub: change GDBState.last_packet to GByteArray
  tests/tcg/aarch64: add test-sve-ioctl guest-debug test
  tests/tcg/aarch64: add SVE iotcl test
  tests/tcg/aarch64: add a gdbstub testcase for SVE registers
  tests/guest-debug: add a simple test runner
  configure: allow user to specify what gdb to use
  tests/tcg/aarch64: userspace system register test
  target/arm: don't bother with id_aa64pfr0_read for USER_ONLY
  target/arm: generate xml description of our SVE registers
  target/arm: default SVE length to 64 bytes for linux-user
  target/arm: explicitly encode regnum in our XML
  target/arm: prepare for multiple dynamic XMLs
  gdbstub: extend GByteArray to read register helpers
  target/i386: use gdb_get_reg helpers
  target/m68k: use gdb_get_reg helpers
  target/arm: use gdb_get_reg helpers
  gdbstub: add helper for 128 bit registers
  gdbstub: move mem_buf to GDBState and use GByteArray
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-03-18 20:25:23 +00:00
commit 9214813489
54 changed files with 1497 additions and 701 deletions

View File

@ -79,6 +79,7 @@ env:
- MAIN_SOFTMMU_TARGETS="aarch64-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
- CCACHE_SLOPPINESS="include_file_ctime,include_file_mtime"
- CCACHE_MAXSIZE=1G
- G_MESSAGES_DEBUG=error
git:

9
configure vendored
View File

@ -303,6 +303,7 @@ libs_qga=""
debug_info="yes"
stack_protector=""
use_containers="yes"
gdb_bin=$(command -v "gdb")
if test -e "$source_path/.git"
then
@ -1598,6 +1599,8 @@ for opt do
;;
--disable-fuzzing) fuzzing=no
;;
--gdb=*) gdb_bin="$optarg"
;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@ -1783,6 +1786,7 @@ Advanced options (experts only):
--enable-plugins
enable plugins via shared library loading
--disable-containers don't use containers for cross-building
--gdb=GDB-path gdb to use for gdbstub tests [$gdb_bin]
Optional features, enabled with --enable-FEATURE and
disabled with --disable-FEATURE, default is enabled if available:
@ -6785,6 +6789,7 @@ echo "libudev $libudev"
echo "default devices $default_devices"
echo "plugin support $plugins"
echo "fuzzing support $fuzzing"
echo "gdb $gdb_bin"
if test "$supported_cpu" = "no"; then
echo
@ -7666,6 +7671,10 @@ if test "$plugins" = "yes" ; then
fi
fi
if test -n "$gdb_bin" ; then
echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
fi
if test "$tcg_interpreter" = "yes"; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
elif test "$ARCH" = "sparc64" ; then

936
gdbstub.c

File diff suppressed because it is too large Load Diff

View File

@ -177,7 +177,7 @@ static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
}
static int cpu_common_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg)
static int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
{
return 0;
}

View File

@ -68,40 +68,76 @@ void gdb_signalled(CPUArchState *, int);
void gdbserver_fork(CPUState *);
#endif
/* Get or set a register. Returns the size of the register. */
typedef int (*gdb_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
void gdb_register_coprocessor(CPUState *cpu,
gdb_reg_cb get_reg, gdb_reg_cb set_reg,
gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
int num_regs, const char *xml, int g_pos);
/* The GDB remote protocol transfers values in target byte order. This means
* we can use the raw memory access routines to access the value buffer.
* Conveniently, these also handle the case where the buffer is mis-aligned.
/*
* The GDB remote protocol transfers values in target byte order. As
* the gdbstub may be batching up several register values we always
* append to the array.
*/
static inline int gdb_get_reg8(uint8_t *mem_buf, uint8_t val)
static inline int gdb_get_reg8(GByteArray *buf, uint8_t val)
{
stb_p(mem_buf, val);
g_byte_array_append(buf, &val, 1);
return 1;
}
static inline int gdb_get_reg16(uint8_t *mem_buf, uint16_t val)
static inline int gdb_get_reg16(GByteArray *buf, uint16_t val)
{
stw_p(mem_buf, val);
uint16_t to_word = tswap16(val);
g_byte_array_append(buf, (uint8_t *) &to_word, 2);
return 2;
}
static inline int gdb_get_reg32(uint8_t *mem_buf, uint32_t val)
static inline int gdb_get_reg32(GByteArray *buf, uint32_t val)
{
stl_p(mem_buf, val);
uint32_t to_long = tswap32(val);
g_byte_array_append(buf, (uint8_t *) &to_long, 4);
return 4;
}
static inline int gdb_get_reg64(uint8_t *mem_buf, uint64_t val)
static inline int gdb_get_reg64(GByteArray *buf, uint64_t val)
{
stq_p(mem_buf, val);
uint64_t to_quad = tswap64(val);
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
return 8;
}
static inline int gdb_get_reg128(GByteArray *buf, uint64_t val_hi,
uint64_t val_lo)
{
uint64_t to_quad;
#ifdef TARGET_WORDS_BIGENDIAN
to_quad = tswap64(val_hi);
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
to_quad = tswap64(val_lo);
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
#else
to_quad = tswap64(val_lo);
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
to_quad = tswap64(val_hi);
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
#endif
return 16;
}
/**
* gdb_get_reg_ptr: get pointer to start of last element
* @len: length of element
*
* This is a helper function to extract the pointer to the last
* element for additional processing. Some front-ends do additional
* dynamic swapping of the elements based on CPU state.
*/
static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
{
return buf->data + buf->len - len;
}
#if TARGET_LONG_BITS == 64
#define gdb_get_regl(buf, val) gdb_get_reg64(buf, val)
#define ldtul_p(addr) ldq_p(addr)

View File

@ -195,7 +195,7 @@ typedef struct CPUClass {
hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
void (*debug_excp_handler)(CPUState *cpu);

View File

@ -280,7 +280,7 @@ void alpha_cpu_do_interrupt(CPUState *cpu);
bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,

View File

@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int alpha_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;

View File

@ -195,9 +195,10 @@ static void arm_cpu_reset(CPUState *s)
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
/* and to the SVE instructions */
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
/* with maximum vector length */
env->vfp.zcr_el[1] = cpu_isar_feature(aa64_sve, cpu) ?
cpu->sve_max_vq - 1 : 0;
/* with reasonable vector length */
if (cpu_isar_feature(aa64_sve, cpu)) {
env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3);
}
/*
* Enable TBI0 and TBI1. While the real kernel only enables TBI0,
* turning on both here will produce smaller code and otherwise

View File

@ -128,14 +128,20 @@ enum {
/**
* DynamicGDBXMLInfo:
* @desc: Contains the XML descriptions.
* @num_cpregs: Number of the Coprocessor registers seen by GDB.
* @cpregs_keys: Array that contains the corresponding Key of
* a given cpreg with the same order of the cpreg in the XML description.
* @num: Number of the registers in this XML seen by GDB.
* @data: A union with data specific to the set of registers
* @cpregs_keys: Array that contains the corresponding Key of
* a given cpreg with the same order of the cpreg
* in the XML description.
*/
typedef struct DynamicGDBXMLInfo {
char *desc;
int num_cpregs;
uint32_t *cpregs_keys;
int num;
union {
struct {
uint32_t *keys;
} cpregs;
} data;
} DynamicGDBXMLInfo;
/* CPU state for each instance of a generic timer (in cp15 c14) */
@ -749,7 +755,8 @@ struct ARMCPU {
uint64_t *cpreg_vmstate_values;
int32_t cpreg_vmstate_array_len;
DynamicGDBXMLInfo dyn_xml;
DynamicGDBXMLInfo dyn_sysreg_xml;
DynamicGDBXMLInfo dyn_svereg_xml;
/* Timers used by the generic (architected) timer */
QEMUTimer *gt_timer[NUM_GTIMERS];
@ -968,13 +975,15 @@ bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
/* Dynamically generates for gdb stub an XML description of the sysregs from
* the cp_regs hashtable. Returns the registered sysregs number.
/*
* Helpers to dynamically generates XML descriptions of the sysregs
* and SVE registers. Returns the number of registers in each set.
*/
int arm_gen_dynamic_xml(CPUState *cpu);
int arm_gen_dynamic_sysreg_xml(CPUState *cpu, int base_reg);
int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
/* Returns the dynamically generated XML for the gdb stub.
* Returns a pointer to the XML contents for the specified XML file or NULL
@ -988,7 +997,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
#ifdef TARGET_AARCH64
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
void aarch64_sve_change_el(CPUARMState *env, int old_el,

View File

@ -24,6 +24,7 @@
typedef struct RegisterSysregXmlParam {
CPUState *cs;
GString *s;
int n;
} RegisterSysregXmlParam;
/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
@ -32,7 +33,7 @@ typedef struct RegisterSysregXmlParam {
We hack round this by giving the FPA regs zero size when talking to a
newer gdb. */
int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
@ -106,15 +107,16 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
static void arm_gen_one_xml_reg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
ARMCPRegInfo *ri, uint32_t ri_key,
int bitsize)
static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
ARMCPRegInfo *ri, uint32_t ri_key,
int bitsize, int regnum)
{
g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
g_string_append_printf(s, " regnum=\"%d\"", regnum);
g_string_append_printf(s, " group=\"cp_regs\"/>");
dyn_xml->num_cpregs++;
dyn_xml->cpregs_keys[dyn_xml->num_cpregs - 1] = ri_key;
dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
dyn_xml->num++;
}
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
@ -126,12 +128,13 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
GString *s = param->s;
ARMCPU *cpu = ARM_CPU(param->cs);
CPUARMState *env = &cpu->env;
DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_xml;
DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
if (ri->state == ARM_CP_STATE_AA64) {
arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
param->n++);
}
} else {
if (ri->state == ARM_CP_STATE_AA32) {
@ -140,38 +143,174 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
return;
}
if (ri->type & ARM_CP_64BIT) {
arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
param->n++);
} else {
arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 32);
arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
param->n++);
}
}
}
}
}
int arm_gen_dynamic_xml(CPUState *cs)
int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
{
ARMCPU *cpu = ARM_CPU(cs);
GString *s = g_string_new(NULL);
RegisterSysregXmlParam param = {cs, s};
RegisterSysregXmlParam param = {cs, s, base_reg};
cpu->dyn_xml.num_cpregs = 0;
cpu->dyn_xml.cpregs_keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
cpu->dyn_sysreg_xml.num = 0;
cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
g_string_printf(s, "<?xml version=\"1.0\"?>");
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
g_string_append_printf(s, "</feature>");
cpu->dyn_xml.desc = g_string_free(s, false);
return cpu->dyn_xml.num_cpregs;
cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
return cpu->dyn_sysreg_xml.num;
}
struct TypeSize {
const char *gdb_type;
int size;
const char sz, suffix;
};
static const struct TypeSize vec_lanes[] = {
/* quads */
{ "uint128", 128, 'q', 'u' },
{ "int128", 128, 'q', 's' },
/* 64 bit */
{ "uint64", 64, 'd', 'u' },
{ "int64", 64, 'd', 's' },
{ "ieee_double", 64, 'd', 'f' },
/* 32 bit */
{ "uint32", 32, 's', 'u' },
{ "int32", 32, 's', 's' },
{ "ieee_single", 32, 's', 'f' },
/* 16 bit */
{ "uint16", 16, 'h', 'u' },
{ "int16", 16, 'h', 's' },
{ "ieee_half", 16, 'h', 'f' },
/* bytes */
{ "uint8", 8, 'b', 'u' },
{ "int8", 8, 'b', 's' },
};
int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
{
ARMCPU *cpu = ARM_CPU(cs);
GString *s = g_string_new(NULL);
DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
g_autoptr(GString) ts = g_string_new("");
int i, bits, reg_width = (cpu->sve_max_vq * 128);
info->num = 0;
g_string_printf(s, "<?xml version=\"1.0\"?>");
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
g_string_append_printf(s, "<feature name=\"org.qemu.gdb.aarch64.sve\">");
/* First define types and totals in a whole VL */
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
int count = reg_width / vec_lanes[i].size;
g_string_printf(ts, "vq%d%c%c", count,
vec_lanes[i].sz, vec_lanes[i].suffix);
g_string_append_printf(s,
"<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
ts->str, vec_lanes[i].gdb_type, count);
}
/*
* Now define a union for each size group containing unsigned and
* signed and potentially float versions of each size from 128 to
* 8 bits.
*/
for (bits = 128; bits >= 8; bits /= 2) {
int count = reg_width / bits;
g_string_append_printf(s, "<union id=\"vq%dn\">", count);
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
if (vec_lanes[i].size == bits) {
g_string_append_printf(s, "<field name=\"%c\" type=\"vq%d%c%c\"/>",
vec_lanes[i].suffix,
count,
vec_lanes[i].sz, vec_lanes[i].suffix);
}
}
g_string_append(s, "</union>");
}
/* And now the final union of unions */
g_string_append(s, "<union id=\"vq\">");
for (bits = 128; bits >= 8; bits /= 2) {
int count = reg_width / bits;
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
if (vec_lanes[i].size == bits) {
g_string_append_printf(s, "<field name=\"%c\" type=\"vq%dn\"/>",
vec_lanes[i].sz, count);
break;
}
}
}
g_string_append(s, "</union>");
/* Then define each register in parts for each vq */
for (i = 0; i < 32; i++) {
g_string_append_printf(s,
"<reg name=\"z%d\" bitsize=\"%d\""
" regnum=\"%d\" group=\"vector\""
" type=\"vq\"/>",
i, reg_width, base_reg++);
info->num++;
}
/* fpscr & status registers */
g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
" regnum=\"%d\" group=\"float\""
" type=\"int\"/>", base_reg++);
g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
" regnum=\"%d\" group=\"float\""
" type=\"int\"/>", base_reg++);
info->num += 2;
/*
* Predicate registers aren't so big they are worth splitting up
* but we do need to define a type to hold the array of quad
* references.
*/
g_string_append_printf(s,
"<vector id=\"vqp\" type=\"uint16\" count=\"%d\"/>",
cpu->sve_max_vq);
for (i = 0; i < 16; i++) {
g_string_append_printf(s,
"<reg name=\"p%d\" bitsize=\"%d\""
" regnum=\"%d\" group=\"vector\""
" type=\"vqp\"/>",
i, cpu->sve_max_vq * 16, base_reg++);
info->num++;
}
g_string_append_printf(s,
"<reg name=\"ffr\" bitsize=\"%d\""
" regnum=\"%d\" group=\"vector\""
" type=\"vqp\"/>",
cpu->sve_max_vq * 16, base_reg++);
g_string_append_printf(s,
"<reg name=\"vg\" bitsize=\"64\""
" regnum=\"%d\" group=\"vector\""
" type=\"uint32\"/>",
base_reg++);
info->num += 2;
g_string_append_printf(s, "</feature>");
cpu->dyn_svereg_xml.desc = g_string_free(s, false);
return cpu->dyn_svereg_xml.num;
}
const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
{
ARMCPU *cpu = ARM_CPU(cs);
if (strcmp(xmlname, "system-registers.xml") == 0) {
return cpu->dyn_xml.desc;
return cpu->dyn_sysreg_xml.desc;
} else if (strcmp(xmlname, "sve-registers.xml") == 0) {
return cpu->dyn_svereg_xml.desc;
}
return NULL;
}

View File

@ -20,7 +20,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int aarch64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;

View File

@ -48,30 +48,27 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
static void switch_mode(CPUARMState *env, int mode);
static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
{
ARMCPU *cpu = env_archcpu(env);
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
/* VFP data registers are always little-endian. */
if (reg < nregs) {
stq_le_p(buf, *aa32_vfp_dreg(env, reg));
return 8;
return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
}
if (arm_feature(env, ARM_FEATURE_NEON)) {
/* Aliases for Q regs. */
nregs += 16;
if (reg < nregs) {
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
stq_le_p(buf, q[0]);
stq_le_p(buf + 8, q[1]);
return 16;
return gdb_get_reg128(buf, q[0], q[1]);
}
}
switch (reg - nregs) {
case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
case 1: stl_p(buf, vfp_get_fpscr(env)); return 4;
case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
case 0: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); break;
case 1: return gdb_get_reg32(buf, vfp_get_fpscr(env)); break;
case 2: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); break;
}
return 0;
}
@ -102,25 +99,21 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
{
switch (reg) {
case 0 ... 31:
/* 128 bit FP register */
{
uint64_t *q = aa64_vfp_qreg(env, reg);
stq_le_p(buf, q[0]);
stq_le_p(buf + 8, q[1]);
return 16;
}
{
/* 128 bit FP register - quads are in LE order */
uint64_t *q = aa64_vfp_qreg(env, reg);
return gdb_get_reg128(buf, q[1], q[0]);
}
case 32:
/* FPSR */
stl_p(buf, vfp_get_fpsr(env));
return 4;
return gdb_get_reg32(buf, vfp_get_fpsr(env));
case 33:
/* FPCR */
stl_p(buf, vfp_get_fpcr(env));
return 4;
return gdb_get_reg32(buf,vfp_get_fpcr(env));
default:
return 0;
}
@ -209,13 +202,22 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
}
}
static int arm_gdb_get_sysreg(CPUARMState *env, uint8_t *buf, int reg)
/**
* arm_get/set_gdb_*: get/set a gdb register
* @env: the CPU state
* @buf: a buffer to copy to/from
* @reg: register number (offset from start of group)
*
* We return the number of bytes copied
*/
static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
{
ARMCPU *cpu = env_archcpu(env);
const ARMCPRegInfo *ri;
uint32_t key;
key = cpu->dyn_xml.cpregs_keys[reg];
key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
ri = get_arm_cp_reginfo(cpu->cp_regs, key);
if (ri) {
if (cpreg_field_is_64bit(ri)) {
@ -232,6 +234,102 @@ static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
#ifdef TARGET_AARCH64
static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
{
ARMCPU *cpu = env_archcpu(env);
switch (reg) {
/* The first 32 registers are the zregs */
case 0 ... 31:
{
int vq, len = 0;
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
len += gdb_get_reg128(buf,
env->vfp.zregs[reg].d[vq * 2 + 1],
env->vfp.zregs[reg].d[vq * 2]);
}
return len;
}
case 32:
return gdb_get_reg32(buf, vfp_get_fpsr(env));
case 33:
return gdb_get_reg32(buf, vfp_get_fpcr(env));
/* then 16 predicates and the ffr */
case 34 ... 50:
{
int preg = reg - 34;
int vq, len = 0;
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
}
return len;
}
case 51:
{
/*
* We report in Vector Granules (VG) which is 64bit in a Z reg
* while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
*/
int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
return gdb_get_reg32(buf, vq * 2);
}
default:
/* gdbstub asked for something out our range */
qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
break;
}
return 0;
}
static int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
{
ARMCPU *cpu = env_archcpu(env);
/* The first 32 registers are the zregs */
switch (reg) {
/* The first 32 registers are the zregs */
case 0 ... 31:
{
int vq, len = 0;
uint64_t *p = (uint64_t *) buf;
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
env->vfp.zregs[reg].d[vq * 2] = *p++;
len += 16;
}
return len;
}
case 32:
vfp_set_fpsr(env, *(uint32_t *)buf);
return 4;
case 33:
vfp_set_fpcr(env, *(uint32_t *)buf);
return 4;
case 34 ... 50:
{
int preg = reg - 34;
int vq, len = 0;
uint64_t *p = (uint64_t *) buf;
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
env->vfp.pregs[preg].p[vq / 4] = *p++;
len += 8;
}
return len;
}
case 51:
/* cannot set vg via gdbstub */
return 0;
default:
/* gdbstub asked for something out our range */
break;
}
return 0;
}
#endif /* TARGET_AARCH64 */
static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
{
/* Return true if the regdef would cause an assertion if you called
@ -6599,6 +6697,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
return pfr1;
}
#ifndef CONFIG_USER_ONLY
static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
ARMCPU *cpu = env_archcpu(env);
@ -6609,6 +6708,7 @@ static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
return pfr0;
}
#endif
/* Shared logic between LORID and the rest of the LOR* registers.
* Secure state has already been delt with.
@ -7182,16 +7282,24 @@ void register_cp_regs_for_features(ARMCPU *cpu)
* define new registers here.
*/
ARMCPRegInfo v8_idregs[] = {
/* ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST because we don't
* know the right value for the GIC field until after we
* define these regs.
/*
* ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST in system
* emulation because we don't know the right value for the
* GIC field until after we define these regs.
*/
{ .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
.access = PL1_R, .type = ARM_CP_NO_RAW,
.access = PL1_R,
#ifdef CONFIG_USER_ONLY
.type = ARM_CP_CONST,
.resetvalue = cpu->isar.id_aa64pfr0
#else
.type = ARM_CP_NO_RAW,
.accessfn = access_aa64_tid3,
.readfn = id_aa64pfr0_read,
.writefn = arm_cp_write_ignore },
.writefn = arm_cp_write_ignore
#endif
},
{ .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST,
@ -7966,9 +8074,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
CPUARMState *env = &cpu->env;
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
aarch64_fpu_gdb_set_reg,
34, "aarch64-fpu.xml", 0);
/*
* The lower part of each SVE register aliases to the FPU
* registers so we don't need to include both.
*/
#ifdef TARGET_AARCH64
if (isar_feature_aa64_sve(&cpu->isar)) {
gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
"sve-registers.xml", 0);
} else
#endif
{
gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
aarch64_fpu_gdb_set_reg,
34, "aarch64-fpu.xml", 0);
}
} else if (arm_feature(env, ARM_FEATURE_NEON)) {
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
51, "arm-neon.xml", 0);
@ -7980,8 +8101,9 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
19, "arm-vfp.xml", 0);
}
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
arm_gen_dynamic_xml(cs),
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
"system-registers.xml", 0);
}
/* Sort alphabetically by type name, except for "any". */

View File

@ -195,8 +195,8 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int crisv10_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int cris_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
/* you can call this signal handler from your SIGBUS and SIGSEGV

View File

@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
@ -53,7 +53,7 @@ int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
int cris_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;

View File

@ -321,7 +321,7 @@ void cpu_hppa_change_prot_id(CPUHPPAState *env);
int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void hppa_cpu_do_interrupt(CPUState *cpu);
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);

View File

@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int hppa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;

View File

@ -1766,7 +1766,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr x86_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
int x86_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int x86_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void x86_cpu_exec_enter(CPUState *cpu);

View File

@ -79,7 +79,7 @@ static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
#endif
int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
@ -98,26 +98,22 @@ int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
return gdb_get_reg64(mem_buf,
env->regs[gpr_map[n]] & 0xffffffffUL);
} else {
memset(mem_buf, 0, sizeof(target_ulong));
return sizeof(target_ulong);
return gdb_get_regl(mem_buf, 0);
}
} else {
return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
}
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
#ifdef USE_X86LDOUBLE
/* FIXME: byteswap float values - after fixing fpregs layout. */
memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
#else
memset(mem_buf, 0, 10);
#endif
return 10;
floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
int len = gdb_get_reg64(mem_buf, cpu_to_le64(fp->low));
len += gdb_get_reg16(mem_buf + len, cpu_to_le16(fp->high));
return len;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
stq_p(mem_buf, env->xmm_regs[n].ZMM_Q(0));
stq_p(mem_buf + 8, env->xmm_regs[n].ZMM_Q(1));
return 16;
return gdb_get_reg128(mem_buf,
env->xmm_regs[n].ZMM_Q(0),
env->xmm_regs[n].ZMM_Q(1));
}
} else {
switch (n) {
@ -290,10 +286,9 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 4;
}
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
#ifdef USE_X86LDOUBLE
/* FIXME: byteswap float values - after fixing fpregs layout. */
memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
#endif
floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
fp->low = le64_to_cpu(* (uint64_t *) mem_buf);
fp->high = le16_to_cpu(* (uint16_t *) (mem_buf + 8));
return 10;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;

View File

@ -202,7 +202,7 @@ void lm32_cpu_do_interrupt(CPUState *cpu);
bool lm32_cpu_exec_interrupt(CPUState *cs, int int_req);
void lm32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int lm32_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int lm32_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int lm32_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
typedef enum {

View File

@ -22,7 +22,7 @@
#include "exec/gdbstub.h"
#include "hw/lm32/lm32_pic.h"
int lm32_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int lm32_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
LM32CPU *cpu = LM32_CPU(cs);
CPULM32State *env = &cpu->env;

View File

@ -168,7 +168,7 @@ void m68k_cpu_do_interrupt(CPUState *cpu);
bool m68k_cpu_exec_interrupt(CPUState *cpu, int int_req);
void m68k_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int m68k_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int m68k_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void m68k_tcg_init(void);

View File

@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int m68k_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int m68k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
M68kCPU *cpu = M68K_CPU(cs);
CPUM68KState *env = &cpu->env;

View File

@ -68,23 +68,19 @@ void m68k_cpu_list(void)
g_slist_free(list);
}
static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
static int cf_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n)
{
if (n < 8) {
float_status s;
stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
return 8;
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
}
switch (n) {
case 8: /* fpcontrol */
stl_be_p(mem_buf, env->fpcr);
return 4;
return gdb_get_reg32(mem_buf, env->fpcr);
case 9: /* fpstatus */
stl_be_p(mem_buf, env->fpsr);
return 4;
return gdb_get_reg32(mem_buf, env->fpsr);
case 10: /* fpiar, not implemented */
memset(mem_buf, 0, 4);
return 4;
return gdb_get_reg32(mem_buf, 0);
}
return 0;
}
@ -109,24 +105,21 @@ static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
return 0;
}
static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
static int m68k_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n)
{
if (n < 8) {
stw_be_p(mem_buf, env->fregs[n].l.upper);
memset(mem_buf + 2, 0, 2);
stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
return 12;
int len = gdb_get_reg16(mem_buf, env->fregs[n].l.upper);
len += gdb_get_reg16(mem_buf + len, 0);
len += gdb_get_reg64(mem_buf + len, env->fregs[n].l.lower);
return len;
}
switch (n) {
case 8: /* fpcontrol */
stl_be_p(mem_buf, env->fpcr);
return 4;
return gdb_get_reg32(mem_buf, env->fpcr);
case 9: /* fpstatus */
stl_be_p(mem_buf, env->fpsr);
return 4;
return gdb_get_reg32(mem_buf, env->fpsr);
case 10: /* fpiar, not implemented */
memset(mem_buf, 0, 4);
return 4;
return gdb_get_reg32(mem_buf, 0);
}
return 0;
}

View File

@ -313,7 +313,7 @@ void mb_cpu_do_interrupt(CPUState *cs);
bool mb_cpu_exec_interrupt(CPUState *cs, int int_req);
void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int mb_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void mb_tcg_init(void);

View File

@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int mb_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;

View File

@ -22,7 +22,7 @@
#include "internal.h"
#include "exec/gdbstub.h"
int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;

View File

@ -82,7 +82,7 @@ void mips_cpu_do_interrupt(CPUState *cpu);
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,

View File

@ -124,7 +124,7 @@ static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
#endif
}
static int nios2_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
Nios2CPU *cpu = NIOS2_CPU(cs);
CPUClass *cc = CPU_GET_CLASS(cs);

View File

@ -320,7 +320,7 @@ void openrisc_cpu_do_interrupt(CPUState *cpu);
bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int openrisc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void openrisc_translate_init(void);
bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,

View File

@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int openrisc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
CPUOpenRISCState *env = &cpu->env;

View File

@ -1207,8 +1207,8 @@ bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
void ppc_cpu_dump_statistics(CPUState *cpu, int flags);
hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_read_register_apple(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int ppc_cpu_gdb_read_register_apple(CPUState *cpu, GByteArray *buf, int reg);
int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
#ifndef CONFIG_USER_ONLY

View File

@ -114,10 +114,11 @@ void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
* the FP regs zero size when talking to a newer gdb.
*/
int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
uint8_t *mem_buf;
int r = ppc_gdb_register_len(n);
if (!r) {
@ -126,17 +127,17 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
if (n < 32) {
/* gprs */
gdb_get_regl(mem_buf, env->gpr[n]);
gdb_get_regl(buf, env->gpr[n]);
} else if (n < 64) {
/* fprs */
stfq_p(mem_buf, *cpu_fpr_ptr(env, n - 32));
gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32));
} else {
switch (n) {
case 64:
gdb_get_regl(mem_buf, env->nip);
gdb_get_regl(buf, env->nip);
break;
case 65:
gdb_get_regl(mem_buf, env->msr);
gdb_get_regl(buf, env->msr);
break;
case 66:
{
@ -145,31 +146,33 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
for (i = 0; i < 8; i++) {
cr |= env->crf[i] << (32 - ((i + 1) * 4));
}
gdb_get_reg32(mem_buf, cr);
gdb_get_reg32(buf, cr);
break;
}
case 67:
gdb_get_regl(mem_buf, env->lr);
gdb_get_regl(buf, env->lr);
break;
case 68:
gdb_get_regl(mem_buf, env->ctr);
gdb_get_regl(buf, env->ctr);
break;
case 69:
gdb_get_reg32(mem_buf, env->xer);
gdb_get_reg32(buf, env->xer);
break;
case 70:
gdb_get_reg32(mem_buf, env->fpscr);
gdb_get_reg32(buf, env->fpscr);
break;
}
}
mem_buf = buf->data + buf->len - r;
ppc_maybe_bswap_register(env, mem_buf, r);
return r;
}
int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
uint8_t *mem_buf;
int r = ppc_gdb_register_len_apple(n);
if (!r) {
@ -178,21 +181,21 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
if (n < 32) {
/* gprs */
gdb_get_reg64(mem_buf, env->gpr[n]);
gdb_get_reg64(buf, env->gpr[n]);
} else if (n < 64) {
/* fprs */
stfq_p(mem_buf, *cpu_fpr_ptr(env, n - 32));
gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32));
} else if (n < 96) {
/* Altivec */
stq_p(mem_buf, n - 64);
stq_p(mem_buf + 8, 0);
gdb_get_reg64(buf, n - 64);
gdb_get_reg64(buf, 0);
} else {
switch (n) {
case 64 + 32:
gdb_get_reg64(mem_buf, env->nip);
gdb_get_reg64(buf, env->nip);
break;
case 65 + 32:
gdb_get_reg64(mem_buf, env->msr);
gdb_get_reg64(buf, env->msr);
break;
case 66 + 32:
{
@ -201,23 +204,24 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
for (i = 0; i < 8; i++) {
cr |= env->crf[i] << (32 - ((i + 1) * 4));
}
gdb_get_reg32(mem_buf, cr);
gdb_get_reg32(buf, cr);
break;
}
case 67 + 32:
gdb_get_reg64(mem_buf, env->lr);
gdb_get_reg64(buf, env->lr);
break;
case 68 + 32:
gdb_get_reg64(mem_buf, env->ctr);
gdb_get_reg64(buf, env->ctr);
break;
case 69 + 32:
gdb_get_reg32(mem_buf, env->xer);
gdb_get_reg32(buf, env->xer);
break;
case 70 + 32:
gdb_get_reg64(mem_buf, env->fpscr);
gdb_get_reg64(buf, env->fpscr);
break;
}
}
mem_buf = buf->data + buf->len - r;
ppc_maybe_bswap_register(env, mem_buf, r);
return r;
}

View File

@ -9843,7 +9843,7 @@ static int gdb_find_spr_idx(CPUPPCState *env, int n)
return -1;
}
static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
static int gdb_get_spr_reg(CPUPPCState *env, GByteArray *buf, int n)
{
int reg;
int len;
@ -9854,8 +9854,8 @@ static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
}
len = TARGET_LONG_SIZE;
stn_p(mem_buf, len, env->spr[reg]);
ppc_maybe_bswap_register(env, mem_buf, len);
gdb_get_regl(buf, env->spr[reg]);
ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, len), len);
return len;
}
@ -9877,15 +9877,18 @@ static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
}
#endif
static int gdb_get_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
static int gdb_get_float_reg(CPUPPCState *env, GByteArray *buf, int n)
{
uint8_t *mem_buf;
if (n < 32) {
stfq_p(mem_buf, *cpu_fpr_ptr(env, n));
gdb_get_reg64(buf, *cpu_fpr_ptr(env, n));
mem_buf = gdb_get_reg_ptr(buf, 8);
ppc_maybe_bswap_register(env, mem_buf, 8);
return 8;
}
if (n == 32) {
stl_p(mem_buf, env->fpscr);
gdb_get_reg32(buf, env->fpscr);
mem_buf = gdb_get_reg_ptr(buf, 4);
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
@ -9907,28 +9910,31 @@ static int gdb_set_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
static int gdb_get_avr_reg(CPUPPCState *env, GByteArray *buf, int n)
{
uint8_t *mem_buf;
if (n < 32) {
ppc_avr_t *avr = cpu_avr_ptr(env, n);
if (!avr_need_swap(env)) {
stq_p(mem_buf, avr->u64[0]);
stq_p(mem_buf + 8, avr->u64[1]);
gdb_get_reg128(buf, avr->u64[0] , avr->u64[1]);
} else {
stq_p(mem_buf, avr->u64[1]);
stq_p(mem_buf + 8, avr->u64[0]);
gdb_get_reg128(buf, avr->u64[1] , avr->u64[0]);
}
mem_buf = gdb_get_reg_ptr(buf, 16);
ppc_maybe_bswap_register(env, mem_buf, 8);
ppc_maybe_bswap_register(env, mem_buf + 8, 8);
return 16;
}
if (n == 32) {
stl_p(mem_buf, helper_mfvscr(env));
gdb_get_reg32(buf, helper_mfvscr(env));
mem_buf = gdb_get_reg_ptr(buf, 4);
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
if (n == 33) {
stl_p(mem_buf, (uint32_t)env->spr[SPR_VRSAVE]);
gdb_get_reg32(buf, (uint32_t)env->spr[SPR_VRSAVE]);
mem_buf = gdb_get_reg_ptr(buf, 4);
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
@ -9963,25 +9969,25 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
static int gdb_get_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
static int gdb_get_spe_reg(CPUPPCState *env, GByteArray *buf, int n)
{
if (n < 32) {
#if defined(TARGET_PPC64)
stl_p(mem_buf, env->gpr[n] >> 32);
ppc_maybe_bswap_register(env, mem_buf, 4);
gdb_get_reg32(buf, env->gpr[n] >> 32);
ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4);
#else
stl_p(mem_buf, env->gprh[n]);
gdb_get_reg32(buf, env->gprh[n]);
#endif
return 4;
}
if (n == 32) {
stq_p(mem_buf, env->spe_acc);
ppc_maybe_bswap_register(env, mem_buf, 8);
gdb_get_reg64(buf, env->spe_acc);
ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8);
return 8;
}
if (n == 33) {
stl_p(mem_buf, env->spe_fscr);
ppc_maybe_bswap_register(env, mem_buf, 4);
gdb_get_reg32(buf, env->spe_fscr);
ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4);
return 4;
}
return 0;
@ -10016,11 +10022,11 @@ static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
static int gdb_get_vsx_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
static int gdb_get_vsx_reg(CPUPPCState *env, GByteArray *buf, int n)
{
if (n < 32) {
stq_p(mem_buf, *cpu_vsrl_ptr(env, n));
ppc_maybe_bswap_register(env, mem_buf, 8);
gdb_get_reg64(buf, *cpu_vsrl_ptr(env, n));
ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8);
return 8;
}
return 0;

View File

@ -293,7 +293,7 @@ extern const char * const riscv_excp_names[];
extern const char * const riscv_intr_names[];
void riscv_cpu_do_interrupt(CPUState *cpu);
int riscv_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
bool riscv_cpu_fp_enabled(CPURISCVState *env);

View File

@ -270,7 +270,7 @@ static int csr_register_map[] = {
CSR_MHCOUNTEREN,
};
int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
@ -301,14 +301,14 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n)
{
if (n < 32) {
if (env->misa & RVD) {
return gdb_get_reg64(mem_buf, env->fpr[n]);
return gdb_get_reg64(buf, env->fpr[n]);
}
if (env->misa & RVF) {
return gdb_get_reg32(mem_buf, env->fpr[n]);
return gdb_get_reg32(buf, env->fpr[n]);
}
/* there is hole between ft11 and fflags in fpu.xml */
} else if (n < 36 && n > 32) {
@ -322,7 +322,7 @@ static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
result = riscv_csrrw_debug(env, n - 33 + csr_register_map[8], &val,
0, 0);
if (result == 0) {
return gdb_get_regl(mem_buf, val);
return gdb_get_regl(buf, val);
}
}
return 0;
@ -351,7 +351,7 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}
static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
{
if (n < ARRAY_SIZE(csr_register_map)) {
target_ulong val = 0;
@ -359,7 +359,7 @@ static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
result = riscv_csrrw_debug(env, csr_register_map[n], &val, 0, 0);
if (result == 0) {
return gdb_get_regl(mem_buf, val);
return gdb_get_regl(buf, val);
}
}
return 0;
@ -379,13 +379,13 @@ static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}
static int riscv_gdb_get_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
static int riscv_gdb_get_virtual(CPURISCVState *cs, GByteArray *buf, int n)
{
if (n == 0) {
#ifdef CONFIG_USER_ONLY
return gdb_get_regl(mem_buf, 0);
return gdb_get_regl(buf, 0);
#else
return gdb_get_regl(mem_buf, cs->priv);
return gdb_get_regl(buf, cs->priv);
#endif
}
return 0;

View File

@ -27,7 +27,7 @@
#include "sysemu/hw_accel.h"
#include "sysemu/tcg.h"
int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
@ -82,11 +82,11 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
/* total number of registers in s390-acr.xml */
#define S390_NUM_AC_REGS 16
static int cpu_read_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n)
{
switch (n) {
case S390_A0_REGNUM ... S390_A15_REGNUM:
return gdb_get_reg32(mem_buf, env->aregs[n]);
return gdb_get_reg32(buf, env->aregs[n]);
default:
return 0;
}
@ -111,13 +111,13 @@ static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-fpr.xml */
#define S390_NUM_FP_REGS 17
static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n)
{
switch (n) {
case S390_FPC_REGNUM:
return gdb_get_reg32(mem_buf, env->fpc);
return gdb_get_reg32(buf, env->fpc);
case S390_F0_REGNUM ... S390_F15_REGNUM:
return gdb_get_reg64(mem_buf, *get_freg(env, n - S390_F0_REGNUM));
return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM));
default:
return 0;
}
@ -145,17 +145,17 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* 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)
static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n)
{
int ret;
switch (n) {
case S390_V0L_REGNUM ... S390_V15L_REGNUM:
ret = gdb_get_reg64(mem_buf, env->vregs[n][1]);
ret = gdb_get_reg64(buf, env->vregs[n][1]);
break;
case S390_V16_REGNUM ... S390_V31_REGNUM:
ret = gdb_get_reg64(mem_buf, env->vregs[n][0]);
ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1]);
ret = gdb_get_reg64(buf, env->vregs[n][0]);
ret += gdb_get_reg64(buf, env->vregs[n][1]);
break;
default:
ret = 0;
@ -186,11 +186,11 @@ static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
#define S390_NUM_C_REGS 16
#ifndef CONFIG_USER_ONLY
static int cpu_read_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n)
{
switch (n) {
case S390_C0_REGNUM ... S390_C15_REGNUM:
return gdb_get_regl(mem_buf, env->cregs[n]);
return gdb_get_regl(buf, env->cregs[n]);
default:
return 0;
}
@ -223,7 +223,7 @@ static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-virt.xml */
#define S390_NUM_VIRT_REGS 8
static int cpu_read_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
{
switch (n) {
case S390_VIRT_CKC_REGNUM:
@ -296,9 +296,9 @@ static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-gs.xml */
#define S390_NUM_GS_REGS 4
static int cpu_read_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n)
{
return gdb_get_regl(mem_buf, env->gscb[n]);
return gdb_get_regl(buf, env->gscb[n]);
}
static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n)

View File

@ -292,7 +292,7 @@ uint16_t float128_dcmask(CPUS390XState *env, float128 f1);
/* gdbstub.c */
int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int s390_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void s390_cpu_gdb_init(CPUState *cs);

View File

@ -208,7 +208,7 @@ void superh_cpu_do_interrupt(CPUState *cpu);
bool superh_cpu_exec_interrupt(CPUState *cpu, int int_req);
void superh_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int superh_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int superh_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,

View File

@ -24,7 +24,7 @@
/* Hint: Use "set architecture sh4" in GDB to see fpu registers */
/* FIXME: We should use XML for this. */
int superh_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int superh_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
SuperHCPU *cpu = SUPERH_CPU(cs);
CPUSH4State *env = &cpu->env;

View File

@ -571,7 +571,7 @@ extern const VMStateDescription vmstate_sparc_cpu;
void sparc_cpu_do_interrupt(CPUState *cpu);
void sparc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int sparc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int sparc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,

View File

@ -27,7 +27,7 @@
#define gdb_get_rega(buf, val) gdb_get_regl(buf, val)
#endif
int sparc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;

View File

@ -569,7 +569,7 @@ void xtensa_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
void xtensa_count_regs(const XtensaConfig *config,
unsigned *n_regs, unsigned *n_core_regs);
int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int xtensa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,

View File

@ -63,7 +63,7 @@ void xtensa_count_regs(const XtensaConfig *config,
}
}
int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
XtensaCPU *cpu = XTENSA_CPU(cs);
CPUXtensaState *env = &cpu->env;

1
tests/.gitignore vendored
View File

@ -10,6 +10,7 @@ qht-bench
rcutorture
test-*
!test-*.c
!test-*.py
!docker/test-*
test-qapi-commands.[ch]
test-qapi-init-commands.[ch]

View File

@ -28,9 +28,9 @@ RUN apt update && \
libegl1-mesa-dev \
libepoxy-dev \
libgbm-dev
RUN git clone https://anongit.freedesktop.org/git/virglrenderer.git /usr/src/virglrenderer && \
cd /usr/src/virglrenderer && git checkout virglrenderer-0.7.0
RUN cd /usr/src/virglrenderer && ./autogen.sh && ./configure --with-glx --disable-tests && make install
RUN git clone https://gitlab.freedesktop.org/virgl/virglrenderer.git /usr/src/virglrenderer && \
cd /usr/src/virglrenderer && git checkout virglrenderer-0.8.0
RUN cd /usr/src/virglrenderer && ./autogen.sh && ./configure --disable-tests && make install
# netmap
RUN apt update && \

View File

@ -17,14 +17,17 @@ RUN apt update && \
DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
bc \
bison \
build-essential \
ca-certificates \
clang \
dbus \
flex \
gdb-multiarch \
gettext \
git \
libncurses5-dev \
pkg-config \
psmisc \
python3 \

View File

@ -17,13 +17,16 @@ RUN apt update && \
DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
bc \
bison \
build-essential \
ca-certificates \
clang \
flex \
gdb-multiarch \
gettext \
git \
libncurses5-dev \
pkg-config \
psmisc \
python3 \

57
tests/guest-debug/run-test.py Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env python3
#
# Run a gdbstub test case
#
# Copyright (c) 2019 Linaro
#
# Author: Alex Bennée <alex.bennee@linaro.org>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later.
# See the COPYING file in the top-level directory.
#
# SPDX-License-Identifier: GPL-2.0-or-later
import argparse
import subprocess
import shutil
import shlex
def get_args():
parser = argparse.ArgumentParser(description="A gdbstub test runner")
parser.add_argument("--qemu", help="Qemu binary for test",
required=True)
parser.add_argument("--qargs", help="Qemu arguments for test")
parser.add_argument("--binary", help="Binary to debug",
required=True)
parser.add_argument("--test", help="GDB test script",
required=True)
parser.add_argument("--gdb", help="The gdb binary to use", default=None)
return parser.parse_args()
if __name__ == '__main__':
args = get_args()
# Search for a gdb we can use
if not args.gdb:
args.gdb = shutil.which("gdb-multiarch")
if not args.gdb:
args.gdb = shutil.which("gdb")
if not args.gdb:
print("We need gdb to run the test")
exit(-1)
# Launch QEMU with binary
if "system" in args.qemu:
cmd = "%s %s %s -s -S" % (args.qemu, args.qargs, args.binary)
else:
cmd = "%s %s -g 1234 %s" % (args.qemu, args.qargs, args.binary)
inferior = subprocess.Popen(shlex.split(cmd))
# Now launch gdb with our test and collect the result
gdb_cmd = "%s %s -ex 'target remote localhost:1234' -x %s" % (args.gdb, args.binary, args.test)
result = subprocess.call(gdb_cmd, shell=True);
exit(result)

View File

@ -42,4 +42,36 @@ run-semiconsole: semiconsole
run-plugin-semiconsole-with-%:
$(call skip-test, $<, "MANUAL ONLY")
ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_SVE),)
# System Registers Tests
AARCH64_TESTS += sysregs
sysregs: CFLAGS+=-march=armv8.1-a+sve
# SVE ioctl test
AARCH64_TESTS += sve-ioctls
sve-ioctls: CFLAGS+=-march=armv8.1-a+sve
ifneq ($(HAVE_GDB_BIN),)
GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py
AARCH64_TESTS += gdbstub-sysregs gdbstub-sve-ioctls
.PHONY: gdbstub-sysregs gdbstub-sve-ioctls
run-gdbstub-sysregs: sysregs
$(call run-test, $@, $(GDB_SCRIPT) \
--gdb $(HAVE_GDB_BIN) \
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
--bin $< --test $(AARCH64_SRC)/gdbstub/test-sve.py, \
"basic gdbstub SVE support")
run-gdbstub-sve-ioctls: sve-ioctls
$(call run-test, $@, $(GDB_SCRIPT) \
--gdb $(HAVE_GDB_BIN) \
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
--bin $< --test $(AARCH64_SRC)/gdbstub/test-sve-ioctl.py, \
"basic gdbstub SVE ZLEN support")
endif
endif
TESTS += $(AARCH64_TESTS)

View File

@ -0,0 +1,85 @@
from __future__ import print_function
#
# Test the SVE ZReg reports the right amount of data. It uses the
# sve-ioctl test and examines the register data each time the
# __sve_ld_done breakpoint is hit.
#
# This is launched via tests/guest-debug/run-test.py
#
import gdb
import sys
initial_vlen = 0
failcount = 0
def report(cond, msg):
"Report success/fail of test"
if cond:
print ("PASS: %s" % (msg))
else:
print ("FAIL: %s" % (msg))
global failcount
failcount += 1
class TestBreakpoint(gdb.Breakpoint):
def __init__(self, sym_name="__sve_ld_done"):
super(TestBreakpoint, self).__init__(sym_name)
# self.sym, ok = gdb.lookup_symbol(sym_name)
def stop(self):
val_i = gdb.parse_and_eval('i')
global initial_vlen
try:
for i in range(0, int(val_i)):
val_z = gdb.parse_and_eval("$z0.b.u[%d]" % i)
report(int(val_z) == i, "z0.b.u[%d] == %d" % (i, i))
for i in range(i + 1, initial_vlen):
val_z = gdb.parse_and_eval("$z0.b.u[%d]" % i)
report(int(val_z) == 0, "z0.b.u[%d] == 0" % (i))
except gdb.error:
report(False, "checking zregs (out of range)")
def run_test():
"Run through the tests one by one"
print ("Setup breakpoint")
bp = TestBreakpoint()
global initial_vlen
vg = gdb.parse_and_eval("$vg")
initial_vlen = int(vg) * 8
gdb.execute("c")
#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
if inferior.was_attached == False:
print("SKIPPING (failed to attach)", file=sys.stderr)
exit(0)
arch = inferior.architecture()
report(arch.name() == "aarch64", "connected to aarch64")
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)
try:
# These are not very useful in scripts
gdb.execute("set pagination off")
gdb.execute("set confirm off")
# Run the actual tests
run_test()
except:
print ("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
import code
code.InteractiveConsole(locals=globals()).interact()
raise
print("All tests complete: %d failures" % failcount)
exit(failcount)

View File

@ -0,0 +1,84 @@
from __future__ import print_function
#
# Test the SVE registers are visable and changeable via gdbstub
#
# This is launched via tests/guest-debug/run-test.py
#
import gdb
import sys
MAGIC = 0xDEADBEEF
failcount = 0
def report(cond, msg):
"Report success/fail of test"
if cond:
print ("PASS: %s" % (msg))
else:
print ("FAIL: %s" % (msg))
global failcount
failcount += 1
def run_test():
"Run through the tests one by one"
gdb.execute("info registers")
report(True, "info registers")
gdb.execute("info registers vector")
report(True, "info registers vector")
# Now all the zregs
frame = gdb.selected_frame()
for i in range(0, 32):
rname = "z%d" % (i)
zreg = frame.read_register(rname)
report(True, "Reading %s" % rname)
for j in range(0, 4):
cmd = "set $%s.q.u[%d] = 0x%x" % (rname, j, MAGIC)
gdb.execute(cmd)
report(True, "%s" % cmd)
for j in range(0, 4):
reg = "$%s.q.u[%d]" % (rname, j)
v = gdb.parse_and_eval(reg)
report(str(v.type) == "uint128_t", "size of %s" % (reg))
for j in range(0, 8):
cmd = "set $%s.d.u[%d] = 0x%x" % (rname, j, MAGIC)
gdb.execute(cmd)
report(True, "%s" % cmd)
for j in range(0, 8):
reg = "$%s.d.u[%d]" % (rname, j)
v = gdb.parse_and_eval(reg)
report(str(v.type) == "uint64_t", "size of %s" % (reg))
report(int(v) == MAGIC, "%s is 0x%x" % (reg, MAGIC))
#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
if inferior.was_attached == False:
print("SKIPPING (failed to attach)", file=sys.stderr)
exit(0)
arch = inferior.architecture()
report(arch.name() == "aarch64", "connected to aarch64")
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)
try:
# These are not very useful in scripts
gdb.execute("set pagination off")
gdb.execute("set confirm off")
# Run the actual tests
run_test()
except:
print ("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
print("All tests complete: %d failures" % failcount)
exit(failcount)

View File

@ -0,0 +1,70 @@
/*
* SVE ioctls tests
*
* Test the SVE width setting ioctls work and provide a base for
* testing the gdbstub.
*
* Copyright (c) 2019 Linaro Ltd
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <sys/prctl.h>
#include <asm/hwcap.h>
#include <stdio.h>
#include <sys/auxv.h>
#include <stdint.h>
#include <stdlib.h>
#ifndef HWCAP_CPUID
#define HWCAP_CPUID (1 << 11)
#endif
#define SVE_MAX_QUADS (2048 / 128)
#define BYTES_PER_QUAD (128 / 8)
#define get_cpu_reg(id) ({ \
unsigned long __val; \
asm("mrs %0, "#id : "=r" (__val)); \
__val; \
})
static int do_sve_ioctl_test(void)
{
int i, res, init_vq;
res = prctl(PR_SVE_GET_VL, 0, 0, 0, 0);
if (res < 0) {
printf("FAILED to PR_SVE_GET_VL (%d)", res);
return -1;
}
init_vq = res & PR_SVE_VL_LEN_MASK;
for (i = init_vq; i > 15; i /= 2) {
printf("Checking PR_SVE_SET_VL=%d\n", i);
res = prctl(PR_SVE_SET_VL, i, 0, 0, 0, 0);
if (res < 0) {
printf("FAILED to PR_SVE_SET_VL (%d)", res);
return -1;
}
asm("index z0.b, #0, #1\n"
".global __sve_ld_done\n"
"__sve_ld_done:\n"
"mov z0.b, #0\n"
: /* no outputs kept */
: /* no inputs */
: "memory", "z0");
}
printf("PASS\n");
return 0;
}
int main(int argc, char **argv)
{
/* we also need to probe for the ioctl support */
if (getauxval(AT_HWCAP) & HWCAP_SVE) {
return do_sve_ioctl_test();
} else {
printf("SKIP: no HWCAP_SVE on this system\n");
return 0;
}
}

172
tests/tcg/aarch64/sysregs.c Normal file
View File

@ -0,0 +1,172 @@
/*
* Check emulated system register access for linux-user mode.
*
* See: https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt
*
* Copyright (c) 2019 Linaro
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <asm/hwcap.h>
#include <stdio.h>
#include <sys/auxv.h>
#include <signal.h>
#include <string.h>
#include <stdbool.h>
#ifndef HWCAP_CPUID
#define HWCAP_CPUID (1 << 11)
#endif
int failed_bit_count;
/* Read and print system register `id' value */
#define get_cpu_reg(id) ({ \
unsigned long __val = 0xdeadbeef; \
asm("mrs %0, "#id : "=r" (__val)); \
printf("%-20s: 0x%016lx\n", #id, __val); \
__val; \
})
/* As above but also check no bits outside of `mask' are set*/
#define get_cpu_reg_check_mask(id, mask) ({ \
unsigned long __cval = get_cpu_reg(id); \
unsigned long __extra = __cval & ~mask; \
if (__extra) { \
printf("%-20s: 0x%016lx\n", " !!extra bits!!", __extra); \
failed_bit_count++; \
} \
})
/* As above but check RAZ */
#define get_cpu_reg_check_zero(id) ({ \
unsigned long __val = 0xdeadbeef; \
asm("mrs %0, "#id : "=r" (__val)); \
if (__val) { \
printf("%-20s: 0x%016lx (not RAZ!)\n", #id, __val); \
failed_bit_count++; \
} \
})
/* Chunk up mask into 63:48, 47:32, 31:16, 15:0 to ease counting */
#define _m(a, b, c, d) (0x ## a ## b ## c ## d ##ULL)
bool should_fail;
int should_fail_count;
int should_not_fail_count;
uintptr_t failed_pc[10];
void sigill_handler(int signo, siginfo_t *si, void *data)
{
ucontext_t *uc = (ucontext_t *)data;
if (should_fail) {
should_fail_count++;
} else {
uintptr_t pc = (uintptr_t) uc->uc_mcontext.pc;
failed_pc[should_not_fail_count++] = pc;
}
uc->uc_mcontext.pc += 4;
}
int main(void)
{
struct sigaction sa;
/* Hook in a SIGILL handler */
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &sigill_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGILL, &sa, 0) != 0) {
perror("sigaction");
return 1;
}
/* Counter values have been exposed since Linux 4.12 */
printf("Checking Counter registers\n");
get_cpu_reg(ctr_el0);
get_cpu_reg(cntvct_el0);
get_cpu_reg(cntfrq_el0);
/* HWCAP_CPUID indicates we can read feature registers, since Linux 4.11 */
if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
printf("CPUID registers unavailable\n");
return 1;
} else {
printf("Checking CPUID registers\n");
}
/*
* Some registers only expose some bits to user-space. Anything
* that is IMPDEF is exported as 0 to user-space. The _mask checks
* assert no extra bits are set.
*
* This check is *not* comprehensive as some fields are set to
* minimum valid fields - for the purposes of this check allowed
* to have non-zero values.
*/
get_cpu_reg_check_mask(id_aa64isar0_el1, _m(00ff,ffff,f0ff,fff0));
get_cpu_reg_check_mask(id_aa64isar1_el1, _m(0000,00f0,ffff,ffff));
/* TGran4 & TGran64 as pegged to -1 */
get_cpu_reg_check_mask(id_aa64mmfr0_el1, _m(0000,0000,ff00,0000));
get_cpu_reg_check_zero(id_aa64mmfr1_el1);
/* EL1/EL0 reported as AA64 only */
get_cpu_reg_check_mask(id_aa64pfr0_el1, _m(000f,000f,00ff,0011));
get_cpu_reg_check_mask(id_aa64pfr1_el1, _m(0000,0000,0000,00f0));
/* all hidden, DebugVer fixed to 0x6 (ARMv8 debug architecture) */
get_cpu_reg_check_mask(id_aa64dfr0_el1, _m(0000,0000,0000,0006));
get_cpu_reg_check_zero(id_aa64dfr1_el1);
get_cpu_reg_check_zero(id_aa64zfr0_el1);
get_cpu_reg_check_zero(id_aa64afr0_el1);
get_cpu_reg_check_zero(id_aa64afr1_el1);
get_cpu_reg_check_mask(midr_el1, _m(0000,0000,ffff,ffff));
/* mpidr sets bit 31, everything else hidden */
get_cpu_reg_check_mask(mpidr_el1, _m(0000,0000,8000,0000));
/* REVIDR is all IMPDEF so should be all zeros to user-space */
get_cpu_reg_check_zero(revidr_el1);
/*
* There are a block of more registers that are RAZ in the rest of
* the Op0=3, Op1=0, CRn=0, CRm=0,4,5,6,7 space. However for
* brevity we don't check stuff that is currently un-allocated
* here. Feel free to add them ;-)
*/
printf("Remaining registers should fail\n");
should_fail = true;
/* Unexposed register access causes SIGILL */
get_cpu_reg(id_mmfr0_el1);
get_cpu_reg(id_mmfr1_el1);
get_cpu_reg(id_mmfr2_el1);
get_cpu_reg(id_mmfr3_el1);
get_cpu_reg(mvfr0_el1);
get_cpu_reg(mvfr1_el1);
if (should_not_fail_count > 0) {
int i;
for (i = 0; i < should_not_fail_count; i++) {
uintptr_t pc = failed_pc[i];
uint32_t insn = *(uint32_t *) pc;
printf("insn %#x @ %#lx unexpected FAIL\n", insn, pc);
}
return 1;
}
if (failed_bit_count > 0) {
printf("Extra information leaked to user-space!\n");
return 1;
}
return should_fail_count == 6 ? 0 : 1;
}