33 #include <linux/kvm.h>
39 #include "arch/registers.hh"
44 #include "debug/Drain.hh"
45 #include "debug/Kvm.hh"
46 #include "debug/KvmContext.hh"
47 #include "debug/KvmIO.hh"
48 #include "debug/KvmInt.hh"
50 using namespace X86ISA;
54 #define IO_PCI_CONF_ADDR 0xCF8
55 #define IO_PCI_CONF_DATA_BASE 0xCFC
58 #define SEG_SYS_TYPE_TSS_AVAILABLE 9
60 #define SEG_SYS_TYPE_TSS_BUSY 11
63 #define SEG_CS_TYPE_ACCESSED 9
65 #define SEG_CS_TYPE_READ_ACCESSED 11
69 #define SEG_TYPE_BIT_ACCESSED 1
99 uint64_t reserved[12];
102 static_assert(
sizeof(
FXSave) == 512,
"Unexpected size of FXSave");
104 #define FOREACH_IREG() \
106 APPLY_IREG(rax, INTREG_RAX); \
107 APPLY_IREG(rbx, INTREG_RBX); \
108 APPLY_IREG(rcx, INTREG_RCX); \
109 APPLY_IREG(rdx, INTREG_RDX); \
110 APPLY_IREG(rsi, INTREG_RSI); \
111 APPLY_IREG(rdi, INTREG_RDI); \
112 APPLY_IREG(rsp, INTREG_RSP); \
113 APPLY_IREG(rbp, INTREG_RBP); \
114 APPLY_IREG(r8, INTREG_R8); \
115 APPLY_IREG(r9, INTREG_R9); \
116 APPLY_IREG(r10, INTREG_R10); \
117 APPLY_IREG(r11, INTREG_R11); \
118 APPLY_IREG(r12, INTREG_R12); \
119 APPLY_IREG(r13, INTREG_R13); \
120 APPLY_IREG(r14, INTREG_R14); \
121 APPLY_IREG(r15, INTREG_R15); \
124 #define FOREACH_SREG() \
126 APPLY_SREG(cr0, MISCREG_CR0); \
127 APPLY_SREG(cr2, MISCREG_CR2); \
128 APPLY_SREG(cr3, MISCREG_CR3); \
129 APPLY_SREG(cr4, MISCREG_CR4); \
130 APPLY_SREG(cr8, MISCREG_CR8); \
131 APPLY_SREG(efer, MISCREG_EFER); \
132 APPLY_SREG(apic_base, MISCREG_APIC_BASE); \
135 #define FOREACH_DREG() \
137 APPLY_DREG(db[0], MISCREG_DR0); \
138 APPLY_DREG(db[1], MISCREG_DR1); \
139 APPLY_DREG(db[2], MISCREG_DR2); \
140 APPLY_DREG(db[3], MISCREG_DR3); \
141 APPLY_DREG(dr6, MISCREG_DR6); \
142 APPLY_DREG(dr7, MISCREG_DR7); \
145 #define FOREACH_SEGMENT() \
147 APPLY_SEGMENT(cs, MISCREG_CS - MISCREG_SEG_SEL_BASE); \
148 APPLY_SEGMENT(ds, MISCREG_DS - MISCREG_SEG_SEL_BASE); \
149 APPLY_SEGMENT(es, MISCREG_ES - MISCREG_SEG_SEL_BASE); \
150 APPLY_SEGMENT(fs, MISCREG_FS - MISCREG_SEG_SEL_BASE); \
151 APPLY_SEGMENT(gs, MISCREG_GS - MISCREG_SEG_SEL_BASE); \
152 APPLY_SEGMENT(ss, MISCREG_SS - MISCREG_SEG_SEL_BASE); \
153 APPLY_SEGMENT(tr, MISCREG_TR - MISCREG_SEG_SEL_BASE); \
154 APPLY_SEGMENT(ldt, MISCREG_TSL - MISCREG_SEG_SEL_BASE); \
157 #define FOREACH_DTABLE() \
159 APPLY_DTABLE(gdt, MISCREG_TSG - MISCREG_SEG_SEL_BASE); \
160 APPLY_DTABLE(idt, MISCREG_IDTR - MISCREG_SEG_SEL_BASE); \
163 template<
typename STRUCT,
typename ENTRY>
166 return (STRUCT *)
operator new(
sizeof(STRUCT) + entries *
sizeof(ENTRY));
172 inform(
"KVM register state:\n");
174 #define APPLY_IREG(kreg, mreg) \
175 inform("\t" # kreg ": 0x%llx\n", regs.kreg)
181 inform(
"\trip: 0x%llx\n", regs.rip);
182 inform(
"\trflags: 0x%llx\n", regs.rflags);
188 inform(
"\t%s: @0x%llx+%x [sel: 0x%x, type: 0x%x]\n"
189 "\t\tpres.: %u, dpl: %u, db: %u, s: %u, l: %u, g: %u, avl: %u, unus.: %u\n",
191 seg.base, seg.limit, seg.selector, seg.type,
192 seg.present, seg.dpl, seg.db, seg.s, seg.l, seg.g, seg.avl, seg.unusable);
196 dumpKvm(
const char *reg_name,
const struct kvm_dtable &dtable)
198 inform(
"\t%s: @0x%llx+%x\n",
199 reg_name, dtable.base, dtable.limit);
205 #define APPLY_SREG(kreg, mreg) \
206 inform("\t" # kreg ": 0x%llx\n", sregs.kreg);
207 #define APPLY_SEGMENT(kreg, idx) \
208 dumpKvm(# kreg, sregs.kreg);
209 #define APPLY_DTABLE(kreg, idx) \
210 dumpKvm(# kreg, sregs.kreg);
212 inform(
"Special registers:\n");
217 inform(
"Interrupt Bitmap:");
218 for (
int i = 0;
i < KVM_NR_INTERRUPTS;
i += 64)
219 inform(
" 0x%.8x", sregs.interrupt_bitmap[
i / 64]);
226 #ifdef KVM_GET_DEBUGREGS
228 dumpKvm(
const struct kvm_debugregs ®s)
230 inform(
"KVM debug state:\n");
232 #define APPLY_DREG(kreg, mreg) \
233 inform("\t" # kreg ": 0x%llx\n", regs.kreg)
239 inform(
"\tflags: 0x%llx\n", regs.flags);
254 inform(
"\tlast_ip: 0x%x\n", fpu.last_ip);
255 inform(
"\tlast_dp: 0x%x\n", fpu.last_dp);
262 const unsigned top((fpu.fsw >> 11) & 0x7);
263 inform(
"\tfcw: 0x%x\n", fpu.fcw);
265 inform(
"\tfsw: 0x%x (top: %i, "
266 "conditions: %s%s%s%s, exceptions: %s%s%s%s%s%s %s%s%s)\n",
269 (fpu.fsw &
CC0Bit) ?
"C0" :
"",
270 (fpu.fsw &
CC1Bit) ?
"C1" :
"",
271 (fpu.fsw &
CC2Bit) ?
"C2" :
"",
272 (fpu.fsw &
CC3Bit) ?
"C3" :
"",
274 (fpu.fsw &
IEBit) ?
"I" :
"",
275 (fpu.fsw &
DEBit) ?
"D" :
"",
276 (fpu.fsw &
ZEBit) ?
"Z" :
"",
277 (fpu.fsw &
OEBit) ?
"O" :
"",
278 (fpu.fsw &
UEBit) ?
"U" :
"",
279 (fpu.fsw &
PEBit) ?
"P" :
"",
283 (fpu.fsw &
BusyBit) ?
"BUSY " :
""
285 inform(
"\tftwx: 0x%x\n", fpu.ftwx);
286 inform(
"\tlast_opcode: 0x%x\n", fpu.last_opcode);
288 inform(
"\tmxcsr: 0x%x\n", fpu.mxcsr);
290 for (
int i = 0;
i < 8; ++
i) {
291 const unsigned reg_idx((
i + top) & 0x7);
292 const bool empty(!((fpu.ftwx >> reg_idx) & 0x1));
295 for (
int j = 0;
j < 10; ++
j)
296 snprintf(&hex[
j*2], 3,
"%.2x", fpu.fpr[
i][j]);
297 inform(
"\t\tST%i/%i: 0x%s (%f)%s\n",
i, reg_idx,
298 hex, value, empty ?
" (e)" :
"");
300 inform(
"\tXMM registers:\n");
301 for (
int i = 0;
i < 16; ++
i) {
303 for (
int j = 0;
j < 16; ++
j)
304 snprintf(&hex[
j*2], 3,
"%.2x", fpu.xmm[
i][j]);
305 inform(
"\t\t%i: 0x%s\n",
i, hex);
312 inform(
"FPU registers:\n");
319 inform(
"FPU registers (XSave):\n");
328 for (
int i = 0;
i < msrs.nmsrs; ++
i) {
329 const struct kvm_msr_entry &
e(msrs.entries[
i]);
331 inform(
"\t0x%x: 0x%x\n", e.index, e.data);
338 inform(
"KVM XCR registers:\n");
340 inform(
"\tFlags: 0x%x\n", regs.flags);
341 for (
int i = 0;
i < regs.nr_xcrs; ++
i) {
342 inform(
"\tXCR[0x%x]: 0x%x\n",
353 inform(
"\tException: [inj: %i, nr: %i, has_ec: %i, ec: %i]\n",
354 events.exception.injected, events.exception.nr,
355 events.exception.has_error_code, events.exception.error_code);
357 inform(
"\tInterrupt: [inj: %i, nr: %i, soft: %i]\n",
358 events.interrupt.injected, events.interrupt.nr,
359 events.interrupt.soft);
361 inform(
"\tNMI: [inj: %i, pending: %i, masked: %i]\n",
362 events.nmi.injected, events.nmi.pending,
365 inform(
"\tSIPI vector: 0x%x\n", events.sipi_vector);
366 inform(
"\tFlags: 0x%x\n", events.flags);
376 uint64_t upper_half(addr & 0xffff800000000000ULL);
377 return upper_half == 0 || upper_half == 0xffff800000000000;
382 struct kvm_sregs sregs)
391 warn(
"Illegal %s base: 0x%x\n", name, seg.base);
400 if (seg.base & 0xffffffff00000000ULL)
401 warn(
"Illegal %s base: 0x%x\n", name, seg.base);
411 warn(
"CS type is 3 but dpl != 0.\n");
415 if (seg.dpl != sregs.ss.dpl)
416 warn(
"CS type is %i but CS DPL != SS DPL\n", seg.type);
420 if (seg.dpl > sregs.ss.dpl)
421 warn(
"CS type is %i but CS DPL > SS DPL\n", seg.type);
424 warn(
"Illegal CS type: %i\n", seg.type);
434 if (sregs.cs.type == 3 && seg.dpl != 0)
435 warn(
"CS type is 3, but SS DPL is != 0.\n");
438 if (!(sregs.cr0 & 1) && seg.dpl != 0)
439 warn(
"SS DPL is %i, but CR0 PE is 0\n", seg.dpl);
442 warn(
"Illegal SS type: %i\n", seg.type);
453 if (!(seg.type & 0x1) ||
454 ((seg.type & 0x8) && !(seg.type & 0x2)))
455 warn(
"%s has an illegal type field: %i\n", name, seg.type);
460 if (seg.type != 3 && seg.type != 11)
461 warn(
"%s: Illegal segment type (%i)\n", name, seg.type);
468 warn(
"%s: Illegal segment type (%i)\n", name, seg.type);
482 warn(
"%s: S flag not set\n", name);
490 warn(
"%s: S flag is set\n", name);
506 warn(
"%s: P flag not set\n", name);
508 if (((seg.limit & 0xFFF) == 0 && seg.g) ||
509 ((seg.limit & 0xFFF00000) != 0 && !seg.g)) {
510 warn(
"%s limit (0x%x) and g (%i) combination is illegal.\n",
511 name, seg.limit, seg.g);
521 useXSave(params->useXSave)
526 panic(
"KVM: Missing capability (KVM_CAP_SET_TSS_ADDR)\n");
528 panic(
"KVM: Missing capability (KVM_CAP_EXT_CPUID)\n");
530 warn(
"KVM: Missing capability (KVM_CAP_USER_NMI)\n");
532 warn(
"KVM: Missing capability (KVM_CAP_VCPU_EVENTS)\n");
539 warn(
"KVM: XSAVE not supported by host. MXCSR synchronization might be "
540 "unreliable due to kernel bugs.\n");
543 warn(
"KVM: XSave FPU/SIMD synchronization disabled by user.\n");
591 struct kvm_regs regs;
599 struct kvm_sregs sregs;
608 #ifdef KVM_GET_DEBUGREGS
609 struct kvm_debugregs dregs;
614 inform(
"Debug registers not supported by kernel.\n");
622 struct kvm_xcrs xcrs;
626 inform(
"XCRs not supported by kernel.\n");
634 struct kvm_xsave xsave;
638 inform(
"XSave not supported by kernel.\n");
645 struct kvm_vcpu_events events;
653 const Kvm::MSRIndexVector &supported_msrs(
vm.
kvm->getSupportedMSRs());
654 std::unique_ptr<struct kvm_msrs> msrs(
655 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(
656 supported_msrs.size()));
658 msrs->nmsrs = supported_msrs.size();
659 for (
int i = 0;
i < supported_msrs.size(); ++
i) {
660 struct kvm_msr_entry &
e(msrs->entries[
i]);
661 e.index = supported_msrs[
i];
678 DPRINTF(KvmContext,
"X86KvmCPU::updateKvmState():\n");
686 struct kvm_regs regs;
688 #define APPLY_IREG(kreg, mreg) regs.kreg = tc->readIntReg(mreg)
714 kvm_seg.type =
attr.type;
715 kvm_seg.present =
attr.present;
716 kvm_seg.dpl =
attr.dpl;
717 kvm_seg.db =
attr.defaultSize;
718 kvm_seg.s =
attr.system;
719 kvm_seg.l =
attr.longMode;
720 kvm_seg.g =
attr.granularity;
721 kvm_seg.avl =
attr.avl;
727 kvm_seg.unusable = 0;
753 struct kvm_sregs sregs;
755 #define APPLY_SREG(kreg, mreg) sregs.kreg = tc->readMiscRegNoEffect(mreg)
756 #define APPLY_SEGMENT(kreg, idx) setKvmSegmentReg(tc, sregs.kreg, idx)
757 #define APPLY_DTABLE(kreg, idx) setKvmDTableReg(tc, sregs.kreg, idx)
768 memset(&sregs.interrupt_bitmap, 0,
sizeof(sregs.interrupt_bitmap));
782 hack(
"tr.type (%i) is not busy. Forcing the busy bit.\n",
793 sregs.cs.dpl != sregs.ss.dpl) {
795 hack(
"CS.DPL (%i) != SS.DPL (%i): Forcing SS.DPL to %i\n",
796 sregs.cs.dpl, sregs.ss.dpl, sregs.cs.dpl);
797 sregs.ss.dpl = sregs.cs.dpl;
803 if (!rflags_nocc.vm) {
808 #define APPLY_SEGMENT(kreg, idx) \
809 checkSeg(# kreg, idx + MISCREG_SEG_SEL_BASE, sregs.kreg, sregs)
818 template <
typename T>
823 "Unexpected size of X86ISA::FloatRegBits");
836 const unsigned top((fpu.fsw >> 11) & 0x7);
837 for (
int i = 0;
i < 8; ++
i) {
838 const unsigned reg_idx((
i + top) & 0x7);
840 DPRINTF(KvmContext,
"Setting KVM FP reg %i (st[%i]) := %f\n",
847 for (
int i = 0;
i < 16; ++
i) {
862 memset(&fpu, 0,
sizeof(fpu));
867 warn_once(
"MISCREG_FISEG is non-zero.\n");
872 warn_once(
"MISCREG_FOSEG is non-zero.\n");
882 struct kvm_xsave kxsave;
887 memset(&kxsave, 0,
sizeof(kxsave));
892 warn_once(
"MISCREG_FISEG is non-zero.\n");
897 warn_once(
"MISCREG_FOSEG is non-zero.\n");
920 for (
auto it = indices.cbegin(); it != indices.cend(); ++it) {
921 struct kvm_msr_entry e;
926 DPRINTF(KvmContext,
"Adding MSR: idx: 0x%x, data: 0x%x\n",
938 struct kvm_regs regs;
939 struct kvm_sregs sregs;
944 DPRINTF(KvmContext,
"X86KvmCPU::updateThreadContext():\n");
951 struct kvm_xsave xsave;
971 const struct kvm_sregs &sregs)
973 #define APPLY_IREG(kreg, mreg) tc->setIntReg(mreg, regs.kreg)
993 attr.type = kvm_seg.type;
994 attr.present = kvm_seg.present;
995 attr.dpl = kvm_seg.dpl;
996 attr.defaultSize = kvm_seg.db;
997 attr.system = kvm_seg.s;
998 attr.longMode = kvm_seg.l;
999 attr.granularity = kvm_seg.g;
1000 attr.avl = kvm_seg.avl;
1001 attr.unusable = kvm_seg.unusable;
1029 #define APPLY_SREG(kreg, mreg) tc->setMiscRegNoEffect(mreg, sregs.kreg)
1030 #define APPLY_SEGMENT(kreg, idx) setContextSegment(tc, sregs.kreg, idx)
1031 #define APPLY_DTABLE(kreg, idx) setContextSegment(tc, sregs.kreg, idx)
1036 #undef APPLY_SEGMENT
1040 template<
typename T>
1044 const unsigned top((fpu.fsw >> 11) & 0x7);
1047 "Unexpected size of X86ISA::FloatRegBits");
1049 for (
int i = 0;
i < 8; ++
i) {
1050 const unsigned reg_idx((
i + top) & 0x7);
1052 DPRINTF(KvmContext,
"Setting gem5 FP reg %i (st[%i]) := %f\n",
1071 for (
int i = 0;
i < 16; ++
i) {
1108 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1109 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(msrs.size()));
1110 struct kvm_msr_entry *entry;
1113 kvm_msrs->nmsrs = msrs.size();
1114 entry = &kvm_msrs->entries[0];
1115 for (
auto it = msrs.cbegin(); it != msrs.cend(); ++it, ++entry) {
1117 entry->reserved = 0;
1124 entry = &kvm_msrs->entries[0];
1125 for (
int i = 0;
i < kvm_msrs->nmsrs; ++
i, ++entry) {
1126 DPRINTF(KvmContext,
"Setting M5 MSR: idx: 0x%x, data: 0x%x\n",
1127 entry->index, entry->data);
1147 fault = interrupts[0]->getInterrupt(
tc);
1148 interrupts[0]->updateIntrInfo(
tc);
1151 X86Interrupt *x86int(dynamic_cast<X86Interrupt *>(fault.get()));
1152 if (dynamic_cast<NonMaskableInterrupt *>(fault.get())) {
1153 DPRINTF(KvmInt,
"Delivering NMI\n");
1155 }
else if (dynamic_cast<InitInterrupt *>(fault.get())) {
1156 DPRINTF(KvmInt,
"INIT interrupt\n");
1157 fault.get()->invoke(
tc);
1166 }
else if (dynamic_cast<StartupInterrupt *>(fault.get())) {
1167 DPRINTF(KvmInt,
"STARTUP interrupt\n");
1168 fault.get()->invoke(
tc);
1172 }
else if (x86int) {
1173 struct kvm_interrupt kvm_int;
1176 DPRINTF(KvmInt,
"Delivering interrupt: %s (%u)\n",
1177 fault->name(), kvm_int.irq);
1181 panic(
"KVM: Unknown interrupt type\n");
1191 if (interrupts[0]->checkInterruptsRaw()) {
1192 if (interrupts[0]->hasPendingUnmaskable()) {
1194 "Delivering unmaskable interrupt.\n");
1197 }
else if (kvm_run.ready_for_interrupt_injection) {
1204 if (interrupts[0]->checkInterrupts(
tc)) {
1206 "M5 has pending interrupts, delivering interrupt.\n");
1211 "Interrupt delivery delayed due to KVM confusion.\n");
1212 kvm_run.request_interrupt_window = 1;
1214 }
else if (!kvm_run.request_interrupt_window) {
1216 "M5 has pending interrupts, requesting interrupt "
1218 kvm_run.request_interrupt_window = 1;
1221 kvm_run.request_interrupt_window = 0;
1238 DPRINTF(Drain,
"kvmRunDrain: Architecture code isn't drained\n");
1244 kvm_run.request_interrupt_window = 1;
1251 DPRINTF(Drain,
"kvmRunDrain: Delivering pending IO\n");
1286 const uint16_t port(kvm_run.io.port);
1288 assert(kvm_run.exit_reason == KVM_EXIT_IO);
1290 if (kvm_run.io.size != 4) {
1291 panic(
"Unexpected IO size (%u) for address 0x%x.\n",
1292 kvm_run.io.size, port);
1295 if (kvm_run.io.count != 1) {
1296 panic(
"Unexpected IO count (%u) for address 0x%x.\n",
1297 kvm_run.io.count, port);
1301 if (kvm_run.io.direction == KVM_EXIT_IO_OUT)
1311 bool isWrite(kvm_run.io.direction == KVM_EXIT_IO_OUT);
1312 unsigned char *guestData(
getGuestData(kvm_run.io.data_offset));
1314 uint16_t port(kvm_run.io.port);
1316 const int count(kvm_run.io.count);
1318 assert(kvm_run.io.direction == KVM_EXIT_IO_IN ||
1319 kvm_run.io.direction == KVM_EXIT_IO_OUT);
1321 DPRINTF(KvmIO,
"KVM-x86: Handling IO instruction (%s) (port: 0x%x)\n",
1322 (isWrite ?
"out" :
"in"), kvm_run.io.port);
1338 if (pciConfigAddr & 0x80000000) {
1363 guestData += kvm_run.io.size;
1381 struct kvm_vcpu_events events;
1392 const bool pending_events(events.exception.injected ||
1393 events.interrupt.injected ||
1394 events.nmi.injected || events.nmi.pending);
1396 if (pending_events) {
1397 DPRINTF(Drain,
"archIsDrained: Pending events: %s %s %s %s\n",
1398 events.exception.injected ?
"exception" :
"",
1399 events.interrupt.injected ?
"interrupt" :
"",
1400 events.nmi.injected ?
"nmi[i]" :
"",
1401 events.nmi.pending ?
"nmi[p]" :
"");
1404 return !pending_events;
1407 static struct kvm_cpuid_entry2
1411 struct kvm_cpuid_entry2 e;
1412 e.function =
function;
1415 e.eax = (uint32_t)result.rax;
1416 e.ebx = (uint32_t)result.rbx;
1417 e.ecx = (uint32_t)result.rcx;
1418 e.edx = (uint32_t)result.rdx;
1426 Kvm::CPUIDVector m5_supported;
1437 for (uint32_t
function = 0;
function <= func0.
rax; ++
function) {
1442 m5_supported.push_back(
makeKvmCpuid(
function, idx, cpuid));
1448 for (uint32_t
function = 0x80000000;
function <= efunc0.
rax; ++
function) {
1453 m5_supported.push_back(
makeKvmCpuid(
function, idx, cpuid));
1462 if (
ioctl(KVM_SET_CPUID2, (
void *)&cpuid) == -1)
1463 panic(
"KVM: Failed to set guest CPUID2 (errno: %i)\n",
1470 std::unique_ptr<struct kvm_cpuid2> kvm_cpuid(
1471 newVarStruct<struct kvm_cpuid2, struct kvm_cpuid_entry2>(cpuid.size()));
1473 kvm_cpuid->nent = cpuid.size();
1474 std::copy(cpuid.begin(), cpuid.end(), kvm_cpuid->entries);
1482 if (
ioctl(KVM_SET_MSRS, (
void *)&msrs) == -1)
1483 panic(
"KVM: Failed to set guest MSRs (errno: %i)\n",
1490 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1491 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(msrs.size()));
1493 kvm_msrs->nmsrs = msrs.size();
1494 std::copy(msrs.begin(), msrs.end(), kvm_msrs->entries);
1502 if (
ioctl(KVM_GET_MSRS, (
void *)&msrs) == -1)
1503 panic(
"KVM: Failed to get guest MSRs (errno: %i)\n",
1511 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1512 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(1));
1513 struct kvm_msr_entry &entry(kvm_msrs->entries[0]);
1515 kvm_msrs->nmsrs = 1;
1516 entry.index =
index;
1526 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1527 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(1));
1528 struct kvm_msr_entry &entry(kvm_msrs->entries[0]);
1530 kvm_msrs->nmsrs = 1;
1531 entry.index =
index;
1539 const Kvm::MSRIndexVector &
1543 const Kvm::MSRIndexVector &kvm_msrs(
vm.
kvm->getSupportedMSRs());
1545 DPRINTF(
Kvm,
"kvm-x86: Updating MSR intersection\n");
1546 for (
auto it = kvm_msrs.cbegin(); it != kvm_msrs.cend(); ++it) {
1549 DPRINTF(
Kvm,
"kvm-x86: Adding MSR 0x%x\n", *it);
1551 warn(
"kvm-x86: MSR (0x%x) unsupported by gem5. Skipping.\n",
1563 #ifdef KVM_GET_DEBUGREGS
1564 if (
ioctl(KVM_GET_DEBUGREGS, ®s) == -1)
1565 panic(
"KVM: Failed to get guest debug registers\n");
1567 panic(
"KVM: Unsupported getDebugRegisters call.\n");
1574 #ifdef KVM_SET_DEBUGREGS
1575 if (
ioctl(KVM_SET_DEBUGREGS, (
void *)®s) == -1)
1576 panic(
"KVM: Failed to set guest debug registers\n");
1578 panic(
"KVM: Unsupported setDebugRegisters call.\n");
1585 if (
ioctl(KVM_GET_XCRS, ®s) == -1)
1586 panic(
"KVM: Failed to get guest debug registers\n");
1592 if (
ioctl(KVM_SET_XCRS, (
void *)®s) == -1)
1593 panic(
"KVM: Failed to set guest debug registers\n");
1599 if (
ioctl(KVM_GET_XSAVE, &xsave) == -1)
1600 panic(
"KVM: Failed to get guest debug registers\n");
1606 if (
ioctl(KVM_SET_XSAVE, (
void *)&xsave) == -1)
1607 panic(
"KVM: Failed to set guest debug registers\n");
1614 if (
ioctl(KVM_GET_VCPU_EVENTS, &events) == -1)
1615 panic(
"KVM: Failed to get guest debug registers\n");
1621 if (
ioctl(KVM_SET_VCPU_EVENTS, (
void *)&events) == -1)
1622 panic(
"KVM: Failed to set guest debug registers\n");
1626 X86KvmCPUParams::create()
bool capDebugRegs() const
Support for getting and setting the kvm_debugregs structure.
#define SEG_CS_TYPE_ACCESSED
static void updateThreadContextFPUCommon(ThreadContext *tc, const T &fpu)
void handleIOMiscReg32(int miscreg)
Handle a 32-bit IO access that should be mapped to a MiscReg.
uint64_t getRFlags(ThreadContext *tc)
Reconstruct the rflags register from the internal gem5 register state.
void setXCRs(const struct kvm_xcrs ®s)
void setMSRs(const struct kvm_msrs &msrs)
Methods to access MSRs in the guest.
#define SEG_SYS_TYPE_TSS_AVAILABLE
virtual Addr instAddr()=0
void setDebugRegisters(const struct kvm_debugregs ®s)
static void forceSegAccessed(struct kvm_segment &seg)
const std::string & name()
void deliverInterrupts()
Inject pending interrupts from gem5 into the virtual CPU.
bool haveXSave
Kvm::capXSave() available?
Tick submitIO(PacketPtr pkt)
Interface to send Atomic or Timing IO request.
bool threadContextDirty
Is the gem5 context dirty? Set to true to force an update of the KVM vCPU state upon the next call to...
FloatRegBits fpr[NumFloatRegs]
virtual Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
static void setKvmDTableReg(ThreadContext *tc, struct kvm_dtable &kvm_dtable, const int index)
void updateKvmStateFPUXSave()
Update FPU and SIMD registers using the XSave API.
#define SEG_SYS_TYPE_TSS_BUSY
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
Tick handleKvmExitIRQWindowOpen() override
The guest exited because an interrupt window was requested.
ThreadContext * tc
ThreadContext object, provides an interface for external objects to modify this thread's state...
void kvmNonMaskableInterrupt()
Send a non-maskable interrupt to the guest.
void updateKvmStateRegs()
Support routines to update the state of the KVM CPU from gem5's state representation.
void setVCpuEvents(const struct kvm_vcpu_events &events)
void updateThreadContextFPU(const struct kvm_fpu &fpu)
Update FPU and SIMD registers using the legacy API.
#define SEG_CS_TYPE_READ_ACCESSED
virtual void setMiscReg(int misc_reg, const MiscReg &val)=0
uint64_t getMSR(uint32_t index) const
void setContext(ContextID context_id)
Set up Context numbers.
void dumpDebugRegs() const
void setCPUID(const struct kvm_cpuid2 &cpuid)
Methods to access CPUID information using the extended API.
void updateThreadContextSRegs(const struct kvm_sregs &sregs)
Update control registers (CRx, segments, etc.)
#define SEG_TYPE_BIT_ACCESSED
void storeFloat80(void *_mem, double value)
Convert and store a double as an 80-bit float.
virtual FloatRegBits readFloatRegBits(int reg_idx)=0
virtual TheISA::PCState pcState()=0
Base class for KVM based CPU models.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
bool capXCRs() const
Support for getting and setting the x86 XCRs.
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
static void checkSeg(const char *name, const int idx, const struct kvm_segment &seg, struct kvm_sregs sregs)
static bool isCanonicalAddress(uint64_t addr)
virtual void setFloatRegBits(int reg_idx, FloatRegBits val)=0
void suspend()
Set the status to Suspended.
static void dumpKvm(const struct kvm_regs ®s)
void getMSRs(struct kvm_msrs &msrs) const
void updateKvmState() override
Update the KVM state from the current thread context.
void getVCpuEvents(struct kvm_vcpu_events &events) const
void setSpecialRegisters(const struct kvm_sregs ®s)
#define FOREACH_SEGMENT()
Temporarily migrate execution to a different event queue.
struct FXSave::@32::@35 ctrl64
static MiscRegIndex MISCREG_SEG_ATTR(int index)
static MiscRegIndex MISCREG_SEG_LIMIT(int index)
void dump() const override
Dump the internal state to the terminal.
static FloatRegIndex FLOATREG_FPR(int index)
bool archIsDrained() const override
Check if there are pending events in the vCPU that prevents it from being drained.
static FloatRegIndex FLOATREG_XMM_HIGH(int index)
uint64_t Tick
Tick count type.
The request is to an uncacheable address.
void updateCPUID()
Transfer gem5's CPUID values into the virtual CPU.
bool capSetTSSAddress() const
Support for KvmVM::setTSSAddress()
static STRUCT * newVarStruct(size_t entries)
const Kvm::MSRIndexVector & getMsrIntersection() const
Get a list of MSRs supported by both gem5 and KVM.
uint16_t convX87XTagsToTags(uint8_t ftwx)
Convert an x87 xtag word to normal tags format.
void setRFlags(ThreadContext *tc, uint64_t val)
Set update the rflags register and internal gem5 state.
void dumpVCpuEvents() const
uint8_t * getGuestData(uint64_t offset) const
Retrieve a pointer to guest data stored at the end of the kvm_run structure.
void updateKvmStateFPU()
Update FPU and SIMD registers.
void updateThreadContextMSRs()
Update MSR registers.
static MiscRegIndex MISCREG_SEG_SEL(int index)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void updateThreadContextRegs(const struct kvm_regs ®s, const struct kvm_sregs &sregs)
Support routines to update the state of gem5's thread context from KVM's state representation.
void setMSR(uint32_t index, uint64_t value)
static void updateKvmStateFPUCommon(ThreadContext *tc, T &fpu)
void updateKvmStateSRegs()
Update control registers (CRx, segments, etc.)
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
EventQueue * eventQueue() const
Tick handleKvmExitIO() override
Handle x86 legacy IO (in/out)
Status _status
CPU run state.
bool doCpuid(ThreadContext *tc, uint32_t function, uint32_t index, CpuidResult &result)
bool useXSave
Should the XSave interface be used to sync the FPU and SIMD registers?
static void dumpFpuCommon(const T &fpu)
void kvmInterrupt(const struct kvm_interrupt &interrupt)
Send a normal interrupt to the guest.
static Addr x86IOAddress(const uint32_t port)
void setFPUState(const struct kvm_fpu &state)
void getXSave(struct kvm_xsave &xsave) const
struct FXSave M5_ATTR_PACKED
virtual MiscReg readMiscReg(int misc_reg)=0
const MsrMap msrMap
Map between MSR addresses and their corresponding misc registers.
static FloatRegIndex FLOATREG_XMM_LOW(int index)
bool capUserNMI() const
Support for BaseKvmCPU::kvmNonMaskableInterrupt().
void getDebugRegisters(struct kvm_debugregs ®s) const
Wrappers around KVM's state transfer methods.
void setXSave(const struct kvm_xsave &xsave)
bool capVCPUEvents() const
Support for getting and setting the kvm_vcpu_events structure.
static struct kvm_cpuid_entry2 makeKvmCpuid(uint32_t function, uint32_t index, CpuidResult &result)
virtual FloatReg readFloatReg(int reg_idx)=0
bool capXSave() const
Support for getting and setting the kvm_xsave structure.
static MiscRegIndex MISCREG_SEG_BASE(int index)
KVMCpuPort dataPort
Port for data requests.
uint64_t getHostCycles() const override
Get the value of the hardware cycle counter in the guest.
GenericISA::SimplePCState< MachInst > PCState
void setRegisters(const struct kvm_regs ®s)
uint8_t convX87TagsToXTags(uint16_t ftw)
Convert an x87 tag word to abridged tag format.
static Addr x86PciConfigAddress(const uint32_t addr)
void getXCRs(struct kvm_xcrs ®s) const
Tick kvmRunDrain() override
Run the virtual CPU until draining completes.
virtual int contextId() const =0
static void setKvmSegmentReg(ThreadContext *tc, struct kvm_segment &kvm_seg, const int index)
#define IO_PCI_CONF_DATA_BASE
virtual void setFloatReg(int reg_idx, FloatReg val)=0
void updateThreadContext() override
Update the current thread context with the KVM state.
Tick kvmRunWrapper(Tick ticks)
Wrapper that synchronizes state in kvm_run.
void setContextSegment(ThreadContext *tc, const struct kvm_segment &kvm_seg, const int index)
Kvm * kvm
Global KVM interface.
Context not scheduled in KVM.
void updateKvmStateMSRs()
Update MSR registers.
SimpleThread * thread
A cached copy of a thread's state in the form of a SimpleThread object.
double loadFloat80(const void *_mem)
Load an 80-bit float from memory and convert it to double.
void getFPUState(struct kvm_fpu &state) const
Get/Set the guest FPU/vector state.
void getRegisters(struct kvm_regs ®s) const
Get/Set the register state of the guest vCPU.
Tick kvmRun(Tick ticks) override
Request KVM to run the guest for a given number of ticks.
virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val)=0
void updateKvmStateFPULegacy()
Update FPU and SIMD registers using the legacy API.
virtual uint8_t getVector() const
Get the vector of an interrupt.
void updateThreadContextXSave(const struct kvm_xsave &kxsave)
Update FPU and SIMD registers using the XSave API.
bool haveXCRs
Kvm::capXCRs() available?
X86KvmCPU(X86KvmCPUParams *params)
std::shared_ptr< FaultBase > Fault
static void dumpFpuSpec(const struct FXSave &xs)
void dumpSpecRegs() const
bool haveDebugRegs
Kvm::capDebugRegs() available?
x86 implementation of a KVM-based hardware virtualized CPU.
Kvm::MSRIndexVector cachedMsrIntersection
Cached intersection of supported MSRs.
void syncThreadContext()
Update a thread context if the KVM state is dirty with respect to the cached thread context...
bool capExtendedCPUID() const
Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID().
ProbePointArg< PacketInfo > Packet
Packet probe point.
void getSpecialRegisters(struct kvm_sregs ®s) const
int ioctl(int request, long p1) const
vCPU ioctl interface.
struct kvm_run * getKvmRunState()
Get a pointer to the kvm_run structure containing all the input and output parameters from kvmRun()...