arm_cpu.cc revision 10857
19657SN/A/* 29657SN/A * Copyright (c) 2012 ARM Limited 39657SN/A * All rights reserved 49657SN/A * 59657SN/A * The license below extends only to copyright in the software and shall 69657SN/A * not be construed as granting a license to any other intellectual 79657SN/A * property including but not limited to intellectual property relating 89657SN/A * to a hardware implementation of the functionality of the software 99657SN/A * licensed hereunder. You may use the software subject to the license 109657SN/A * terms below provided that you ensure that this notice is replicated 119657SN/A * unmodified and in its entirety in all distributions of the software, 129657SN/A * modified or unmodified, in source code or in binary form. 139657SN/A * 149657SN/A * Redistribution and use in source and binary forms, with or without 159657SN/A * modification, are permitted provided that the following conditions are 169657SN/A * met: redistributions of source code must retain the above copyright 179657SN/A * notice, this list of conditions and the following disclaimer; 189657SN/A * redistributions in binary form must reproduce the above copyright 199657SN/A * notice, this list of conditions and the following disclaimer in the 209657SN/A * documentation and/or other materials provided with the distribution; 219657SN/A * neither the name of the copyright holders nor the names of its 229657SN/A * contributors may be used to endorse or promote products derived from 239657SN/A * this software without specific prior written permission. 249657SN/A * 259657SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269657SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 279657SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 289657SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 299657SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309657SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 319657SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 329657SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 339657SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 349657SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359657SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369657SN/A * 379657SN/A * Authors: Andreas Sandberg 389657SN/A */ 399657SN/A 4010857Sandreas.sandberg@arm.com#include "arch/arm/kvm/arm_cpu.hh" 4110857Sandreas.sandberg@arm.com 429657SN/A#include <linux/kvm.h> 439657SN/A 449657SN/A#include <algorithm> 459657SN/A#include <cerrno> 469657SN/A#include <memory> 479657SN/A 489657SN/A#include "arch/registers.hh" 499657SN/A#include "cpu/kvm/base.hh" 509657SN/A#include "debug/Kvm.hh" 519657SN/A#include "debug/KvmContext.hh" 529657SN/A#include "debug/KvmInt.hh" 539660SN/A#include "sim/pseudo_inst.hh" 549657SN/A 559657SN/Ausing namespace ArmISA; 569657SN/A 579657SN/A#define EXTRACT_FIELD(val, mask, shift) \ 589657SN/A (((val) & (mask)) >> (shift)) 599657SN/A 609657SN/A#define REG_IS_ARM(id) \ 619657SN/A (((id) & KVM_REG_ARCH_MASK) == KVM_REG_ARM) 629657SN/A 639657SN/A#define REG_IS_32BIT(id) \ 649657SN/A (((id) & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) 659657SN/A 669657SN/A#define REG_IS_64BIT(id) \ 679657SN/A (((id) & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) 689657SN/A 699657SN/A#define REG_IS_CP(id, cp) \ 709657SN/A (((id) & KVM_REG_ARM_COPROC_MASK) == (cp)) 719657SN/A 729657SN/A#define REG_IS_CORE(id) REG_IS_CP((id), KVM_REG_ARM_CORE) 739657SN/A 749657SN/A#define REG_IS_VFP(id) REG_IS_CP((id), KVM_REG_ARM_VFP) 759657SN/A#define REG_VFP_REG(id) ((id) & KVM_REG_ARM_VFP_MASK) 769657SN/A// HACK: These aren't really defined in any of the headers, so we'll 779657SN/A// assume some reasonable values for now. 789657SN/A#define REG_IS_VFP_REG(id) (REG_VFP_REG(id) < 0x100) 799657SN/A#define REG_IS_VFP_CTRL(id) (REG_VFP_REG(id) >= 0x100) 809657SN/A 819657SN/A#define REG_IS_DEMUX(id) REG_IS_CP((id), KVM_REG_ARM_DEMUX) 829657SN/A 839657SN/A 849657SN/A// There is no constant in the kernel headers defining the mask to use 859657SN/A// to get the core register index. We'll just do what they do 869657SN/A// internally. 879657SN/A#define REG_CORE_IDX(id) \ 889657SN/A (~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE)) 899657SN/A 909657SN/A#define REG_CP(id) \ 919657SN/A EXTRACT_FIELD(id, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_SHIFT) 929657SN/A 939657SN/A#define REG_CRN(id) \ 949657SN/A EXTRACT_FIELD(id, KVM_REG_ARM_32_CRN_MASK, KVM_REG_ARM_32_CRN_SHIFT) 959657SN/A 969657SN/A#define REG_OPC1(id) \ 979657SN/A EXTRACT_FIELD(id, KVM_REG_ARM_OPC1_MASK, KVM_REG_ARM_OPC1_SHIFT) 989657SN/A 999657SN/A#define REG_CRM(id) \ 1009657SN/A EXTRACT_FIELD(id, KVM_REG_ARM_CRM_MASK, KVM_REG_ARM_CRM_SHIFT) 1019657SN/A 1029657SN/A#define REG_OPC2(id) \ 1039657SN/A EXTRACT_FIELD(id, KVM_REG_ARM_32_OPC2_MASK, KVM_REG_ARM_32_OPC2_SHIFT) 1049657SN/A 1059657SN/A#define REG_CP32(cpnum, crn, opc1, crm, opc2) ( \ 1069657SN/A (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 1079657SN/A ((cpnum) << KVM_REG_ARM_COPROC_SHIFT) | \ 1089657SN/A ((crn) << KVM_REG_ARM_32_CRN_SHIFT) | \ 1099657SN/A ((opc1) << KVM_REG_ARM_OPC1_SHIFT) | \ 1109657SN/A ((crm) << KVM_REG_ARM_CRM_SHIFT) | \ 1119657SN/A ((opc2) << KVM_REG_ARM_32_OPC2_SHIFT)) 1129657SN/A 1139657SN/A#define REG_CP64(cpnum, opc1, crm) ( \ 1149657SN/A (KVM_REG_ARM | KVM_REG_SIZE_U64) | \ 1159657SN/A ((cpnum) << KVM_REG_ARM_COPROC_SHIFT) | \ 1169657SN/A ((opc1) << KVM_REG_ARM_OPC1_SHIFT) | \ 1179657SN/A ((crm) << KVM_REG_ARM_CRM_SHIFT)) 1189657SN/A 1199657SN/A#define REG_CORE32(kname) ( \ 1209657SN/A (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 1219657SN/A (KVM_REG_ARM_CORE) | \ 1229657SN/A (KVM_REG_ARM_CORE_REG(kname))) 1239657SN/A 1249657SN/A#define REG_VFP32(regno) ( \ 1259657SN/A (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 1269657SN/A KVM_REG_ARM_VFP | (regno)) 1279657SN/A 1289657SN/A#define REG_VFP64(regno) ( \ 1299657SN/A (KVM_REG_ARM | KVM_REG_SIZE_U64) | \ 1309657SN/A KVM_REG_ARM_VFP | (regno)) 1319657SN/A 1329657SN/A#define REG_DEMUX32(dmxid, val) ( \ 1339657SN/A (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 1349657SN/A (dmxid) | (val)) 1359657SN/A 1369657SN/A// Some of the co-processor registers are invariants and must have the 1379657SN/A// same value on both the host and the guest. We need to keep a list 1389657SN/A// of these to prevent gem5 from fiddling with them on the guest. 1399657SN/Astatic uint64_t invariant_reg_vector[] = { 1409657SN/A REG_CP32(15, 0, 0, 0, 0), // MIDR 1419657SN/A REG_CP32(15, 0, 0, 0, 1), // CTR 1429657SN/A REG_CP32(15, 0, 0, 0, 2), // TCMTR 1439657SN/A REG_CP32(15, 0, 0, 0, 3), // TLBTR 1449657SN/A REG_CP32(15, 0, 0, 0, 6), // REVIDR 1459657SN/A 1469657SN/A REG_CP32(15, 0, 0, 1, 0), // ID_PFR0 1479657SN/A REG_CP32(15, 0, 0, 1, 1), // ID_PFR1 1489657SN/A REG_CP32(15, 0, 0, 1, 2), // ID_DFR0 1499657SN/A REG_CP32(15, 0, 0, 1, 3), // ID_AFR0 1509657SN/A REG_CP32(15, 0, 0, 1, 4), // ID_MMFR0 1519657SN/A REG_CP32(15, 0, 0, 1, 5), // ID_MMFR1 1529657SN/A REG_CP32(15, 0, 0, 1, 6), // ID_MMFR2 1539657SN/A REG_CP32(15, 0, 0, 1, 7), // ID_MMFR3 1549657SN/A 1559657SN/A REG_CP32(15, 0, 0, 2, 0), // ID_ISAR0 1569657SN/A REG_CP32(15, 0, 0, 2, 1), // ID_ISAR1 1579657SN/A REG_CP32(15, 0, 0, 2, 2), // ID_ISAR2 1589657SN/A REG_CP32(15, 0, 0, 2, 3), // ID_ISAR3 1599657SN/A REG_CP32(15, 0, 0, 2, 4), // ID_ISAR4 1609657SN/A REG_CP32(15, 0, 0, 2, 5), // ID_ISAR5 1619657SN/A 1629657SN/A REG_CP32(15, 0, 1, 0, 0), // CSSIDR 1639657SN/A REG_CP32(15, 0, 1, 0, 1), // CLIDR 1649657SN/A REG_CP32(15, 0, 1, 0, 7), // AIDR 1659657SN/A 1669657SN/A REG_VFP32(KVM_REG_ARM_VFP_MVFR0), 1679657SN/A REG_VFP32(KVM_REG_ARM_VFP_MVFR1), 1689657SN/A REG_VFP32(KVM_REG_ARM_VFP_FPSID), 1699657SN/A 1709657SN/A REG_DEMUX32(KVM_REG_ARM_DEMUX_ID_CCSIDR, 0), 1719657SN/A}; 1729657SN/A 1739657SN/Aconst static uint64_t KVM_REG64_TTBR0(REG_CP64(15, 0, 2)); 1749657SN/Aconst static uint64_t KVM_REG64_TTBR1(REG_CP64(15, 1, 2)); 1759657SN/A 1769657SN/A#define INTERRUPT_ID(type, vcpu, irq) ( \ 1779657SN/A ((type) << KVM_ARM_IRQ_TYPE_SHIFT) | \ 1789657SN/A ((vcpu) << KVM_ARM_IRQ_VCPU_SHIFT) | \ 1799657SN/A ((irq) << KVM_ARM_IRQ_NUM_SHIFT)) 1809657SN/A 1819657SN/A#define INTERRUPT_VCPU_IRQ(vcpu) \ 1829657SN/A INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_IRQ) 1839657SN/A 1849657SN/A#define INTERRUPT_VCPU_FIQ(vcpu) \ 1859657SN/A INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_FIQ) 1869657SN/A 1879657SN/A 1889657SN/A#define COUNT_OF(l) (sizeof(l) / sizeof(*l)) 1899657SN/A 1909657SN/Aconst std::set<uint64_t> ArmKvmCPU::invariant_regs( 1919657SN/A invariant_reg_vector, 1929657SN/A invariant_reg_vector + COUNT_OF(invariant_reg_vector)); 1939657SN/A 1949657SN/A 1959657SN/AArmKvmCPU::KvmIntRegInfo ArmKvmCPU::kvmIntRegs[] = { 1969657SN/A { REG_CORE32(usr_regs.ARM_r0), INTREG_R0, "R0" }, 1979657SN/A { REG_CORE32(usr_regs.ARM_r1), INTREG_R1, "R1" }, 1989657SN/A { REG_CORE32(usr_regs.ARM_r2), INTREG_R2, "R2" }, 1999657SN/A { REG_CORE32(usr_regs.ARM_r3), INTREG_R3, "R3" }, 2009657SN/A { REG_CORE32(usr_regs.ARM_r4), INTREG_R4, "R4" }, 2019657SN/A { REG_CORE32(usr_regs.ARM_r5), INTREG_R5, "R5" }, 2029657SN/A { REG_CORE32(usr_regs.ARM_r6), INTREG_R6, "R6" }, 2039657SN/A { REG_CORE32(usr_regs.ARM_r7), INTREG_R7, "R7" }, 2049657SN/A { REG_CORE32(usr_regs.ARM_r8), INTREG_R8, "R8" }, 2059657SN/A { REG_CORE32(usr_regs.ARM_r9), INTREG_R9, "R9" }, 2069657SN/A { REG_CORE32(usr_regs.ARM_r10), INTREG_R10, "R10" }, 2079657SN/A { REG_CORE32(usr_regs.ARM_fp), INTREG_R11, "R11" }, 2089657SN/A { REG_CORE32(usr_regs.ARM_ip), INTREG_R12, "R12" }, 2099657SN/A { REG_CORE32(usr_regs.ARM_sp), INTREG_R13, "R13(USR)" }, 2109657SN/A { REG_CORE32(usr_regs.ARM_lr), INTREG_R14, "R14(USR)" }, 2119657SN/A 2129657SN/A { REG_CORE32(svc_regs[0]), INTREG_SP_SVC, "R13(SVC)" }, 2139657SN/A { REG_CORE32(svc_regs[1]), INTREG_LR_SVC, "R14(SVC)" }, 2149657SN/A 2159657SN/A { REG_CORE32(abt_regs[0]), INTREG_SP_ABT, "R13(ABT)" }, 2169657SN/A { REG_CORE32(abt_regs[1]), INTREG_LR_ABT, "R14(ABT)" }, 2179657SN/A 2189657SN/A { REG_CORE32(und_regs[0]), INTREG_SP_UND, "R13(UND)" }, 2199657SN/A { REG_CORE32(und_regs[1]), INTREG_LR_UND, "R14(UND)" }, 2209657SN/A 2219657SN/A { REG_CORE32(irq_regs[0]), INTREG_SP_IRQ, "R13(IRQ)" }, 2229657SN/A { REG_CORE32(irq_regs[1]), INTREG_LR_IRQ, "R14(IRQ)" }, 2239657SN/A 2249657SN/A 2259657SN/A { REG_CORE32(fiq_regs[0]), INTREG_R8_FIQ, "R8(FIQ)" }, 2269657SN/A { REG_CORE32(fiq_regs[1]), INTREG_R9_FIQ, "R9(FIQ)" }, 2279657SN/A { REG_CORE32(fiq_regs[2]), INTREG_R10_FIQ, "R10(FIQ)" }, 2289657SN/A { REG_CORE32(fiq_regs[3]), INTREG_R11_FIQ, "R11(FIQ)" }, 2299657SN/A { REG_CORE32(fiq_regs[4]), INTREG_R12_FIQ, "R12(FIQ)" }, 2309657SN/A { REG_CORE32(fiq_regs[5]), INTREG_R13_FIQ, "R13(FIQ)" }, 2319657SN/A { REG_CORE32(fiq_regs[6]), INTREG_R14_FIQ, "R14(FIQ)" }, 2329657SN/A { 0, NUM_INTREGS, NULL } 2339657SN/A}; 2349657SN/A 2359657SN/AArmKvmCPU::KvmCoreMiscRegInfo ArmKvmCPU::kvmCoreMiscRegs[] = { 2369657SN/A { REG_CORE32(usr_regs.ARM_cpsr), MISCREG_CPSR, "CPSR" }, 2379657SN/A { REG_CORE32(svc_regs[2]), MISCREG_SPSR_SVC, "SPSR(SVC)" }, 2389657SN/A { REG_CORE32(abt_regs[2]), MISCREG_SPSR_ABT, "SPSR(ABT)" }, 2399657SN/A { REG_CORE32(und_regs[2]), MISCREG_SPSR_UND, "SPSR(UND)" }, 2409657SN/A { REG_CORE32(irq_regs[2]), MISCREG_SPSR_IRQ, "SPSR(IRQ)" }, 2419657SN/A { REG_CORE32(fiq_regs[2]), MISCREG_SPSR_FIQ, "SPSR(FIQ)" }, 2429657SN/A { 0, NUM_MISCREGS } 2439657SN/A}; 2449657SN/A 2459657SN/AArmKvmCPU::ArmKvmCPU(ArmKvmCPUParams *params) 2469657SN/A : BaseKvmCPU(params), 2479657SN/A irqAsserted(false), fiqAsserted(false) 2489657SN/A{ 2499657SN/A} 2509657SN/A 2519657SN/AArmKvmCPU::~ArmKvmCPU() 2529657SN/A{ 2539657SN/A} 2549657SN/A 2559657SN/Avoid 2569657SN/AArmKvmCPU::startup() 2579657SN/A{ 2589657SN/A BaseKvmCPU::startup(); 2599657SN/A 2609657SN/A /* TODO: This needs to be moved when we start to support VMs with 2619657SN/A * multiple threads since kvmArmVCpuInit requires that all CPUs in 2629657SN/A * the VM have been created. 2639657SN/A */ 2649657SN/A /* TODO: The CPU type needs to be configurable once KVM on ARM 2659657SN/A * starts to support more CPUs. 2669657SN/A */ 2679657SN/A kvmArmVCpuInit(KVM_ARM_TARGET_CORTEX_A15); 2689657SN/A} 2699657SN/A 2709753SN/ATick 2719753SN/AArmKvmCPU::kvmRun(Tick ticks) 2729657SN/A{ 2739657SN/A bool simFIQ(interrupts->checkRaw(INT_FIQ)); 2749657SN/A bool simIRQ(interrupts->checkRaw(INT_IRQ)); 2759657SN/A 2769657SN/A if (fiqAsserted != simFIQ) { 2779657SN/A fiqAsserted = simFIQ; 2789657SN/A DPRINTF(KvmInt, "KVM: Update FIQ state: %i\n", simFIQ); 2799657SN/A vm.setIRQLine(INTERRUPT_VCPU_FIQ(vcpuID), simFIQ); 2809657SN/A } 2819657SN/A if (irqAsserted != simIRQ) { 2829657SN/A irqAsserted = simIRQ; 2839657SN/A DPRINTF(KvmInt, "KVM: Update IRQ state: %i\n", simIRQ); 2849657SN/A vm.setIRQLine(INTERRUPT_VCPU_IRQ(vcpuID), simIRQ); 2859657SN/A } 2869657SN/A 2879753SN/A return BaseKvmCPU::kvmRun(ticks); 2889657SN/A} 2899657SN/A 2909657SN/Avoid 2919658SN/AArmKvmCPU::dump() 2929658SN/A{ 2939658SN/A dumpKvmStateCore(); 2949658SN/A dumpKvmStateMisc(); 2959658SN/A} 2969658SN/A 2979658SN/Avoid 2989657SN/AArmKvmCPU::updateKvmState() 2999657SN/A{ 3009657SN/A DPRINTF(KvmContext, "Updating KVM state...\n"); 3019657SN/A 3029657SN/A updateKvmStateCore(); 3039657SN/A updateKvmStateMisc(); 3049657SN/A} 3059657SN/A 3069657SN/Avoid 3079657SN/AArmKvmCPU::updateThreadContext() 3089657SN/A{ 3099657SN/A DPRINTF(KvmContext, "Updating gem5 state...\n"); 3109657SN/A 3119657SN/A updateTCStateCore(); 3129657SN/A updateTCStateMisc(); 3139657SN/A} 3149657SN/A 3159660SN/ATick 3169660SN/AArmKvmCPU::onKvmExitHypercall() 3179660SN/A{ 3189660SN/A ThreadContext *tc(getContext(0)); 3199660SN/A const uint32_t reg_ip(tc->readIntRegFlat(INTREG_R12)); 3209660SN/A const uint8_t func((reg_ip >> 8) & 0xFF); 3219660SN/A const uint8_t subfunc(reg_ip & 0xFF); 3229660SN/A 3239660SN/A DPRINTF(Kvm, "KVM Hypercall: 0x%x/0x%x\n", func, subfunc); 3249660SN/A const uint64_t ret(PseudoInst::pseudoInst(getContext(0), func, subfunc)); 3259660SN/A 3269660SN/A // Just set the return value using the KVM API instead of messing 3279660SN/A // with the context. We could have used the context, but that 3289660SN/A // would have required us to request a full context sync. 3299660SN/A setOneReg(REG_CORE32(usr_regs.ARM_r0), ret & 0xFFFFFFFF); 3309660SN/A setOneReg(REG_CORE32(usr_regs.ARM_r1), (ret >> 32) & 0xFFFFFFFF); 3319660SN/A 3329660SN/A return 0; 3339660SN/A} 3349660SN/A 3359657SN/Aconst ArmKvmCPU::RegIndexVector & 3369657SN/AArmKvmCPU::getRegList() const 3379657SN/A{ 3389657SN/A if (_regIndexList.size() == 0) { 3399657SN/A std::unique_ptr<struct kvm_reg_list> regs; 3409657SN/A uint64_t i(1); 3419657SN/A 3429657SN/A do { 3439657SN/A i <<= 1; 3449657SN/A regs.reset((struct kvm_reg_list *) 3459657SN/A operator new(sizeof(struct kvm_reg_list) + 3469657SN/A i * sizeof(uint64_t))); 3479657SN/A regs->n = i; 3489657SN/A } while (!getRegList(*regs)); 3499657SN/A _regIndexList.assign(regs->reg, 3509657SN/A regs->reg + regs->n); 3519657SN/A } 3529657SN/A 3539657SN/A return _regIndexList; 3549657SN/A} 3559657SN/A 3569657SN/Avoid 3579657SN/AArmKvmCPU::kvmArmVCpuInit(uint32_t target) 3589657SN/A{ 3599657SN/A struct kvm_vcpu_init init; 3609657SN/A 3619657SN/A memset(&init, 0, sizeof(init)); 3629657SN/A 3639657SN/A init.target = target; 3649657SN/A 3659657SN/A kvmArmVCpuInit(init); 3669657SN/A} 3679657SN/A 3689657SN/Avoid 3699657SN/AArmKvmCPU::kvmArmVCpuInit(const struct kvm_vcpu_init &init) 3709657SN/A{ 3719657SN/A if (ioctl(KVM_ARM_VCPU_INIT, (void *)&init) == -1) 3729657SN/A panic("KVM: Failed to initialize vCPU\n"); 3739657SN/A} 3749657SN/A 3759657SN/AMiscRegIndex 3769657SN/AArmKvmCPU::decodeCoProcReg(uint64_t id) const 3779657SN/A{ 3789657SN/A const unsigned cp(REG_CP(id)); 3799657SN/A const bool is_reg32(REG_IS_32BIT(id)); 3809657SN/A const bool is_reg64(REG_IS_64BIT(id)); 3819657SN/A 3829657SN/A // CP numbers larger than 15 are reserved for KVM extensions 3839657SN/A if (cp > 15) 3849657SN/A return NUM_MISCREGS; 3859657SN/A 3869657SN/A const unsigned crm(REG_CRM(id)); 3879657SN/A const unsigned crn(REG_CRN(id)); 3889657SN/A const unsigned opc1(REG_OPC1(id)); 3899657SN/A const unsigned opc2(REG_OPC2(id)); 3909657SN/A 3919657SN/A if (is_reg32) { 3929657SN/A switch (cp) { 3939657SN/A case 14: 3949657SN/A return decodeCP14Reg(crn, opc1, crm, opc2); 3959657SN/A 3969657SN/A case 15: 3979657SN/A return decodeCP15Reg(crn, opc1, crm, opc2); 3989657SN/A 3999657SN/A default: 4009657SN/A return NUM_MISCREGS; 4019657SN/A } 4029657SN/A } else if(is_reg64) { 4039657SN/A return NUM_MISCREGS; 4049657SN/A } else { 4059657SN/A warn("Unhandled register length, register (0x%x) ignored.\n"); 4069657SN/A return NUM_MISCREGS; 4079657SN/A } 4089657SN/A} 4099657SN/A 4109657SN/AArmISA::MiscRegIndex 4119657SN/AArmKvmCPU::decodeVFPCtrlReg(uint64_t id) const 4129657SN/A{ 4139657SN/A if (!REG_IS_ARM(id) || !REG_IS_VFP(id) || !REG_IS_VFP_CTRL(id)) 4149657SN/A return NUM_MISCREGS; 4159657SN/A 4169657SN/A const unsigned vfp_reg(REG_VFP_REG(id)); 4179657SN/A switch (vfp_reg) { 4189657SN/A case KVM_REG_ARM_VFP_FPSID: return MISCREG_FPSID; 4199657SN/A case KVM_REG_ARM_VFP_FPSCR: return MISCREG_FPSCR; 4209657SN/A case KVM_REG_ARM_VFP_MVFR0: return MISCREG_MVFR0; 4219657SN/A case KVM_REG_ARM_VFP_MVFR1: return MISCREG_MVFR1; 4229657SN/A case KVM_REG_ARM_VFP_FPEXC: return MISCREG_FPEXC; 4239657SN/A 4249657SN/A case KVM_REG_ARM_VFP_FPINST: 4259657SN/A case KVM_REG_ARM_VFP_FPINST2: 4269657SN/A warn_once("KVM: FPINST not implemented.\n"); 4279657SN/A return NUM_MISCREGS; 4289657SN/A 4299657SN/A default: 4309657SN/A return NUM_MISCREGS; 4319657SN/A } 4329657SN/A} 4339657SN/A 4349657SN/Abool 4359657SN/AArmKvmCPU::isInvariantReg(uint64_t id) 4369657SN/A{ 4379657SN/A /* Mask away the value field from multiplexed registers, we assume 4389657SN/A * that entire groups of multiplexed registers can be treated as 4399657SN/A * invariant. */ 4409657SN/A if (REG_IS_ARM(id) && REG_IS_DEMUX(id)) 4419657SN/A id &= ~KVM_REG_ARM_DEMUX_VAL_MASK; 4429657SN/A 4439657SN/A return invariant_regs.find(id) != invariant_regs.end(); 4449657SN/A} 4459657SN/A 4469657SN/Abool 4479657SN/AArmKvmCPU::getRegList(struct kvm_reg_list ®s) const 4489657SN/A{ 4499657SN/A if (ioctl(KVM_GET_REG_LIST, (void *)®s) == -1) { 4509657SN/A if (errno == E2BIG) { 4519657SN/A return false; 4529657SN/A } else { 4539657SN/A panic("KVM: Failed to get vCPU register list (errno: %i)\n", 4549657SN/A errno); 4559657SN/A } 4569657SN/A } else { 4579657SN/A return true; 4589657SN/A } 4599657SN/A} 4609657SN/A 4619657SN/Avoid 4629658SN/AArmKvmCPU::dumpKvmStateCore() 4639658SN/A{ 4649658SN/A /* Print core registers */ 4659658SN/A uint32_t pc(getOneRegU32(REG_CORE32(usr_regs.ARM_pc))); 4669658SN/A inform("PC: 0x%x\n", pc); 4679658SN/A 4689658SN/A for (const KvmIntRegInfo *ri(kvmIntRegs); 4699658SN/A ri->idx != NUM_INTREGS; ++ri) { 4709658SN/A 4719658SN/A uint32_t value(getOneRegU32(ri->id)); 4729658SN/A inform("%s: 0x%x\n", ri->name, value); 4739658SN/A } 4749658SN/A 4759658SN/A for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); 4769658SN/A ri->idx != NUM_MISCREGS; ++ri) { 4779658SN/A 4789658SN/A uint32_t value(getOneRegU32(ri->id)); 4799658SN/A inform("%s: 0x%x\n", miscRegName[ri->idx], value); 4809658SN/A } 4819658SN/A} 4829658SN/A 4839658SN/Avoid 4849658SN/AArmKvmCPU::dumpKvmStateMisc() 4859658SN/A{ 4869658SN/A /* Print co-processor registers */ 4879658SN/A const RegIndexVector ®_ids(getRegList());; 4889658SN/A for (RegIndexVector::const_iterator it(reg_ids.begin()); 4899658SN/A it != reg_ids.end(); ++it) { 4909658SN/A uint64_t id(*it); 4919658SN/A 4929658SN/A if (REG_IS_ARM(id) && REG_CP(id) <= 15) { 4939658SN/A dumpKvmStateCoProc(id); 4949658SN/A } else if (REG_IS_ARM(id) && REG_IS_VFP(id)) { 4959658SN/A dumpKvmStateVFP(id); 4969658SN/A } else if (REG_IS_ARM(id) && REG_IS_DEMUX(id)) { 4979658SN/A switch (id & KVM_REG_ARM_DEMUX_ID_MASK) { 4989658SN/A case KVM_REG_ARM_DEMUX_ID_CCSIDR: 4999658SN/A inform("CCSIDR [0x%x]: %s\n", 5009658SN/A EXTRACT_FIELD(id, 5019658SN/A KVM_REG_ARM_DEMUX_VAL_MASK, 5029658SN/A KVM_REG_ARM_DEMUX_VAL_SHIFT), 5039658SN/A getAndFormatOneReg(id)); 5049658SN/A break; 5059658SN/A default: 5069658SN/A inform("DEMUX [0x%x, 0x%x]: %s\n", 5079658SN/A EXTRACT_FIELD(id, 5089658SN/A KVM_REG_ARM_DEMUX_ID_MASK, 5099658SN/A KVM_REG_ARM_DEMUX_ID_SHIFT), 5109658SN/A EXTRACT_FIELD(id, 5119658SN/A KVM_REG_ARM_DEMUX_VAL_MASK, 5129658SN/A KVM_REG_ARM_DEMUX_VAL_SHIFT), 5139658SN/A getAndFormatOneReg(id)); 5149658SN/A break; 5159658SN/A } 5169658SN/A } else if (!REG_IS_CORE(id)) { 5179658SN/A inform("0x%x: %s\n", id, getAndFormatOneReg(id)); 5189658SN/A } 5199658SN/A } 5209658SN/A} 5219658SN/A 5229658SN/Avoid 5239658SN/AArmKvmCPU::dumpKvmStateCoProc(uint64_t id) 5249658SN/A{ 5259658SN/A assert(REG_IS_ARM(id)); 5269658SN/A assert(REG_CP(id) <= 15); 5279658SN/A 5289658SN/A if (REG_IS_32BIT(id)) { 5299658SN/A // 32-bit co-proc registers 5309658SN/A MiscRegIndex idx(decodeCoProcReg(id)); 5319658SN/A uint32_t value(getOneRegU32(id)); 5329658SN/A 5339658SN/A if (idx != NUM_MISCREGS && 5349658SN/A !(idx >= MISCREG_CP15_UNIMP_START && idx < MISCREG_CP15_END)) { 5359658SN/A const char *name(miscRegName[idx]); 5369658SN/A const unsigned m5_ne(tc->readMiscRegNoEffect(idx)); 5379658SN/A const unsigned m5_e(tc->readMiscReg(idx)); 5389658SN/A inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: " 5399658SN/A "[%s]: 0x%x/0x%x\n", 5409658SN/A REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), 5419658SN/A REG_OPC2(id), isInvariantReg(id), 5429658SN/A name, value, m5_e); 5439658SN/A if (m5_e != m5_ne) { 5449658SN/A inform("readMiscReg: %x, readMiscRegNoEffect: %x\n", 5459658SN/A m5_e, m5_ne); 5469658SN/A } 5479658SN/A } else { 5489658SN/A const char *name(idx != NUM_MISCREGS ? miscRegName[idx] : "-"); 5499658SN/A inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: [%s]: " 5509658SN/A "0x%x\n", 5519658SN/A REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), 5529658SN/A REG_OPC2(id), isInvariantReg(id), name, value); 5539658SN/A } 5549658SN/A } else { 5559658SN/A inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i " 5569658SN/A "len: 0x%x]: %s\n", 5579658SN/A REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), 5589658SN/A REG_OPC2(id), isInvariantReg(id), 5599658SN/A EXTRACT_FIELD(id, KVM_REG_SIZE_MASK, KVM_REG_SIZE_SHIFT), 5609658SN/A getAndFormatOneReg(id)); 5619658SN/A } 5629658SN/A} 5639658SN/A 5649658SN/Avoid 5659658SN/AArmKvmCPU::dumpKvmStateVFP(uint64_t id) 5669658SN/A{ 5679658SN/A assert(REG_IS_ARM(id)); 5689658SN/A assert(REG_IS_VFP(id)); 5699658SN/A 5709658SN/A if (REG_IS_VFP_REG(id)) { 5719658SN/A const unsigned idx(id & KVM_REG_ARM_VFP_MASK); 5729658SN/A inform("VFP reg %i: %s", idx, getAndFormatOneReg(id)); 5739658SN/A } else if (REG_IS_VFP_CTRL(id)) { 5749658SN/A MiscRegIndex idx(decodeVFPCtrlReg(id)); 5759658SN/A if (idx != NUM_MISCREGS) { 5769658SN/A inform("VFP [%s]: %s", miscRegName[idx], getAndFormatOneReg(id)); 5779658SN/A } else { 5789658SN/A inform("VFP [0x%x]: %s", id, getAndFormatOneReg(id)); 5799658SN/A } 5809658SN/A } else { 5819658SN/A inform("VFP [0x%x]: %s", id, getAndFormatOneReg(id)); 5829658SN/A } 5839658SN/A} 5849658SN/A 5859658SN/Avoid 5869657SN/AArmKvmCPU::updateKvmStateCore() 5879657SN/A{ 5889657SN/A for (const KvmIntRegInfo *ri(kvmIntRegs); 5899657SN/A ri->idx != NUM_INTREGS; ++ri) { 5909657SN/A 5919657SN/A uint64_t value(tc->readIntRegFlat(ri->idx)); 5929657SN/A DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value); 5939657SN/A setOneReg(ri->id, value); 5949657SN/A } 5959657SN/A 5969657SN/A DPRINTF(KvmContext, "kvm(PC) := 0x%x\n", tc->instAddr()); 5979657SN/A setOneReg(REG_CORE32(usr_regs.ARM_pc), tc->instAddr()); 5989657SN/A 5999657SN/A for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); 6009657SN/A ri->idx != NUM_MISCREGS; ++ri) { 6019657SN/A 6029657SN/A uint64_t value(tc->readMiscReg(ri->idx)); 6039657SN/A DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value); 6049657SN/A setOneReg(ri->id, value); 6059657SN/A } 6069658SN/A 6079658SN/A if (DTRACE(KvmContext)) 6089658SN/A dumpKvmStateCore(); 6099657SN/A} 6109657SN/A 6119657SN/Avoid 6129657SN/AArmKvmCPU::updateKvmStateMisc() 6139657SN/A{ 6149657SN/A static bool warned(false); // We can't use warn_once since we want 6159657SN/A // to show /all/ registers 6169657SN/A 6179657SN/A const RegIndexVector ®s(getRegList()); 6189657SN/A 6199657SN/A for (RegIndexVector::const_iterator it(regs.begin()); 6209657SN/A it != regs.end(); 6219657SN/A ++it) { 6229657SN/A 6239657SN/A if (!REG_IS_ARM(*it)) { 6249657SN/A if (!warned) 6259657SN/A warn("Skipping non-ARM register: 0x%x\n", *it); 6269657SN/A } else if (isInvariantReg(*it)) { 6279657SN/A DPRINTF(Kvm, "Skipping invariant register: 0x%x\n", *it); 6289657SN/A } else if (REG_IS_CORE(*it)) { 6299657SN/A // Core registers are handled in updateKvmStateCore 6309657SN/A continue; 6319657SN/A } else if (REG_CP(*it) <= 15) { 6329657SN/A updateKvmStateCoProc(*it, !warned); 6339657SN/A } else if (REG_IS_VFP(*it)) { 6349657SN/A updateKvmStateVFP(*it, !warned); 6359657SN/A } else { 6369657SN/A if (!warned) { 6379657SN/A warn("Skipping register with unknown CP (%i) id: 0x%x\n", 6389657SN/A REG_CP(*it), *it); 6399657SN/A } 6409657SN/A } 6419657SN/A 6429657SN/A } 6439657SN/A 6449657SN/A warned = true; 6459658SN/A if (DTRACE(KvmContext)) 6469658SN/A dumpKvmStateMisc(); 6479657SN/A} 6489657SN/A 6499657SN/Avoid 6509657SN/AArmKvmCPU::updateKvmStateCoProc(uint64_t id, bool show_warnings) 6519657SN/A{ 6529657SN/A MiscRegIndex reg(decodeCoProcReg(id)); 6539657SN/A 6549657SN/A assert(REG_IS_ARM(id)); 6559657SN/A assert(REG_CP(id) <= 15); 6569657SN/A 6579657SN/A if (id == KVM_REG64_TTBR0 || id == KVM_REG64_TTBR1) { 6589657SN/A // HACK HACK HACK: Workaround for 64-bit TTBRx 6599657SN/A reg = (id == KVM_REG64_TTBR0 ? MISCREG_TTBR0 : MISCREG_TTBR1); 6609657SN/A if (show_warnings) 6619657SN/A hack("KVM: 64-bit TTBBRx workaround\n"); 6629657SN/A } 6639657SN/A 6649657SN/A if (reg == NUM_MISCREGS) { 6659657SN/A if (show_warnings) { 6669657SN/A warn("KVM: Ignoring unknown KVM co-processor register (0x%.8x):\n", 6679657SN/A id); 6689657SN/A warn("\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i" 6699657SN/A " opc2: %i]\n", 6709657SN/A id, REG_CP(id), REG_IS_64BIT(id), REG_CRN(id), 6719657SN/A REG_OPC1(id), REG_CRM(id), REG_OPC2(id)); 6729657SN/A } 6739657SN/A } else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) { 6749657SN/A if (show_warnings) 6759657SN/A warn("KVM: Co-processor reg. %s not implemented by gem5.\n", 6769657SN/A miscRegName[reg]); 6779657SN/A } else { 6789657SN/A setOneReg(id, tc->readMiscRegNoEffect(reg)); 6799657SN/A } 6809657SN/A} 6819657SN/A 6829657SN/A 6839657SN/Avoid 6849657SN/AArmKvmCPU::updateKvmStateVFP(uint64_t id, bool show_warnings) 6859657SN/A{ 6869657SN/A assert(REG_IS_ARM(id)); 6879657SN/A assert(REG_IS_VFP(id)); 6889657SN/A 6899657SN/A if (REG_IS_VFP_REG(id)) { 6909657SN/A if (!REG_IS_64BIT(id)) { 6919657SN/A if (show_warnings) 6929657SN/A warn("Unexpected VFP register length (reg: 0x%x).\n", id); 6939657SN/A return; 6949657SN/A } 6959657SN/A const unsigned idx(id & KVM_REG_ARM_VFP_MASK); 6969657SN/A const unsigned idx_base(idx << 1); 6979657SN/A const unsigned idx_hi(idx_base + 1); 6989657SN/A const unsigned idx_lo(idx_base + 0); 6999657SN/A uint64_t value( 7009657SN/A ((uint64_t)tc->readFloatRegBitsFlat(idx_hi) << 32) | 7019657SN/A tc->readFloatRegBitsFlat(idx_lo)); 7029657SN/A 7039657SN/A setOneReg(id, value); 7049657SN/A } else if (REG_IS_VFP_CTRL(id)) { 7059657SN/A MiscRegIndex idx(decodeVFPCtrlReg(id)); 7069657SN/A if (idx == NUM_MISCREGS) { 7079657SN/A if (show_warnings) 7089657SN/A warn("Unhandled VFP control register: 0x%x\n", id); 7099657SN/A return; 7109657SN/A } 7119657SN/A if (!REG_IS_32BIT(id)) { 7129657SN/A if (show_warnings) 7139657SN/A warn("Ignoring VFP control register (%s) with " 7149657SN/A "unexpected size.\n", 7159657SN/A miscRegName[idx]); 7169657SN/A return; 7179657SN/A } 7189657SN/A setOneReg(id, (uint32_t)tc->readMiscReg(idx)); 7199657SN/A } else { 7209657SN/A if (show_warnings) 7219657SN/A warn("Unhandled VFP register: 0x%x\n", id); 7229657SN/A } 7239657SN/A} 7249657SN/A 7259657SN/Avoid 7269657SN/AArmKvmCPU::updateTCStateCore() 7279657SN/A{ 7289657SN/A for (const KvmIntRegInfo *ri(kvmIntRegs); 7299657SN/A ri->idx != NUM_INTREGS; ++ri) { 7309657SN/A 7319657SN/A tc->setIntRegFlat(ri->idx, getOneRegU32(ri->id)); 7329657SN/A } 7339657SN/A 7349657SN/A for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); 7359657SN/A ri->idx != NUM_MISCREGS; ++ri) { 7369657SN/A 7379657SN/A tc->setMiscRegNoEffect(ri->idx, getOneRegU32(ri->id)); 7389657SN/A } 7399657SN/A 7409657SN/A /* We want the simulator to execute all side-effects of the CPSR 7419657SN/A * update since this updates PC state and register maps. 7429657SN/A */ 7439657SN/A tc->setMiscReg(MISCREG_CPSR, tc->readMiscRegNoEffect(MISCREG_CPSR)); 7449657SN/A 7459657SN/A // We update the PC state after we have updated the CPSR the 7469657SN/A // contents of the CPSR affects how the npc is updated. 7479657SN/A PCState pc(tc->pcState()); 7489657SN/A pc.set(getOneRegU32(REG_CORE32(usr_regs.ARM_pc))); 7499657SN/A tc->pcState(pc); 7509658SN/A 7519658SN/A if (DTRACE(KvmContext)) 7529658SN/A dumpKvmStateCore(); 7539657SN/A} 7549657SN/A 7559657SN/Avoid 7569657SN/AArmKvmCPU::updateTCStateMisc() 7579657SN/A{ 7589657SN/A static bool warned(false); // We can't use warn_once since we want 7599657SN/A // to show /all/ registers 7609657SN/A 7619657SN/A const RegIndexVector ®_ids(getRegList());; 7629657SN/A for (RegIndexVector::const_iterator it(reg_ids.begin()); 7639657SN/A it != reg_ids.end(); ++it) { 7649657SN/A 7659657SN/A if (!REG_IS_ARM(*it)) { 7669657SN/A if (!warned) 7679657SN/A warn("Skipping non-ARM register: 0x%x\n", *it); 7689657SN/A } else if (REG_IS_CORE(*it)) { 7699657SN/A // Core registers are handled in updateKvmStateCore 7709657SN/A } else if (REG_CP(*it) <= 15) { 7719657SN/A updateTCStateCoProc(*it, !warned); 7729657SN/A } else if (REG_IS_VFP(*it)) { 7739657SN/A updateTCStateVFP(*it, !warned); 7749657SN/A } else { 7759657SN/A if (!warned) { 7769657SN/A warn("Skipping register with unknown CP (%i) id: 0x%x\n", 7779657SN/A REG_CP(*it), *it); 7789657SN/A } 7799657SN/A } 7809657SN/A } 7819657SN/A 7829657SN/A warned = true; 7839658SN/A 7849658SN/A if (DTRACE(KvmContext)) 7859658SN/A dumpKvmStateMisc(); 7869657SN/A} 7879657SN/A 7889657SN/Avoid 7899657SN/AArmKvmCPU::updateTCStateCoProc(uint64_t id, bool show_warnings) 7909657SN/A{ 7919657SN/A MiscRegIndex reg(decodeCoProcReg(id)); 7929657SN/A 7939657SN/A assert(REG_IS_ARM(id)); 7949657SN/A assert(REG_CP(id) <= 15); 7959657SN/A 7969657SN/A if (id == KVM_REG64_TTBR0 || id == KVM_REG64_TTBR1) { 7979657SN/A // HACK HACK HACK: We don't currently support 64-bit TTBR0/TTBR1 7989657SN/A hack_once("KVM: 64-bit TTBRx workaround\n"); 7999657SN/A tc->setMiscRegNoEffect( 8009657SN/A id == KVM_REG64_TTBR0 ? MISCREG_TTBR0 : MISCREG_TTBR1, 8019657SN/A (uint32_t)(getOneRegU64(id) & 0xFFFFFFFF)); 8029657SN/A } else if (reg == MISCREG_TTBCR) { 8039657SN/A uint32_t value(getOneRegU64(id)); 8049657SN/A if (value & 0x80000000) 8059657SN/A panic("KVM: Guest tried to enable LPAE.\n"); 8069657SN/A tc->setMiscRegNoEffect(reg, value); 8079657SN/A } else if (reg == NUM_MISCREGS) { 8089657SN/A if (show_warnings) { 8099657SN/A warn("KVM: Ignoring unknown KVM co-processor register:\n", id); 8109657SN/A warn("\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i" 8119657SN/A " opc2: %i]\n", 8129657SN/A id, REG_CP(id), REG_IS_64BIT(id), REG_CRN(id), 8139657SN/A REG_OPC1(id), REG_CRM(id), REG_OPC2(id)); 8149657SN/A } 8159657SN/A } else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) { 8169657SN/A if (show_warnings) 8179657SN/A warn_once("KVM: Co-processor reg. %s not implemented by gem5.\n", 8189657SN/A miscRegName[reg]); 8199657SN/A } else { 8209657SN/A tc->setMiscRegNoEffect(reg, getOneRegU32(id)); 8219657SN/A } 8229657SN/A} 8239657SN/A 8249657SN/Avoid 8259657SN/AArmKvmCPU::updateTCStateVFP(uint64_t id, bool show_warnings) 8269657SN/A{ 8279657SN/A assert(REG_IS_ARM(id)); 8289657SN/A assert(REG_IS_VFP(id)); 8299657SN/A 8309657SN/A if (REG_IS_VFP_REG(id)) { 8319657SN/A if (!REG_IS_64BIT(id)) { 8329657SN/A if (show_warnings) 8339657SN/A warn("Unexpected VFP register length (reg: 0x%x).\n", id); 8349657SN/A return; 8359657SN/A } 8369657SN/A const unsigned idx(id & KVM_REG_ARM_VFP_MASK); 8379657SN/A const unsigned idx_base(idx << 1); 8389657SN/A const unsigned idx_hi(idx_base + 1); 8399657SN/A const unsigned idx_lo(idx_base + 0); 8409657SN/A uint64_t value(getOneRegU64(id)); 8419657SN/A 8429657SN/A tc->setFloatRegBitsFlat(idx_hi, (value >> 32) & 0xFFFFFFFF); 8439657SN/A tc->setFloatRegBitsFlat(idx_lo, value & 0xFFFFFFFF); 8449657SN/A } else if (REG_IS_VFP_CTRL(id)) { 8459657SN/A MiscRegIndex idx(decodeVFPCtrlReg(id)); 8469657SN/A if (idx == NUM_MISCREGS) { 8479657SN/A if (show_warnings) 8489657SN/A warn("Unhandled VFP control register: 0x%x\n", id); 8499657SN/A return; 8509657SN/A } 8519657SN/A if (!REG_IS_32BIT(id)) { 8529657SN/A if (show_warnings) 8539657SN/A warn("Ignoring VFP control register (%s) with " 8549657SN/A "unexpected size.\n", 8559657SN/A miscRegName[idx]); 8569657SN/A return; 8579657SN/A } 8589657SN/A tc->setMiscReg(idx, getOneRegU64(id)); 8599657SN/A } else { 8609657SN/A if (show_warnings) 8619657SN/A warn("Unhandled VFP register: 0x%x\n", id); 8629657SN/A } 8639657SN/A} 8649657SN/A 8659657SN/AArmKvmCPU * 8669657SN/AArmKvmCPUParams::create() 8679657SN/A{ 8689657SN/A return new ArmKvmCPU(this); 8699657SN/A} 870