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.com
10010860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::IntRegInfo> ArmV8KvmCPU::intRegMap = {
10110860Sandreas.sandberg@arm.com    { INT_REG(regs.sp), INTREG_SP0, "SP(EL0)" },
10210860Sandreas.sandberg@arm.com    { INT_REG(sp_el1), INTREG_SP1, "SP(EL1)" },
10310860Sandreas.sandberg@arm.com};
10410860Sandreas.sandberg@arm.com
10510860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
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
11612103SCurtis.Dunham@arm.comconst std::set<MiscRegIndex> ArmV8KvmCPU::deviceRegSet = {
11712103SCurtis.Dunham@arm.com    MISCREG_CNTV_CTL_EL0,
11812103SCurtis.Dunham@arm.com    MISCREG_CNTV_CVAL_EL0,
11912103SCurtis.Dunham@arm.com    MISCREG_CNTKCTL_EL1,
12012103SCurtis.Dunham@arm.com};
12112103SCurtis.Dunham@arm.com
12211934Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegIdMap = {
12311934Sandreas.sandberg@arm.com    MiscRegInfo(SYS_MPIDR_EL1, MISCREG_MPIDR_EL1, "MPIDR(EL1)"),
12411934Sandreas.sandberg@arm.com};
12511934Sandreas.sandberg@arm.com
12610860Sandreas.sandberg@arm.comArmV8KvmCPU::ArmV8KvmCPU(ArmV8KvmCPUParams *params)
12710860Sandreas.sandberg@arm.com    : BaseArmKvmCPU(params)
12810860Sandreas.sandberg@arm.com{
12910860Sandreas.sandberg@arm.com}
13010860Sandreas.sandberg@arm.com
13110860Sandreas.sandberg@arm.comArmV8KvmCPU::~ArmV8KvmCPU()
13210860Sandreas.sandberg@arm.com{
13310860Sandreas.sandberg@arm.com}
13410860Sandreas.sandberg@arm.com
13510860Sandreas.sandberg@arm.comvoid
13611934Sandreas.sandberg@arm.comArmV8KvmCPU::startup()
13711934Sandreas.sandberg@arm.com{
13811934Sandreas.sandberg@arm.com    BaseArmKvmCPU::startup();
13911934Sandreas.sandberg@arm.com
14011934Sandreas.sandberg@arm.com    // Override ID registers that KVM should "inherit" from gem5.
14111934Sandreas.sandberg@arm.com    for (const auto &ri : miscRegIdMap) {
14211934Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
14311934Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
14411934Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
14511934Sandreas.sandberg@arm.com    }
14611934Sandreas.sandberg@arm.com}
14711934Sandreas.sandberg@arm.com
14811934Sandreas.sandberg@arm.comvoid
14911178Svictor.garcia@arm.comArmV8KvmCPU::dump() const
15010860Sandreas.sandberg@arm.com{
15110860Sandreas.sandberg@arm.com    inform("Integer registers:\n");
15210860Sandreas.sandberg@arm.com    inform("  PC: %s\n", getAndFormatOneReg(INT_REG(regs.pc)));
15310860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i)
15410860Sandreas.sandberg@arm.com        inform("  X%i: %s\n", i, getAndFormatOneReg(kvmXReg(i)));
15510860Sandreas.sandberg@arm.com
15610860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i)
15710860Sandreas.sandberg@arm.com        inform("  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
15810860Sandreas.sandberg@arm.com
15910860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap)
16010860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
16110860Sandreas.sandberg@arm.com
16211890Srjthakur@google.com    inform("  %s: %s\n", "PSTATE", getAndFormatOneReg(INT_REG(regs.pstate)));
16311890Srjthakur@google.com
16410860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap)
16510860Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
16610860Sandreas.sandberg@arm.com
16711934Sandreas.sandberg@arm.com    for (const auto &ri : miscRegIdMap)
16811934Sandreas.sandberg@arm.com        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
16911934Sandreas.sandberg@arm.com
17010860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
17110860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
17210860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64) {
17310860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
17410860Sandreas.sandberg@arm.com            continue;
17510860Sandreas.sandberg@arm.com        }
17610860Sandreas.sandberg@arm.com
17710860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
17810860Sandreas.sandberg@arm.com        switch (type) {
17910860Sandreas.sandberg@arm.com          case KVM_REG_ARM_CORE:
18010860Sandreas.sandberg@arm.com            // These have already been printed
18110860Sandreas.sandberg@arm.com            break;
18210860Sandreas.sandberg@arm.com
18310860Sandreas.sandberg@arm.com          case KVM_REG_ARM64_SYSREG: {
18410860Sandreas.sandberg@arm.com              const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
18510860Sandreas.sandberg@arm.com              const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
18610860Sandreas.sandberg@arm.com              const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
18710860Sandreas.sandberg@arm.com              const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
18810860Sandreas.sandberg@arm.com              const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
18910860Sandreas.sandberg@arm.com              const MiscRegIndex idx(
19010860Sandreas.sandberg@arm.com                  decodeAArch64SysReg(op0, op1, crn, crm, op2));
19110860Sandreas.sandberg@arm.com
19210860Sandreas.sandberg@arm.com              inform("  %s (op0: %i, op1: %i, crn: %i, crm: %i, op2: %i): %s",
19310860Sandreas.sandberg@arm.com                     miscRegName[idx], op0, op1, crn, crm, op2,
19410860Sandreas.sandberg@arm.com                     getAndFormatOneReg(reg));
19510860Sandreas.sandberg@arm.com          } break;
19610860Sandreas.sandberg@arm.com
19710860Sandreas.sandberg@arm.com          case KVM_REG_ARM_DEMUX: {
19810860Sandreas.sandberg@arm.com              const uint64_t id(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_ID));
19910860Sandreas.sandberg@arm.com              const uint64_t val(EXTRACT_FIELD(reg, KVM_REG_ARM_DEMUX_VAL));
20010860Sandreas.sandberg@arm.com              if (id == KVM_REG_ARM_DEMUX_ID_CCSIDR) {
20110860Sandreas.sandberg@arm.com                  inform("  CSSIDR[%i]: %s\n", val,
20210860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
20310860Sandreas.sandberg@arm.com              } else {
20410860Sandreas.sandberg@arm.com                  inform("  UNKNOWN[%i:%i]: %s\n", id, val,
20510860Sandreas.sandberg@arm.com                         getAndFormatOneReg(reg));
20610860Sandreas.sandberg@arm.com              }
20710860Sandreas.sandberg@arm.com          } break;
20810860Sandreas.sandberg@arm.com
20910860Sandreas.sandberg@arm.com          default:
21010860Sandreas.sandberg@arm.com            inform("0x%x: %s\n", reg, getAndFormatOneReg(reg));
21110860Sandreas.sandberg@arm.com        }
21210860Sandreas.sandberg@arm.com    }
21310860Sandreas.sandberg@arm.com}
21410860Sandreas.sandberg@arm.com
21510860Sandreas.sandberg@arm.comvoid
21610860Sandreas.sandberg@arm.comArmV8KvmCPU::updateKvmState()
21710860Sandreas.sandberg@arm.com{
21810860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateKvmState():\n");
21911890Srjthakur@google.com
22011890Srjthakur@google.com    // update pstate register state
22111890Srjthakur@google.com    CPSR cpsr(tc->readMiscReg(MISCREG_CPSR));
22211890Srjthakur@google.com    cpsr.nz = tc->readCCReg(CCREG_NZ);
22311890Srjthakur@google.com    cpsr.c = tc->readCCReg(CCREG_C);
22411890Srjthakur@google.com    cpsr.v = tc->readCCReg(CCREG_V);
22511890Srjthakur@google.com    if (cpsr.width) {
22611890Srjthakur@google.com        cpsr.ge = tc->readCCReg(CCREG_GE);
22711890Srjthakur@google.com    } else {
22811890Srjthakur@google.com        cpsr.ge = 0;
22911890Srjthakur@google.com    }
23011890Srjthakur@google.com    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
23112004Sandreas.sandberg@arm.com    setOneReg(INT_REG(regs.pstate), static_cast<uint64_t>(cpsr));
23211890Srjthakur@google.com
23310860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
23410860Sandreas.sandberg@arm.com        const uint64_t value(tc->readMiscReg(ri.idx));
23510860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
23610860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
23710860Sandreas.sandberg@arm.com    }
23810860Sandreas.sandberg@arm.com
23910860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
24010860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(INTREG_X0 + i));
24110860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
24210860Sandreas.sandberg@arm.com        setOneReg(kvmXReg(i), value);
24310860Sandreas.sandberg@arm.com    }
24410860Sandreas.sandberg@arm.com
24510860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
24610860Sandreas.sandberg@arm.com        const uint64_t value(tc->readIntReg(ri.idx));
24710860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
24810860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
24910860Sandreas.sandberg@arm.com    }
25010860Sandreas.sandberg@arm.com
25110860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
25210860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
25310860Sandreas.sandberg@arm.com        KvmFPReg reg;
25410860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
25513611Sgabeblack@google.com            reg.s[j].i = tc->readFloatReg(reg_base + j);
25610860Sandreas.sandberg@arm.com
25710860Sandreas.sandberg@arm.com        setOneReg(kvmFPReg(i), reg.data);
25810860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
25910860Sandreas.sandberg@arm.com    }
26010860Sandreas.sandberg@arm.com
26110860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
26212156Sandreas.sandberg@arm.com        uint64_t value;
26312156Sandreas.sandberg@arm.com        if (ri.is_device) {
26412156Sandreas.sandberg@arm.com            // This system register is backed by a device. This means
26512156Sandreas.sandberg@arm.com            // we need to lock the device event queue.
26612156Sandreas.sandberg@arm.com            EventQueue::ScopedMigration migrate(deviceEventQueue());
26712156Sandreas.sandberg@arm.com
26812156Sandreas.sandberg@arm.com            value = tc->readMiscReg(ri.idx);
26912156Sandreas.sandberg@arm.com        } else {
27012156Sandreas.sandberg@arm.com            value = tc->readMiscReg(ri.idx);
27112156Sandreas.sandberg@arm.com        }
27212156Sandreas.sandberg@arm.com
27310860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
27410860Sandreas.sandberg@arm.com        setOneReg(ri.kvm, value);
27510860Sandreas.sandberg@arm.com    }
27610860Sandreas.sandberg@arm.com
27710860Sandreas.sandberg@arm.com    setOneReg(INT_REG(regs.pc), tc->instAddr());
27810860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x\n", tc->instAddr());
27910860Sandreas.sandberg@arm.com}
28010860Sandreas.sandberg@arm.com
28110860Sandreas.sandberg@arm.comvoid
28210860Sandreas.sandberg@arm.comArmV8KvmCPU::updateThreadContext()
28310860Sandreas.sandberg@arm.com{
28410860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "In updateThreadContext():\n");
28510860Sandreas.sandberg@arm.com
28611890Srjthakur@google.com    // Update pstate thread context
28712004Sandreas.sandberg@arm.com    const CPSR cpsr(getOneRegU64(INT_REG(regs.pstate)));
28811890Srjthakur@google.com    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
28911890Srjthakur@google.com    tc->setMiscRegNoEffect(MISCREG_CPSR, cpsr);
29011890Srjthakur@google.com    tc->setCCReg(CCREG_NZ, cpsr.nz);
29111890Srjthakur@google.com    tc->setCCReg(CCREG_C, cpsr.c);
29211890Srjthakur@google.com    tc->setCCReg(CCREG_V, cpsr.v);
29311890Srjthakur@google.com    if (cpsr.width) {
29411890Srjthakur@google.com        tc->setCCReg(CCREG_GE, cpsr.ge);
29511890Srjthakur@google.com    }
29611890Srjthakur@google.com
29711890Srjthakur@google.com    // Update core misc regs first as they
29810860Sandreas.sandberg@arm.com    // affect how other registers are mapped.
29910860Sandreas.sandberg@arm.com    for (const auto &ri : miscRegMap) {
30010860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
30110860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
30210860Sandreas.sandberg@arm.com        tc->setMiscRegNoEffect(ri.idx, value);
30310860Sandreas.sandberg@arm.com    }
30410860Sandreas.sandberg@arm.com
30510860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_XREGS; ++i) {
30610860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(kvmXReg(i)));
30710860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  X%i := 0x%x\n", i, value);
30811891Srjthakur@google.com        // KVM64 returns registers in 64-bit layout. If we are in aarch32
30911891Srjthakur@google.com        // mode, we need to map these to banked ARM32 registers.
31011891Srjthakur@google.com        if (inAArch64(tc)) {
31111891Srjthakur@google.com            tc->setIntReg(INTREG_X0 + i, value);
31211891Srjthakur@google.com        } else {
31311891Srjthakur@google.com            tc->setIntRegFlat(IntReg64Map[INTREG_X0 + i], value);
31411891Srjthakur@google.com        }
31510860Sandreas.sandberg@arm.com    }
31610860Sandreas.sandberg@arm.com
31710860Sandreas.sandberg@arm.com    for (const auto &ri : intRegMap) {
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->setIntReg(ri.idx, value);
32110860Sandreas.sandberg@arm.com    }
32210860Sandreas.sandberg@arm.com
32310860Sandreas.sandberg@arm.com    for (int i = 0; i < NUM_QREGS; ++i) {
32410860Sandreas.sandberg@arm.com        const RegIndex reg_base(i * FP_REGS_PER_VFP_REG);
32510860Sandreas.sandberg@arm.com        KvmFPReg reg;
32610860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  Q%i: %s\n", i, getAndFormatOneReg(kvmFPReg(i)));
32710860Sandreas.sandberg@arm.com        getOneReg(kvmFPReg(i), reg.data);
32810860Sandreas.sandberg@arm.com        for (int j = 0; j < FP_REGS_PER_VFP_REG; j++)
32913611Sgabeblack@google.com            tc->setFloatReg(reg_base + j, reg.s[j].i);
33010860Sandreas.sandberg@arm.com    }
33110860Sandreas.sandberg@arm.com
33210860Sandreas.sandberg@arm.com    for (const auto &ri : getSysRegMap()) {
33310860Sandreas.sandberg@arm.com        const auto value(getOneRegU64(ri.kvm));
33410860Sandreas.sandberg@arm.com        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
33512156Sandreas.sandberg@arm.com        if (ri.is_device) {
33612156Sandreas.sandberg@arm.com            // This system register is backed by a device. This means
33712156Sandreas.sandberg@arm.com            // we need to lock the device event queue.
33812156Sandreas.sandberg@arm.com            EventQueue::ScopedMigration migrate(deviceEventQueue());
33912156Sandreas.sandberg@arm.com
34012103SCurtis.Dunham@arm.com            tc->setMiscReg(ri.idx, value);
34112156Sandreas.sandberg@arm.com        } else {
34212103SCurtis.Dunham@arm.com            tc->setMiscRegNoEffect(ri.idx, value);
34312156Sandreas.sandberg@arm.com        }
34410860Sandreas.sandberg@arm.com    }
34510860Sandreas.sandberg@arm.com
34610860Sandreas.sandberg@arm.com    PCState pc(getOneRegU64(INT_REG(regs.pc)));
34710860Sandreas.sandberg@arm.com    pc.aarch64(inAArch64(tc));
34810860Sandreas.sandberg@arm.com    pc.thumb(cpsr.t);
34910860Sandreas.sandberg@arm.com    pc.nextAArch64(inAArch64(tc));
35010860Sandreas.sandberg@arm.com    // TODO: This is a massive assumption that will break when
35110860Sandreas.sandberg@arm.com    // switching to thumb.
35210860Sandreas.sandberg@arm.com    pc.nextThumb(cpsr.t);
35310860Sandreas.sandberg@arm.com    DPRINTF(KvmContext, "  PC := 0x%x (t: %i, a64: %i)\n",
35410860Sandreas.sandberg@arm.com            pc.instAddr(), pc.thumb(), pc.aarch64());
35510860Sandreas.sandberg@arm.com    tc->pcState(pc);
35610860Sandreas.sandberg@arm.com}
35710860Sandreas.sandberg@arm.com
35810860Sandreas.sandberg@arm.comconst std::vector<ArmV8KvmCPU::MiscRegInfo> &
35910860Sandreas.sandberg@arm.comArmV8KvmCPU::getSysRegMap() const
36010860Sandreas.sandberg@arm.com{
36110860Sandreas.sandberg@arm.com    // Try to use the cached map
36210860Sandreas.sandberg@arm.com    if (!sysRegMap.empty())
36310860Sandreas.sandberg@arm.com        return sysRegMap;
36410860Sandreas.sandberg@arm.com
36510860Sandreas.sandberg@arm.com    for (const auto &reg : getRegList()) {
36610860Sandreas.sandberg@arm.com        const uint64_t arch(reg & KVM_REG_ARCH_MASK);
36710860Sandreas.sandberg@arm.com        if (arch != KVM_REG_ARM64)
36810860Sandreas.sandberg@arm.com            continue;
36910860Sandreas.sandberg@arm.com
37010860Sandreas.sandberg@arm.com        const uint64_t type(reg & KVM_REG_ARM_COPROC_MASK);
37110860Sandreas.sandberg@arm.com        if (type != KVM_REG_ARM64_SYSREG)
37210860Sandreas.sandberg@arm.com            continue;
37310860Sandreas.sandberg@arm.com
37410860Sandreas.sandberg@arm.com        const uint64_t op0(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP0));
37510860Sandreas.sandberg@arm.com        const uint64_t op1(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP1));
37610860Sandreas.sandberg@arm.com        const uint64_t crn(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRN));
37710860Sandreas.sandberg@arm.com        const uint64_t crm(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_CRM));
37810860Sandreas.sandberg@arm.com        const uint64_t op2(EXTRACT_FIELD(reg, KVM_REG_ARM64_SYSREG_OP2));
37910860Sandreas.sandberg@arm.com        const MiscRegIndex idx(decodeAArch64SysReg(op0, op1, crn, crm, op2));
38010860Sandreas.sandberg@arm.com        const auto &info(miscRegInfo[idx]);
38110860Sandreas.sandberg@arm.com        const bool writeable(
38210860Sandreas.sandberg@arm.com            info[MISCREG_USR_NS_WR] || info[MISCREG_USR_S_WR] ||
38310860Sandreas.sandberg@arm.com            info[MISCREG_PRI_S_WR] || info[MISCREG_PRI_NS_WR] ||
38410860Sandreas.sandberg@arm.com            info[MISCREG_HYP_WR] ||
38510860Sandreas.sandberg@arm.com            info[MISCREG_MON_NS0_WR] || info[MISCREG_MON_NS1_WR]);
38610860Sandreas.sandberg@arm.com        const bool implemented(
38710860Sandreas.sandberg@arm.com            info[MISCREG_IMPLEMENTED] || info[MISCREG_WARN_NOT_FAIL]);
38810860Sandreas.sandberg@arm.com
38910860Sandreas.sandberg@arm.com        // Only add implemented registers that we are going to be able
39010860Sandreas.sandberg@arm.com        // to write.
39110860Sandreas.sandberg@arm.com        if (implemented && writeable)
39212103SCurtis.Dunham@arm.com            sysRegMap.emplace_back(reg, idx, miscRegName[idx],
39312103SCurtis.Dunham@arm.com                deviceRegSet.find(idx) != deviceRegSet.end());
39410860Sandreas.sandberg@arm.com    }
39510860Sandreas.sandberg@arm.com
39610860Sandreas.sandberg@arm.com    return sysRegMap;
39710860Sandreas.sandberg@arm.com}
39810860Sandreas.sandberg@arm.com
39910860Sandreas.sandberg@arm.comArmV8KvmCPU *
40010860Sandreas.sandberg@arm.comArmV8KvmCPUParams::create()
40110860Sandreas.sandberg@arm.com{
40210860Sandreas.sandberg@arm.com    return new ArmV8KvmCPU(this);
40310860Sandreas.sandberg@arm.com}
404