1/* 2 * Copyright (c) 2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#include "arch/arm/kvm/arm_cpu.hh" 41 42#include <linux/kvm.h> 43 44#include <algorithm> 45#include <cerrno> 46#include <memory> 47 48#include "arch/registers.hh" 49#include "cpu/kvm/base.hh" 50#include "debug/Kvm.hh" 51#include "debug/KvmContext.hh" 52#include "debug/KvmInt.hh" 53#include "sim/pseudo_inst.hh" 54 55using namespace ArmISA; 56 57#define EXTRACT_FIELD(val, mask, shift) \ 58 (((val) & (mask)) >> (shift)) 59 60#define REG_IS_ARM(id) \ 61 (((id) & KVM_REG_ARCH_MASK) == KVM_REG_ARM) 62 63#define REG_IS_32BIT(id) \ 64 (((id) & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) 65 66#define REG_IS_64BIT(id) \ 67 (((id) & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) 68 69#define REG_IS_CP(id, cp) \ 70 (((id) & KVM_REG_ARM_COPROC_MASK) == (cp)) 71 72#define REG_IS_CORE(id) REG_IS_CP((id), KVM_REG_ARM_CORE) 73 74#define REG_IS_VFP(id) REG_IS_CP((id), KVM_REG_ARM_VFP) 75#define REG_VFP_REG(id) ((id) & KVM_REG_ARM_VFP_MASK) 76// HACK: These aren't really defined in any of the headers, so we'll 77// assume some reasonable values for now. 78#define REG_IS_VFP_REG(id) (REG_VFP_REG(id) < 0x100) 79#define REG_IS_VFP_CTRL(id) (REG_VFP_REG(id) >= 0x100) 80 81#define REG_IS_DEMUX(id) REG_IS_CP((id), KVM_REG_ARM_DEMUX) 82 83 84// There is no constant in the kernel headers defining the mask to use 85// to get the core register index. We'll just do what they do 86// internally. 87#define REG_CORE_IDX(id) \ 88 (~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE)) 89 90#define REG_CP(id) \ 91 EXTRACT_FIELD(id, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_SHIFT) 92 93#define REG_CRN(id) \ 94 EXTRACT_FIELD(id, KVM_REG_ARM_32_CRN_MASK, KVM_REG_ARM_32_CRN_SHIFT) 95 96#define REG_OPC1(id) \ 97 EXTRACT_FIELD(id, KVM_REG_ARM_OPC1_MASK, KVM_REG_ARM_OPC1_SHIFT) 98 99#define REG_CRM(id) \ 100 EXTRACT_FIELD(id, KVM_REG_ARM_CRM_MASK, KVM_REG_ARM_CRM_SHIFT) 101 102#define REG_OPC2(id) \ 103 EXTRACT_FIELD(id, KVM_REG_ARM_32_OPC2_MASK, KVM_REG_ARM_32_OPC2_SHIFT) 104 105#define REG_CP32(cpnum, crn, opc1, crm, opc2) ( \ 106 (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 107 ((cpnum) << KVM_REG_ARM_COPROC_SHIFT) | \ 108 ((crn) << KVM_REG_ARM_32_CRN_SHIFT) | \ 109 ((opc1) << KVM_REG_ARM_OPC1_SHIFT) | \ 110 ((crm) << KVM_REG_ARM_CRM_SHIFT) | \ 111 ((opc2) << KVM_REG_ARM_32_OPC2_SHIFT)) 112 113#define REG_CP64(cpnum, opc1, crm) ( \ 114 (KVM_REG_ARM | KVM_REG_SIZE_U64) | \ 115 ((cpnum) << KVM_REG_ARM_COPROC_SHIFT) | \ 116 ((opc1) << KVM_REG_ARM_OPC1_SHIFT) | \ 117 ((crm) << KVM_REG_ARM_CRM_SHIFT)) 118 119#define REG_CORE32(kname) ( \ 120 (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 121 (KVM_REG_ARM_CORE) | \ 122 (KVM_REG_ARM_CORE_REG(kname))) 123 124#define REG_VFP32(regno) ( \ 125 (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 126 KVM_REG_ARM_VFP | (regno)) 127 128#define REG_VFP64(regno) ( \ 129 (KVM_REG_ARM | KVM_REG_SIZE_U64) | \ 130 KVM_REG_ARM_VFP | (regno)) 131 132#define REG_DEMUX32(dmxid, val) ( \ 133 (KVM_REG_ARM | KVM_REG_SIZE_U32) | \ 134 (dmxid) | (val)) 135 136// Some of the co-processor registers are invariants and must have the 137// same value on both the host and the guest. We need to keep a list 138// of these to prevent gem5 from fiddling with them on the guest. 139static uint64_t invariant_reg_vector[] = { 140 REG_CP32(15, 0, 0, 0, 0), // MIDR 141 REG_CP32(15, 0, 0, 0, 1), // CTR 142 REG_CP32(15, 0, 0, 0, 2), // TCMTR 143 REG_CP32(15, 0, 0, 0, 3), // TLBTR 144 REG_CP32(15, 0, 0, 0, 6), // REVIDR 145 146 REG_CP32(15, 0, 0, 1, 0), // ID_PFR0 147 REG_CP32(15, 0, 0, 1, 1), // ID_PFR1 148 REG_CP32(15, 0, 0, 1, 2), // ID_DFR0 149 REG_CP32(15, 0, 0, 1, 3), // ID_AFR0 150 REG_CP32(15, 0, 0, 1, 4), // ID_MMFR0 151 REG_CP32(15, 0, 0, 1, 5), // ID_MMFR1 152 REG_CP32(15, 0, 0, 1, 6), // ID_MMFR2 153 REG_CP32(15, 0, 0, 1, 7), // ID_MMFR3 154 155 REG_CP32(15, 0, 0, 2, 0), // ID_ISAR0 156 REG_CP32(15, 0, 0, 2, 1), // ID_ISAR1 157 REG_CP32(15, 0, 0, 2, 2), // ID_ISAR2 158 REG_CP32(15, 0, 0, 2, 3), // ID_ISAR3 159 REG_CP32(15, 0, 0, 2, 4), // ID_ISAR4 160 REG_CP32(15, 0, 0, 2, 5), // ID_ISAR5 161 162 REG_CP32(15, 0, 1, 0, 0), // CSSIDR 163 REG_CP32(15, 0, 1, 0, 1), // CLIDR 164 REG_CP32(15, 0, 1, 0, 7), // AIDR 165 166 REG_VFP32(KVM_REG_ARM_VFP_MVFR0), 167 REG_VFP32(KVM_REG_ARM_VFP_MVFR1), 168 REG_VFP32(KVM_REG_ARM_VFP_FPSID), 169 170 REG_DEMUX32(KVM_REG_ARM_DEMUX_ID_CCSIDR, 0), 171}; 172 173const static uint64_t KVM_REG64_TTBR0(REG_CP64(15, 0, 2)); 174const static uint64_t KVM_REG64_TTBR1(REG_CP64(15, 1, 2)); 175 176#define INTERRUPT_ID(type, vcpu, irq) ( \ 177 ((type) << KVM_ARM_IRQ_TYPE_SHIFT) | \ 178 ((vcpu) << KVM_ARM_IRQ_VCPU_SHIFT) | \ 179 ((irq) << KVM_ARM_IRQ_NUM_SHIFT)) 180 181#define INTERRUPT_VCPU_IRQ(vcpu) \ 182 INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_IRQ) 183 184#define INTERRUPT_VCPU_FIQ(vcpu) \ 185 INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_FIQ) 186 187 188#define COUNT_OF(l) (sizeof(l) / sizeof(*l)) 189 190const std::set<uint64_t> ArmKvmCPU::invariant_regs( 191 invariant_reg_vector, 192 invariant_reg_vector + COUNT_OF(invariant_reg_vector)); 193 194 195ArmKvmCPU::KvmIntRegInfo ArmKvmCPU::kvmIntRegs[] = { 196 { REG_CORE32(usr_regs.ARM_r0), INTREG_R0, "R0" }, 197 { REG_CORE32(usr_regs.ARM_r1), INTREG_R1, "R1" }, 198 { REG_CORE32(usr_regs.ARM_r2), INTREG_R2, "R2" }, 199 { REG_CORE32(usr_regs.ARM_r3), INTREG_R3, "R3" }, 200 { REG_CORE32(usr_regs.ARM_r4), INTREG_R4, "R4" }, 201 { REG_CORE32(usr_regs.ARM_r5), INTREG_R5, "R5" }, 202 { REG_CORE32(usr_regs.ARM_r6), INTREG_R6, "R6" }, 203 { REG_CORE32(usr_regs.ARM_r7), INTREG_R7, "R7" }, 204 { REG_CORE32(usr_regs.ARM_r8), INTREG_R8, "R8" }, 205 { REG_CORE32(usr_regs.ARM_r9), INTREG_R9, "R9" }, 206 { REG_CORE32(usr_regs.ARM_r10), INTREG_R10, "R10" }, 207 { REG_CORE32(usr_regs.ARM_fp), INTREG_R11, "R11" }, 208 { REG_CORE32(usr_regs.ARM_ip), INTREG_R12, "R12" }, 209 { REG_CORE32(usr_regs.ARM_sp), INTREG_R13, "R13(USR)" }, 210 { REG_CORE32(usr_regs.ARM_lr), INTREG_R14, "R14(USR)" }, 211 212 { REG_CORE32(svc_regs[0]), INTREG_SP_SVC, "R13(SVC)" }, 213 { REG_CORE32(svc_regs[1]), INTREG_LR_SVC, "R14(SVC)" }, 214 215 { REG_CORE32(abt_regs[0]), INTREG_SP_ABT, "R13(ABT)" }, 216 { REG_CORE32(abt_regs[1]), INTREG_LR_ABT, "R14(ABT)" }, 217 218 { REG_CORE32(und_regs[0]), INTREG_SP_UND, "R13(UND)" }, 219 { REG_CORE32(und_regs[1]), INTREG_LR_UND, "R14(UND)" }, 220 221 { REG_CORE32(irq_regs[0]), INTREG_SP_IRQ, "R13(IRQ)" }, 222 { REG_CORE32(irq_regs[1]), INTREG_LR_IRQ, "R14(IRQ)" }, 223 224 225 { REG_CORE32(fiq_regs[0]), INTREG_R8_FIQ, "R8(FIQ)" }, 226 { REG_CORE32(fiq_regs[1]), INTREG_R9_FIQ, "R9(FIQ)" }, 227 { REG_CORE32(fiq_regs[2]), INTREG_R10_FIQ, "R10(FIQ)" }, 228 { REG_CORE32(fiq_regs[3]), INTREG_R11_FIQ, "R11(FIQ)" }, 229 { REG_CORE32(fiq_regs[4]), INTREG_R12_FIQ, "R12(FIQ)" }, 230 { REG_CORE32(fiq_regs[5]), INTREG_R13_FIQ, "R13(FIQ)" }, 231 { REG_CORE32(fiq_regs[6]), INTREG_R14_FIQ, "R14(FIQ)" }, 232 { 0, NUM_INTREGS, NULL } 233}; 234 235ArmKvmCPU::KvmCoreMiscRegInfo ArmKvmCPU::kvmCoreMiscRegs[] = { 236 { REG_CORE32(usr_regs.ARM_cpsr), MISCREG_CPSR, "CPSR" }, 237 { REG_CORE32(svc_regs[2]), MISCREG_SPSR_SVC, "SPSR(SVC)" }, 238 { REG_CORE32(abt_regs[2]), MISCREG_SPSR_ABT, "SPSR(ABT)" }, 239 { REG_CORE32(und_regs[2]), MISCREG_SPSR_UND, "SPSR(UND)" }, 240 { REG_CORE32(irq_regs[2]), MISCREG_SPSR_IRQ, "SPSR(IRQ)" }, 241 { REG_CORE32(fiq_regs[2]), MISCREG_SPSR_FIQ, "SPSR(FIQ)" }, 242 { 0, NUM_MISCREGS } 243}; 244 245ArmKvmCPU::ArmKvmCPU(ArmKvmCPUParams *params) 246 : BaseKvmCPU(params), 247 irqAsserted(false), fiqAsserted(false) 248{ 249} 250 251ArmKvmCPU::~ArmKvmCPU() 252{ 253} 254 255void 256ArmKvmCPU::startup() 257{ 258 BaseKvmCPU::startup(); 259 260 /* TODO: This needs to be moved when we start to support VMs with 261 * multiple threads since kvmArmVCpuInit requires that all CPUs in 262 * the VM have been created. 263 */ 264 /* TODO: The CPU type needs to be configurable once KVM on ARM 265 * starts to support more CPUs. 266 */ 267 kvmArmVCpuInit(KVM_ARM_TARGET_CORTEX_A15); 268} 269 270Tick 271ArmKvmCPU::kvmRun(Tick ticks) 272{ 273 bool simFIQ(interrupts[0]->checkRaw(INT_FIQ)); 274 bool simIRQ(interrupts[0]->checkRaw(INT_IRQ)); 275 276 if (fiqAsserted != simFIQ) { 277 fiqAsserted = simFIQ; 278 DPRINTF(KvmInt, "KVM: Update FIQ state: %i\n", simFIQ); 279 vm.setIRQLine(INTERRUPT_VCPU_FIQ(vcpuID), simFIQ); 280 } 281 if (irqAsserted != simIRQ) { 282 irqAsserted = simIRQ; 283 DPRINTF(KvmInt, "KVM: Update IRQ state: %i\n", simIRQ); 284 vm.setIRQLine(INTERRUPT_VCPU_IRQ(vcpuID), simIRQ); 285 } 286 287 return BaseKvmCPU::kvmRun(ticks); 288} 289 290void 291ArmKvmCPU::dump() 292{ 293 dumpKvmStateCore(); 294 dumpKvmStateMisc(); 295} 296 297void 298ArmKvmCPU::updateKvmState() 299{ 300 DPRINTF(KvmContext, "Updating KVM state...\n"); 301 302 updateKvmStateCore(); 303 updateKvmStateMisc(); 304} 305 306void 307ArmKvmCPU::updateThreadContext() 308{ 309 DPRINTF(KvmContext, "Updating gem5 state...\n"); 310 311 updateTCStateCore(); 312 updateTCStateMisc(); 313} 314 315Tick 316ArmKvmCPU::onKvmExitHypercall() 317{ 318 ThreadContext *tc(getContext(0)); 319 const uint32_t reg_ip(tc->readIntRegFlat(INTREG_R12)); 320 const uint8_t func((reg_ip >> 8) & 0xFF); 321 const uint8_t subfunc(reg_ip & 0xFF); 322 323 DPRINTF(Kvm, "KVM Hypercall: 0x%x/0x%x\n", func, subfunc); 324 const uint64_t ret(PseudoInst::pseudoInst(getContext(0), func, subfunc)); 325 326 // Just set the return value using the KVM API instead of messing 327 // with the context. We could have used the context, but that 328 // would have required us to request a full context sync. 329 setOneReg(REG_CORE32(usr_regs.ARM_r0), ret & 0xFFFFFFFF); 330 setOneReg(REG_CORE32(usr_regs.ARM_r1), (ret >> 32) & 0xFFFFFFFF); 331 332 return 0; 333} 334 335const ArmKvmCPU::RegIndexVector & 336ArmKvmCPU::getRegList() const 337{ 338 if (_regIndexList.size() == 0) { 339 std::unique_ptr<struct kvm_reg_list> regs; 340 uint64_t i(1); 341 342 do { 343 i <<= 1; 344 regs.reset((struct kvm_reg_list *) 345 operator new(sizeof(struct kvm_reg_list) + 346 i * sizeof(uint64_t))); 347 regs->n = i; 348 } while (!getRegList(*regs)); 349 _regIndexList.assign(regs->reg, 350 regs->reg + regs->n); 351 } 352 353 return _regIndexList; 354} 355 356void 357ArmKvmCPU::kvmArmVCpuInit(uint32_t target) 358{ 359 struct kvm_vcpu_init init; 360 361 memset(&init, 0, sizeof(init)); 362 363 init.target = target; 364 365 kvmArmVCpuInit(init); 366} 367 368void 369ArmKvmCPU::kvmArmVCpuInit(const struct kvm_vcpu_init &init) 370{ 371 if (ioctl(KVM_ARM_VCPU_INIT, (void *)&init) == -1) 372 panic("KVM: Failed to initialize vCPU\n"); 373} 374 375MiscRegIndex 376ArmKvmCPU::decodeCoProcReg(uint64_t id) const 377{ 378 const unsigned cp(REG_CP(id)); 379 const bool is_reg32(REG_IS_32BIT(id)); 380 const bool is_reg64(REG_IS_64BIT(id)); 381 382 // CP numbers larger than 15 are reserved for KVM extensions 383 if (cp > 15) 384 return NUM_MISCREGS; 385 386 const unsigned crm(REG_CRM(id)); 387 const unsigned crn(REG_CRN(id)); 388 const unsigned opc1(REG_OPC1(id)); 389 const unsigned opc2(REG_OPC2(id)); 390 391 if (is_reg32) { 392 switch (cp) { 393 case 14: 394 return decodeCP14Reg(crn, opc1, crm, opc2); 395 396 case 15: 397 return decodeCP15Reg(crn, opc1, crm, opc2); 398 399 default: 400 return NUM_MISCREGS; 401 } 402 } else if (is_reg64) { 403 return NUM_MISCREGS; 404 } else { 405 warn("Unhandled register length, register (0x%x) ignored.\n"); 406 return NUM_MISCREGS; 407 } 408} 409 410ArmISA::MiscRegIndex 411ArmKvmCPU::decodeVFPCtrlReg(uint64_t id) const 412{ 413 if (!REG_IS_ARM(id) || !REG_IS_VFP(id) || !REG_IS_VFP_CTRL(id)) 414 return NUM_MISCREGS; 415 416 const unsigned vfp_reg(REG_VFP_REG(id)); 417 switch (vfp_reg) { 418 case KVM_REG_ARM_VFP_FPSID: return MISCREG_FPSID; 419 case KVM_REG_ARM_VFP_FPSCR: return MISCREG_FPSCR; 420 case KVM_REG_ARM_VFP_MVFR0: return MISCREG_MVFR0; 421 case KVM_REG_ARM_VFP_MVFR1: return MISCREG_MVFR1; 422 case KVM_REG_ARM_VFP_FPEXC: return MISCREG_FPEXC; 423 424 case KVM_REG_ARM_VFP_FPINST: 425 case KVM_REG_ARM_VFP_FPINST2: 426 warn_once("KVM: FPINST not implemented.\n"); 427 return NUM_MISCREGS; 428 429 default: 430 return NUM_MISCREGS; 431 } 432} 433 434bool 435ArmKvmCPU::isInvariantReg(uint64_t id) 436{ 437 /* Mask away the value field from multiplexed registers, we assume 438 * that entire groups of multiplexed registers can be treated as 439 * invariant. */ 440 if (REG_IS_ARM(id) && REG_IS_DEMUX(id)) 441 id &= ~KVM_REG_ARM_DEMUX_VAL_MASK; 442 443 return invariant_regs.find(id) != invariant_regs.end(); 444} 445 446bool 447ArmKvmCPU::getRegList(struct kvm_reg_list ®s) const 448{ 449 if (ioctl(KVM_GET_REG_LIST, (void *)®s) == -1) { 450 if (errno == E2BIG) { 451 return false; 452 } else { 453 panic("KVM: Failed to get vCPU register list (errno: %i)\n", 454 errno); 455 } 456 } else { 457 return true; 458 } 459} 460 461void 462ArmKvmCPU::dumpKvmStateCore() 463{ 464 /* Print core registers */ 465 uint32_t pc(getOneRegU32(REG_CORE32(usr_regs.ARM_pc))); 466 inform("PC: 0x%x\n", pc); 467 468 for (const KvmIntRegInfo *ri(kvmIntRegs); 469 ri->idx != NUM_INTREGS; ++ri) { 470 471 uint32_t value(getOneRegU32(ri->id)); 472 inform("%s: 0x%x\n", ri->name, value); 473 } 474 475 for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); 476 ri->idx != NUM_MISCREGS; ++ri) { 477 478 uint32_t value(getOneRegU32(ri->id)); 479 inform("%s: 0x%x\n", miscRegName[ri->idx], value); 480 } 481} 482 483void 484ArmKvmCPU::dumpKvmStateMisc() 485{ 486 /* Print co-processor registers */ 487 const RegIndexVector ®_ids(getRegList());; 488 for (RegIndexVector::const_iterator it(reg_ids.begin()); 489 it != reg_ids.end(); ++it) { 490 uint64_t id(*it); 491 492 if (REG_IS_ARM(id) && REG_CP(id) <= 15) { 493 dumpKvmStateCoProc(id); 494 } else if (REG_IS_ARM(id) && REG_IS_VFP(id)) { 495 dumpKvmStateVFP(id); 496 } else if (REG_IS_ARM(id) && REG_IS_DEMUX(id)) { 497 switch (id & KVM_REG_ARM_DEMUX_ID_MASK) { 498 case KVM_REG_ARM_DEMUX_ID_CCSIDR: 499 inform("CCSIDR [0x%x]: %s\n", 500 EXTRACT_FIELD(id, 501 KVM_REG_ARM_DEMUX_VAL_MASK, 502 KVM_REG_ARM_DEMUX_VAL_SHIFT), 503 getAndFormatOneReg(id)); 504 break; 505 default: 506 inform("DEMUX [0x%x, 0x%x]: %s\n", 507 EXTRACT_FIELD(id, 508 KVM_REG_ARM_DEMUX_ID_MASK, 509 KVM_REG_ARM_DEMUX_ID_SHIFT), 510 EXTRACT_FIELD(id, 511 KVM_REG_ARM_DEMUX_VAL_MASK, 512 KVM_REG_ARM_DEMUX_VAL_SHIFT), 513 getAndFormatOneReg(id)); 514 break; 515 } 516 } else if (!REG_IS_CORE(id)) { 517 inform("0x%x: %s\n", id, getAndFormatOneReg(id)); 518 } 519 } 520} 521 522void 523ArmKvmCPU::dumpKvmStateCoProc(uint64_t id) 524{ 525 assert(REG_IS_ARM(id)); 526 assert(REG_CP(id) <= 15); 527 528 if (REG_IS_32BIT(id)) { 529 // 32-bit co-proc registers 530 MiscRegIndex idx(decodeCoProcReg(id)); 531 uint32_t value(getOneRegU32(id)); 532 533 if (idx != NUM_MISCREGS && 534 !(idx >= MISCREG_CP15_UNIMP_START && idx < MISCREG_CP15_END)) { 535 const char *name(miscRegName[idx]); 536 const unsigned m5_ne(tc->readMiscRegNoEffect(idx)); 537 const unsigned m5_e(tc->readMiscReg(idx)); 538 inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: " 539 "[%s]: 0x%x/0x%x\n", 540 REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), 541 REG_OPC2(id), isInvariantReg(id), 542 name, value, m5_e); 543 if (m5_e != m5_ne) { 544 inform("readMiscReg: %x, readMiscRegNoEffect: %x\n", 545 m5_e, m5_ne); 546 } 547 } else { 548 const char *name(idx != NUM_MISCREGS ? miscRegName[idx] : "-"); 549 inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: [%s]: " 550 "0x%x\n", 551 REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), 552 REG_OPC2(id), isInvariantReg(id), name, value); 553 } 554 } else { 555 inform("CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i " 556 "len: 0x%x]: %s\n", 557 REG_CP(id), REG_CRN(id), REG_OPC1(id), REG_CRM(id), 558 REG_OPC2(id), isInvariantReg(id), 559 EXTRACT_FIELD(id, KVM_REG_SIZE_MASK, KVM_REG_SIZE_SHIFT), 560 getAndFormatOneReg(id)); 561 } 562} 563 564void 565ArmKvmCPU::dumpKvmStateVFP(uint64_t id) 566{ 567 assert(REG_IS_ARM(id)); 568 assert(REG_IS_VFP(id)); 569 570 if (REG_IS_VFP_REG(id)) { 571 const unsigned idx(id & KVM_REG_ARM_VFP_MASK); 572 inform("VFP reg %i: %s", idx, getAndFormatOneReg(id)); 573 } else if (REG_IS_VFP_CTRL(id)) { 574 MiscRegIndex idx(decodeVFPCtrlReg(id)); 575 if (idx != NUM_MISCREGS) { 576 inform("VFP [%s]: %s", miscRegName[idx], getAndFormatOneReg(id)); 577 } else { 578 inform("VFP [0x%x]: %s", id, getAndFormatOneReg(id)); 579 } 580 } else { 581 inform("VFP [0x%x]: %s", id, getAndFormatOneReg(id)); 582 } 583} 584 585void 586ArmKvmCPU::updateKvmStateCore() 587{ 588 for (const KvmIntRegInfo *ri(kvmIntRegs); 589 ri->idx != NUM_INTREGS; ++ri) { 590 591 uint64_t value(tc->readIntRegFlat(ri->idx)); 592 DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value); 593 setOneReg(ri->id, value); 594 } 595 596 DPRINTF(KvmContext, "kvm(PC) := 0x%x\n", tc->instAddr()); 597 setOneReg(REG_CORE32(usr_regs.ARM_pc), tc->instAddr()); 598 599 for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); 600 ri->idx != NUM_MISCREGS; ++ri) { 601 602 uint64_t value(tc->readMiscReg(ri->idx)); 603 DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value); 604 setOneReg(ri->id, value); 605 } 606 607 if (DTRACE(KvmContext)) 608 dumpKvmStateCore(); 609} 610 611void 612ArmKvmCPU::updateKvmStateMisc() 613{ 614 static bool warned(false); // We can't use warn_once since we want 615 // to show /all/ registers 616 617 const RegIndexVector ®s(getRegList()); 618 619 for (RegIndexVector::const_iterator it(regs.begin()); 620 it != regs.end(); 621 ++it) { 622 623 if (!REG_IS_ARM(*it)) { 624 if (!warned) 625 warn("Skipping non-ARM register: 0x%x\n", *it); 626 } else if (isInvariantReg(*it)) { 627 DPRINTF(Kvm, "Skipping invariant register: 0x%x\n", *it); 628 } else if (REG_IS_CORE(*it)) { 629 // Core registers are handled in updateKvmStateCore 630 continue; 631 } else if (REG_CP(*it) <= 15) { 632 updateKvmStateCoProc(*it, !warned); 633 } else if (REG_IS_VFP(*it)) { 634 updateKvmStateVFP(*it, !warned); 635 } else { 636 if (!warned) { 637 warn("Skipping register with unknown CP (%i) id: 0x%x\n", 638 REG_CP(*it), *it); 639 } 640 } 641 642 } 643 644 warned = true; 645 if (DTRACE(KvmContext)) 646 dumpKvmStateMisc(); 647} 648 649void 650ArmKvmCPU::updateKvmStateCoProc(uint64_t id, bool show_warnings) 651{ 652 MiscRegIndex reg(decodeCoProcReg(id)); 653 654 assert(REG_IS_ARM(id)); 655 assert(REG_CP(id) <= 15); 656 657 if (id == KVM_REG64_TTBR0 || id == KVM_REG64_TTBR1) { 658 // HACK HACK HACK: Workaround for 64-bit TTBRx 659 reg = (id == KVM_REG64_TTBR0 ? MISCREG_TTBR0 : MISCREG_TTBR1); 660 if (show_warnings) 661 hack("KVM: 64-bit TTBBRx workaround\n"); 662 } 663 664 if (reg == NUM_MISCREGS) { 665 if (show_warnings) { 666 warn("KVM: Ignoring unknown KVM co-processor register (0x%.8x):\n", 667 id); 668 warn("\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i" 669 " opc2: %i]\n", 670 id, REG_CP(id), REG_IS_64BIT(id), REG_CRN(id), 671 REG_OPC1(id), REG_CRM(id), REG_OPC2(id)); 672 } 673 } else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) { 674 if (show_warnings) 675 warn("KVM: Co-processor reg. %s not implemented by gem5.\n", 676 miscRegName[reg]); 677 } else { 678 setOneReg(id, tc->readMiscRegNoEffect(reg)); 679 } 680} 681 682 683void 684ArmKvmCPU::updateKvmStateVFP(uint64_t id, bool show_warnings) 685{ 686 assert(REG_IS_ARM(id)); 687 assert(REG_IS_VFP(id)); 688 689 if (REG_IS_VFP_REG(id)) { 690 if (!REG_IS_64BIT(id)) { 691 if (show_warnings) 692 warn("Unexpected VFP register length (reg: 0x%x).\n", id); 693 return; 694 } 695 const unsigned idx(id & KVM_REG_ARM_VFP_MASK); 696 const unsigned idx_base(idx << 1); 697 const unsigned idx_hi(idx_base + 1); 698 const unsigned idx_lo(idx_base + 0); 699 uint64_t value( 700 ((uint64_t)tc->readFloatRegFlat(idx_hi) << 32) | 701 tc->readFloatRegFlat(idx_lo)); 702 703 setOneReg(id, value); 704 } else if (REG_IS_VFP_CTRL(id)) { 705 MiscRegIndex idx(decodeVFPCtrlReg(id)); 706 if (idx == NUM_MISCREGS) { 707 if (show_warnings) 708 warn("Unhandled VFP control register: 0x%x\n", id); 709 return; 710 } 711 if (!REG_IS_32BIT(id)) { 712 if (show_warnings) 713 warn("Ignoring VFP control register (%s) with " 714 "unexpected size.\n", 715 miscRegName[idx]); 716 return; 717 } 718 setOneReg(id, (uint32_t)tc->readMiscReg(idx)); 719 } else { 720 if (show_warnings) 721 warn("Unhandled VFP register: 0x%x\n", id); 722 } 723} 724 725void 726ArmKvmCPU::updateTCStateCore() 727{ 728 for (const KvmIntRegInfo *ri(kvmIntRegs); 729 ri->idx != NUM_INTREGS; ++ri) { 730 731 tc->setIntRegFlat(ri->idx, getOneRegU32(ri->id)); 732 } 733 734 for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs); 735 ri->idx != NUM_MISCREGS; ++ri) { 736 737 tc->setMiscRegNoEffect(ri->idx, getOneRegU32(ri->id)); 738 } 739 740 /* We want the simulator to execute all side-effects of the CPSR 741 * update since this updates PC state and register maps. 742 */ 743 tc->setMiscReg(MISCREG_CPSR, tc->readMiscRegNoEffect(MISCREG_CPSR)); 744 745 // We update the PC state after we have updated the CPSR the 746 // contents of the CPSR affects how the npc is updated. 747 PCState pc(tc->pcState()); 748 pc.set(getOneRegU32(REG_CORE32(usr_regs.ARM_pc))); 749 tc->pcState(pc); 750 751 if (DTRACE(KvmContext)) 752 dumpKvmStateCore(); 753} 754 755void 756ArmKvmCPU::updateTCStateMisc() 757{ 758 static bool warned(false); // We can't use warn_once since we want 759 // to show /all/ registers 760 761 const RegIndexVector ®_ids(getRegList());; 762 for (RegIndexVector::const_iterator it(reg_ids.begin()); 763 it != reg_ids.end(); ++it) { 764 765 if (!REG_IS_ARM(*it)) { 766 if (!warned) 767 warn("Skipping non-ARM register: 0x%x\n", *it); 768 } else if (REG_IS_CORE(*it)) { 769 // Core registers are handled in updateKvmStateCore 770 } else if (REG_CP(*it) <= 15) { 771 updateTCStateCoProc(*it, !warned); 772 } else if (REG_IS_VFP(*it)) { 773 updateTCStateVFP(*it, !warned); 774 } else { 775 if (!warned) { 776 warn("Skipping register with unknown CP (%i) id: 0x%x\n", 777 REG_CP(*it), *it); 778 } 779 } 780 } 781 782 warned = true; 783 784 if (DTRACE(KvmContext)) 785 dumpKvmStateMisc(); 786} 787 788void 789ArmKvmCPU::updateTCStateCoProc(uint64_t id, bool show_warnings) 790{ 791 MiscRegIndex reg(decodeCoProcReg(id)); 792 793 assert(REG_IS_ARM(id)); 794 assert(REG_CP(id) <= 15); 795 796 if (id == KVM_REG64_TTBR0 || id == KVM_REG64_TTBR1) { 797 // HACK HACK HACK: We don't currently support 64-bit TTBR0/TTBR1 798 hack_once("KVM: 64-bit TTBRx workaround\n"); 799 tc->setMiscRegNoEffect( 800 id == KVM_REG64_TTBR0 ? MISCREG_TTBR0 : MISCREG_TTBR1, 801 (uint32_t)(getOneRegU64(id) & 0xFFFFFFFF)); 802 } else if (reg == MISCREG_TTBCR) { 803 uint32_t value(getOneRegU64(id)); 804 if (value & 0x80000000) 805 panic("KVM: Guest tried to enable LPAE.\n"); 806 tc->setMiscRegNoEffect(reg, value); 807 } else if (reg == NUM_MISCREGS) { 808 if (show_warnings) { 809 warn("KVM: Ignoring unknown KVM co-processor register:\n", id); 810 warn("\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i" 811 " opc2: %i]\n", 812 id, REG_CP(id), REG_IS_64BIT(id), REG_CRN(id), 813 REG_OPC1(id), REG_CRM(id), REG_OPC2(id)); 814 } 815 } else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) { 816 if (show_warnings) 817 warn_once("KVM: Co-processor reg. %s not implemented by gem5.\n", 818 miscRegName[reg]); 819 } else { 820 tc->setMiscRegNoEffect(reg, getOneRegU32(id)); 821 } 822} 823 824void 825ArmKvmCPU::updateTCStateVFP(uint64_t id, bool show_warnings) 826{ 827 assert(REG_IS_ARM(id)); 828 assert(REG_IS_VFP(id)); 829 830 if (REG_IS_VFP_REG(id)) { 831 if (!REG_IS_64BIT(id)) { 832 if (show_warnings) 833 warn("Unexpected VFP register length (reg: 0x%x).\n", id); 834 return; 835 } 836 const unsigned idx(id & KVM_REG_ARM_VFP_MASK); 837 const unsigned idx_base(idx << 1); 838 const unsigned idx_hi(idx_base + 1); 839 const unsigned idx_lo(idx_base + 0); 840 uint64_t value(getOneRegU64(id)); 841 842 tc->setFloatRegFlat(idx_hi, (value >> 32) & 0xFFFFFFFF); 843 tc->setFloatRegFlat(idx_lo, value & 0xFFFFFFFF); 844 } else if (REG_IS_VFP_CTRL(id)) { 845 MiscRegIndex idx(decodeVFPCtrlReg(id)); 846 if (idx == NUM_MISCREGS) { 847 if (show_warnings) 848 warn("Unhandled VFP control register: 0x%x\n", id); 849 return; 850 } 851 if (!REG_IS_32BIT(id)) { 852 if (show_warnings) 853 warn("Ignoring VFP control register (%s) with " 854 "unexpected size.\n", 855 miscRegName[idx]); 856 return; 857 } 858 tc->setMiscReg(idx, getOneRegU64(id)); 859 } else { 860 if (show_warnings) 861 warn("Unhandled VFP register: 0x%x\n", id); 862 } 863} 864 865ArmKvmCPU * 866ArmKvmCPUParams::create() 867{ 868 return new ArmKvmCPU(this); 869} 870