armv8_cpu.cc revision 11891
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(elr_el1), MISCREG_ELR_EL1, "ELR(EL1)"),
10610860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_EL1]), MISCREG_SPSR_EL1, "SPSR(EL1)"),
10710860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_ABT]), MISCREG_SPSR_ABT, "SPSR(ABT)"),
10810860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_UND]), MISCREG_SPSR_UND, "SPSR(UND)"),
10910860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_IRQ]), MISCREG_SPSR_IRQ, "SPSR(IRQ)"),
11010860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(spsr[KVM_SPSR_FIQ]), MISCREG_SPSR_FIQ, "SPSR(FIQ)"),
11110860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(fp_regs.fpsr), MISCREG_FPSR, "FPSR"),
11210860Sandreas.sandberg@arm.com    MiscRegInfo(INT_REG(fp_regs.fpcr), MISCREG_FPCR, "FPCR"),
11310860Sandreas.sandberg@arm.com};
11410860Sandreas.sandberg@arm.com
11510860Sandreas.sandberg@arm.comArmV8KvmCPU::ArmV8KvmCPU(ArmV8KvmCPUParams *params)
11610860Sandreas.sandberg@arm.com    : BaseArmKvmCPU(params)
11710860Sandreas.sandberg@arm.com{
11810860Sandreas.sandberg@arm.com}
11910860Sandreas.sandberg@arm.com
12010860Sandreas.sandberg@arm.comArmV8KvmCPU::~ArmV8KvmCPU()
12110860Sandreas.sandberg@arm.com{
12210860Sandreas.sandberg@arm.com}
12310860Sandreas.sandberg@arm.com
12410860Sandreas.sandberg@arm.comvoid
12511178Svictor.garcia@arm.comArmV8KvmCPU::dump() const
12610860Sandreas.sandberg@arm.com{
12710860Sandreas.sandberg@arm.com    inform("Integer registers:\n");
12810860Sandreas.sandberg@arm.com    inform("  PC: %s\n", getAndFormatOneReg(INT_REG(regs.pc)));
12910860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i)
13010860Sandreas.sandberg@arm.com        inform("  X%i: %s\n", i, getAndFormatOneReg(kvmXReg(i)));
13110860Sandreas.sandberg@arm.com
13210860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i)
13310860Sandreas.sandberg@arm.com        inform("  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
13410860Sandreas.sandberg@arm.com
13510860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap)
13610860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
13710860Sandreas.sandberg@arm.com
13811890Srjthakur@google.com    inform("  %s: %s\n", "PSTATE", getAndFormatOneReg(INT_REG(regs.pstate)));
13911890Srjthakur@google.com
14010860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap)
14110860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
14210860Sandreas.sandberg@arm.com
14310860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
14410860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
14510860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64) {
14610860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
14710860Sandreas.sandberg@arm.com            continue;
14810860Sandreas.sandberg@arm.com        }
14910860Sandreas.sandberg@arm.com
15010860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
15110860Sandreas.sandberg@arm.com        switch (type) {
15210860Sandreas.sandberg@arm.com          case KVM_REG_ARM_CORE:
15310860Sandreas.sandberg@arm.com            // These have already been printed
15410860Sandreas.sandberg@arm.com            break;
15510860Sandreas.sandberg@arm.com
15610860Sandreas.sandberg@arm.com          case KVM_REG_ARM64_SYSREG: {
15710860Sandreas.sandberg@arm.com              const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
15810860Sandreas.sandberg@arm.com              const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
15910860Sandreas.sandberg@arm.com              const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
16010860Sandreas.sandberg@arm.com              const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
16110860Sandreas.sandberg@arm.com              const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
16210860Sandreas.sandberg@arm.com              const MiscRegIndex idx(
16310860Sandreas.sandberg@arm.com                  decodeAArch64SysReg(op0, op1, crn, crm, op2));
16410860Sandreas.sandberg@arm.com
16510860Sandreas.sandberg@arm.com              inform("  %s (op0: %i, op1: %i, crn: %i, crm: %i, op2: %i): %s",
16610860Sandreas.sandberg@arm.com                     miscRegName[idx], op0, op1, crn, crm, op2,
16710860Sandreas.sandberg@arm.com                     getAndFormatOneReg(reg));
16810860Sandreas.sandberg@arm.com          } break;
16910860Sandreas.sandberg@arm.com
17010860Sandreas.sandberg@arm.com          case KVM_REG_ARM_DEMUX: {
17110860Sandreas.sandberg@arm.com              const uint64_t id(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_ID));
17210860Sandreas.sandberg@arm.com              const uint64_t val(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_VAL));
17310860Sandreas.sandberg@arm.com              if (id == KVM_REG_ARM_DEMUX_ID_CCSIDR) {
17410860Sandreas.sandberg@arm.com                  inform("  CSSIDR[%i]: %s\n", val,
17510860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
17610860Sandreas.sandberg@arm.com              } else {
17710860Sandreas.sandberg@arm.com                  inform("  UNKNOWN[%i:%i]: %s\n", id, val,
17810860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
17910860Sandreas.sandberg@arm.com              }
18010860Sandreas.sandberg@arm.com          } break;
18110860Sandreas.sandberg@arm.com
18210860Sandreas.sandberg@arm.com          default:
18310860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
18410860Sandreas.sandberg@arm.com        }
18510860Sandreas.sandberg@arm.com    }
18610860Sandreas.sandberg@arm.com}
18710860Sandreas.sandberg@arm.com
18810860Sandreas.sandberg@arm.comvoid
18910860Sandreas.sandberg@arm.comArmV8KvmCPU::updateKvmState()
19010860Sandreas.sandberg@arm.com{
19110860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateKvmState():\n");
19211890Srjthakur@google.com
19311890Srjthakur@google.com    // update pstate register state
19411890Srjthakur@google.com    CPSR cpsr(tc->readMiscReg(MISCREG_CPSR));
19511890Srjthakur@google.com    cpsr.nz = tc->readCCReg(CCREG_NZ);
19611890Srjthakur@google.com    cpsr.c = tc->readCCReg(CCREG_C);
19711890Srjthakur@google.com    cpsr.v = tc->readCCReg(CCREG_V);
19811890Srjthakur@google.com    if (cpsr.width) {
19911890Srjthakur@google.com        cpsr.ge = tc->readCCReg(CCREG_GE);
20011890Srjthakur@google.com    } else {
20111890Srjthakur@google.com        cpsr.ge = 0;
20211890Srjthakur@google.com    }
20311890Srjthakur@google.com    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
20411890Srjthakur@google.com    setOneReg(INT_REG(regs.pstate), cpsr);
20511890Srjthakur@google.com
20610860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
20710860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
20810860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
20910860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
21010860Sandreas.sandberg@arm.com    }
21110860Sandreas.sandberg@arm.com
21210860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
21310860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(INTREG_X0 + i));
21410860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
21510860Sandreas.sandberg@arm.com        setOneReg(kvmXReg(i), value);
21610860Sandreas.sandberg@arm.com    }
21710860Sandreas.sandberg@arm.com
21810860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
21910860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(ri.idx));
22010860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
22110860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
22210860Sandreas.sandberg@arm.com    }
22310860Sandreas.sandberg@arm.com
22410860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
22510860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
22610860Sandreas.sandberg@arm.com        KvmFPReg reg;
22710860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
22810860Sandreas.sandberg@arm.com            reg.s[j].i = tc->readFloatRegBits(reg_base + j);
22910860Sandreas.sandberg@arm.com
23010860Sandreas.sandberg@arm.com        setOneReg(kvmFPReg(i), reg.data);
23110860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
23210860Sandreas.sandberg@arm.com    }
23310860Sandreas.sandberg@arm.com
23410860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
23510860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
23610860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
23710860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
23810860Sandreas.sandberg@arm.com    }
23910860Sandreas.sandberg@arm.com
24010860Sandreas.sandberg@arm.com    setOneReg(INT_REG(regs.pc), tc->instAddr());
24110860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x\n", tc->instAddr());
24210860Sandreas.sandberg@arm.com}
24310860Sandreas.sandberg@arm.com
24410860Sandreas.sandberg@arm.comvoid
24510860Sandreas.sandberg@arm.comArmV8KvmCPU::updateThreadContext()
24610860Sandreas.sandberg@arm.com{
24710860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateThreadContext():\n");
24810860Sandreas.sandberg@arm.com
24911890Srjthakur@google.com    // Update pstate thread context
25011890Srjthakur@google.com    const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
25111890Srjthakur@google.com    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
25211890Srjthakur@google.com    tc->setMiscRegNoEffect(MISCREG_CPSR, cpsr);
25311890Srjthakur@google.com    tc->setCCReg(CCREG_NZ, cpsr.nz);
25411890Srjthakur@google.com    tc->setCCReg(CCREG_C, cpsr.c);
25511890Srjthakur@google.com    tc->setCCReg(CCREG_V, cpsr.v);
25611890Srjthakur@google.com    if (cpsr.width) {
25711890Srjthakur@google.com        tc->setCCReg(CCREG_GE, cpsr.ge);
25811890Srjthakur@google.com    }
25911890Srjthakur@google.com
26011890Srjthakur@google.com    // Update core misc regs first as they
26110860Sandreas.sandberg@arm.com    // affect how other registers are mapped.
26210860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
26310860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
26410860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
26510860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
26610860Sandreas.sandberg@arm.com    }
26710860Sandreas.sandberg@arm.com
26810860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
26910860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(kvmXReg(i)));
27010860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
27111891Srjthakur@google.com        // KVM64 returns registers in 64-bit layout. If we are in aarch32
27211891Srjthakur@google.com        // mode, we need to map these to banked ARM32 registers.
27311891Srjthakur@google.com        if (inAArch64(tc)) {
27411891Srjthakur@google.com            tc->setIntReg(INTREG_X0 + i, value);
27511891Srjthakur@google.com        } else {
27611891Srjthakur@google.com            tc->setIntRegFlat(IntReg64Map[INTREG_X0 + i], value);
27711891Srjthakur@google.com        }
27810860Sandreas.sandberg@arm.com    }
27910860Sandreas.sandberg@arm.com
28010860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
28110860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
28210860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
28310860Sandreas.sandberg@arm.com        tc->setIntReg(ri.idx, value);
28410860Sandreas.sandberg@arm.com    }
28510860Sandreas.sandberg@arm.com
28610860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
28710860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
28810860Sandreas.sandberg@arm.com        KvmFPReg reg;
28910860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
29010860Sandreas.sandberg@arm.com        getOneReg(kvmFPReg(i), reg.data);
29110860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
29210860Sandreas.sandberg@arm.com            tc->setFloatRegBits(reg_base + j, reg.s[j].i);
29310860Sandreas.sandberg@arm.com    }
29410860Sandreas.sandberg@arm.com
29510860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
29610860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
29710860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
29810860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
29910860Sandreas.sandberg@arm.com    }
30010860Sandreas.sandberg@arm.com
30110860Sandreas.sandberg@arm.com    PCState pc(getOneRegU64(INT_REG(regs.pc)));
30210860Sandreas.sandberg@arm.com    pc.aarch64(inAArch64(tc));
30310860Sandreas.sandberg@arm.com    pc.thumb(cpsr.t);
30410860Sandreas.sandberg@arm.com    pc.nextAArch64(inAArch64(tc));
30510860Sandreas.sandberg@arm.com    // TODO: This is a massive assumption that will break when
30610860Sandreas.sandberg@arm.com    // switching to thumb.
30710860Sandreas.sandberg@arm.com    pc.nextThumb(cpsr.t);
30810860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x (t: %i, a64: %i)\n",
30910860Sandreas.sandberg@arm.com            pc.instAddr(), pc.thumb(), pc.aarch64());
31010860Sandreas.sandberg@arm.com    tc->pcState(pc);
31110860Sandreas.sandberg@arm.com}
31210860Sandreas.sandberg@arm.com
31310860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> &
31410860Sandreas.sandberg@arm.comArmV8KvmCPU::getSysRegMap() const
31510860Sandreas.sandberg@arm.com{
31610860Sandreas.sandberg@arm.com    // Try to use the cached map
31710860Sandreas.sandberg@arm.com    if (!sysRegMap.empty())
31810860Sandreas.sandberg@arm.com        return sysRegMap;
31910860Sandreas.sandberg@arm.com
32010860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
32110860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
32210860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64)
32310860Sandreas.sandberg@arm.com            continue;
32410860Sandreas.sandberg@arm.com
32510860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
32610860Sandreas.sandberg@arm.com        if (type != KVM_REG_ARM64_SYSREG)
32710860Sandreas.sandberg@arm.com            continue;
32810860Sandreas.sandberg@arm.com
32910860Sandreas.sandberg@arm.com        const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
33010860Sandreas.sandberg@arm.com        const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
33110860Sandreas.sandberg@arm.com        const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
33210860Sandreas.sandberg@arm.com        const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
33310860Sandreas.sandberg@arm.com        const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
33410860Sandreas.sandberg@arm.com        const MiscRegIndex idx(decodeAArch64SysReg(op0, op1, crn, crm, op2));
33510860Sandreas.sandberg@arm.com        const auto &info(miscRegInfo[idx]);
33610860Sandreas.sandberg@arm.com        const bool writeable(
33710860Sandreas.sandberg@arm.com            info[MISCREG_USR_NS_WR] || info[MISCREG_USR_S_WR] ||
33810860Sandreas.sandberg@arm.com            info[MISCREG_PRI_S_WR] || info[MISCREG_PRI_NS_WR] ||
33910860Sandreas.sandberg@arm.com            info[MISCREG_HYP_WR] ||
34010860Sandreas.sandberg@arm.com            info[MISCREG_MON_NS0_WR] || info[MISCREG_MON_NS1_WR]);
34110860Sandreas.sandberg@arm.com        const bool implemented(
34210860Sandreas.sandberg@arm.com            info[MISCREG_IMPLEMENTED] || info[MISCREG_WARN_NOT_FAIL]);
34310860Sandreas.sandberg@arm.com
34410860Sandreas.sandberg@arm.com        // Only add implemented registers that we are going to be able
34510860Sandreas.sandberg@arm.com        // to write.
34610860Sandreas.sandberg@arm.com        if (implemented && writeable)
34710860Sandreas.sandberg@arm.com            sysRegMap.emplace_back(reg, idx, miscRegName[idx]);
34810860Sandreas.sandberg@arm.com    }
34910860Sandreas.sandberg@arm.com
35010860Sandreas.sandberg@arm.com    return sysRegMap;
35110860Sandreas.sandberg@arm.com}
35210860Sandreas.sandberg@arm.com
35310860Sandreas.sandberg@arm.comArmV8KvmCPU *
35410860Sandreas.sandberg@arm.comArmV8KvmCPUParams::create()
35510860Sandreas.sandberg@arm.com{
35610860Sandreas.sandberg@arm.com    return new ArmV8KvmCPU(this);
35710860Sandreas.sandberg@arm.com}
358