armv8_cpu.cc revision 10860
110860Sandreas.sandberg@arm.com/*
210860Sandreas.sandberg@arm.com * Copyright (c) 2015 ARM Limited
310860Sandreas.sandberg@arm.com * All rights reserved
410860Sandreas.sandberg@arm.com *
510860Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
610860Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
710860Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
810860Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
910860Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1010860Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1110860Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1210860Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1310860Sandreas.sandberg@arm.com *
1410860Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
1510860Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
1610860Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
1710860Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
1810860Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1910860Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
2010860Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
2110860Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
2210860Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
2310860Sandreas.sandberg@arm.com * this software without specific prior written permission.
2410860Sandreas.sandberg@arm.com *
2510860Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610860Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710860Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810860Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910860Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010860Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110860Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210860Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310860Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410860Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510860Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610860Sandreas.sandberg@arm.com *
3710860Sandreas.sandberg@arm.com * Authors: Andreas Sandberg
3810860Sandreas.sandberg@arm.com */
3910860Sandreas.sandberg@arm.com
4010860Sandreas.sandberg@arm.com#include "arch/arm/kvm/armv8_cpu.hh"
4110860Sandreas.sandberg@arm.com
4210860Sandreas.sandberg@arm.com#include <linux/kvm.h>
4310860Sandreas.sandberg@arm.com
4410860Sandreas.sandberg@arm.com#include "debug/KvmContext.hh"
4510860Sandreas.sandberg@arm.com#include "params/ArmV8KvmCPU.hh"
4610860Sandreas.sandberg@arm.com
4710860Sandreas.sandberg@arm.com// Unlike gem5, kvm doesn't count the SP as a normal integer register,
4810860Sandreas.sandberg@arm.com// which means we only have 31 normal integer registers.
4910860Sandreas.sandberg@arm.comconstexpr static unsigned NUM_XREGS = NUM_ARCH_INTREGS - 1;
5010860Sandreas.sandberg@arm.comstatic_assert(NUM_XREGS == 31, "Unexpected number of aarch64 int. regs.");
5110860Sandreas.sandberg@arm.com
5210860Sandreas.sandberg@arm.com// The KVM interface accesses vector registers of 4 single precision
5310860Sandreas.sandberg@arm.com// floats instead of individual registers.
5410860Sandreas.sandberg@arm.comconstexpr static unsigned NUM_QREGS = NumFloatV8ArchRegs / 4;
5510860Sandreas.sandberg@arm.comstatic_assert(NUM_QREGS == 32, "Unexpected number of aarch64 vector regs.");
5610860Sandreas.sandberg@arm.com
5710860Sandreas.sandberg@arm.com#define EXTRACT_FIELD(v, name) \
5810860Sandreas.sandberg@arm.com    (((v) & name ## _MASK) >> name ## _SHIFT)
5910860Sandreas.sandberg@arm.com
6010860Sandreas.sandberg@arm.com#define CORE_REG(name, size)                               \
6110860Sandreas.sandberg@arm.com    (KVM_REG_ARM64 | KVM_REG_ARM_CORE |                    \
6210860Sandreas.sandberg@arm.com     KVM_REG_SIZE_ ## size |                               \
6310860Sandreas.sandberg@arm.com     KVM_REG_ARM_CORE_REG(name))
6410860Sandreas.sandberg@arm.com
6510860Sandreas.sandberg@arm.com#define INT_REG(name) CORE_REG(name, U64)
6610860Sandreas.sandberg@arm.com#define SIMD_REG(name) CORE_REG(name, U128)
6710860Sandreas.sandberg@arm.com
6810860Sandreas.sandberg@arm.comconstexpr uint64_t
6910860Sandreas.sandberg@arm.comkvmXReg(const int num)
7010860Sandreas.sandberg@arm.com{
7110860Sandreas.sandberg@arm.com    return INT_REG(regs.regs[0]) +
7210860Sandreas.sandberg@arm.com        (INT_REG(regs.regs[1]) - INT_REG(regs.regs[0])) * num;
7310860Sandreas.sandberg@arm.com}
7410860Sandreas.sandberg@arm.com
7510860Sandreas.sandberg@arm.comconstexpr uint64_t
7610860Sandreas.sandberg@arm.comkvmFPReg(const int num)
7710860Sandreas.sandberg@arm.com{
7810860Sandreas.sandberg@arm.com    return SIMD_REG(fp_regs.vregs[0]) +
7910860Sandreas.sandberg@arm.com        (SIMD_REG(fp_regs.vregs[1]) - SIMD_REG(fp_regs.vregs[0])) * num;
8010860Sandreas.sandberg@arm.com}
8110860Sandreas.sandberg@arm.com
8210860Sandreas.sandberg@arm.comunion KvmFPReg {
8310860Sandreas.sandberg@arm.com    union {
8410860Sandreas.sandberg@arm.com        uint32_t i;
8510860Sandreas.sandberg@arm.com        float f;
8610860Sandreas.sandberg@arm.com    } s[4];
8710860Sandreas.sandberg@arm.com
8810860Sandreas.sandberg@arm.com    union {
8910860Sandreas.sandberg@arm.com        uint64_t i;
9010860Sandreas.sandberg@arm.com        double f;
9110860Sandreas.sandberg@arm.com    } d[2];
9210860Sandreas.sandberg@arm.com
9310860Sandreas.sandberg@arm.com    uint8_t data[32];
9410860Sandreas.sandberg@arm.com};
9510860Sandreas.sandberg@arm.com
9610860Sandreas.sandberg@arm.com#define FP_REGS_PER_VFP_REG 4
9710860Sandreas.sandberg@arm.comstatic_assert(sizeof(FloatRegBits) == 4, "Unexpected float reg size");
9810860Sandreas.sandberg@arm.com
9910860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::IntRegInfo> ArmV8KvmCPU::intRegMap = {
10010860Sandreas.sandberg@arm.com    { INT_REG(regs.sp), INTREG_SP0, "SP(EL0)" },
10110860Sandreas.sandberg@arm.com    { INT_REG(sp_el1), INTREG_SP1, "SP(EL1)" },
10210860Sandreas.sandberg@arm.com};
10310860Sandreas.sandberg@arm.com
10410860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
10510860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(regs.pstate), MISCREG_CPSR, "PSTATE"),
10610860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(elr_el1), MISCREG_ELR_EL1, "ELR(EL1)"),
10710860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_EL1]), MISCREG_SPSR_EL1, "SPSR(EL1)"),
10810860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_ABT]), MISCREG_SPSR_ABT, "SPSR(ABT)"),
10910860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_UND]), MISCREG_SPSR_UND, "SPSR(UND)"),
11010860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_IRQ]), MISCREG_SPSR_IRQ, "SPSR(IRQ)"),
11110860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_FIQ]), MISCREG_SPSR_FIQ, "SPSR(FIQ)"),
11210860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(fp_regs.fpsr), MISCREG_FPSR, "FPSR"),
11310860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(fp_regs.fpcr), MISCREG_FPCR, "FPCR"),
11410860Sandreas.sandberg@arm.com};
11510860Sandreas.sandberg@arm.com
11610860Sandreas.sandberg@arm.comArmV8KvmCPU::ArmV8KvmCPU(ArmV8KvmCPUParams *params)
11710860Sandreas.sandberg@arm.com    : BaseArmKvmCPU(params)
11810860Sandreas.sandberg@arm.com{
11910860Sandreas.sandberg@arm.com}
12010860Sandreas.sandberg@arm.com
12110860Sandreas.sandberg@arm.comArmV8KvmCPU::~ArmV8KvmCPU()
12210860Sandreas.sandberg@arm.com{
12310860Sandreas.sandberg@arm.com}
12410860Sandreas.sandberg@arm.com
12510860Sandreas.sandberg@arm.comvoid
12610860Sandreas.sandberg@arm.comArmV8KvmCPU::dump()
12710860Sandreas.sandberg@arm.com{
12810860Sandreas.sandberg@arm.com    inform("Integer registers:\n");
12910860Sandreas.sandberg@arm.com    inform("  PC: %s\n", getAndFormatOneReg(INT_REG(regs.pc)));
13010860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i)
13110860Sandreas.sandberg@arm.com        inform("  X%i: %s\n", i, getAndFormatOneReg(kvmXReg(i)));
13210860Sandreas.sandberg@arm.com
13310860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i)
13410860Sandreas.sandberg@arm.com        inform("  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
13510860Sandreas.sandberg@arm.com
13610860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap)
13710860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
13810860Sandreas.sandberg@arm.com
13910860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap)
14010860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
14110860Sandreas.sandberg@arm.com
14210860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
14310860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
14410860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64) {
14510860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
14610860Sandreas.sandberg@arm.com            continue;
14710860Sandreas.sandberg@arm.com        }
14810860Sandreas.sandberg@arm.com
14910860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
15010860Sandreas.sandberg@arm.com        switch (type) {
15110860Sandreas.sandberg@arm.com          case KVM_REG_ARM_CORE:
15210860Sandreas.sandberg@arm.com            // These have already been printed
15310860Sandreas.sandberg@arm.com            break;
15410860Sandreas.sandberg@arm.com
15510860Sandreas.sandberg@arm.com          case KVM_REG_ARM64_SYSREG: {
15610860Sandreas.sandberg@arm.com              const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
15710860Sandreas.sandberg@arm.com              const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
15810860Sandreas.sandberg@arm.com              const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
15910860Sandreas.sandberg@arm.com              const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
16010860Sandreas.sandberg@arm.com              const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
16110860Sandreas.sandberg@arm.com              const MiscRegIndex idx(
16210860Sandreas.sandberg@arm.com                  decodeAArch64SysReg(op0, op1, crn, crm, op2));
16310860Sandreas.sandberg@arm.com
16410860Sandreas.sandberg@arm.com              inform("  %s (op0: %i, op1: %i, crn: %i, crm: %i, op2: %i): %s",
16510860Sandreas.sandberg@arm.com                     miscRegName[idx], op0, op1, crn, crm, op2,
16610860Sandreas.sandberg@arm.com                     getAndFormatOneReg(reg));
16710860Sandreas.sandberg@arm.com          } break;
16810860Sandreas.sandberg@arm.com
16910860Sandreas.sandberg@arm.com          case KVM_REG_ARM_DEMUX: {
17010860Sandreas.sandberg@arm.com              const uint64_t id(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_ID));
17110860Sandreas.sandberg@arm.com              const uint64_t val(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_VAL));
17210860Sandreas.sandberg@arm.com              if (id == KVM_REG_ARM_DEMUX_ID_CCSIDR) {
17310860Sandreas.sandberg@arm.com                  inform("  CSSIDR[%i]: %s\n", val,
17410860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
17510860Sandreas.sandberg@arm.com              } else {
17610860Sandreas.sandberg@arm.com                  inform("  UNKNOWN[%i:%i]: %s\n", id, val,
17710860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
17810860Sandreas.sandberg@arm.com              }
17910860Sandreas.sandberg@arm.com          } break;
18010860Sandreas.sandberg@arm.com
18110860Sandreas.sandberg@arm.com          default:
18210860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
18310860Sandreas.sandberg@arm.com        }
18410860Sandreas.sandberg@arm.com    }
18510860Sandreas.sandberg@arm.com}
18610860Sandreas.sandberg@arm.com
18710860Sandreas.sandberg@arm.comvoid
18810860Sandreas.sandberg@arm.comArmV8KvmCPU::updateKvmState()
18910860Sandreas.sandberg@arm.com{
19010860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateKvmState():\n");
19110860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
19210860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
19310860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
19410860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
19510860Sandreas.sandberg@arm.com    }
19610860Sandreas.sandberg@arm.com
19710860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
19810860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(INTREG_X0 + i));
19910860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
20010860Sandreas.sandberg@arm.com        setOneReg(kvmXReg(i), value);
20110860Sandreas.sandberg@arm.com    }
20210860Sandreas.sandberg@arm.com
20310860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
20410860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(ri.idx));
20510860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
20610860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
20710860Sandreas.sandberg@arm.com    }
20810860Sandreas.sandberg@arm.com
20910860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
21010860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
21110860Sandreas.sandberg@arm.com        KvmFPReg reg;
21210860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
21310860Sandreas.sandberg@arm.com            reg.s[j].i = tc->readFloatRegBits(reg_base + j);
21410860Sandreas.sandberg@arm.com
21510860Sandreas.sandberg@arm.com        setOneReg(kvmFPReg(i), reg.data);
21610860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
21710860Sandreas.sandberg@arm.com    }
21810860Sandreas.sandberg@arm.com
21910860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
22010860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
22110860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
22210860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
22310860Sandreas.sandberg@arm.com    }
22410860Sandreas.sandberg@arm.com
22510860Sandreas.sandberg@arm.com    setOneReg(INT_REG(regs.pc), tc->instAddr());
22610860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x\n", tc->instAddr());
22710860Sandreas.sandberg@arm.com}
22810860Sandreas.sandberg@arm.com
22910860Sandreas.sandberg@arm.comvoid
23010860Sandreas.sandberg@arm.comArmV8KvmCPU::updateThreadContext()
23110860Sandreas.sandberg@arm.com{
23210860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateThreadContext():\n");
23310860Sandreas.sandberg@arm.com
23410860Sandreas.sandberg@arm.com    // Update core misc regs first as they (particularly PSTATE/CPSR)
23510860Sandreas.sandberg@arm.com    // affect how other registers are mapped.
23610860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
23710860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
23810860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
23910860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
24010860Sandreas.sandberg@arm.com    }
24110860Sandreas.sandberg@arm.com
24210860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
24310860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(kvmXReg(i)));
24410860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
24510860Sandreas.sandberg@arm.com        tc->setIntReg(INTREG_X0 + i, value);
24610860Sandreas.sandberg@arm.com    }
24710860Sandreas.sandberg@arm.com
24810860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
24910860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
25010860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
25110860Sandreas.sandberg@arm.com        tc->setIntReg(ri.idx, value);
25210860Sandreas.sandberg@arm.com    }
25310860Sandreas.sandberg@arm.com
25410860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
25510860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
25610860Sandreas.sandberg@arm.com        KvmFPReg reg;
25710860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
25810860Sandreas.sandberg@arm.com        getOneReg(kvmFPReg(i), reg.data);
25910860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
26010860Sandreas.sandberg@arm.com            tc->setFloatRegBits(reg_base + j, reg.s[j].i);
26110860Sandreas.sandberg@arm.com    }
26210860Sandreas.sandberg@arm.com
26310860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
26410860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
26510860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
26610860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
26710860Sandreas.sandberg@arm.com    }
26810860Sandreas.sandberg@arm.com
26910860Sandreas.sandberg@arm.com    const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
27010860Sandreas.sandberg@arm.com    PCState pc(getOneRegU64(INT_REG(regs.pc)));
27110860Sandreas.sandberg@arm.com    pc.aarch64(inAArch64(tc));
27210860Sandreas.sandberg@arm.com    pc.thumb(cpsr.t);
27310860Sandreas.sandberg@arm.com    pc.nextAArch64(inAArch64(tc));
27410860Sandreas.sandberg@arm.com    // TODO: This is a massive assumption that will break when
27510860Sandreas.sandberg@arm.com    // switching to thumb.
27610860Sandreas.sandberg@arm.com    pc.nextThumb(cpsr.t);
27710860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x (t: %i, a64: %i)\n",
27810860Sandreas.sandberg@arm.com            pc.instAddr(), pc.thumb(), pc.aarch64());
27910860Sandreas.sandberg@arm.com    tc->pcState(pc);
28010860Sandreas.sandberg@arm.com}
28110860Sandreas.sandberg@arm.com
28210860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> &
28310860Sandreas.sandberg@arm.comArmV8KvmCPU::getSysRegMap() const
28410860Sandreas.sandberg@arm.com{
28510860Sandreas.sandberg@arm.com    // Try to use the cached map
28610860Sandreas.sandberg@arm.com    if (!sysRegMap.empty())
28710860Sandreas.sandberg@arm.com        return sysRegMap;
28810860Sandreas.sandberg@arm.com
28910860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
29010860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
29110860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64)
29210860Sandreas.sandberg@arm.com            continue;
29310860Sandreas.sandberg@arm.com
29410860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
29510860Sandreas.sandberg@arm.com        if (type != KVM_REG_ARM64_SYSREG)
29610860Sandreas.sandberg@arm.com            continue;
29710860Sandreas.sandberg@arm.com
29810860Sandreas.sandberg@arm.com        const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
29910860Sandreas.sandberg@arm.com        const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
30010860Sandreas.sandberg@arm.com        const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
30110860Sandreas.sandberg@arm.com        const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
30210860Sandreas.sandberg@arm.com        const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
30310860Sandreas.sandberg@arm.com        const MiscRegIndex idx(decodeAArch64SysReg(op0, op1, crn, crm, op2));
30410860Sandreas.sandberg@arm.com        const auto &info(miscRegInfo[idx]);
30510860Sandreas.sandberg@arm.com        const bool writeable(
30610860Sandreas.sandberg@arm.com            info[MISCREG_USR_NS_WR] || info[MISCREG_USR_S_WR] ||
30710860Sandreas.sandberg@arm.com            info[MISCREG_PRI_S_WR] || info[MISCREG_PRI_NS_WR] ||
30810860Sandreas.sandberg@arm.com            info[MISCREG_HYP_WR] ||
30910860Sandreas.sandberg@arm.com            info[MISCREG_MON_NS0_WR] || info[MISCREG_MON_NS1_WR]);
31010860Sandreas.sandberg@arm.com        const bool implemented(
31110860Sandreas.sandberg@arm.com            info[MISCREG_IMPLEMENTED] || info[MISCREG_WARN_NOT_FAIL]);
31210860Sandreas.sandberg@arm.com
31310860Sandreas.sandberg@arm.com        // Only add implemented registers that we are going to be able
31410860Sandreas.sandberg@arm.com        // to write.
31510860Sandreas.sandberg@arm.com        if (implemented && writeable)
31610860Sandreas.sandberg@arm.com            sysRegMap.emplace_back(reg, idx, miscRegName[idx]);
31710860Sandreas.sandberg@arm.com    }
31810860Sandreas.sandberg@arm.com
31910860Sandreas.sandberg@arm.com    return sysRegMap;
32010860Sandreas.sandberg@arm.com}
32110860Sandreas.sandberg@arm.com
32210860Sandreas.sandberg@arm.comArmV8KvmCPU *
32310860Sandreas.sandberg@arm.comArmV8KvmCPUParams::create()
32410860Sandreas.sandberg@arm.com{
32510860Sandreas.sandberg@arm.com    return new ArmV8KvmCPU(this);
32610860Sandreas.sandberg@arm.com}
327