Skip to content

Commit

Permalink
cpu: Introduce CPUState::gdb_num_regs and CPUClass::gdb_num_core_regs
Browse files Browse the repository at this point in the history
CPUState::gdb_num_regs replaces num_g_regs.
CPUClass::gdb_num_core_regs replaces NUM_CORE_REGS.

Allows building gdb_register_coprocessor() for xtensa, too.

As a side effect this should fix coprocessor register numbering for SMP.

Acked-by: Michael Walle <michael@walle.cc> (for lm32)
Acked-by: Max Filippov <jcmvbkbc@gmail.com> (for xtensa)
Signed-off-by: Andreas Färber <afaerber@suse.de>
  • Loading branch information
afaerber committed Jul 26, 2013
1 parent 19a7721 commit a0e372f
Show file tree
Hide file tree
Showing 18 changed files with 66 additions and 65 deletions.
83 changes: 19 additions & 64 deletions gdbstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,6 @@ static const int gpr_map[16] = {
#endif
static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };

#define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25)

#define IDX_IP_REG CPU_NB_REGS
#define IDX_FLAGS_REG (IDX_IP_REG + 1)
#define IDX_SEG_REGS (IDX_FLAGS_REG + 1)
Expand Down Expand Up @@ -732,7 +730,6 @@ static int cpu_gdb_write_register(CPUX86State *env, uint8_t *mem_buf, int n)
historical mishap the FP registers appear in between core integer
regs and PC, MSR, CR, and so forth. We hack round this by giving the
FP regs zero size when talking to a newer gdb. */
#define NUM_CORE_REGS 71
#if defined (TARGET_PPC64)
#define GDB_CORE_XML "power64-core.xml"
#else
Expand Down Expand Up @@ -837,12 +834,6 @@ static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n)

#elif defined (TARGET_SPARC)

#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
#define NUM_CORE_REGS 86
#else
#define NUM_CORE_REGS 72
#endif

#ifdef TARGET_ABI32
#define GET_REGA(val) GET_REG32(val)
#else
Expand Down Expand Up @@ -1030,7 +1021,6 @@ static int cpu_gdb_write_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
the FPA registers appear in between core integer regs and the CPSR.
We hack round this by giving the FPA regs zero size when talking to a
newer gdb. */
#define NUM_CORE_REGS 26
#define GDB_CORE_XML "arm-core.xml"

static int cpu_gdb_read_register(CPUARMState *env, uint8_t *mem_buf, int n)
Expand Down Expand Up @@ -1104,8 +1094,6 @@ static int cpu_gdb_write_register(CPUARMState *env, uint8_t *mem_buf, int n)

#elif defined (TARGET_M68K)

#define NUM_CORE_REGS 18

#define GDB_CORE_XML "cf-core.xml"

static int cpu_gdb_read_register(CPUM68KState *env, uint8_t *mem_buf, int n)
Expand Down Expand Up @@ -1157,8 +1145,6 @@ static int cpu_gdb_write_register(CPUM68KState *env, uint8_t *mem_buf, int n)
}
#elif defined (TARGET_MIPS)

#define NUM_CORE_REGS 73

static int cpu_gdb_read_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
Expand Down Expand Up @@ -1285,8 +1271,6 @@ static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
}
#elif defined(TARGET_OPENRISC)

#define NUM_CORE_REGS (32 + 3)

