gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
arm_cpu.cc
Go to the documentation of this file.
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 
55 using 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.
139 static 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 
173 const static uint64_t KVM_REG64_TTBR0(REG_CP64(15, 0, 2));
174 const 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 
190 const std::set<uint64_t> ArmKvmCPU::invariant_regs(
193 
194 
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 
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 
245 ArmKvmCPU::ArmKvmCPU(ArmKvmCPUParams *params)
246  : BaseKvmCPU(params),
247  irqAsserted(false), fiqAsserted(false)
248 {
249 }
250 
252 {
253 }
254 
255 void
257 {
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 
270 Tick
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);
280  }
281  if (irqAsserted != simIRQ) {
282  irqAsserted = simIRQ;
283  DPRINTF(KvmInt, "KVM: Update IRQ state: %i\n", simIRQ);
285  }
286 
287  return BaseKvmCPU::kvmRun(ticks);
288 }
289 
290 void
292 {
295 }
296 
297 void
299 {
300  DPRINTF(KvmContext, "Updating KVM state...\n");
301 
304 }
305 
306 void
308 {
309  DPRINTF(KvmContext, "Updating gem5 state...\n");
310 
313 }
314 
315 Tick
317 {
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 
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 
356 void
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 
368 void
369 ArmKvmCPU::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 
376 ArmKvmCPU::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 
411 ArmKvmCPU::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 
434 bool
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 
446 bool
447 ArmKvmCPU::getRegList(struct kvm_reg_list &regs) const
448 {
449  if (ioctl(KVM_GET_REG_LIST, (void *)&regs) == -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 
461 void
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 
483 void
485 {
486  /* Print co-processor registers */
487  const RegIndexVector &reg_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 
522 void
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 
564 void
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)) {
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 
585 void
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))
609 }
610 
611 void
613 {
614  static bool warned(false); // We can't use warn_once since we want
615  // to show /all/ registers
616 
617  const RegIndexVector &regs(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))
647 }
648 
649 void
650 ArmKvmCPU::updateKvmStateCoProc(uint64_t id, bool show_warnings)
651 {
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 
683 void
684 ArmKvmCPU::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->readFloatRegBitsFlat(idx_hi) << 32) |
701  tc->readFloatRegBitsFlat(idx_lo));
702 
703  setOneReg(id, value);
704  } else if (REG_IS_VFP_CTRL(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 
725 void
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  */
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))
753 }
754 
755 void
757 {
758  static bool warned(false); // We can't use warn_once since we want
759  // to show /all/ registers
760 
761  const RegIndexVector &reg_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))
786 }
787 
788 void
789 ArmKvmCPU::updateTCStateCoProc(uint64_t id, bool show_warnings)
790 {
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");
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 {
821  }
822 }
823 
824 void
825 ArmKvmCPU::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->setFloatRegBitsFlat(idx_hi, (value >> 32) & 0xFFFFFFFF);
843  tc->setFloatRegBitsFlat(idx_lo, value & 0xFFFFFFFF);
844  } else if (REG_IS_VFP_CTRL(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 
865 ArmKvmCPU *
866 ArmKvmCPUParams::create()
867 {
868  return new ArmKvmCPU(this);
869 }
#define REG_IS_CORE(id)
Definition: arm_cpu.cc:72
void kvmArmVCpuInit(uint32_t target)
Definition: arm_cpu.cc:357
#define DPRINTF(x,...)
Definition: trace.hh:212
ArmISA::MiscRegIndex decodeVFPCtrlReg(uint64_t id) const
Definition: arm_cpu.cc:411
void updateTCStateCore()
Definition: arm_cpu.cc:726
Tick onKvmExitHypercall()
Definition: arm_cpu.cc:316
MiscRegIndex
Definition: miscregs.hh:57
#define hack_once(...)
Definition: misc.hh:230
Bitfield< 5, 3 > reg
Definition: types.hh:89
virtual Addr instAddr()=0
const std::string & name()
Definition: trace.cc:49
#define REG_CP64(cpnum, opc1, crm)
Definition: arm_cpu.cc:113
Bitfield< 7 > i
Definition: miscregs.hh:1378
#define hack(...)
Definition: misc.hh:223
void updateKvmStateVFP(uint64_t id, bool show_warnings)
Definition: arm_cpu.cc:684
#define panic(...)
Definition: misc.hh:153
void dumpKvmStateVFP(uint64_t id)
Definition: arm_cpu.cc:565
virtual void setFloatRegBitsFlat(int idx, FloatRegBits val)=0
void updateKvmStateCore()
Definition: arm_cpu.cc:586
virtual Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
Definition: base.cc:723
virtual uint64_t readIntRegFlat(int idx)=0
Flat register interfaces.
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
ThreadContext * tc
ThreadContext object, provides an interface for external objects to modify this thread's state...
Definition: base.hh:150
void updateKvmState()
Update the KVM state from the current thread context.
Definition: arm_cpu.cc:298
#define REG_CP32(cpnum, crn, opc1, crm, opc2)
Definition: arm_cpu.cc:105
virtual FloatRegBits readFloatRegBitsFlat(int idx)=0
bool irqAsserted
Cached state of the IRQ line.
Definition: arm_cpu.hh:152
virtual void setMiscReg(int misc_reg, const MiscReg &val)=0
virtual void setIntRegFlat(int idx, uint64_t val)=0
#define warn_once(...)
Definition: misc.hh:226
#define EXTRACT_FIELD(val, mask, shift)
Definition: arm_cpu.cc:57
#define COUNT_OF(l)
Definition: arm_cpu.cc:188
const char *const miscRegName[]
Definition: miscregs.hh:739
#define REG_CP(id)
Definition: arm_cpu.cc:90
virtual TheISA::PCState pcState()=0
Base class for KVM based CPU models.
Definition: base.hh:78
void dumpKvmStateCoProc(uint64_t id)
Definition: arm_cpu.cc:523
static KvmCoreMiscRegInfo kvmCoreMiscRegs[]
Definition: arm_cpu.hh:123
#define REG_IS_64BIT(id)
Definition: arm_cpu.cc:66
static KvmIntRegInfo kvmIntRegs[]
Definition: arm_cpu.hh:122
const RegIndexVector & getRegList() const
Get a list of registers supported by getOneReg() and setOneReg().
Definition: arm_cpu.cc:336
const MiscRegIndex idx
gem5 index
Definition: arm_cpu.hh:85
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define REG_IS_VFP_REG(id)
Definition: arm_cpu.cc:78
void setIRQLine(uint32_t irq, bool high)
Set the status of an IRQ line using KVM_IRQ_LINE.
Definition: vm.cc:502
const long vcpuID
KVM internal ID of the vCPU.
Definition: base.hh:627
static const uint64_t KVM_REG64_TTBR0(REG_CP64(15, 0, 2))
#define REG_VFP32(regno)
Definition: arm_cpu.cc:124
#define warn(...)
Definition: misc.hh:219
static const uint64_t KVM_REG64_TTBR1(REG_CP64(15, 1, 2))
#define DTRACE(x)
Definition: trace.hh:210
#define REG_IS_VFP(id)
Definition: arm_cpu.cc:74
const IntRegIndex idx
gem5 index
Definition: arm_cpu.hh:76
KvmVM & vm
Definition: base.hh:152
ThreadContext * getContext(int tn) override
Definition: base.cc:583
void setOneReg(uint64_t id, const void *addr)
Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
Definition: base.cc:880
uint64_t Tick
Tick count type.
Definition: types.hh:63
uint64_t getOneRegU64(uint64_t id) const
Definition: base.hh:372
void dump()
Definition: arm_cpu.cc:291
Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
Definition: arm_cpu.cc:271
#define INTERRUPT_VCPU_FIQ(vcpu)
Definition: arm_cpu.cc:184
void updateThreadContext()
Update the current thread context with the KVM state.
Definition: arm_cpu.cc:307
static const std::set< uint64_t > invariant_regs
List of co-processor registers that KVM requires to be identical on both the host and the guest...
Definition: arm_cpu.hh:167
uint32_t getOneRegU32(uint64_t id) const
Definition: base.hh:377
void updateTCStateVFP(uint64_t id, bool show_warnings)
Definition: arm_cpu.cc:825
void dumpKvmStateCore()
Definition: arm_cpu.cc:462
#define REG_IS_ARM(id)
Definition: arm_cpu.cc:60
uint64_t pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc)
Execute a decoded M5 pseudo instruction.
Definition: pseudo_inst.cc:95
virtual ~ArmKvmCPU()
Definition: arm_cpu.cc:251
void updateKvmStateCoProc(uint64_t id, bool show_warnings)
Definition: arm_cpu.cc:650
static uint64_t invariant_reg_vector[]
Definition: arm_cpu.cc:139
#define INTERRUPT_VCPU_IRQ(vcpu)
Definition: arm_cpu.cc:181
#define REG_CRM(id)
Definition: arm_cpu.cc:99
virtual MiscReg readMiscReg(int misc_reg)=0
#define REG_CORE32(kname)
Definition: arm_cpu.cc:119
void startup()
Definition: arm_cpu.cc:256
GenericISA::SimplePCState< MachInst > PCState
Definition: types.hh:43
std::string getAndFormatOneReg(uint64_t id) const
Get and format one register for printout.
Definition: base.cc:914
#define REG_VFP_REG(id)
Definition: arm_cpu.cc:75
#define REG_CRN(id)
Definition: arm_cpu.cc:93
ArmKvmCPU(ArmKvmCPUParams *params)
Definition: arm_cpu.cc:245
bool fiqAsserted
Cached state of the FIQ line.
Definition: arm_cpu.hh:154
Bitfield< 7, 5 > opc2
Definition: types.hh:111
IntReg pc
Definition: remote_gdb.hh:91
void updateKvmStateMisc()
Definition: arm_cpu.cc:612
void startup() override
Definition: base.cc:123
#define REG_IS_VFP_CTRL(id)
Definition: arm_cpu.cc:79
#define REG_DEMUX32(dmxid, val)
Definition: arm_cpu.cc:132
KVM parent interface.
Definition: vm.hh:74
Bitfield< 11 > id
Definition: miscregs.hh:124
RegIndexVector _regIndexList
Cached copy of the list of co-processor registers supported by KVM.
Definition: arm_cpu.hh:160
ARM implementation of a KVM-based hardware virtualized CPU.
Definition: arm_cpu.hh:61
virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val)=0
MiscRegIndex decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
Definition: miscregs.cc:1359
#define inform(...)
Definition: misc.hh:221
MiscRegIndex decodeCP14Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
Definition: miscregs.cc:55
void updateTCStateMisc()
Definition: arm_cpu.cc:756
const FlagsType init
This Stat is Initialized.
Definition: info.hh:45
void dumpKvmStateMisc()
Definition: arm_cpu.cc:484
#define REG_IS_32BIT(id)
Definition: arm_cpu.cc:63
void updateTCStateCoProc(uint64_t id, bool show_warnings)
Definition: arm_cpu.cc:789
#define REG_OPC1(id)
Definition: arm_cpu.cc:96
bool isInvariantReg(uint64_t id)
Determine if a register is invariant.
Definition: arm_cpu.cc:435
#define REG_OPC2(id)
Definition: arm_cpu.cc:102
ArmISA::MiscRegIndex decodeCoProcReg(uint64_t id) const
Definition: arm_cpu.cc:376
#define REG_IS_DEMUX(id)
Definition: arm_cpu.cc:81
int ioctl(int request, long p1) const
vCPU ioctl interface.
Definition: base.cc:1174

Generated on Fri Jun 9 2017 13:03:39 for gem5 by doxygen 1.8.6