monitor/target-ppc: Define target_get_monitor_def

At the moment get_monitor_def() returns only registers from statically
defined monitor_defs array. However there is a lot of BOOK3S SPRs
which are not in the list and cannot be printed from the monitor.

This adds a new target platform hook - target_get_monitor_def().
The hook is called if a register was not found in the static
array returned by the target_monitor_defs() hook.

The hook is only defined for POWERPC, it returns registered
SPRs and fails on unregistered ones providing the user with information
on what is actually supported on the running CPU. The register value is
saved as uint64_t as it is the biggest supported register size;
target_ulong cannot be used because of the stub - it is in a "common"
code and cannot include "cpu.h", etc; this is also why the hook prototype
is redefined in the stub instead of being included from some header.

This replaces static descriptors for GPRs, FPRs, SRs with a helper which
looks for a value in a corresponding array in the CPUPPCState.
The immediate effect is that all 32 SRs can be printed now (instead of 16);
later this can be reused for VSX or TM registers.

This replaces callbacks for MSR and XER with static descriptors in
monitor_defs as they are stored in CPUPPCState.

While we are here, this adds "cr" as a synonym of "ccr".

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Alexey Kardashevskiy 2015-11-12 14:44:23 +11:00 committed by David Gibson
parent cffc331a31
commit 0a9516c2d6
6 changed files with 107 additions and 173 deletions

View File

@ -35,6 +35,7 @@ struct MonitorDef {
}; };
const MonitorDef *target_monitor_defs(void); const MonitorDef *target_monitor_defs(void);
int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval);
CPUArchState *mon_get_cpu_env(void); CPUArchState *mon_get_cpu_env(void);
CPUState *mon_get_cpu(void); CPUState *mon_get_cpu(void);

View File

@ -2136,6 +2136,8 @@ static int get_monitor_def(target_long *pval, const char *name)
{ {
const MonitorDef *md = target_monitor_defs(); const MonitorDef *md = target_monitor_defs();
void *ptr; void *ptr;
uint64_t tmp = 0;
int ret;
if (md == NULL) { if (md == NULL) {
return -1; return -1;
@ -2163,7 +2165,13 @@ static int get_monitor_def(target_long *pval, const char *name)
return 0; return 0;
} }
} }
return -1;
ret = target_get_monitor_def(mon_get_cpu(), name, &tmp);
if (!ret) {
*pval = (target_long) tmp;
}
return ret;
} }
static void next(void) static void next(void)

View File

@ -36,4 +36,5 @@ stub-obj-y += cpus.o
stub-obj-y += kvm.o stub-obj-y += kvm.o
stub-obj-y += qmp_pc_dimm_device_list.o stub-obj-y += qmp_pc_dimm_device_list.o
stub-obj-y += target-monitor-defs.o stub-obj-y += target-monitor-defs.o
stub-obj-y += target-get-monitor-def.o
stub-obj-y += vhost.o stub-obj-y += vhost.o

View File

