monitor: add PPC BookE SPRs

Read them via KVM_GET_SREGS in kvm_arch_get_registers(),
and display them in "info registers".

Also get CR and PID from the existing KVM_GET_REGS.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Scott Wood 2011-04-29 17:10:23 -05:00 committed by Alexander Graf
parent 5666ca4ae0
commit 90dc881222
5 changed files with 296 additions and 13 deletions

View File

@ -452,6 +452,10 @@ uint64_t cpu_ppc_load_tbl (CPUState *env)
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
if (kvm_enabled()) {
return env->spr[SPR_TBL];
}
tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
@ -471,6 +475,10 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
uint32_t cpu_ppc_load_tbu (CPUState *env)
{
if (kvm_enabled()) {
return env->spr[SPR_TBU];
}
return _cpu_ppc_load_tbu(env);
}
@ -616,6 +624,10 @@ uint32_t cpu_ppc_load_decr (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
if (kvm_enabled()) {
return env->spr[SPR_DECR];
}
return _cpu_ppc_load_decr(env, tb_env->decr_next);
}

View File

@ -3466,7 +3466,76 @@ static const MonitorDef monitor_defs[] = {
{ "sr13", offsetof(CPUState, sr[13]) },
{ "sr14", offsetof(CPUState, sr[14]) },
{ "sr15", offsetof(CPUState, sr[15]) },
/* Too lazy to put BATs and SPRs ... */
/* Too lazy to put BATs... */
{ "pvr", offsetof(CPUState, spr[SPR_PVR]) },
{ "srr0", offsetof(CPUState, spr[SPR_SRR0]) },
{ "srr1", offsetof(CPUState, spr[SPR_SRR1]) },
{ "sprg0", offsetof(CPUState, spr[SPR_SPRG0]) },
{ "sprg1", offsetof(CPUState, spr[SPR_SPRG1]) },
{ "sprg2", offsetof(CPUState, spr[SPR_SPRG2]) },
{ "sprg3", offsetof(CPUState, spr[SPR_SPRG3]) },
{ "sprg4", offsetof(CPUState, spr[SPR_SPRG4]) },
{ "sprg5", offsetof(CPUState, spr[SPR_SPRG5]) },
{ "sprg6", offsetof(CPUState, spr[SPR_SPRG6]) },
{ "sprg7", offsetof(CPUState, spr[SPR_SPRG7]) },
{ "pid", offsetof(CPUState, spr[SPR_BOOKE_PID]) },
{ "csrr0", offsetof(CPUState, spr[SPR_BOOKE_CSRR0]) },
{ "csrr1", offsetof(CPUState, spr[SPR_BOOKE_CSRR1]) },
{ "esr", offsetof(CPUState, spr[SPR_BOOKE_ESR]) },
{ "dear", offsetof(CPUState, spr[SPR_BOOKE_DEAR]) },
{ "mcsr", offsetof(CPUState, spr[SPR_BOOKE_MCSR]) },
{ "tsr", offsetof(CPUState, spr[SPR_BOOKE_TSR]) },
{ "tcr", offsetof(CPUState, spr[SPR_BOOKE_TCR]) },
{ "vrsave", offsetof(CPUState, spr[SPR_VRSAVE]) },
{ "pir", offsetof(CPUState, spr[SPR_BOOKE_PIR]) },
{ "mcsrr0", offsetof(CPUState, spr[SPR_BOOKE_MCSRR0]) },
{ "mcsrr1", offsetof(CPUState, spr[SPR_BOOKE_MCSRR1]) },
{ "decar", offsetof(CPUState, spr[SPR_BOOKE_DECAR]) },
{ "ivpr", offsetof(CPUState, spr[SPR_BOOKE_IVPR]) },
{ "epcr", offsetof(CPUState, spr[SPR_BOOKE_EPCR]) },
{ "sprg8", offsetof(CPUState, spr[SPR_BOOKE_SPRG8]) },
{ "ivor0", offsetof(CPUState, spr[SPR_BOOKE_IVOR0]) },
{ "ivor1", offsetof(CPUState, spr[SPR_BOOKE_IVOR1]) },
{ "ivor2", offsetof(CPUState, spr[SPR_BOOKE_IVOR2]) },
{ "ivor3", offsetof(CPUState, spr[SPR_BOOKE_IVOR3]) },
{ "ivor4", offsetof(CPUState, spr[SPR_BOOKE_IVOR4]) },
{ "ivor5", offsetof(CPUState, spr[SPR_BOOKE_IVOR5]) },
{ "ivor6", offsetof(CPUState, spr[SPR_BOOKE_IVOR6]) },
{ "ivor7", offsetof(CPUState, spr[SPR_BOOKE_IVOR7]) },
{ "ivor8", offsetof(CPUState, spr[SPR_BOOKE_IVOR8]) },
{ "ivor9", offsetof(CPUState, spr[SPR_BOOKE_IVOR9]) },
{ "ivor10", offsetof(CPUState, spr[SPR_BOOKE_IVOR10]) },
{ "ivor11", offsetof(CPUState, spr[SPR_BOOKE_IVOR11]) },
{ "ivor12", offsetof(CPUState, spr[SPR_BOOKE_IVOR12]) },
{ "ivor13", offsetof(CPUState, spr[SPR_BOOKE_IVOR13]) },
{ "ivor14", offsetof(CPUState, spr[SPR_BOOKE_IVOR14]) },
{ "ivor15", offsetof(CPUState, spr[SPR_BOOKE_IVOR15]) },
{ "ivor32", offsetof(CPUState, spr[SPR_BOOKE_IVOR32]) },
{ "ivor33", offsetof(CPUState, spr[SPR_BOOKE_IVOR33]) },
{ "ivor34", offsetof(CPUState, spr[SPR_BOOKE_IVOR34]) },
{ "ivor35", offsetof(CPUState, spr[SPR_BOOKE_IVOR35]) },
{ "ivor36", offsetof(CPUState, spr[SPR_BOOKE_IVOR36]) },
{ "ivor37", offsetof(CPUState, spr[SPR_BOOKE_IVOR37]) },
{ "mas0", offsetof(CPUState, spr[SPR_BOOKE_MAS0]) },
{ "mas1", offsetof(CPUState, spr[SPR_BOOKE_MAS1]) },
{ "mas2", offsetof(CPUState, spr[SPR_BOOKE_MAS2]) },
{ "mas3", offsetof(CPUState, spr[SPR_BOOKE_MAS3]) },
{ "mas4", offsetof(CPUState, spr[SPR_BOOKE_MAS4]) },
{ "mas6", offsetof(CPUState, spr[SPR_BOOKE_MAS6]) },
{ "mas7", offsetof(CPUState, spr[SPR_BOOKE_MAS7]) },
{ "mmucfg", offsetof(CPUState, spr[SPR_MMUCFG]) },
{ "tlb0cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB0CFG]) },
{ "tlb1cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB1CFG]) },
{ "epr", offsetof(CPUState, spr[SPR_BOOKE_EPR]) },
{ "eplc", offsetof(CPUState, spr[SPR_BOOKE_EPLC]) },
{ "epsc", offsetof(CPUState, spr[SPR_BOOKE_EPSC]) },
{ "svr", offsetof(CPUState, spr[SPR_E500_SVR]) },
{ "mcar", offsetof(CPUState, spr[SPR_Exxx_MCAR]) },
{ "pid1", offsetof(CPUState, spr[SPR_BOOKE_PID1]) },
{ "pid2", offsetof(CPUState, spr[SPR_BOOKE_PID2]) },
{ "hid0", offsetof(CPUState, spr[SPR_HID0]) },
#elif defined(TARGET_SPARC)
{ "g0", offsetof(CPUState, gregs[0]) },
{ "g1", offsetof(CPUState, gregs[1]) },

View File

@ -1016,6 +1016,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#define SPR_HSPRG1 (0x131)
#define SPR_HDSISR (0x132)
#define SPR_HDAR (0x133)
#define SPR_BOOKE_EPCR (0x133)
#define SPR_SPURR (0x134)
#define SPR_BOOKE_DBCR0 (0x134)
#define SPR_IBCR (0x135)

View File

@ -2,6 +2,7 @@
* PowerPC implementation of KVM hooks
*
* Copyright IBM Corp. 2007
* Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* Authors:
* Jerone Young <jyoung5@us.ibm.com>
@ -43,6 +44,10 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
static int cap_interrupt_unset = false;
static int cap_interrupt_level = false;
static int cap_segstate;
#ifdef KVM_CAP_PPC_BOOKE_SREGS
static int cap_booke_sregs;
#endif
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@ -68,6 +73,12 @@ int kvm_arch_init(KVMState *s)
#ifdef KVM_CAP_PPC_IRQ_LEVEL
cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
#endif
#ifdef KVM_CAP_PPC_SEGSTATE
cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
#endif
#ifdef KVM_CAP_PPC_BOOKE_SREGS
cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
#endif
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@ -85,13 +96,9 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
return 0;
} else {
#ifdef KVM_CAP_PPC_SEGSTATE
if (!kvm_check_extension(cenv->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
if (!cap_segstate) {
return 0;
}
#else
return 0;
#endif
}
ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
@ -149,6 +156,8 @@ int kvm_arch_put_registers(CPUState *env, int level)
regs.sprg6 = env->spr[SPR_SPRG6];
regs.sprg7 = env->spr[SPR_SPRG7];
regs.pid = env->spr[SPR_BOOKE_PID];
for (i = 0;i < 32; i++)
regs.gpr[i] = env->gpr[i];
@ -163,15 +172,18 @@ int kvm_arch_get_registers(CPUState *env)
{
struct kvm_regs regs;
struct kvm_sregs sregs;
uint32_t cr;
int i, ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
if (ret < 0)
return ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
if (ret < 0)
return ret;
cr = regs.cr;
for (i = 7; i >= 0; i--) {
env->crf[i] = cr & 15;
cr >>= 4;
}
env->ctr = regs.ctr;
env->lr = regs.lr;
@ -191,11 +203,124 @@ int kvm_arch_get_registers(CPUState *env)
env->spr[SPR_SPRG6] = regs.sprg6;
env->spr[SPR_SPRG7] = regs.sprg7;
env->spr[SPR_BOOKE_PID] = regs.pid;
for (i = 0;i < 32; i++)
env->gpr[i] = regs.gpr[i];
#ifdef KVM_CAP_PPC_BOOKE_SREGS
if (cap_booke_sregs) {
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
if (ret < 0) {
return ret;
}
if (sregs.u.e.features & KVM_SREGS_E_BASE) {
env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0;
env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1;
env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr;
env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear;
env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr;
env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr;
env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr;
env->spr[SPR_DECR] = sregs.u.e.dec;
env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff;
env->spr[SPR_TBU] = sregs.u.e.tb >> 32;
env->spr[SPR_VRSAVE] = sregs.u.e.vrsave;
}
if (sregs.u.e.features & KVM_SREGS_E_ARCH206) {
env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir;
env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0;
env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1;
env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar;
env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr;
}
if (sregs.u.e.features & KVM_SREGS_E_64) {
env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr;
}
if (sregs.u.e.features & KVM_SREGS_E_SPRG8) {
env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8;
}
if (sregs.u.e.features & KVM_SREGS_E_IVOR) {
env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0];
env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1];
env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2];
env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3];
env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4];
env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5];
env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6];
env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7];
env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8];
env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9];
env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10];
env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11];
env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12];
env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13];
env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14];
env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15];
if (sregs.u.e.features & KVM_SREGS_E_SPE) {
env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0];
env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1];
env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2];
}
if (sregs.u.e.features & KVM_SREGS_E_PM) {
env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3];
}
if (sregs.u.e.features & KVM_SREGS_E_PC) {
env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4];
env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5];
}
}
if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) {
env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0;
env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1;
env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2;
env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff;
env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4;
env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6;
env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32;
env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg;
env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0];
env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1];
}
if (sregs.u.e.features & KVM_SREGS_EXP) {
env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr;
}
if (sregs.u.e.features & KVM_SREGS_E_PD) {
env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc;
env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc;
}
if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) {
env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr;
env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar;
env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0;
if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) {
env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1;
env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2;
}
}
}
#endif
#ifdef KVM_CAP_PPC_SEGSTATE
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
if (cap_segstate) {
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
if (ret < 0) {
return ret;
}
ppc_store_sdr1(env, sregs.u.s.sdr1);
/* Sync SLB */

View File

@ -2,6 +2,7 @@
* PowerPC emulation for qemu: main translation routines.
*
* Copyright (c) 2003-2007 Jocelyn Mayer
* Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -9124,9 +9125,84 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
}
cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
#if !defined(CONFIG_USER_ONLY)
cpu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " SDR1 "
TARGET_FMT_lx "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1],
env->spr[SPR_SDR1]);
cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
" PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
env->spr[SPR_SRR0], env->spr[SPR_SRR1],
env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
" SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
" SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
if (env->excp_model == POWERPC_EXCP_BOOKE) {
cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
" MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
" ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
" IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
" EPR " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
env->spr[SPR_BOOKE_EPR]);
/* FSL-specific */
cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
" PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
/*
* IVORs are left out as they are large and do not change often --
* they can be read with "p $ivor0", "p $ivor1", etc.
*/
}
switch (env->mmu_model) {
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64)
case POWERPC_MMU_620:
case POWERPC_MMU_64B:
#endif
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
break;
case POWERPC_MMU_BOOKE_FSL:
cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
" MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
" MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
" TLB1CFG " TARGET_FMT_lx "\n",
env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
env->spr[SPR_BOOKE_TLB1CFG]);
break;
default:
break;
}
#endif
#undef RGPL