arm_cpu.cc revision 9657
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::updateKvmState()
290{
291    DPRINTF(KvmContext, "Updating KVM state...\n");
292
293    updateKvmStateCore();
294    updateKvmStateMisc();
295}
296
297void
298ArmKvmCPU::updateThreadContext()
299{
300    DPRINTF(KvmContext, "Updating gem5 state...\n");
301
302    updateTCStateCore();
303    updateTCStateMisc();
304}
305
306const ArmKvmCPU::RegIndexVector &
307ArmKvmCPU::getRegList() const
308{
309    if (_regIndexList.size() == 0) {
310        std::unique_ptr<struct kvm_reg_list> regs;
311        uint64_t i(1);
312
313        do {
314            i <<= 1;
315            regs.reset((struct kvm_reg_list *)
316                       operator new(sizeof(struct kvm_reg_list) +
317                                    i * sizeof(uint64_t)));
318            regs->n = i;
319        } while (!getRegList(*regs));
320        _regIndexList.assign(regs->reg,
321                             regs->reg + regs->n);
322    }
323
324    return _regIndexList;
325}
326
327void
328ArmKvmCPU::kvmArmVCpuInit(uint32_t target)
329{
330    struct kvm_vcpu_init init;
331
332    memset(&init, 0, sizeof(init));
333
334    init.target = target;
335
336    kvmArmVCpuInit(init);
337}
338
339void
340ArmKvmCPU::kvmArmVCpuInit(const struct kvm_vcpu_init &init)
341{
342    if (ioctl(KVM_ARM_VCPU_INIT, (void *)&init) == -1)
343        panic("KVM: Failed to initialize vCPU\n");
344}
345
346MiscRegIndex
347ArmKvmCPU::decodeCoProcReg(uint64_t id) const
348{
349    const unsigned cp(REG_CP(id));
350    const bool is_reg32(REG_IS_32BIT(id));
351    const bool is_reg64(REG_IS_64BIT(id));
352
353    // CP numbers larger than 15 are reserved for KVM extensions
354    if (cp > 15)
355        return NUM_MISCREGS;
356
357    const unsigned crm(REG_CRM(id));
358    const unsigned crn(REG_CRN(id));
359    const unsigned opc1(REG_OPC1(id));
360    const unsigned opc2(REG_OPC2(id));
361
362    if (is_reg32) {
363        switch (cp) {
364          case 14:
365            return decodeCP14Reg(crn, opc1, crm, opc2);
366
367          case 15:
368            return decodeCP15Reg(crn, opc1, crm, opc2);
369
370          default:
371            return NUM_MISCREGS;
372        }
373    } else if(is_reg64) {
374        return NUM_MISCREGS;
375    } else {
376        warn("Unhandled register length, register (0x%x) ignored.\n");
377        return NUM_MISCREGS;
378    }
379}
380
381ArmISA::MiscRegIndex
382ArmKvmCPU::decodeVFPCtrlReg(uint64_t id) const
383{
384    if (!REG_IS_ARM(id) || !REG_IS_VFP(id) || !REG_IS_VFP_CTRL(id))
385        return NUM_MISCREGS;
386
387    const unsigned vfp_reg(REG_VFP_REG(id));
388    switch (vfp_reg) {
389      case KVM_REG_ARM_VFP_FPSID: return MISCREG_FPSID;
390      case KVM_REG_ARM_VFP_FPSCR: return MISCREG_FPSCR;
391      case KVM_REG_ARM_VFP_MVFR0: return MISCREG_MVFR0;
392      case KVM_REG_ARM_VFP_MVFR1: return MISCREG_MVFR1;
393      case KVM_REG_ARM_VFP_FPEXC: return MISCREG_FPEXC;
394
395      case KVM_REG_ARM_VFP_FPINST:
396      case KVM_REG_ARM_VFP_FPINST2:
397        warn_once("KVM: FPINST not implemented.\n");
398        return NUM_MISCREGS;
399
400      default:
401        return NUM_MISCREGS;
402    }
403}
404
405bool
406ArmKvmCPU::isInvariantReg(uint64_t id)
407{
408    /* Mask away the value field from multiplexed registers, we assume
409     * that entire groups of multiplexed registers can be treated as
410     * invariant. */
411    if (REG_IS_ARM(id) && REG_IS_DEMUX(id))
412        id &= ~KVM_REG_ARM_DEMUX_VAL_MASK;
413
414    return invariant_regs.find(id) != invariant_regs.end();
415}
416
417bool
418ArmKvmCPU::getRegList(struct kvm_reg_list &regs) const
419{
420    if (ioctl(KVM_GET_REG_LIST, (void *)&regs) == -1) {
421        if (errno == E2BIG) {
422            return false;
423        } else {
424            panic("KVM: Failed to get vCPU register list (errno: %i)\n",
425                  errno);
426        }
427    } else {
428        return true;
429    }
430}
431
432void
433ArmKvmCPU::updateKvmStateCore()
434{
435    for (const KvmIntRegInfo *ri(kvmIntRegs);
436         ri->idx != NUM_INTREGS; ++ri) {
437
438        uint64_t value(tc->readIntRegFlat(ri->idx));
439        DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value);
440        setOneReg(ri->id, value);
441    }
442
443    DPRINTF(KvmContext, "kvm(PC) := 0x%x\n", tc->instAddr());
444    setOneReg(REG_CORE32(usr_regs.ARM_pc), tc->instAddr());
445
446    for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs);
447         ri->idx != NUM_MISCREGS; ++ri) {
448
449        uint64_t value(tc->readMiscReg(ri->idx));
450        DPRINTF(KvmContext, "kvm(%s) := 0x%x\n", ri->name, value);
451        setOneReg(ri->id, value);
452    }
453}
454
455void
456ArmKvmCPU::updateKvmStateMisc()
457{
458    static bool warned(false); // We can't use warn_once since we want
459                               // to show /all/ registers
460
461    const RegIndexVector &regs(getRegList());
462
463    for (RegIndexVector::const_iterator it(regs.begin());
464         it != regs.end();
465         ++it) {
466
467        if (!REG_IS_ARM(*it)) {
468            if (!warned)
469                warn("Skipping non-ARM register: 0x%x\n", *it);
470        } else if (isInvariantReg(*it)) {
471            DPRINTF(Kvm, "Skipping invariant register: 0x%x\n", *it);
472        } else if (REG_IS_CORE(*it)) {
473            // Core registers are handled in updateKvmStateCore
474            continue;
475        } else if (REG_CP(*it) <= 15) {
476            updateKvmStateCoProc(*it, !warned);
477        } else if (REG_IS_VFP(*it)) {
478            updateKvmStateVFP(*it, !warned);
479        } else {
480            if (!warned) {
481                warn("Skipping register with unknown CP (%i) id: 0x%x\n",
482                     REG_CP(*it), *it);
483            }
484        }
485
486    }
487
488    warned = true;
489}
490
491void
492ArmKvmCPU::updateKvmStateCoProc(uint64_t id, bool show_warnings)
493{
494    MiscRegIndex reg(decodeCoProcReg(id));
495
496    assert(REG_IS_ARM(id));
497    assert(REG_CP(id) <= 15);
498
499    if (id == KVM_REG64_TTBR0 || id == KVM_REG64_TTBR1) {
500        // HACK HACK HACK: Workaround for 64-bit TTBRx
501        reg = (id == KVM_REG64_TTBR0 ? MISCREG_TTBR0 : MISCREG_TTBR1);
502        if (show_warnings)
503            hack("KVM: 64-bit TTBBRx workaround\n");
504    }
505
506    if (reg == NUM_MISCREGS) {
507        if (show_warnings) {
508            warn("KVM: Ignoring unknown KVM co-processor register (0x%.8x):\n",
509                 id);
510            warn("\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i"
511                 " opc2: %i]\n",
512                 id, REG_CP(id), REG_IS_64BIT(id), REG_CRN(id),
513                 REG_OPC1(id), REG_CRM(id), REG_OPC2(id));
514        }
515    } else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) {
516        if (show_warnings)
517            warn("KVM: Co-processor reg. %s not implemented by gem5.\n",
518                 miscRegName[reg]);
519    } else {
520        setOneReg(id, tc->readMiscRegNoEffect(reg));
521    }
522}
523
524
525void
526ArmKvmCPU::updateKvmStateVFP(uint64_t id, bool show_warnings)
527{
528    assert(REG_IS_ARM(id));
529    assert(REG_IS_VFP(id));
530
531    if (REG_IS_VFP_REG(id)) {
532        if (!REG_IS_64BIT(id)) {
533            if (show_warnings)
534                warn("Unexpected VFP register length (reg: 0x%x).\n", id);
535            return;
536        }
537        const unsigned idx(id & KVM_REG_ARM_VFP_MASK);
538        const unsigned idx_base(idx << 1);
539        const unsigned idx_hi(idx_base + 1);
540        const unsigned idx_lo(idx_base + 0);
541        uint64_t value(
542            ((uint64_t)tc->readFloatRegBitsFlat(idx_hi) << 32) |
543            tc->readFloatRegBitsFlat(idx_lo));
544
545        setOneReg(id, value);
546    } else if (REG_IS_VFP_CTRL(id)) {
547        MiscRegIndex idx(decodeVFPCtrlReg(id));
548        if (idx == NUM_MISCREGS) {
549            if (show_warnings)
550                warn("Unhandled VFP control register: 0x%x\n", id);
551            return;
552        }
553        if (!REG_IS_32BIT(id)) {
554            if (show_warnings)
555                warn("Ignoring VFP control register (%s) with "
556                     "unexpected size.\n",
557                     miscRegName[idx]);
558            return;
559        }
560        setOneReg(id, (uint32_t)tc->readMiscReg(idx));
561    } else {
562        if (show_warnings)
563            warn("Unhandled VFP register: 0x%x\n", id);
564    }
565}
566
567void
568ArmKvmCPU::updateTCStateCore()
569{
570    for (const KvmIntRegInfo *ri(kvmIntRegs);
571         ri->idx != NUM_INTREGS; ++ri) {
572
573        tc->setIntRegFlat(ri->idx, getOneRegU32(ri->id));
574    }
575
576    for (const KvmCoreMiscRegInfo *ri(kvmCoreMiscRegs);
577         ri->idx != NUM_MISCREGS; ++ri) {
578
579        tc->setMiscRegNoEffect(ri->idx, getOneRegU32(ri->id));
580    }
581
582    /* We want the simulator to execute all side-effects of the CPSR
583     * update since this updates PC state and register maps.
584     */
585    tc->setMiscReg(MISCREG_CPSR, tc->readMiscRegNoEffect(MISCREG_CPSR));
586
587    // We update the PC state after we have updated the CPSR the
588    // contents of the CPSR affects how the npc is updated.
589    PCState pc(tc->pcState());
590    pc.set(getOneRegU32(REG_CORE32(usr_regs.ARM_pc)));
591    tc->pcState(pc);
592}
593
594void
595ArmKvmCPU::updateTCStateMisc()
596{
597    static bool warned(false); // We can't use warn_once since we want
598                               // to show /all/ registers
599
600    const RegIndexVector &reg_ids(getRegList());;
601    for (RegIndexVector::const_iterator it(reg_ids.begin());
602         it != reg_ids.end(); ++it) {
603
604        if (!REG_IS_ARM(*it)) {
605            if (!warned)
606                warn("Skipping non-ARM register: 0x%x\n", *it);
607        } else if (REG_IS_CORE(*it)) {
608            // Core registers are handled in updateKvmStateCore
609        } else if (REG_CP(*it) <= 15) {
610            updateTCStateCoProc(*it, !warned);
611        } else if (REG_IS_VFP(*it)) {
612            updateTCStateVFP(*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    warned = true;
622}
623
624void
625ArmKvmCPU::updateTCStateCoProc(uint64_t id, bool show_warnings)
626{
627    MiscRegIndex reg(decodeCoProcReg(id));
628
629    assert(REG_IS_ARM(id));
630    assert(REG_CP(id) <= 15);
631
632    if (id == KVM_REG64_TTBR0 || id == KVM_REG64_TTBR1) {
633        // HACK HACK HACK: We don't currently support 64-bit TTBR0/TTBR1
634        hack_once("KVM: 64-bit TTBRx workaround\n");
635        tc->setMiscRegNoEffect(
636            id == KVM_REG64_TTBR0 ? MISCREG_TTBR0 : MISCREG_TTBR1,
637            (uint32_t)(getOneRegU64(id) & 0xFFFFFFFF));
638    } else if (reg == MISCREG_TTBCR) {
639        uint32_t value(getOneRegU64(id));
640        if (value & 0x80000000)
641            panic("KVM: Guest tried to enable LPAE.\n");
642        tc->setMiscRegNoEffect(reg, value);
643    } else if (reg == NUM_MISCREGS) {
644        if (show_warnings) {
645            warn("KVM: Ignoring unknown KVM co-processor register:\n", 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_once("KVM: Co-processor reg. %s not implemented by gem5.\n",
654                      miscRegName[reg]);
655    } else {
656        tc->setMiscRegNoEffect(reg, getOneRegU32(id));
657    }
658}
659
660void
661ArmKvmCPU::updateTCStateVFP(uint64_t id, bool show_warnings)
662{
663    assert(REG_IS_ARM(id));
664    assert(REG_IS_VFP(id));
665
666    if (REG_IS_VFP_REG(id)) {
667        if (!REG_IS_64BIT(id)) {
668            if (show_warnings)
669                warn("Unexpected VFP register length (reg: 0x%x).\n", id);
670            return;
671        }
672        const unsigned idx(id & KVM_REG_ARM_VFP_MASK);
673        const unsigned idx_base(idx << 1);
674        const unsigned idx_hi(idx_base + 1);
675        const unsigned idx_lo(idx_base + 0);
676        uint64_t value(getOneRegU64(id));
677
678        tc->setFloatRegBitsFlat(idx_hi, (value >> 32) & 0xFFFFFFFF);
679        tc->setFloatRegBitsFlat(idx_lo, value & 0xFFFFFFFF);
680    } else if (REG_IS_VFP_CTRL(id)) {
681        MiscRegIndex idx(decodeVFPCtrlReg(id));
682        if (idx == NUM_MISCREGS) {
683            if (show_warnings)
684                warn("Unhandled VFP control register: 0x%x\n", id);
685            return;
686        }
687        if (!REG_IS_32BIT(id)) {
688            if (show_warnings)
689                warn("Ignoring VFP control register (%s) with "
690                     "unexpected size.\n",
691                     miscRegName[idx]);
692            return;
693        }
694        tc->setMiscReg(idx, getOneRegU64(id));
695    } else {
696        if (show_warnings)
697            warn("Unhandled VFP register: 0x%x\n", id);
698    }
699}
700
701ArmKvmCPU *
702ArmKvmCPUParams::create()
703{
704    return new ArmKvmCPU(this);
705}
706