armv8_cpu.cc revision 11934
110860Sandreas.sandberg@arm.com/*
211934Sandreas.sandberg@arm.com * Copyright (c) 2015, 2017 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
6811934Sandreas.sandberg@arm.com#define SYS_MPIDR_EL1 ARM64_SYS_REG(0b11, 0b000, 0b0000, 0b0000, 0b101)
6911934Sandreas.sandberg@arm.com
7010860Sandreas.sandberg@arm.comconstexpr uint64_t
7110860Sandreas.sandberg@arm.comkvmXReg(const int num)
7210860Sandreas.sandberg@arm.com{
7310860Sandreas.sandberg@arm.com    return INT_REG(regs.regs[0]) +
7410860Sandreas.sandberg@arm.com        (INT_REG(regs.regs[1]) - INT_REG(regs.regs[0])) * num;
7510860Sandreas.sandberg@arm.com}
7610860Sandreas.sandberg@arm.com
7710860Sandreas.sandberg@arm.comconstexpr uint64_t
7810860Sandreas.sandberg@arm.comkvmFPReg(const int num)
7910860Sandreas.sandberg@arm.com{
8010860Sandreas.sandberg@arm.com    return SIMD_REG(fp_regs.vregs[0]) +
8110860Sandreas.sandberg@arm.com        (SIMD_REG(fp_regs.vregs[1]) - SIMD_REG(fp_regs.vregs[0])) * num;
8210860Sandreas.sandberg@arm.com}
8310860Sandreas.sandberg@arm.com
8410860Sandreas.sandberg@arm.comunion KvmFPReg {
8510860Sandreas.sandberg@arm.com    union {
8610860Sandreas.sandberg@arm.com        uint32_t i;
8710860Sandreas.sandberg@arm.com        float f;
8810860Sandreas.sandberg@arm.com    } s[4];
8910860Sandreas.sandberg@arm.com
9010860Sandreas.sandberg@arm.com    union {
9110860Sandreas.sandberg@arm.com        uint64_t i;
9210860Sandreas.sandberg@arm.com        double f;
9310860Sandreas.sandberg@arm.com    } d[2];
9410860Sandreas.sandberg@arm.com
9510860Sandreas.sandberg@arm.com    uint8_t data[32];
9610860Sandreas.sandberg@arm.com};
9710860Sandreas.sandberg@arm.com
9810860Sandreas.sandberg@arm.com#define FP_REGS_PER_VFP_REG 4
9910860Sandreas.sandberg@arm.comstatic_assert(sizeof(FloatRegBits) == 4, "Unexpected float reg size");
10010860Sandreas.sandberg@arm.com
10110860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::IntRegInfo> ArmV8KvmCPU::intRegMap = {
10210860Sandreas.sandberg@arm.com    { INT_REG(regs.sp), INTREG_SP0, "SP(EL0)" },
10310860Sandreas.sandberg@arm.com    { INT_REG(sp_el1), INTREG_SP1, "SP(EL1)" },
10410860Sandreas.sandberg@arm.com};
10510860Sandreas.sandberg@arm.com
10610860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
10710860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(elr_el1), MISCREG_ELR_EL1, "ELR(EL1)"),
10810860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_EL1]), MISCREG_SPSR_EL1, "SPSR(EL1)"),
10910860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_ABT]), MISCREG_SPSR_ABT, "SPSR(ABT)"),
11010860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_UND]), MISCREG_SPSR_UND, "SPSR(UND)"),
11110860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_IRQ]), MISCREG_SPSR_IRQ, "SPSR(IRQ)"),
11210860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_FIQ]), MISCREG_SPSR_FIQ, "SPSR(FIQ)"),
11310860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(fp_regs.fpsr), MISCREG_FPSR, "FPSR"),
11410860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(fp_regs.fpcr), MISCREG_FPCR, "FPCR"),
11510860Sandreas.sandberg@arm.com};
11610860Sandreas.sandberg@arm.com
11711934Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegIdMap = {
11811934Sandreas.sandberg@arm.com    MiscRegInfo(SYS_MPIDR_EL1, MISCREG_MPIDR_EL1, "MPIDR(EL1)"),
11911934Sandreas.sandberg@arm.com};
12011934Sandreas.sandberg@arm.com
12110860Sandreas.sandberg@arm.comArmV8KvmCPU::ArmV8KvmCPU(ArmV8KvmCPUParams *params)
12210860Sandreas.sandberg@arm.com    : BaseArmKvmCPU(params)
12310860Sandreas.sandberg@arm.com{
12410860Sandreas.sandberg@arm.com}
12510860Sandreas.sandberg@arm.com
12610860Sandreas.sandberg@arm.comArmV8KvmCPU::~ArmV8KvmCPU()
12710860Sandreas.sandberg@arm.com{
12810860Sandreas.sandberg@arm.com}
12910860Sandreas.sandberg@arm.com
13010860Sandreas.sandberg@arm.comvoid
13111934Sandreas.sandberg@arm.comArmV8KvmCPU::startup()
13211934Sandreas.sandberg@arm.com{
13311934Sandreas.sandberg@arm.com    BaseArmKvmCPU::startup();
13411934Sandreas.sandberg@arm.com
13511934Sandreas.sandberg@arm.com    // Override ID registers that KVM should "inherit" from gem5.
13611934Sandreas.sandberg@arm.com    for (const auto &ri : miscRegIdMap) {
13711934Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
13811934Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
13911934Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
14011934Sandreas.sandberg@arm.com    }
14111934Sandreas.sandberg@arm.com}
14211934Sandreas.sandberg@arm.com
14311934Sandreas.sandberg@arm.comvoid
14411178Svictor.garcia@arm.comArmV8KvmCPU::dump() const
14510860Sandreas.sandberg@arm.com{
14610860Sandreas.sandberg@arm.com    inform("Integer registers:\n");
14710860Sandreas.sandberg@arm.com    inform("  PC: %s\n", getAndFormatOneReg(INT_REG(regs.pc)));
14810860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i)
14910860Sandreas.sandberg@arm.com        inform("  X%i: %s\n", i, getAndFormatOneReg(kvmXReg(i)));
15010860Sandreas.sandberg@arm.com
15110860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i)
15210860Sandreas.sandberg@arm.com        inform("  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
15310860Sandreas.sandberg@arm.com
15410860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap)
15510860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
15610860Sandreas.sandberg@arm.com
15711890Srjthakur@google.com    inform("  %s: %s\n", "PSTATE", getAndFormatOneReg(INT_REG(regs.pstate)));
15811890Srjthakur@google.com
15910860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap)
16010860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
16110860Sandreas.sandberg@arm.com
16211934Sandreas.sandberg@arm.com    for (const auto &ri : miscRegIdMap)
16311934Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
16411934Sandreas.sandberg@arm.com
16510860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
16610860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
16710860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64) {
16810860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
16910860Sandreas.sandberg@arm.com            continue;
17010860Sandreas.sandberg@arm.com        }
17110860Sandreas.sandberg@arm.com
17210860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
17310860Sandreas.sandberg@arm.com        switch (type) {
17410860Sandreas.sandberg@arm.com          case KVM_REG_ARM_CORE:
17510860Sandreas.sandberg@arm.com            // These have already been printed
17610860Sandreas.sandberg@arm.com            break;
17710860Sandreas.sandberg@arm.com
17810860Sandreas.sandberg@arm.com          case KVM_REG_ARM64_SYSREG: {
17910860Sandreas.sandberg@arm.com              const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
18010860Sandreas.sandberg@arm.com              const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
18110860Sandreas.sandberg@arm.com              const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
18210860Sandreas.sandberg@arm.com              const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
18310860Sandreas.sandberg@arm.com              const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
18410860Sandreas.sandberg@arm.com              const MiscRegIndex idx(
18510860Sandreas.sandberg@arm.com                  decodeAArch64SysReg(op0, op1, crn, crm, op2));
18610860Sandreas.sandberg@arm.com
18710860Sandreas.sandberg@arm.com              inform("  %s (op0: %i, op1: %i, crn: %i, crm: %i, op2: %i): %s",
18810860Sandreas.sandberg@arm.com                     miscRegName[idx], op0, op1, crn, crm, op2,
18910860Sandreas.sandberg@arm.com                     getAndFormatOneReg(reg));
19010860Sandreas.sandberg@arm.com          } break;
19110860Sandreas.sandberg@arm.com
19210860Sandreas.sandberg@arm.com          case KVM_REG_ARM_DEMUX: {
19310860Sandreas.sandberg@arm.com              const uint64_t id(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_ID));
19410860Sandreas.sandberg@arm.com              const uint64_t val(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_VAL));
19510860Sandreas.sandberg@arm.com              if (id == KVM_REG_ARM_DEMUX_ID_CCSIDR) {
19610860Sandreas.sandberg@arm.com                  inform("  CSSIDR[%i]: %s\n", val,
19710860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
19810860Sandreas.sandberg@arm.com              } else {
19910860Sandreas.sandberg@arm.com                  inform("  UNKNOWN[%i:%i]: %s\n", id, val,
20010860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
20110860Sandreas.sandberg@arm.com              }
20210860Sandreas.sandberg@arm.com          } break;
20310860Sandreas.sandberg@arm.com
20410860Sandreas.sandberg@arm.com          default:
20510860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
20610860Sandreas.sandberg@arm.com        }
20710860Sandreas.sandberg@arm.com    }
20810860Sandreas.sandberg@arm.com}
20910860Sandreas.sandberg@arm.com
21010860Sandreas.sandberg@arm.comvoid
21110860Sandreas.sandberg@arm.comArmV8KvmCPU::updateKvmState()
21210860Sandreas.sandberg@arm.com{
21310860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateKvmState():\n");
21411890Srjthakur@google.com
21511890Srjthakur@google.com    // update pstate register state
21611890Srjthakur@google.com    CPSR cpsr(tc->readMiscReg(MISCREG_CPSR));
21711890Srjthakur@google.com    cpsr.nz = tc->readCCReg(CCREG_NZ);
21811890Srjthakur@google.com    cpsr.c = tc->readCCReg(CCREG_C);
21911890Srjthakur@google.com    cpsr.v = tc->readCCReg(CCREG_V);
22011890Srjthakur@google.com    if (cpsr.width) {
22111890Srjthakur@google.com        cpsr.ge = tc->readCCReg(CCREG_GE);
22211890Srjthakur@google.com    } else {
22311890Srjthakur@google.com        cpsr.ge = 0;
22411890Srjthakur@google.com    }
22511890Srjthakur@google.com    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
22611890Srjthakur@google.com    setOneReg(INT_REG(regs.pstate), cpsr);
22711890Srjthakur@google.com
22810860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
22910860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
23010860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
23110860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
23210860Sandreas.sandberg@arm.com    }
23310860Sandreas.sandberg@arm.com
23410860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
23510860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(INTREG_X0 + i));
23610860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
23710860Sandreas.sandberg@arm.com        setOneReg(kvmXReg(i), value);
23810860Sandreas.sandberg@arm.com    }
23910860Sandreas.sandberg@arm.com
24010860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
24110860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(ri.idx));
24210860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
24310860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
24410860Sandreas.sandberg@arm.com    }
24510860Sandreas.sandberg@arm.com
24610860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
24710860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
24810860Sandreas.sandberg@arm.com        KvmFPReg reg;
24910860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
25010860Sandreas.sandberg@arm.com            reg.s[j].i = tc->readFloatRegBits(reg_base + j);
25110860Sandreas.sandberg@arm.com
25210860Sandreas.sandberg@arm.com        setOneReg(kvmFPReg(i), reg.data);
25310860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
25410860Sandreas.sandberg@arm.com    }
25510860Sandreas.sandberg@arm.com
25610860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
25710860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
25810860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
25910860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
26010860Sandreas.sandberg@arm.com    }
26110860Sandreas.sandberg@arm.com
26210860Sandreas.sandberg@arm.com    setOneReg(INT_REG(regs.pc), tc->instAddr());
26310860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x\n", tc->instAddr());
26410860Sandreas.sandberg@arm.com}
26510860Sandreas.sandberg@arm.com
26610860Sandreas.sandberg@arm.comvoid
26710860Sandreas.sandberg@arm.comArmV8KvmCPU::updateThreadContext()
26810860Sandreas.sandberg@arm.com{
26910860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateThreadContext():\n");
27010860Sandreas.sandberg@arm.com
27111890Srjthakur@google.com    // Update pstate thread context
27211890Srjthakur@google.com    const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
27311890Srjthakur@google.com    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
27411890Srjthakur@google.com    tc->setMiscRegNoEffect(MISCREG_CPSR, cpsr);
27511890Srjthakur@google.com    tc->setCCReg(CCREG_NZ, cpsr.nz);
27611890Srjthakur@google.com    tc->setCCReg(CCREG_C, cpsr.c);
27711890Srjthakur@google.com    tc->setCCReg(CCREG_V, cpsr.v);
27811890Srjthakur@google.com    if (cpsr.width) {
27911890Srjthakur@google.com        tc->setCCReg(CCREG_GE, cpsr.ge);
28011890Srjthakur@google.com    }
28111890Srjthakur@google.com
28211890Srjthakur@google.com    // Update core misc regs first as they
28310860Sandreas.sandberg@arm.com    // affect how other registers are mapped.
28410860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
28510860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
28610860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
28710860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
28810860Sandreas.sandberg@arm.com    }
28910860Sandreas.sandberg@arm.com
29010860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
29110860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(kvmXReg(i)));
29210860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
29311891Srjthakur@google.com        // KVM64 returns registers in 64-bit layout. If we are in aarch32
29411891Srjthakur@google.com        // mode, we need to map these to banked ARM32 registers.
29511891Srjthakur@google.com        if (inAArch64(tc)) {
29611891Srjthakur@google.com            tc->setIntReg(INTREG_X0 + i, value);
29711891Srjthakur@google.com        } else {
29811891Srjthakur@google.com            tc->setIntRegFlat(IntReg64Map[INTREG_X0 + i], value);
29911891Srjthakur@google.com        }
30010860Sandreas.sandberg@arm.com    }
30110860Sandreas.sandberg@arm.com
30210860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
30310860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
30410860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
30510860Sandreas.sandberg@arm.com        tc->setIntReg(ri.idx, value);
30610860Sandreas.sandberg@arm.com    }
30710860Sandreas.sandberg@arm.com
30810860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
30910860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
31010860Sandreas.sandberg@arm.com        KvmFPReg reg;
31110860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
31210860Sandreas.sandberg@arm.com        getOneReg(kvmFPReg(i), reg.data);
31310860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
31410860Sandreas.sandberg@arm.com            tc->setFloatRegBits(reg_base + j, reg.s[j].i);
31510860Sandreas.sandberg@arm.com    }
31610860Sandreas.sandberg@arm.com
31710860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
31810860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
31910860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
32010860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
32110860Sandreas.sandberg@arm.com    }
32210860Sandreas.sandberg@arm.com
32310860Sandreas.sandberg@arm.com    PCState pc(getOneRegU64(INT_REG(regs.pc)));
32410860Sandreas.sandberg@arm.com    pc.aarch64(inAArch64(tc));
32510860Sandreas.sandberg@arm.com    pc.thumb(cpsr.t);
32610860Sandreas.sandberg@arm.com    pc.nextAArch64(inAArch64(tc));
32710860Sandreas.sandberg@arm.com    // TODO: This is a massive assumption that will break when
32810860Sandreas.sandberg@arm.com    // switching to thumb.
32910860Sandreas.sandberg@arm.com    pc.nextThumb(cpsr.t);
33010860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x (t: %i, a64: %i)\n",
33110860Sandreas.sandberg@arm.com            pc.instAddr(), pc.thumb(), pc.aarch64());
33210860Sandreas.sandberg@arm.com    tc->pcState(pc);
33310860Sandreas.sandberg@arm.com}
33410860Sandreas.sandberg@arm.com
33510860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> &
33610860Sandreas.sandberg@arm.comArmV8KvmCPU::getSysRegMap() const
33710860Sandreas.sandberg@arm.com{
33810860Sandreas.sandberg@arm.com    // Try to use the cached map
33910860Sandreas.sandberg@arm.com    if (!sysRegMap.empty())
34010860Sandreas.sandberg@arm.com        return sysRegMap;
34110860Sandreas.sandberg@arm.com
34210860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
34310860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
34410860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64)
34510860Sandreas.sandberg@arm.com            continue;
34610860Sandreas.sandberg@arm.com
34710860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
34810860Sandreas.sandberg@arm.com        if (type != KVM_REG_ARM64_SYSREG)
34910860Sandreas.sandberg@arm.com            continue;
35010860Sandreas.sandberg@arm.com
35110860Sandreas.sandberg@arm.com        const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
35210860Sandreas.sandberg@arm.com        const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
35310860Sandreas.sandberg@arm.com        const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
35410860Sandreas.sandberg@arm.com        const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
35510860Sandreas.sandberg@arm.com        const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
35610860Sandreas.sandberg@arm.com        const MiscRegIndex idx(decodeAArch64SysReg(op0, op1, crn, crm, op2));
35710860Sandreas.sandberg@arm.com        const auto &info(miscRegInfo[idx]);
35810860Sandreas.sandberg@arm.com        const bool writeable(
35910860Sandreas.sandberg@arm.com            info[MISCREG_USR_NS_WR] || info[MISCREG_USR_S_WR] ||
36010860Sandreas.sandberg@arm.com            info[MISCREG_PRI_S_WR] || info[MISCREG_PRI_NS_WR] ||
36110860Sandreas.sandberg@arm.com            info[MISCREG_HYP_WR] ||
36210860Sandreas.sandberg@arm.com            info[MISCREG_MON_NS0_WR] || info[MISCREG_MON_NS1_WR]);
36310860Sandreas.sandberg@arm.com        const bool implemented(
36410860Sandreas.sandberg@arm.com            info[MISCREG_IMPLEMENTED] || info[MISCREG_WARN_NOT_FAIL]);
36510860Sandreas.sandberg@arm.com
36610860Sandreas.sandberg@arm.com        // Only add implemented registers that we are going to be able
36710860Sandreas.sandberg@arm.com        // to write.
36810860Sandreas.sandberg@arm.com        if (implemented && writeable)
36910860Sandreas.sandberg@arm.com            sysRegMap.emplace_back(reg, idx, miscRegName[idx]);
37010860Sandreas.sandberg@arm.com    }
37110860Sandreas.sandberg@arm.com
37210860Sandreas.sandberg@arm.com    return sysRegMap;
37310860Sandreas.sandberg@arm.com}
37410860Sandreas.sandberg@arm.com
37510860Sandreas.sandberg@arm.comArmV8KvmCPU *
37610860Sandreas.sandberg@arm.comArmV8KvmCPUParams::create()
37710860Sandreas.sandberg@arm.com{
37810860Sandreas.sandberg@arm.com    return new ArmV8KvmCPU(this);
37910860Sandreas.sandberg@arm.com}
380