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