42 #include <linux/kvm.h>
48 #include "arch/registers.hh"
50 #include "debug/Kvm.hh"
51 #include "debug/KvmContext.hh"
52 #include "debug/KvmInt.hh"
55 using namespace ArmISA;
57 #define EXTRACT_FIELD(val, mask, shift) \
58 (((val) & (mask)) >> (shift))
60 #define REG_IS_ARM(id) \
61 (((id) & KVM_REG_ARCH_MASK) == KVM_REG_ARM)
63 #define REG_IS_32BIT(id) \
64 (((id) & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32)
66 #define REG_IS_64BIT(id) \
67 (((id) & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64)
69 #define REG_IS_CP(id, cp) \
70 (((id) & KVM_REG_ARM_COPROC_MASK) == (cp))
72 #define REG_IS_CORE(id) REG_IS_CP((id), KVM_REG_ARM_CORE)
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)
78 #define REG_IS_VFP_REG(id) (REG_VFP_REG(id) < 0x100)
79 #define REG_IS_VFP_CTRL(id) (REG_VFP_REG(id) >= 0x100)
81 #define REG_IS_DEMUX(id) REG_IS_CP((id), KVM_REG_ARM_DEMUX)
87 #define REG_CORE_IDX(id) \
88 (~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE))
91 EXTRACT_FIELD(id, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_SHIFT)
94 EXTRACT_FIELD(id, KVM_REG_ARM_32_CRN_MASK, KVM_REG_ARM_32_CRN_SHIFT)
96 #define REG_OPC1(id) \
97 EXTRACT_FIELD(id, KVM_REG_ARM_OPC1_MASK, KVM_REG_ARM_OPC1_SHIFT)
100 EXTRACT_FIELD(id, KVM_REG_ARM_CRM_MASK, KVM_REG_ARM_CRM_SHIFT)
102 #define REG_OPC2(id) \
103 EXTRACT_FIELD(id, KVM_REG_ARM_32_OPC2_MASK, KVM_REG_ARM_32_OPC2_SHIFT)
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))
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))
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)))
124 #define REG_VFP32(regno) ( \
125 (KVM_REG_ARM | KVM_REG_SIZE_U32) | \
126 KVM_REG_ARM_VFP | (regno))
128 #define REG_VFP64(regno) ( \
129 (KVM_REG_ARM | KVM_REG_SIZE_U64) | \
130 KVM_REG_ARM_VFP | (regno))
132 #define REG_DEMUX32(dmxid, val) ( \
133 (KVM_REG_ARM | KVM_REG_SIZE_U32) | \
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))
181 #define INTERRUPT_VCPU_IRQ(vcpu) \
182 INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_IRQ)
184 #define INTERRUPT_VCPU_FIQ(vcpu) \
185 INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_FIQ)
188 #define COUNT_OF(l) (sizeof(l) / sizeof(*l))
247 irqAsserted(false), fiqAsserted(false)
273 bool simFIQ(interrupts[0]->checkRaw(
INT_FIQ));
274 bool simIRQ(interrupts[0]->checkRaw(
INT_IRQ));
278 DPRINTF(KvmInt,
"KVM: Update FIQ state: %i\n", simFIQ);
283 DPRINTF(KvmInt,
"KVM: Update IRQ state: %i\n", simIRQ);
300 DPRINTF(KvmContext,
"Updating KVM state...\n");
309 DPRINTF(KvmContext,
"Updating gem5 state...\n");
320 const uint8_t func((reg_ip >> 8) & 0xFF);
321 const uint8_t subfunc(reg_ip & 0xFF);
323 DPRINTF(
Kvm,
"KVM Hypercall: 0x%x/0x%x\n", func, subfunc);
339 std::unique_ptr<struct kvm_reg_list> regs;
344 regs.reset((
struct kvm_reg_list *)
345 operator new(
sizeof(
struct kvm_reg_list) +
346 i *
sizeof(uint64_t)));
350 regs->reg + regs->n);
359 struct kvm_vcpu_init init;
361 memset(&init, 0,
sizeof(init));
363 init.target = target;
371 if (
ioctl(KVM_ARM_VCPU_INIT, (
void *)&init) == -1)
372 panic(
"KVM: Failed to initialize vCPU\n");
378 const unsigned cp(
REG_CP(
id));
386 const unsigned crm(
REG_CRM(
id));
387 const unsigned crn(
REG_CRN(
id));
402 }
else if (is_reg64) {
405 warn(
"Unhandled register length, register (0x%x) ignored.\n");
424 case KVM_REG_ARM_VFP_FPINST:
425 case KVM_REG_ARM_VFP_FPINST2:
426 warn_once(
"KVM: FPINST not implemented.\n");
441 id &= ~KVM_REG_ARM_DEMUX_VAL_MASK;
449 if (
ioctl(KVM_GET_REG_LIST, (
void *)®s) == -1) {
450 if (errno == E2BIG) {
453 panic(
"KVM: Failed to get vCPU register list (errno: %i)\n",
472 inform(
"%s: 0x%x\n", ri->name, value);
488 for (RegIndexVector::const_iterator it(reg_ids.begin());
489 it != reg_ids.end(); ++it) {
497 switch (
id & KVM_REG_ARM_DEMUX_ID_MASK) {
498 case KVM_REG_ARM_DEMUX_ID_CCSIDR:
499 inform(
"CCSIDR [0x%x]: %s\n",
501 KVM_REG_ARM_DEMUX_VAL_MASK,
502 KVM_REG_ARM_DEMUX_VAL_SHIFT),
506 inform(
"DEMUX [0x%x, 0x%x]: %s\n",
508 KVM_REG_ARM_DEMUX_ID_MASK,
509 KVM_REG_ARM_DEMUX_ID_SHIFT),
511 KVM_REG_ARM_DEMUX_VAL_MASK,
512 KVM_REG_ARM_DEMUX_VAL_SHIFT),
534 !(idx >= MISCREG_CP15_UNIMP_START && idx < MISCREG_CP15_END)) {
538 inform(
"CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: "
544 inform(
"readMiscReg: %x, readMiscRegNoEffect: %x\n",
549 inform(
"CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i]: [%s]: "
555 inform(
"CP%i: [CRn: c%i opc1: %.2i CRm: c%i opc2: %i inv: %i "
571 const unsigned idx(
id & KVM_REG_ARM_VFP_MASK);
592 DPRINTF(KvmContext,
"kvm(%s) := 0x%x\n", ri->name, value);
603 DPRINTF(KvmContext,
"kvm(%s) := 0x%x\n", ri->name, value);
614 static bool warned(
false);
619 for (RegIndexVector::const_iterator it(regs.begin());
625 warn(
"Skipping non-ARM register: 0x%x\n", *it);
627 DPRINTF(
Kvm,
"Skipping invariant register: 0x%x\n", *it);
631 }
else if (
REG_CP(*it) <= 15) {
637 warn(
"Skipping register with unknown CP (%i) id: 0x%x\n",
661 hack(
"KVM: 64-bit TTBBRx workaround\n");
666 warn(
"KVM: Ignoring unknown KVM co-processor register (0x%.8x):\n",
668 warn(
"\t0x%x: [CP: %i 64: %i CRn: c%i opc1: %.2i CRm: c%i"
673 }
else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) {
675 warn(
"KVM: Co-processor reg. %s not implemented by gem5.\n",
692 warn(
"Unexpected VFP register length (reg: 0x%x).\n",
id);
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);
708 warn(
"Unhandled VFP control register: 0x%x\n",
id);
713 warn(
"Ignoring VFP control register (%s) with "
714 "unexpected size.\n",
721 warn(
"Unhandled VFP register: 0x%x\n",
id);
758 static bool warned(
false);
762 for (RegIndexVector::const_iterator it(reg_ids.begin());
763 it != reg_ids.end(); ++it) {
767 warn(
"Skipping non-ARM register: 0x%x\n", *it);
770 }
else if (
REG_CP(*it) <= 15) {
776 warn(
"Skipping register with unknown CP (%i) id: 0x%x\n",
798 hack_once(
"KVM: 64-bit TTBRx workaround\n");
804 if (value & 0x80000000)
805 panic(
"KVM: Guest tried to enable LPAE.\n");
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"
815 }
else if (reg >= MISCREG_CP15_UNIMP_START && reg < MISCREG_CP15_END) {
817 warn_once(
"KVM: Co-processor reg. %s not implemented by gem5.\n",
833 warn(
"Unexpected VFP register length (reg: 0x%x).\n",
id);
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);
848 warn(
"Unhandled VFP control register: 0x%x\n",
id);
853 warn(
"Ignoring VFP control register (%s) with "
854 "unexpected size.\n",
861 warn(
"Unhandled VFP register: 0x%x\n",
id);
866 ArmKvmCPUParams::create()
void kvmArmVCpuInit(uint32_t target)
ArmISA::MiscRegIndex decodeVFPCtrlReg(uint64_t id) const
Tick onKvmExitHypercall()
virtual Addr instAddr()=0
const std::string & name()
#define REG_CP64(cpnum, opc1, crm)
void updateKvmStateVFP(uint64_t id, bool show_warnings)
void dumpKvmStateVFP(uint64_t id)
virtual void setFloatRegBitsFlat(int idx, FloatRegBits val)=0
void updateKvmStateCore()
virtual Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
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...
void updateKvmState()
Update the KVM state from the current thread context.
#define REG_CP32(cpnum, crn, opc1, crm, opc2)
virtual FloatRegBits readFloatRegBitsFlat(int idx)=0
bool irqAsserted
Cached state of the IRQ line.
virtual void setMiscReg(int misc_reg, const MiscReg &val)=0
virtual void setIntRegFlat(int idx, uint64_t val)=0
#define EXTRACT_FIELD(val, mask, shift)
const char *const miscRegName[]
virtual TheISA::PCState pcState()=0
Base class for KVM based CPU models.
void dumpKvmStateCoProc(uint64_t id)
static KvmCoreMiscRegInfo kvmCoreMiscRegs[]
static KvmIntRegInfo kvmIntRegs[]
const RegIndexVector & getRegList() const
Get a list of registers supported by getOneReg() and setOneReg().
const MiscRegIndex idx
gem5 index
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define REG_IS_VFP_REG(id)
void setIRQLine(uint32_t irq, bool high)
Set the status of an IRQ line using KVM_IRQ_LINE.
const long vcpuID
KVM internal ID of the vCPU.
static const uint64_t KVM_REG64_TTBR0(REG_CP64(15, 0, 2))
static const uint64_t KVM_REG64_TTBR1(REG_CP64(15, 1, 2))
const IntRegIndex idx
gem5 index
ThreadContext * getContext(int tn) override
void setOneReg(uint64_t id, const void *addr)
Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
uint64_t Tick
Tick count type.
uint64_t getOneRegU64(uint64_t id) const
Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
#define INTERRUPT_VCPU_FIQ(vcpu)
void updateThreadContext()
Update the current thread context with the KVM state.
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...
uint32_t getOneRegU32(uint64_t id) const
void updateTCStateVFP(uint64_t id, bool show_warnings)
uint64_t pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc)
Execute a decoded M5 pseudo instruction.
void updateKvmStateCoProc(uint64_t id, bool show_warnings)
static uint64_t invariant_reg_vector[]
#define INTERRUPT_VCPU_IRQ(vcpu)
virtual MiscReg readMiscReg(int misc_reg)=0
#define REG_CORE32(kname)
GenericISA::SimplePCState< MachInst > PCState
std::string getAndFormatOneReg(uint64_t id) const
Get and format one register for printout.
ArmKvmCPU(ArmKvmCPUParams *params)
bool fiqAsserted
Cached state of the FIQ line.
void updateKvmStateMisc()
#define REG_IS_VFP_CTRL(id)
#define REG_DEMUX32(dmxid, val)
RegIndexVector _regIndexList
Cached copy of the list of co-processor registers supported by KVM.
ARM implementation of a KVM-based hardware virtualized CPU.
virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val)=0
MiscRegIndex decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
MiscRegIndex decodeCP14Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
const FlagsType init
This Stat is Initialized.
void updateTCStateCoProc(uint64_t id, bool show_warnings)
bool isInvariantReg(uint64_t id)
Determine if a register is invariant.
ArmISA::MiscRegIndex decodeCoProcReg(uint64_t id) const
int ioctl(int request, long p1) const
vCPU ioctl interface.