@ -0,0 +1,31 @@
/*
* Stub for target_get_monitor_def.
*
* Copyright IBM Corp., 2015
*
* Author: Alexey Kardashevskiy <aik@ozlabs.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "stdint.h"
typedef struct CPUState CPUState;
int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval);
int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval)
{
return -1;
}

View File

@ -118,6 +118,8 @@ void ppc_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags); int flags);
void ppc_cpu_dump_statistics(CPUState *cpu, FILE *f, void ppc_cpu_dump_statistics(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags); fprintf_function cpu_fprintf, int flags);
int ppc_cpu_get_monitor_def(CPUState *cs, const char *name,
uint64_t *pval);
hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); 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(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_apple(CPUState *cpu, uint8_t *buf, int reg);

View File

@ -39,18 +39,6 @@ static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
return u; return u;
} }
static target_long monitor_get_msr (const struct MonitorDef *md, int val)
{
CPUArchState *env = mon_get_cpu_env();
return env->msr;
}
static target_long monitor_get_xer (const struct MonitorDef *md, int val)
{
CPUArchState *env = mon_get_cpu_env();
return env->xer;
}
static target_long monitor_get_decr (const struct MonitorDef *md, int val) static target_long monitor_get_decr (const struct MonitorDef *md, int val)
{ {
CPUArchState *env = mon_get_cpu_env(); CPUArchState *env = mon_get_cpu_env();
@ -76,176 +64,19 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1); dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
} }
const MonitorDef monitor_defs[] = { const MonitorDef monitor_defs[] = {
/* General purpose registers */
{ "r0", offsetof(CPUPPCState, gpr[0]) },
{ "r1", offsetof(CPUPPCState, gpr[1]) },
{ "r2", offsetof(CPUPPCState, gpr[2]) },
{ "r3", offsetof(CPUPPCState, gpr[3]) },
{ "r4", offsetof(CPUPPCState, gpr[4]) },
{ "r5", offsetof(CPUPPCState, gpr[5]) },
{ "r6", offsetof(CPUPPCState, gpr[6]) },
{ "r7", offsetof(CPUPPCState, gpr[7]) },
{ "r8", offsetof(CPUPPCState, gpr[8]) },
{ "r9", offsetof(CPUPPCState, gpr[9]) },
{ "r10", offsetof(CPUPPCState, gpr[10]) },
{ "r11", offsetof(CPUPPCState, gpr[11]) },
{ "r12", offsetof(CPUPPCState, gpr[12]) },
{ "r13", offsetof(CPUPPCState, gpr[13]) },
{ "r14", offsetof(CPUPPCState, gpr[14]) },
{ "r15", offsetof(CPUPPCState, gpr[15]) },
{ "r16", offsetof(CPUPPCState, gpr[16]) },
{ "r17", offsetof(CPUPPCState, gpr[17]) },
{ "r18", offsetof(CPUPPCState, gpr[18]) },
{ "r19", offsetof(CPUPPCState, gpr[19]) },
{ "r20", offsetof(CPUPPCState, gpr[20]) },
{ "r21", offsetof(CPUPPCState, gpr[21]) },
{ "r22", offsetof(CPUPPCState, gpr[22]) },
{ "r23", offsetof(CPUPPCState, gpr[23]) },
{ "r24", offsetof(CPUPPCState, gpr[24]) },
{ "r25", offsetof(CPUPPCState, gpr[25]) },
{ "r26", offsetof(CPUPPCState, gpr[26]) },
{ "r27", offsetof(CPUPPCState, gpr[27]) },
{ "r28", offsetof(CPUPPCState, gpr[28]) },
{ "r29", offsetof(CPUPPCState, gpr[29]) },
{ "r30", offsetof(CPUPPCState, gpr[30]) },
{ "r31", offsetof(CPUPPCState, gpr[31]) },
/* Floating point registers */
{ "f0", offsetof(CPUPPCState, fpr[0]) },
{ "f1", offsetof(CPUPPCState, fpr[1]) },
{ "f2", offsetof(CPUPPCState, fpr[2]) },
{ "f3", offsetof(CPUPPCState, fpr[3]) },
{ "f4", offsetof(CPUPPCState, fpr[4]) },
{ "f5", offsetof(CPUPPCState, fpr[5]) },
{ "f6", offsetof(CPUPPCState, fpr[6]) },
{ "f7", offsetof(CPUPPCState, fpr[7]) },
{ "f8", offsetof(CPUPPCState, fpr[8]) },
{ "f9", offsetof(CPUPPCState, fpr[9]) },
{ "f10", offsetof(CPUPPCState, fpr[10]) },
{ "f11", offsetof(CPUPPCState, fpr[11]) },
{ "f12", offsetof(CPUPPCState, fpr[12]) },
{ "f13", offsetof(CPUPPCState, fpr[13]) },
{ "f14", offsetof(CPUPPCState, fpr[14]) },
{ "f15", offsetof(CPUPPCState, fpr[15]) },
{ "f16", offsetof(CPUPPCState, fpr[16]) },
{ "f17", offsetof(CPUPPCState, fpr[17]) },
{ "f18", offsetof(CPUPPCState, fpr[18]) },
{ "f19", offsetof(CPUPPCState, fpr[19]) },
{ "f20", offsetof(CPUPPCState, fpr[20]) },
{ "f21", offsetof(CPUPPCState, fpr[21]) },
{ "f22", offsetof(CPUPPCState, fpr[22]) },
{ "f23", offsetof(CPUPPCState, fpr[23]) },
{ "f24", offsetof(CPUPPCState, fpr[24]) },
{ "f25", offsetof(CPUPPCState, fpr[25]) },
{ "f26", offsetof(CPUPPCState, fpr[26]) },
{ "f27", offsetof(CPUPPCState, fpr[27]) },
{ "f28", offsetof(CPUPPCState, fpr[28]) },
{ "f29", offsetof(CPUPPCState, fpr[29]) },
{ "f30", offsetof(CPUPPCState, fpr[30]) },
{ "f31", offsetof(CPUPPCState, fpr[31]) },
{ "fpscr", offsetof(CPUPPCState, fpscr) }, { "fpscr", offsetof(CPUPPCState, fpscr) },
/* Next instruction pointer */ /* Next instruction pointer */
{ "nip|pc", offsetof(CPUPPCState, nip) }, { "nip|pc", offsetof(CPUPPCState, nip) },
{ "lr", offsetof(CPUPPCState, lr) }, { "lr", offsetof(CPUPPCState, lr) },
{ "ctr", offsetof(CPUPPCState, ctr) }, { "ctr", offsetof(CPUPPCState, ctr) },
{ "decr", 0, &monitor_get_decr, }, { "decr", 0, &monitor_get_decr, },
{ "ccr", 0, &monitor_get_ccr, }, { "ccr|cr", 0, &monitor_get_ccr, },
/* Machine state register */ /* Machine state register */
{ "msr", 0, &monitor_get_msr, }, { "xer", offsetof(CPUPPCState, xer) },
{ "xer", 0, &monitor_get_xer, }, { "msr", offsetof(CPUPPCState, msr) },
{ "tbu", 0, &monitor_get_tbu, }, { "tbu", 0, &monitor_get_tbu, },
{ "tbl", 0, &monitor_get_tbl, }, { "tbl", 0, &monitor_get_tbl, },
/* Segment registers */
{ "sdr1", offsetof(CPUPPCState, spr[SPR_SDR1]) },
{ "sr0", offsetof(CPUPPCState, sr[0]) },
{ "sr1", offsetof(CPUPPCState, sr[1]) },
{ "sr2", offsetof(CPUPPCState, sr[2]) },
{ "sr3", offsetof(CPUPPCState, sr[3]) },
{ "sr4", offsetof(CPUPPCState, sr[4]) },
{ "sr5", offsetof(CPUPPCState, sr[5]) },
{ "sr6", offsetof(CPUPPCState, sr[6]) },
{ "sr7", offsetof(CPUPPCState, sr[7]) },
{ "sr8", offsetof(CPUPPCState, sr[8]) },
{ "sr9", offsetof(CPUPPCState, sr[9]) },
{ "sr10", offsetof(CPUPPCState, sr[10]) },
{ "sr11", offsetof(CPUPPCState, sr[11]) },
{ "sr12", offsetof(CPUPPCState, sr[12]) },
{ "sr13", offsetof(CPUPPCState, sr[13]) },
{ "sr14", offsetof(CPUPPCState, sr[14]) },
{ "sr15", offsetof(CPUPPCState, sr[15]) },
/* Too lazy to put BATs... */
{ "pvr", offsetof(CPUPPCState, spr[SPR_PVR]) },
{ "srr0", offsetof(CPUPPCState, spr[SPR_SRR0]) },
{ "srr1", offsetof(CPUPPCState, spr[SPR_SRR1]) },
{ "dar", offsetof(CPUPPCState, spr[SPR_DAR]) },
{ "dsisr", offsetof(CPUPPCState, spr[SPR_DSISR]) },
{ "cfar", offsetof(CPUPPCState, spr[SPR_CFAR]) },
{ "sprg0", offsetof(CPUPPCState, spr[SPR_SPRG0]) },
{ "sprg1", offsetof(CPUPPCState, spr[SPR_SPRG1]) },
{ "sprg2", offsetof(CPUPPCState, spr[SPR_SPRG2]) },
{ "sprg3", offsetof(CPUPPCState, spr[SPR_SPRG3]) },
{ "sprg4", offsetof(CPUPPCState, spr[SPR_SPRG4]) },
{ "sprg5", offsetof(CPUPPCState, spr[SPR_SPRG5]) },
{ "sprg6", offsetof(CPUPPCState, spr[SPR_SPRG6]) },
{ "sprg7", offsetof(CPUPPCState, spr[SPR_SPRG7]) },
{ "pid", offsetof(CPUPPCState, spr[SPR_BOOKE_PID]) },
{ "csrr0", offsetof(CPUPPCState, spr[SPR_BOOKE_CSRR0]) },
{ "csrr1", offsetof(CPUPPCState, spr[SPR_BOOKE_CSRR1]) },
{ "esr", offsetof(CPUPPCState, spr[SPR_BOOKE_ESR]) },
{ "dear", offsetof(CPUPPCState, spr[SPR_BOOKE_DEAR]) },
{ "mcsr", offsetof(CPUPPCState, spr[SPR_BOOKE_MCSR]) },
{ "tsr", offsetof(CPUPPCState, spr[SPR_BOOKE_TSR]) },
{ "tcr", offsetof(CPUPPCState, spr[SPR_BOOKE_TCR]) },
{ "vrsave", offsetof(CPUPPCState, spr[SPR_VRSAVE]) },
{ "pir", offsetof(CPUPPCState, spr[SPR_BOOKE_PIR]) },
{ "mcsrr0", offsetof(CPUPPCState, spr[SPR_BOOKE_MCSRR0]) },
{ "mcsrr1", offsetof(CPUPPCState, spr[SPR_BOOKE_MCSRR1]) },
{ "decar", offsetof(CPUPPCState, spr[SPR_BOOKE_DECAR]) },
{ "ivpr", offsetof(CPUPPCState, spr[SPR_BOOKE_IVPR]) },
{ "epcr", offsetof(CPUPPCState, spr[SPR_BOOKE_EPCR]) },
{ "sprg8", offsetof(CPUPPCState, spr[SPR_BOOKE_SPRG8]) },
{ "ivor0", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR0]) },
{ "ivor1", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR1]) },
{ "ivor2", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR2]) },
{ "ivor3", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR3]) },
{ "ivor4", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR4]) },
{ "ivor5", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR5]) },
{ "ivor6", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR6]) },
{ "ivor7", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR7]) },
{ "ivor8", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR8]) },
{ "ivor9", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR9]) },
{ "ivor10", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR10]) },
{ "ivor11", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR11]) },
{ "ivor12", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR12]) },
{ "ivor13", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR13]) },
{ "ivor14", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR14]) },
{ "ivor15", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR15]) },
{ "ivor32", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR32]) },
{ "ivor33", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR33]) },
{ "ivor34", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR34]) },
{ "ivor35", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR35]) },
{ "ivor36", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR36]) },
{ "ivor37", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR37]) },
{ "mas0", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS0]) },
{ "mas1", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS1]) },
{ "mas2", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS2]) },
{ "mas3", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS3]) },
{ "mas4", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS4]) },
{ "mas6", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS6]) },
{ "mas7", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS7]) },
{ "mmucfg", offsetof(CPUPPCState, spr[SPR_MMUCFG]) },
{ "tlb0cfg", offsetof(CPUPPCState, spr[SPR_BOOKE_TLB0CFG]) },
{ "tlb1cfg", offsetof(CPUPPCState, spr[SPR_BOOKE_TLB1CFG]) },
{ "epr", offsetof(CPUPPCState, spr[SPR_BOOKE_EPR]) },
{ "eplc", offsetof(CPUPPCState, spr[SPR_BOOKE_EPLC]) },
{ "epsc", offsetof(CPUPPCState, spr[SPR_BOOKE_EPSC]) },
{ "svr", offsetof(CPUPPCState, spr[SPR_E500_SVR]) },
{ "mcar", offsetof(CPUPPCState, spr[SPR_Exxx_MCAR]) },
{ "pid1", offsetof(CPUPPCState, spr[SPR_BOOKE_PID1]) },
{ "pid2", offsetof(CPUPPCState, spr[SPR_BOOKE_PID2]) },
{ "hid0", offsetof(CPUPPCState, spr[SPR_HID0]) },
{ NULL }, { NULL },
}; };
@ -253,3 +84,63 @@ const MonitorDef *target_monitor_defs(void)
{ {
return monitor_defs; return monitor_defs;
} }
static int ppc_cpu_get_reg_num(const char *numstr, int maxnum, int *pregnum)
{
int regnum;
char *endptr = NULL;
if (!*numstr) {
return false;
}
regnum = strtoul(numstr, &endptr, 10);
if (*endptr || (regnum >= maxnum)) {
return false;
}
*pregnum = regnum;
return true;
}
int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval)
{
int i, regnum;
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
/* General purpose registers */
if ((tolower(name[0]) == 'r') &&
ppc_cpu_get_reg_num(name + 1, ARRAY_SIZE(env->gpr), &regnum)) {
*pval = env->gpr[regnum];
return 0;
}
/* Floating point registers */
if ((tolower(name[0]) == 'f') &&
ppc_cpu_get_reg_num(name + 1, ARRAY_SIZE(env->fpr), &regnum)) {
*pval = env->fpr[regnum];
return 0;
}
/* Special purpose registers */
for (i = 0; i < ARRAY_SIZE(env->spr_cb); ++i) {
ppc_spr_t *spr = &env->spr_cb[i];
if (spr->name && (strcasecmp(name, spr->name) == 0)) {
*pval = env->spr[i];
return 0;
}
}
/* Segment registers */
#if !defined(CONFIG_USER_ONLY)
if ((strncasecmp(name, "sr", 2) == 0) &&
ppc_cpu_get_reg_num(name + 2, ARRAY_SIZE(env->sr), &regnum)) {
*pval = env->sr[regnum];
return 0;
}
#endif
return -EINVAL;
}