static int cpu_gdb_read_register(CPUOpenRISCState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
Expand All @@ -1312,9 +1296,11 @@ static int cpu_gdb_read_register(CPUOpenRISCState *env, uint8_t *mem_buf, int n)
static int cpu_gdb_write_register(CPUOpenRISCState *env,
uint8_t *mem_buf, int n)
{
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
uint32_t tmp;

if (n > NUM_CORE_REGS) {
if (n > cc->gdb_num_core_regs) {
return 0;
}

Expand Down Expand Up @@ -1347,8 +1333,6 @@ static int cpu_gdb_write_register(CPUOpenRISCState *env,
/* Hint: Use "set architecture sh4" in GDB to see fpu registers */
/* FIXME: We should use XML for this. */

#define NUM_CORE_REGS 59

static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
{
switch (n) {
Expand Down Expand Up @@ -1465,8 +1449,6 @@ static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n)
}
#elif defined (TARGET_MICROBLAZE)

#define NUM_CORE_REGS (32 + 5)

static int cpu_gdb_read_register(CPUMBState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
Expand All @@ -1479,9 +1461,11 @@ static int cpu_gdb_read_register(CPUMBState *env, uint8_t *mem_buf, int n)

static int cpu_gdb_write_register(CPUMBState *env, uint8_t *mem_buf, int n)
{
MicroBlazeCPU *cpu = mb_env_get_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
uint32_t tmp;

if (n > NUM_CORE_REGS) {
if (n > cc->gdb_num_core_regs) {
return 0;
}

Expand All @@ -1496,8 +1480,6 @@ static int cpu_gdb_write_register(CPUMBState *env, uint8_t *mem_buf, int n)
}
#elif defined (TARGET_CRIS)

#define NUM_CORE_REGS 49

static int
read_register_crisv10(CPUCRISState *env, uint8_t *mem_buf, int n)
{
Expand Down Expand Up @@ -1605,8 +1587,6 @@ static int cpu_gdb_write_register(CPUCRISState *env, uint8_t *mem_buf, int n)
}
#elif defined (TARGET_ALPHA)

#define NUM_CORE_REGS 67

static int cpu_gdb_read_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
{
uint64_t val;
Expand Down Expand Up @@ -1675,8 +1655,6 @@ static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
}
#elif defined (TARGET_S390X)

#define NUM_CORE_REGS S390_NUM_REGS

static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
{
uint64_t val;
Expand Down Expand Up @@ -1740,7 +1718,6 @@ static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
#elif defined (TARGET_LM32)

#include "hw/lm32/lm32_pic.h"
#define NUM_CORE_REGS (32 + 7)

static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n)
{
Expand Down Expand Up @@ -1770,9 +1747,11 @@ static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n)

static int cpu_gdb_write_register(CPULM32State *env, uint8_t *mem_buf, int n)
{
LM32CPU *cpu = lm32_env_get_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
uint32_t tmp;

if (n > NUM_CORE_REGS) {
if (n > cc->gdb_num_core_regs) {
return 0;
}

Expand Down Expand Up @@ -1806,14 +1785,6 @@ static int cpu_gdb_write_register(CPULM32State *env, uint8_t *mem_buf, int n)
}
#elif defined(TARGET_XTENSA)

/* Use num_core_regs to see only non-privileged registers in an unmodified gdb.
* Use num_regs to see all registers. gdb modification is required for that:
* reset bit 0 in the 'flags' field of the registers definitions in the
* gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
*/
#define NUM_CORE_REGS (env->config->gdb_regmap.num_regs)
#define num_g_regs NUM_CORE_REGS

static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
{
const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
Expand Down Expand Up @@ -1896,8 +1867,6 @@ static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
}
#else

#define NUM_CORE_REGS 0

static int cpu_gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int n)
{
return 0;
Expand All @@ -1910,10 +1879,6 @@ static int cpu_gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int n)

#endif

#if !defined(TARGET_XTENSA)
static int num_g_regs = NUM_CORE_REGS;
#endif

#ifdef GDB_CORE_XML
/* Encode data using the encoding for 'x' packets. */
static int memtox(char *buf, const char *mem, int len)
Expand Down Expand Up @@ -1982,11 +1947,13 @@ static const char *get_feature_xml(const char *p, const char **newp)

static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;

if (reg < NUM_CORE_REGS)
if (reg < cc->gdb_num_core_regs) {
return cpu_gdb_read_register(env, mem_buf, reg);
}

for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
Expand All @@ -1998,11 +1965,13 @@ static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)

static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;

if (reg < NUM_CORE_REGS)
if (reg < cc->gdb_num_core_regs) {
return cpu_gdb_write_register(env, mem_buf, reg);
}

for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
Expand All @@ -2012,7 +1981,6 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
return 0;
}

#if !defined(TARGET_XTENSA)
/* Register a supplemental set of CPU registers. If g_pos is nonzero it
specifies the first register number and these registers are included in
a standard "g" packet. Direction is relative to gdb, i.e. get_reg is
Expand All @@ -2025,7 +1993,6 @@ void gdb_register_coprocessor(CPUState *cpu,
{
GDBRegisterState *s;
GDBRegisterState **p;
static int last_reg = NUM_CORE_REGS;

p = &cpu->gdb_regs;
while (*p) {
Expand All @@ -2036,25 +2003,22 @@ void gdb_register_coprocessor(CPUState *cpu,
}

s = g_new0(GDBRegisterState, 1);
s->base_reg = last_reg;
s->base_reg = cpu->gdb_num_regs;
s->num_regs = num_regs;
s->get_reg = get_reg;
s->set_reg = set_reg;
s->xml = xml;

/* Add to end of list. */
last_reg += num_regs;
cpu->gdb_num_regs += num_regs;
*p = s;
if (g_pos) {
if (g_pos != s->base_reg) {
fprintf(stderr, "Error: Bad gdb register numbering for '%s'\n"
"Expected %d got %d\n", xml, g_pos, s->base_reg);
} else {
num_g_regs = last_reg;
}
}
}
#endif

#ifndef CONFIG_USER_ONLY
static const int xlat_gdb_type[] = {
Expand Down Expand Up @@ -2184,9 +2148,6 @@ static CPUState *find_cpu(uint32_t thread_id)

static int gdb_handle_packet(GDBState *s, const char *line_buf)
{
#ifdef TARGET_XTENSA
CPUArchState *env;
#endif
CPUState *cpu;
const char *p;
uint32_t thread;
Expand Down Expand Up @@ -2334,11 +2295,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
break;
case 'g':
cpu_synchronize_state(s->g_cpu);
#ifdef TARGET_XTENSA
env = s->g_cpu->env_ptr;
#endif
len = 0;
for (addr = 0; addr < num_g_regs; addr++) {
for (addr = 0; addr < s->g_cpu->gdb_num_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
len += reg_size;
}
Expand All @@ -2347,13 +2305,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
break;
case 'G':
cpu_synchronize_state(s->g_cpu);
#ifdef TARGET_XTENSA
env = s->g_cpu->env_ptr;
#endif
registers = mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
for (addr = 0; addr < num_g_regs && len > 0; addr++) {
for (addr = 0; addr < s->g_cpu->gdb_num_regs && len > 0; addr++) {
reg_size = gdb_write_register(s->g_cpu, registers, addr);
len -= reg_size;
registers += reg_size;
Expand Down
7 changes: 6 additions & 1 deletion include/qom/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct TranslationBlock;
* #TranslationBlock.
* @get_phys_page_debug: Callback for obtaining a physical address.
* @vmsd: State description for migration.
* @gdb_num_core_regs: Number of core registers accessible to GDB.
*
* Represents a CPU family or model.
*/
Expand Down Expand Up @@ -109,7 +110,6 @@ typedef struct CPUClass {
void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);

const struct VMStateDescription *vmsd;
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
int cpuid, void *opaque);
int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
Expand All @@ -118,6 +118,9 @@ typedef struct CPUClass {
int cpuid, void *opaque);
int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);

const struct VMStateDescription *vmsd;
int gdb_num_core_regs;
} CPUClass;

struct KVMState;
Expand All @@ -142,6 +145,7 @@ struct kvm_run;
* @env_ptr: Pointer to subclass-specific CPUArchState field.
* @current_tb: Currently executing TB.
* @gdb_regs: Additional GDB registers.
* @gdb_num_regs: Number of total registers accessible to GDB.
* @next_cpu: Next CPU sharing TB cache.
* @kvm_fd: vCPU file descriptor for KVM.
*
Expand Down Expand Up @@ -177,6 +181,7 @@ struct CPUState {
void *env_ptr; /* CPUArchState */
struct TranslationBlock *current_tb;
struct GDBRegisterState *gdb_regs;
int gdb_num_regs;
CPUState *next_cpu;

int kvm_fd;
Expand Down
9 changes: 9 additions & 0 deletions qom/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,14 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
}
}

static void cpu_common_initfn(Object *obj)
{
CPUState *cpu = CPU(obj);
CPUClass *cc = CPU_GET_CLASS(obj);

cpu->gdb_num_regs = cc->gdb_num_core_regs;
}

static int64_t cpu_common_get_arch_id(CPUState *cpu)
{
return cpu->cpu_index;
Expand Down Expand Up @@ -253,6 +261,7 @@ static const TypeInfo cpu_type_info = {
.name = TYPE_CPU,
.parent = TYPE_DEVICE,
.instance_size = sizeof(CPUState),
.instance_init = cpu_common_initfn,
.abstract = true,
.class_size = sizeof(CPUClass),
.class_init = cpu_class_init,
Expand Down
1 change: 1 addition & 0 deletions target-alpha/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_alpha_cpu;
#endif
cc->gdb_num_core_regs = 67;
}

static const TypeInfo alpha_cpu_type_info = {
Expand Down
1 change: 1 addition & 0 deletions target-arm/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_arm_cpu;
#endif
cc->gdb_num_core_regs = 26;
}

static void cpu_register(const ARMCPUInfo *info)
Expand Down
2 changes: 2 additions & 0 deletions target-cris/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
#endif

cc->gdb_num_core_regs = 49;
}

static const TypeInfo cris_cpu_type_info = {
Expand Down
Loading

0 comments on commit a0e372f

Please sign in to comment.