From 32ecd72b6edc1f33ce757da0b0a8032c31582a7e Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Mon, 22 Apr 2013 13:20:32 -0400 Subject: [PATCH] kvm: Add support for state dumping on ARM --- src/cpu/kvm/arm_cpu.cc | 142 +++++++++++++++++++++++++++++++++++++++++ src/cpu/kvm/arm_cpu.hh | 7 ++ 2 files changed, 149 insertions(+) diff --git a/src/cpu/kvm/arm_cpu.cc b/src/cpu/kvm/arm_cpu.cc index 92851520f..d1082c53e 100644 --- a/src/cpu/kvm/arm_cpu.cc +++ b/src/cpu/kvm/arm_cpu.cc @@ -285,6 +285,13 @@ ArmKvmCPU::tick() BaseKvmCPU::tick(); } +void +ArmKvmCPU::dump() +{ + dumpKvmStateCore(); + dumpKvmStateMisc(); +} + void ArmKvmCPU::updateKvmState() { @@ -429,6 +436,130 @@ ArmKvmCPU::getRegList(struct kvm_reg_list ®s) const } } +void +ArmKvmCPU::dumpKvmStateCore() +{ + /* Print core registers */ + uint32_t pc(getOneRegU32(REG_CORE32(usr_regs.ARM_pc))); + inform("PC: 0x%x\n", pc); + + for (const KvmIntRegInfo *ri(kvmIntRegs); + ri->idx != NUM_INTREGS; ++ri) { + + uint32_t value(getOneRegU32(ri->id)); + inform("%s: 0x%x\n", ri->name, value); + } + + for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); + ri->idx != NUM_MISCREGS; ++ri) { + + uint32_t value(getOneRegU32(ri->id)); + inform("%s: 0x%x\n", miscRegName[ri->idx], value); + } +} + +void +ArmKvmCPU::dumpKvmStateMisc() +{ + /* Print co-processor registers */ + const RegIndexVector ®_ids(getRegList());; + for (RegIndexVector::const_iterator it(reg_ids.begin()); + it != reg_ids.end(); ++it) { + uint64_t id(*it); + + if (REG_IS_ARM(id) && REG_CP(id) <= 15) { + dumpKvmStateCoProc(id); + } else if (REG_IS_ARM(id) && REG_IS_VFP(id)) { + dumpKvmStateVFP(id); + } else if (REG_IS_ARM(id) && REG_IS_DEMUX(id)) { + switch (id & KVM_REG_ARM_DEMUX_ID_MASK) { + case KVM_REG_ARM_DEMUX_ID_CCSIDR: + inform("CCSIDR [0x%x]: %s\n", + EXTRACT_FIELD(id, + KVM_REG_ARM_DEMUX_VAL_MASK, + KVM_REG_ARM_DEMUX_VAL_SHIFT), + getAndFormatOneReg(id)); + break; + default: + inform("DEMUX [0x%x, 0x%x]: %s\n", + EXTRACT_FIELD(id, + KVM_REG_ARM_DEMUX_ID_MASK, + KVM_REG_ARM_DEMUX_ID_SHIFT), + EXTRACT_FIELD(id, + KVM_REG_ARM_DEMUX_VAL_MASK, + KVM_REG_ARM_DEMUX_VAL_SHIFT), + getAndFormatOneReg(id)); + break; + } + } else if (!REG_IS_CORE(id)) { + inform("0x%x: %s\n", id, getAndFormatOneReg(id)); + } + } +} + +void +ArmKvmCPU::dumpKvmStateCoProc(uint64_t id) +{ + assert(REG_IS_ARM(id)); + assert(REG_CP(id) <= 15); + + if (REG_IS_32BIT(id)) { + // 32-bit co-proc registers + MiscRegIndex idx(decodeCoProcReg(id)); + uint32_t value(getOneRegU32(id)); + + if (idx != NUM_MISCREGS && + !(idx >= MISCREG_CP15_UNIMP_START && idx < MISCREG_CP15_END)) { + const char *name(miscRegName[idx]); + const unsigned m5_ne(tc->readMiscRegNoEffect(idx)); + const unsigned m5_e(tc->readMiscReg(idx)); + inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: " + "[%s]: 0x%x/0x%x\n", + REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), + REG_OPC2(id), isInvariantReg(id), + name, value, m5_e); + if (m5_e != m5_ne) { + inform("readMiscReg: %x, readMiscRegNoEffect: %x\n", + m5_e, m5_ne); + } + } else { + const char *name(idx != NUM_MISCREGS ? miscRegName[idx] : "-"); + inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: [%s]: " + "0x%x\n", + REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), + REG_OPC2(id), isInvariantReg(id), name, value); + } + } else { + inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i " + "len: 0x%x]: %s\n", + REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), + REG_OPC2(id), isInvariantReg(id), + EXTRACT_FIELD(id, KVM_REG_SIZE_MASK, KVM_REG_SIZE_SHIFT), + getAndFormatOneReg(id)); + } +} + +void +ArmKvmCPU::dumpKvmStateVFP(uint64_t id) +{ + assert(REG_IS_ARM(id)); + assert(REG_IS_VFP(id)); + + if (REG_IS_VFP_REG(id)) { + const unsigned idx(id & KVM_REG_ARM_VFP_MASK); + inform("VFP reg %i: %s", idx, getAndFormatOneReg(id)); + } else if (REG_IS_VFP_CTRL(id)) { + MiscRegIndex idx(decodeVFPCtrlReg(id)); + if (idx != NUM_MISCREGS) { + inform("VFP [%s]: %s", miscRegName[idx], getAndFormatOneReg(id)); + } else { + inform("VFP [0x%x]: %s", id, getAndFormatOneReg(id)); + } + } else { + inform("VFP [0x%x]: %s", id, getAndFormatOneReg(id)); + } +} + void ArmKvmCPU::updateKvmStateCore() { @@ -450,6 +581,9 @@ ArmKvmCPU::updateKvmStateCore() DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value); setOneReg(ri->id, value); } + + if (DTRACE(KvmContext)) + dumpKvmStateCore(); } void @@ -486,6 +620,8 @@ ArmKvmCPU::updateKvmStateMisc() } warned = true; + if (DTRACE(KvmContext)) + dumpKvmStateMisc(); } void @@ -589,6 +725,9 @@ ArmKvmCPU::updateTCStateCore() PCState pc(tc->pcState()); pc.set(getOneRegU32(REG_CORE32(usr_regs.ARM_pc))); tc->pcState(pc); + + if (DTRACE(KvmContext)) + dumpKvmStateCore(); } void @@ -619,6 +758,9 @@ ArmKvmCPU::updateTCStateMisc() } warned = true; + + if (DTRACE(KvmContext)) + dumpKvmStateMisc(); } void diff --git a/src/cpu/kvm/arm_cpu.hh b/src/cpu/kvm/arm_cpu.hh index b9d18b7f1..687cb48b1 100644 --- a/src/cpu/kvm/arm_cpu.hh +++ b/src/cpu/kvm/arm_cpu.hh @@ -66,6 +66,8 @@ class ArmKvmCPU : public BaseKvmCPU void startup(); + void dump(); + protected: struct KvmIntRegInfo { /** KVM ID */ @@ -128,6 +130,11 @@ class ArmKvmCPU : public BaseKvmCPU */ bool getRegList(struct kvm_reg_list ®s) const; + void dumpKvmStateCore(); + void dumpKvmStateMisc(); + void dumpKvmStateCoProc(uint64_t id); + void dumpKvmStateVFP(uint64_t id); + void updateKvmStateCore(); void updateKvmStateMisc(); void updateKvmStateCoProc(uint64_t id, bool show_warnings); -- 2.30.2