40 #include <linux/kvm.h>
51 #include "debug/Kvm.hh"
52 #include "debug/KvmContext.hh"
53 #include "debug/KvmInt.hh"
59 using namespace ArmISA;
73 return (
id & KVM_REG_ARCH_MASK) == KVM_REG_ARM;
77 regIs32Bit(uint64_t
id)
79 return (
id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32;
83 regIs64Bit(uint64_t
id)
85 return (
id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64;
89 regIsCp(uint64_t
id, uint64_t cp)
91 return (
id & KVM_REG_ARM_COPROC_MASK) == cp;
95 regIsCore(uint64_t
id)
97 return regIsCp(
id, KVM_REG_ARM_CORE);
101 regIsVfp(uint64_t
id)
103 return regIsCp(
id, KVM_REG_ARM_VFP);
107 regVfpReg(uint64_t
id)
109 return id & KVM_REG_ARM_VFP_MASK;
115 regIsVfpReg(uint64_t
id)
117 return regVfpReg(
id) < 0x100;
120 regIsVfpCtrl(uint64_t
id)
122 return regVfpReg(
id) >= 0x100;
126 regIsDemux(uint64_t
id)
128 return regIsCp(
id, KVM_REG_ARM_DEMUX);
136 regCoreIdx(uint64_t
id)
138 return ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
144 return extractField(
id, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_SHIFT);
150 return extractField(
id, KVM_REG_ARM_32_CRN_MASK, KVM_REG_ARM_32_CRN_SHIFT);
156 return extractField(
id, KVM_REG_ARM_OPC1_MASK, KVM_REG_ARM_OPC1_SHIFT);
162 return extractField(
id, KVM_REG_ARM_CRM_MASK, KVM_REG_ARM_CRM_SHIFT);
168 return extractField(
id, KVM_REG_ARM_32_OPC2_MASK,
169 KVM_REG_ARM_32_OPC2_SHIFT);
173 regCp32(uint64_t cpnum, uint64_t crn, uint64_t opc1, uint64_t crm,
176 return KVM_REG_ARM | KVM_REG_SIZE_U32 |
177 (cpnum << KVM_REG_ARM_COPROC_SHIFT) |
178 (crn << KVM_REG_ARM_32_CRN_SHIFT) |
179 (opc1 << KVM_REG_ARM_OPC1_SHIFT) |
180 (crm << KVM_REG_ARM_CRM_SHIFT) |
181 (
opc2 << KVM_REG_ARM_32_OPC2_SHIFT);
185 regCp64(uint64_t cpnum, uint64_t opc1, uint64_t crm)
187 return KVM_REG_ARM | KVM_REG_SIZE_U64 |
188 (cpnum << KVM_REG_ARM_COPROC_SHIFT) |
189 (opc1 << KVM_REG_ARM_OPC1_SHIFT) |
190 (crm << KVM_REG_ARM_CRM_SHIFT);
193 constexpr KvmIntRegInfo
194 regCore32(off_t
offset, ArmISA::IntRegIndex idx,
const char *
name)
196 return { KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE |
offset,
201 regVfp32(uint64_t regno)
203 return KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | regno;
207 regVfp64(uint64_t regno)
209 return KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | regno;
213 regDemux32(uint64_t dmxid, uint64_t
val)
215 return KVM_REG_ARM | KVM_REG_SIZE_U32 | dmxid |
val;
219 interruptId(uint64_t
type, uint64_t vcpu, uint64_t
irq)
221 return (
type << KVM_ARM_IRQ_TYPE_SHIFT) |
222 (vcpu << KVM_ARM_IRQ_VCPU_SHIFT) |
223 (
irq << KVM_ARM_IRQ_NUM_SHIFT);
227 interruptVcpuIrq(uint64_t vcpu)
229 return interruptId(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_IRQ);
233 interruptVcpuFiq(uint64_t vcpu)
235 return interruptId(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_FIQ);
244 regCp32(15, 0, 0, 0, 0),
245 regCp32(15, 0, 0, 0, 1),
246 regCp32(15, 0, 0, 0, 2),
247 regCp32(15, 0, 0, 0, 3),
248 regCp32(15, 0, 0, 0, 6),
250 regCp32(15, 0, 0, 1, 0),
251 regCp32(15, 0, 0, 1, 1),
252 regCp32(15, 0, 0, 1, 2),
253 regCp32(15, 0, 0, 1, 3),
254 regCp32(15, 0, 0, 1, 4),
255 regCp32(15, 0, 0, 1, 5),
256 regCp32(15, 0, 0, 1, 6),
257 regCp32(15, 0, 0, 1, 7),
259 regCp32(15, 0, 0, 2, 0),
260 regCp32(15, 0, 0, 2, 1),
261 regCp32(15, 0, 0, 2, 2),
262 regCp32(15, 0, 0, 2, 3),
263 regCp32(15, 0, 0, 2, 4),
264 regCp32(15, 0, 0, 2, 5),
265 regCp32(15, 0, 0, 2, 6),
266 regCp32(15, 0, 0, 2, 7),
268 regCp32(15, 0, 1, 0, 0),
269 regCp32(15, 0, 1, 0, 1),
270 regCp32(15, 0, 1, 0, 7),
272 regVfp32(KVM_REG_ARM_VFP_MVFR0),
273 regVfp32(KVM_REG_ARM_VFP_MVFR1),
274 regVfp32(KVM_REG_ARM_VFP_FPSID),
276 regDemux32(KVM_REG_ARM_DEMUX_ID_CCSIDR, 0),
288 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r0), INTREG_R0,
"R0"),
289 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r1), INTREG_R1,
"R1"),
290 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r2), INTREG_R2,
"R2"),
291 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r3), INTREG_R3,
"R3"),
292 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r4), INTREG_R4,
"R4"),
293 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r5), INTREG_R5,
"R5"),
294 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r6), INTREG_R6,
"R6"),
295 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r7), INTREG_R7,
"R7"),
296 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r8), INTREG_R8,
"R8"),
297 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r9), INTREG_R9,
"R9"),
298 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_r10), INTREG_R10,
"R10"),
299 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_fp), INTREG_R11,
"R11"),
300 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_ip), INTREG_R12,
"R12"),
301 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_sp), INTREG_R13,
"R13(USR)"),
302 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_lr), INTREG_R14,
"R14(USR)"),
304 regCore32(KVM_REG_ARM_CORE_REG(svc_regs[0]), INTREG_SP_SVC,
"R13(SVC)"),
305 regCore32(KVM_REG_ARM_CORE_REG(svc_regs[1]), INTREG_LR_SVC,
"R14(SVC)"),
307 regCore32(KVM_REG_ARM_CORE_REG(abt_regs[0]), INTREG_SP_ABT,
"R13(ABT)"),
308 regCore32(KVM_REG_ARM_CORE_REG(abt_regs[1]), INTREG_LR_ABT,
"R14(ABT)"),
310 regCore32(KVM_REG_ARM_CORE_REG(und_regs[0]), INTREG_SP_UND,
"R13(UND)"),
311 regCore32(KVM_REG_ARM_CORE_REG(und_regs[1]), INTREG_LR_UND,
"R14(UND)"),
313 regCore32(KVM_REG_ARM_CORE_REG(irq_regs[0]), INTREG_SP_IRQ,
"R13(IRQ)"),
314 regCore32(KVM_REG_ARM_CORE_REG(irq_regs[1]), INTREG_LR_IRQ,
"R14(IRQ)"),
317 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[0]), INTREG_R8_FIQ,
"R8(FIQ)"),
318 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[1]), INTREG_R9_FIQ,
"R9(FIQ)"),
319 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[2]), INTREG_R10_FIQ,
"R10(FIQ)"),
320 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[3]), INTREG_R11_FIQ,
"R11(FIQ)"),
321 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[4]), INTREG_R12_FIQ,
"R12(FIQ)"),
322 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[5]), INTREG_R13_FIQ,
"R13(FIQ)"),
323 regCore32(KVM_REG_ARM_CORE_REG(fiq_regs[6]), INTREG_R14_FIQ,
"R14(FIQ)"),
324 { 0, NUM_INTREGS, NULL }
328 regCore32(KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr),
MISCREG_CPSR,
"CPSR"),
344 irqAsserted(false), fiqAsserted(false)
372 const bool simIRQ = interrupt->checkRaw(
INT_IRQ);
376 DPRINTF(KvmInt,
"KVM: Update FIQ state: %i\n", simFIQ);
381 DPRINTF(KvmInt,
"KVM: Update IRQ state: %i\n", simIRQ);
398 DPRINTF(KvmContext,
"Updating KVM state...\n");
407 DPRINTF(KvmContext,
"Updating gem5 state...\n");
417 std::unique_ptr<struct kvm_reg_list> regs;
422 regs.reset((
struct kvm_reg_list *)
423 operator new(
sizeof(
struct kvm_reg_list) +
424 i *
sizeof(uint64_t)));
428 regs->reg + regs->n);
437 struct kvm_vcpu_init
init;
441 init.target = target;
449 if (
ioctl(KVM_ARM_VCPU_INIT, (
void *)&
init) == -1)
450 panic(
"KVM: Failed to initialize vCPU\n");
456 const unsigned cp = regCp(
id);
457 const bool is_reg32 = regIs32Bit(
id);
458 const bool is_reg64 = regIs64Bit(
id);
464 const unsigned crm = regCrm(
id);
465 const unsigned crn = regCrn(
id);
466 const unsigned opc1 = regOpc1(
id);
467 const unsigned opc2 = regOpc2(
id);
480 }
else if (is_reg64) {
483 warn(
"Unhandled register length, register (0x%x) ignored.\n");
491 if (!regIsArm(
id) || !regIsVfp(
id) || !regIsVfpCtrl(
id))
494 const unsigned vfp_reg = regVfpReg(
id);
502 case KVM_REG_ARM_VFP_FPINST:
503 case KVM_REG_ARM_VFP_FPINST2:
504 warn_once(
"KVM: FPINST not implemented.\n");
518 if (regIsArm(
id) && regIsDemux(
id))
519 id &= ~KVM_REG_ARM_DEMUX_VAL_MASK;
527 if (
ioctl(KVM_GET_REG_LIST, (
void *)®s) == -1) {
528 if (errno == E2BIG) {
531 panic(
"KVM: Failed to get vCPU register list (errno: %i)\n",
547 ri->idx != NUM_INTREGS; ++
ri) {
550 inform(
"%s: 0x%x\n",
ri->name, value);
566 for (RegIndexVector::const_iterator it(reg_ids.begin());
567 it != reg_ids.end(); ++it) {
570 if (regIsArm(
id) && regCp(
id) <= 15) {
572 }
else if (regIsArm(
id) && regIsVfp(
id)) {
574 }
else if (regIsArm(
id) && regIsDemux(
id)) {
575 switch (
id & KVM_REG_ARM_DEMUX_ID_MASK) {
576 case KVM_REG_ARM_DEMUX_ID_CCSIDR:
577 inform(
"CCSIDR [0x%x]: %s\n",
578 extractField(
id, KVM_REG_ARM_DEMUX_VAL_MASK,
579 KVM_REG_ARM_DEMUX_VAL_SHIFT),
583 inform(
"DEMUX [0x%x, 0x%x]: %s\n",
584 extractField(
id, KVM_REG_ARM_DEMUX_ID_MASK,
585 KVM_REG_ARM_DEMUX_ID_SHIFT),
586 extractField(
id, KVM_REG_ARM_DEMUX_VAL_MASK,
587 KVM_REG_ARM_DEMUX_VAL_SHIFT),
591 }
else if (!regIsCore(
id)) {
600 assert(regIsArm(
id));
601 assert(regCp(
id) <= 15);
603 if (regIs32Bit(
id)) {
609 !(idx >= MISCREG_CP15_UNIMP_START && idx < MISCREG_CP15_END)) {
613 inform(
"CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: "
615 regCp(
id), regCrn(
id), regOpc1(
id), regCrm(
id),
619 inform(
"readMiscReg: %x, readMiscRegNoEffect: %x\n",
624 inform(
"CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: "
626 regCp(
id), regCrn(
id), regOpc1(
id), regCrm(
id),
630 inform(
"CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i "
632 regCp(
id), regCrn(
id), regOpc1(
id), regCrm(
id),
634 extractField(
id, KVM_REG_SIZE_MASK, KVM_REG_SIZE_SHIFT),
642 assert(regIsArm(
id));
643 assert(regIsVfp(
id));
645 if (regIsVfpReg(
id)) {
646 const unsigned idx =
id & KVM_REG_ARM_VFP_MASK;
648 }
else if (regIsVfpCtrl(
id)) {
664 ri->idx != NUM_INTREGS; ++
ri) {
667 DPRINTF(KvmContext,
"kvm(%s) := 0x%x\n",
ri->name, value);
678 DPRINTF(KvmContext,
"kvm(%s) := 0x%x\n",
ri->name, value);
682 if (debug::KvmContext)
689 static bool warned =
false;
694 for (RegIndexVector::const_iterator it(regs.begin());
698 if (!regIsArm(*it)) {
700 warn(
"Skipping non-ARM register: 0x%x\n", *it);
702 DPRINTF(
Kvm,
"Skipping invariant register: 0x%x\n", *it);
703 }
else if (regIsCore(*it)) {
706 }
else if (regCp(*it) <= 15) {
708 }
else if (regIsVfp(*it)) {
712 warn(
"Skipping register with unknown CP (%i) id: 0x%x\n",
720 if (debug::KvmContext)
729 assert(regIsArm(
id));
730 assert(regCp(
id) <= 15);
736 hack(
"KVM: 64-bit TTBBRx workaround\n");
741 warn(
"KVM: Ignoring unknown KVM co-processor register (0x%.8x):\n",
743 warn(
"\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i"
745 id, regCp(
id), regIs64Bit(
id), regCrn(
id),
746 regOpc1(
id), regCrm(
id), regOpc2(
id));
748 }
else if (
reg >= MISCREG_CP15_UNIMP_START &&
reg < MISCREG_CP15_END) {
750 warn(
"KVM: Co-processor reg. %s not implemented by gem5.\n",
761 assert(regIsArm(
id));
762 assert(regIsVfp(
id));
764 if (regIsVfpReg(
id)) {
765 if (!regIs64Bit(
id)) {
767 warn(
"Unexpected VFP register length (reg: 0x%x).\n",
id);
770 const unsigned idx =
id & KVM_REG_ARM_VFP_MASK;
771 const unsigned idx_base = idx << 1;
772 const unsigned idx_hi = idx_base + 1;
773 const unsigned idx_lo = idx_base + 0;
779 }
else if (regIsVfpCtrl(
id)) {
783 warn(
"Unhandled VFP control register: 0x%x\n",
id);
786 if (!regIs32Bit(
id)) {
788 warn(
"Ignoring VFP control register (%s) with "
789 "unexpected size.\n",
796 warn(
"Unhandled VFP register: 0x%x\n",
id);
804 ri->idx != NUM_INTREGS; ++
ri) {
826 if (debug::KvmContext)
833 static bool warned(
false);
837 for (RegIndexVector::const_iterator it(reg_ids.begin());
838 it != reg_ids.end(); ++it) {
840 if (!regIsArm(*it)) {
842 warn(
"Skipping non-ARM register: 0x%x\n", *it);
843 }
else if (regIsCore(*it)) {
845 }
else if (regCp(*it) <= 15) {
847 }
else if (regIsVfp(*it)) {
851 warn(
"Skipping register with unknown CP (%i) id: 0x%x\n",
859 if (debug::KvmContext)
868 assert(regIsArm(
id));
869 assert(regCp(
id) <= 15);
873 hack_once(
"KVM: 64-bit TTBRx workaround\n");
879 if (value & 0x80000000)
880 panic(
"KVM: Guest tried to enable LPAE.\n");
884 warn(
"KVM: Ignoring unknown KVM co-processor register:\n",
id);
885 warn(
"\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i"
887 id, regCp(
id), regIs64Bit(
id), regCrn(
id),
888 regOpc1(
id), regCrm(
id), regOpc2(
id));
890 }
else if (
reg >= MISCREG_CP15_UNIMP_START &&
reg < MISCREG_CP15_END) {
892 warn_once(
"KVM: Co-processor reg. %s not implemented by gem5.\n",
902 assert(regIsArm(
id));
903 assert(regIsVfp(
id));
905 if (regIsVfpReg(
id)) {
906 if (!regIs64Bit(
id)) {
908 warn(
"Unexpected VFP register length (reg: 0x%x).\n",
id);
911 const unsigned idx =
id & KVM_REG_ARM_VFP_MASK;
912 const unsigned idx_base = idx << 1;
913 const unsigned idx_hi = idx_base + 1;
914 const unsigned idx_lo = idx_base + 0;
919 }
else if (regIsVfpCtrl(
id)) {
923 warn(
"Unhandled VFP control register: 0x%x\n",
id);
926 if (!regIs32Bit(
id)) {
928 warn(
"Ignoring VFP control register (%s) with "
929 "unexpected size.\n",
936 warn(
"Unhandled VFP register: 0x%x\n",
id);