diff options
author | Scott Wood <scottwood@freescale.com> | 2011-04-29 17:10:23 -0500 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2011-05-09 22:31:37 +0200 |
commit | 90dc8812229a1d3f31bc08ccf0aa50e10282faef (patch) | |
tree | 5b8c980d3fa038f6c5e7b2aec60b1487c6885c21 /target-ppc | |
parent | 5666ca4ae06d20497f887241151278e266947087 (diff) |
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>
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/cpu.h | 1 | ||||
-rw-r--r-- | target-ppc/kvm.c | 143 | ||||
-rw-r--r-- | target-ppc/translate.c | 82 |
3 files changed, 214 insertions, 12 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 04b12590fa..303f8cec35 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -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) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 3ca39b7bc2..5a1b6cbdcc 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -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, ®s); 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 */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index a943dbcf8e..99f572a244 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -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 |