Go to the documentation of this file.
31 #include <linux/kvm.h>
45 #include "debug/Drain.hh"
46 #include "debug/Kvm.hh"
47 #include "debug/KvmContext.hh"
48 #include "debug/KvmIO.hh"
49 #include "debug/KvmInt.hh"
54 using namespace X86ISA;
58 #define IO_PCI_CONF_ADDR 0xCF8
59 #define IO_PCI_CONF_DATA_BASE 0xCFC
62 #define SEG_SYS_TYPE_TSS_AVAILABLE 9
64 #define SEG_SYS_TYPE_TSS_BUSY 11
67 #define SEG_CS_TYPE_ACCESSED 9
69 #define SEG_CS_TYPE_READ_ACCESSED 11
73 #define SEG_TYPE_BIT_ACCESSED 1
109 static_assert(
sizeof(
FXSave) == 512,
"Unexpected size of FXSave");
111 #define FOREACH_IREG() \
113 APPLY_IREG(rax, INTREG_RAX); \
114 APPLY_IREG(rbx, INTREG_RBX); \
115 APPLY_IREG(rcx, INTREG_RCX); \
116 APPLY_IREG(rdx, INTREG_RDX); \
117 APPLY_IREG(rsi, INTREG_RSI); \
118 APPLY_IREG(rdi, INTREG_RDI); \
119 APPLY_IREG(rsp, INTREG_RSP); \
120 APPLY_IREG(rbp, INTREG_RBP); \
121 APPLY_IREG(r8, INTREG_R8); \
122 APPLY_IREG(r9, INTREG_R9); \
123 APPLY_IREG(r10, INTREG_R10); \
124 APPLY_IREG(r11, INTREG_R11); \
125 APPLY_IREG(r12, INTREG_R12); \
126 APPLY_IREG(r13, INTREG_R13); \
127 APPLY_IREG(r14, INTREG_R14); \
128 APPLY_IREG(r15, INTREG_R15); \
131 #define FOREACH_SREG() \
133 APPLY_SREG(cr0, MISCREG_CR0); \
134 APPLY_SREG(cr2, MISCREG_CR2); \
135 APPLY_SREG(cr3, MISCREG_CR3); \
136 APPLY_SREG(cr4, MISCREG_CR4); \
137 APPLY_SREG(cr8, MISCREG_CR8); \
138 APPLY_SREG(efer, MISCREG_EFER); \
139 APPLY_SREG(apic_base, MISCREG_APIC_BASE); \
142 #define FOREACH_DREG() \
144 APPLY_DREG(db[0], MISCREG_DR0); \
145 APPLY_DREG(db[1], MISCREG_DR1); \
146 APPLY_DREG(db[2], MISCREG_DR2); \
147 APPLY_DREG(db[3], MISCREG_DR3); \
148 APPLY_DREG(dr6, MISCREG_DR6); \
149 APPLY_DREG(dr7, MISCREG_DR7); \
152 #define FOREACH_SEGMENT() \
154 APPLY_SEGMENT(cs, MISCREG_CS - MISCREG_SEG_SEL_BASE); \
155 APPLY_SEGMENT(ds, MISCREG_DS - MISCREG_SEG_SEL_BASE); \
156 APPLY_SEGMENT(es, MISCREG_ES - MISCREG_SEG_SEL_BASE); \
157 APPLY_SEGMENT(fs, MISCREG_FS - MISCREG_SEG_SEL_BASE); \
158 APPLY_SEGMENT(gs, MISCREG_GS - MISCREG_SEG_SEL_BASE); \
159 APPLY_SEGMENT(ss, MISCREG_SS - MISCREG_SEG_SEL_BASE); \
160 APPLY_SEGMENT(tr, MISCREG_TR - MISCREG_SEG_SEL_BASE); \
161 APPLY_SEGMENT(ldt, MISCREG_TSL - MISCREG_SEG_SEL_BASE); \
164 #define FOREACH_DTABLE() \
166 APPLY_DTABLE(gdt, MISCREG_TSG - MISCREG_SEG_SEL_BASE); \
167 APPLY_DTABLE(idt, MISCREG_IDTR - MISCREG_SEG_SEL_BASE); \
170 template<
typename STRUCT,
typename ENTRY>
173 return (STRUCT *)
operator new(
sizeof(STRUCT) + entries *
sizeof(ENTRY));
179 inform(
"KVM register state:\n");
181 #define APPLY_IREG(kreg, mreg) \
182 inform("\t" # kreg ": 0x%llx\n", regs.kreg)
188 inform(
"\trip: 0x%llx\n", regs.rip);
189 inform(
"\trflags: 0x%llx\n", regs.rflags);
195 inform(
"\t%s: @0x%llx+%x [sel: 0x%x, type: 0x%x]\n"
196 "\t\tpres.: %u, dpl: %u, db: %u, s: %u, l: %u, g: %u, avl: %u, unus.: %u\n",
203 dumpKvm(
const char *reg_name,
const struct kvm_dtable &dtable)
205 inform(
"\t%s: @0x%llx+%x\n",
206 reg_name, dtable.base, dtable.limit);
212 #define APPLY_SREG(kreg, mreg) \
213 inform("\t" # kreg ": 0x%llx\n", sregs.kreg);
214 #define APPLY_SEGMENT(kreg, idx) \
215 dumpKvm(# kreg, sregs.kreg);
216 #define APPLY_DTABLE(kreg, idx) \
217 dumpKvm(# kreg, sregs.kreg);
219 inform(
"Special registers:\n");
224 inform(
"Interrupt Bitmap:");
225 for (
int i = 0;
i < KVM_NR_INTERRUPTS;
i += 64)
226 inform(
" 0x%.8x", sregs.interrupt_bitmap[
i / 64]);
233 #ifdef KVM_GET_DEBUGREGS
235 dumpKvm(
const struct kvm_debugregs ®s)
237 inform(
"KVM debug state:\n");
239 #define APPLY_DREG(kreg, mreg) \
240 inform("\t" # kreg ": 0x%llx\n", regs.kreg)
246 inform(
"\tflags: 0x%llx\n", regs.flags);
253 inform(
"\tlast_ip: 0x%x\n",
xs.ctrl64.fpu_ip);
254 inform(
"\tlast_dp: 0x%x\n",
xs.ctrl64.fpu_dp);
255 inform(
"\tmxcsr_mask: 0x%x\n",
xs.mxcsr_mask);
261 inform(
"\tlast_ip: 0x%x\n", fpu.last_ip);
262 inform(
"\tlast_dp: 0x%x\n", fpu.last_dp);
269 const unsigned top((fpu.fsw >> 11) & 0x7);
270 inform(
"\tfcw: 0x%x\n", fpu.fcw);
272 inform(
"\tfsw: 0x%x (top: %i, "
273 "conditions: %s%s%s%s, exceptions: %s%s%s%s%s%s %s%s%s)\n",
276 (fpu.fsw &
CC0Bit) ?
"C0" :
"",
277 (fpu.fsw &
CC1Bit) ?
"C1" :
"",
278 (fpu.fsw &
CC2Bit) ?
"C2" :
"",
279 (fpu.fsw &
CC3Bit) ?
"C3" :
"",
281 (fpu.fsw &
IEBit) ?
"I" :
"",
282 (fpu.fsw &
DEBit) ?
"D" :
"",
283 (fpu.fsw &
ZEBit) ?
"Z" :
"",
284 (fpu.fsw &
OEBit) ?
"O" :
"",
285 (fpu.fsw &
UEBit) ?
"U" :
"",
286 (fpu.fsw &
PEBit) ?
"P" :
"",
290 (fpu.fsw &
BusyBit) ?
"BUSY " :
""
292 inform(
"\tftwx: 0x%x\n", fpu.ftwx);
293 inform(
"\tlast_opcode: 0x%x\n", fpu.last_opcode);
295 inform(
"\tmxcsr: 0x%x\n", fpu.mxcsr);
297 for (
int i = 0;
i < 8; ++
i) {
298 const unsigned reg_idx((
i +
top) & 0x7);
299 const bool empty(!((fpu.ftwx >> reg_idx) & 0x1));
302 for (
int j = 0;
j < 10; ++
j)
303 snprintf(&hex[
j*2], 3,
"%.2x", fpu.fpr[
i][
j]);
304 inform(
"\t\tST%i/%i: 0x%s (%f)%s\n",
i, reg_idx,
305 hex, value, empty ?
" (e)" :
"");
307 inform(
"\tXMM registers:\n");
308 for (
int i = 0;
i < 16; ++
i) {
310 for (
int j = 0;
j < 16; ++
j)
311 snprintf(&hex[
j*2], 3,
"%.2x", fpu.xmm[
i][
j]);
312 inform(
"\t\t%i: 0x%s\n",
i, hex);
319 inform(
"FPU registers:\n");
326 inform(
"FPU registers (XSave):\n");
335 for (
int i = 0;
i < msrs.nmsrs; ++
i) {
336 const struct kvm_msr_entry &
e(msrs.entries[
i]);
338 inform(
"\t0x%x: 0x%x\n",
e.index,
e.data);
345 inform(
"KVM XCR registers:\n");
347 inform(
"\tFlags: 0x%x\n", regs.flags);
348 for (
int i = 0;
i < regs.nr_xcrs; ++
i) {
349 inform(
"\tXCR[0x%x]: 0x%x\n",
360 inform(
"\tException: [inj: %i, nr: %i, has_ec: %i, ec: %i]\n",
361 events.exception.injected, events.exception.nr,
362 events.exception.has_error_code, events.exception.error_code);
364 inform(
"\tInterrupt: [inj: %i, nr: %i, soft: %i]\n",
365 events.interrupt.injected, events.interrupt.nr,
366 events.interrupt.soft);
368 inform(
"\tNMI: [inj: %i, pending: %i, masked: %i]\n",
369 events.nmi.injected, events.nmi.pending,
372 inform(
"\tSIPI vector: 0x%x\n", events.sipi_vector);
373 inform(
"\tFlags: 0x%x\n", events.flags);
383 uint64_t upper_half(
addr & 0xffff800000000000ULL);
384 return upper_half == 0 || upper_half == 0xffff800000000000;
389 struct kvm_sregs sregs)
408 if (
seg.base & 0xffffffff00000000ULL)
419 warn(
"CS type is 3 but dpl != 0.\n");
423 if (
seg.dpl != sregs.ss.dpl)
424 warn(
"CS type is %i but CS DPL != SS DPL\n",
seg.type);
428 if (
seg.dpl > sregs.ss.dpl)
429 warn(
"CS type is %i but CS DPL > SS DPL\n",
seg.type);
432 warn(
"Illegal CS type: %i\n",
seg.type);
442 if (sregs.cs.type == 3 &&
seg.dpl != 0)
443 warn(
"CS type is 3, but SS DPL is != 0.\n");
446 if (!(sregs.cr0 & 1) &&
seg.dpl != 0)
447 warn(
"SS DPL is %i, but CR0 PE is 0\n",
seg.dpl);
450 warn(
"Illegal SS type: %i\n",
seg.type);
461 if (!(
seg.type & 0x1) ||
462 ((
seg.type & 0x8) && !(
seg.type & 0x2)))
463 warn(
"%s has an illegal type field: %i\n",
name,
seg.type);
468 if (
seg.type != 3 &&
seg.type != 11)
469 warn(
"%s: Illegal segment type (%i)\n",
name,
seg.type);
476 warn(
"%s: Illegal segment type (%i)\n",
name,
seg.type);
519 if (((
seg.limit & 0xFFF) == 0 &&
seg.g) ||
520 ((
seg.limit & 0xFFF00000) != 0 && !
seg.g)) {
521 warn(
"%s limit (0x%x) and g (%i) combination is illegal.\n",
532 useXSave(params.useXSave)
537 panic(
"KVM: Missing capability (KVM_CAP_SET_TSS_ADDR)\n");
539 panic(
"KVM: Missing capability (KVM_CAP_EXT_CPUID)\n");
541 warn(
"KVM: Missing capability (KVM_CAP_USER_NMI)\n");
543 warn(
"KVM: Missing capability (KVM_CAP_VCPU_EVENTS)\n");
550 warn(
"KVM: XSAVE not supported by host. MXCSR synchronization might be "
551 "unreliable due to kernel bugs.\n");
554 warn(
"KVM: XSave FPU/SIMD synchronization disabled by user.\n");
602 struct kvm_regs regs;
610 struct kvm_sregs sregs;
619 #ifdef KVM_GET_DEBUGREGS
620 struct kvm_debugregs dregs;
625 inform(
"Debug registers not supported by kernel.\n");
633 struct kvm_xcrs xcrs;
637 inform(
"XCRs not supported by kernel.\n");
645 struct kvm_xsave xsave;
649 inform(
"XSave not supported by kernel.\n");
656 struct kvm_vcpu_events events;
664 const Kvm::MSRIndexVector &supported_msrs(
vm.
kvm->getSupportedMSRs());
665 std::unique_ptr<struct kvm_msrs> msrs(
666 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(
667 supported_msrs.size()));
669 msrs->nmsrs = supported_msrs.size();
670 for (
int i = 0;
i < supported_msrs.size(); ++
i) {
671 struct kvm_msr_entry &
e(msrs->entries[
i]);
672 e.index = supported_msrs[
i];
689 DPRINTF(KvmContext,
"X86KvmCPU::updateKvmState():\n");
690 if (debug::KvmContext)
697 struct kvm_regs regs;
699 #define APPLY_IREG(kreg, mreg) regs.kreg = tc->readIntReg(mreg)
725 kvm_seg.type =
attr.type;
726 kvm_seg.present =
attr.present;
727 kvm_seg.dpl =
attr.dpl;
728 kvm_seg.db =
attr.defaultSize;
729 kvm_seg.s =
attr.system;
730 kvm_seg.l =
attr.longMode;
731 kvm_seg.g =
attr.granularity;
732 kvm_seg.avl =
attr.avl;
738 kvm_seg.unusable = 0;
764 struct kvm_sregs sregs;
766 #define APPLY_SREG(kreg, mreg) sregs.kreg = tc->readMiscRegNoEffect(mreg)
767 #define APPLY_SEGMENT(kreg, idx) setKvmSegmentReg(tc, sregs.kreg, idx)
768 #define APPLY_DTABLE(kreg, idx) setKvmDTableReg(tc, sregs.kreg, idx)
779 memset(&sregs.interrupt_bitmap, 0,
sizeof(sregs.interrupt_bitmap));
793 hack(
"tr.type (%i) is not busy. Forcing the busy bit.\n",
804 sregs.cs.dpl != sregs.ss.dpl) {
806 hack(
"CS.DPL (%i) != SS.DPL (%i): Forcing SS.DPL to %i\n",
807 sregs.cs.dpl, sregs.ss.dpl, sregs.cs.dpl);
808 sregs.ss.dpl = sregs.cs.dpl;
814 if (!rflags_nocc.vm) {
819 #define APPLY_SEGMENT(kreg, idx) \
820 checkSeg(# kreg, idx + MISCREG_SEG_SEL_BASE, sregs.kreg, sregs)
829 template <
typename T>
844 const unsigned top((fpu.fsw >> 11) & 0x7);
845 for (
int i = 0;
i < 8; ++
i) {
846 const unsigned reg_idx((
i +
top) & 0x7);
849 DPRINTF(KvmContext,
"Setting KVM FP reg %i (st[%i]) := %f\n",
856 for (
int i = 0;
i < 16; ++
i) {
857 *(uint64_t *)&fpu.xmm[
i][0] =
859 *(uint64_t *)&fpu.xmm[
i][8] =
871 memset(&fpu, 0,
sizeof(fpu));
876 warn_once(
"MISCREG_FISEG is non-zero.\n");
881 warn_once(
"MISCREG_FOSEG is non-zero.\n");
891 struct kvm_xsave kxsave;
896 memset(&kxsave, 0,
sizeof(kxsave));
901 warn_once(
"MISCREG_FISEG is non-zero.\n");
906 warn_once(
"MISCREG_FOSEG is non-zero.\n");
929 for (
auto it = indices.cbegin(); it != indices.cend(); ++it) {
930 struct kvm_msr_entry
e;
935 DPRINTF(KvmContext,
"Adding MSR: idx: 0x%x, data: 0x%x\n",
947 struct kvm_regs regs;
948 struct kvm_sregs sregs;
953 DPRINTF(KvmContext,
"X86KvmCPU::updateThreadContext():\n");
954 if (debug::KvmContext)
960 struct kvm_xsave xsave;
980 const struct kvm_sregs &sregs)
982 #define APPLY_IREG(kreg, mreg) tc->setIntReg(mreg, regs.kreg)
1002 attr.type = kvm_seg.type;
1003 attr.present = kvm_seg.present;
1004 attr.dpl = kvm_seg.dpl;
1005 attr.defaultSize = kvm_seg.db;
1006 attr.system = kvm_seg.s;
1007 attr.longMode = kvm_seg.l;
1008 attr.granularity = kvm_seg.g;
1009 attr.avl = kvm_seg.avl;
1010 attr.unusable = kvm_seg.unusable;
1038 #define APPLY_SREG(kreg, mreg) tc->setMiscRegNoEffect(mreg, sregs.kreg)
1039 #define APPLY_SEGMENT(kreg, idx) setContextSegment(tc, sregs.kreg, idx)
1040 #define APPLY_DTABLE(kreg, idx) setContextSegment(tc, sregs.kreg, idx)
1045 #undef APPLY_SEGMENT
1049 template<
typename T>
1053 const unsigned top((fpu.fsw >> 11) & 0x7);
1055 for (
int i = 0;
i < 8; ++
i) {
1056 const unsigned reg_idx((
i +
top) & 0x7);
1058 DPRINTF(KvmContext,
"Setting gem5 FP reg %i (st[%i]) := %f\n",
1077 for (
int i = 0;
i < 16; ++
i) {
1112 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1113 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(msrs.size()));
1114 struct kvm_msr_entry *entry;
1117 kvm_msrs->nmsrs = msrs.size();
1118 entry = &kvm_msrs->entries[0];
1119 for (
auto it = msrs.cbegin(); it != msrs.cend(); ++it, ++entry) {
1121 entry->reserved = 0;
1128 entry = &kvm_msrs->entries[0];
1129 for (
int i = 0;
i < kvm_msrs->nmsrs; ++
i, ++entry) {
1130 DPRINTF(KvmContext,
"Setting M5 MSR: idx: 0x%x, data: 0x%x\n",
1131 entry->index, entry->data);
1157 DPRINTF(KvmInt,
"Delivering NMI\n");
1160 DPRINTF(KvmInt,
"INIT interrupt\n");
1161 fault.get()->invoke(
tc);
1171 DPRINTF(KvmInt,
"STARTUP interrupt\n");
1172 fault.get()->invoke(
tc);
1176 }
else if (x86int) {
1177 struct kvm_interrupt kvm_int;
1180 DPRINTF(KvmInt,
"Delivering interrupt: %s (%u)\n",
1181 fault->name(), kvm_int.irq);
1185 panic(
"KVM: Unknown interrupt type\n");
1197 if (lapic->checkInterruptsRaw()) {
1198 if (lapic->hasPendingUnmaskable()) {
1200 "Delivering unmaskable interrupt.\n");
1203 }
else if (kvm_run.ready_for_interrupt_injection) {
1210 if (lapic->checkInterrupts()) {
1212 "M5 has pending interrupts, delivering interrupt.\n");
1217 "Interrupt delivery delayed due to KVM confusion.\n");
1218 kvm_run.request_interrupt_window = 1;
1220 }
else if (!kvm_run.request_interrupt_window) {
1222 "M5 has pending interrupts, requesting interrupt "
1224 kvm_run.request_interrupt_window = 1;
1227 kvm_run.request_interrupt_window = 0;
1244 DPRINTF(Drain,
"kvmRunDrain: Architecture code isn't drained\n");
1250 kvm_run.request_interrupt_window = 1;
1257 DPRINTF(Drain,
"kvmRunDrain: Delivering pending IO\n");
1273 const uint16_t port(kvm_run.io.port);
1275 assert(kvm_run.exit_reason == KVM_EXIT_IO);
1277 if (kvm_run.io.size != 4) {
1278 panic(
"Unexpected IO size (%u) for address 0x%x.\n",
1279 kvm_run.io.size, port);
1282 if (kvm_run.io.count != 1) {
1283 panic(
"Unexpected IO count (%u) for address 0x%x.\n",
1284 kvm_run.io.count, port);
1288 if (kvm_run.io.direction == KVM_EXIT_IO_OUT)
1298 bool isWrite(kvm_run.io.direction == KVM_EXIT_IO_OUT);
1299 unsigned char *guestData(
getGuestData(kvm_run.io.data_offset));
1301 uint16_t port(kvm_run.io.port);
1303 const int count(kvm_run.io.count);
1305 assert(kvm_run.io.direction == KVM_EXIT_IO_IN ||
1306 kvm_run.io.direction == KVM_EXIT_IO_OUT);
1308 DPRINTF(KvmIO,
"KVM-x86: Handling IO instruction (%s) (port: 0x%x)\n",
1309 (isWrite ?
"out" :
"in"), kvm_run.io.port);
1325 if (pciConfigAddr & 0x80000000) {
1340 RequestPtr io_req = std::make_shared<Request>(
1341 pAddr, kvm_run.io.size,
1351 guestData += kvm_run.io.size;
1369 struct kvm_vcpu_events events;
1380 const bool pending_events(events.exception.injected ||
1381 events.interrupt.injected ||
1382 events.nmi.injected || events.nmi.pending);
1384 if (pending_events) {
1385 DPRINTF(Drain,
"archIsDrained: Pending events: %s %s %s %s\n",
1386 events.exception.injected ?
"exception" :
"",
1387 events.interrupt.injected ?
"interrupt" :
"",
1388 events.nmi.injected ?
"nmi[i]" :
"",
1389 events.nmi.pending ?
"nmi[p]" :
"");
1392 return !pending_events;
1412 static struct kvm_cpuid_entry2
1416 struct kvm_cpuid_entry2
e;
1417 e.function =
function;
1420 e.eax = (uint32_t)result.rax;
1421 e.ebx = (uint32_t)result.rbx;
1422 e.ecx = (uint32_t)result.rcx;
1423 e.edx = (uint32_t)result.rdx;
1431 Kvm::CPUIDVector m5_supported;
1442 for (uint32_t
function = 0;
function <= func0.
rax; ++
function) {
1453 for (uint32_t
function = 0x80000000;
function <= efunc0.
rax; ++
function) {
1467 if (
ioctl(KVM_SET_CPUID2, (
void *)&
cpuid) == -1)
1468 panic(
"KVM: Failed to set guest CPUID2 (errno: %i)\n",
1475 std::unique_ptr<struct kvm_cpuid2> kvm_cpuid(
1476 newVarStruct<struct kvm_cpuid2, struct kvm_cpuid_entry2>(
cpuid.size()));
1478 kvm_cpuid->nent =
cpuid.size();
1479 std::copy(
cpuid.begin(),
cpuid.end(), kvm_cpuid->entries);
1487 if (
ioctl(KVM_SET_MSRS, (
void *)&msrs) == -1)
1488 panic(
"KVM: Failed to set guest MSRs (errno: %i)\n",
1495 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1496 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(msrs.size()));
1498 kvm_msrs->nmsrs = msrs.size();
1499 std::copy(msrs.begin(), msrs.end(), kvm_msrs->entries);
1507 if (
ioctl(KVM_GET_MSRS, (
void *)&msrs) == -1)
1508 panic(
"KVM: Failed to get guest MSRs (errno: %i)\n",
1516 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1517 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(1));
1518 struct kvm_msr_entry &entry(kvm_msrs->entries[0]);
1520 kvm_msrs->nmsrs = 1;
1521 entry.index =
index;
1531 std::unique_ptr<struct kvm_msrs> kvm_msrs(
1532 newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(1));
1533 struct kvm_msr_entry &entry(kvm_msrs->entries[0]);
1535 kvm_msrs->nmsrs = 1;
1536 entry.index =
index;
1544 const Kvm::MSRIndexVector &
1548 const Kvm::MSRIndexVector &kvm_msrs(
vm.
kvm->getSupportedMSRs());
1550 DPRINTF(
Kvm,
"kvm-x86: Updating MSR intersection\n");
1551 for (
auto it = kvm_msrs.cbegin(); it != kvm_msrs.cend(); ++it) {
1554 DPRINTF(
Kvm,
"kvm-x86: Adding MSR 0x%x\n", *it);
1556 warn(
"kvm-x86: MSR (0x%x) unsupported by gem5. Skipping.\n",
1568 #ifdef KVM_GET_DEBUGREGS
1569 if (
ioctl(KVM_GET_DEBUGREGS, ®s) == -1)
1570 panic(
"KVM: Failed to get guest debug registers\n");
1572 panic(
"KVM: Unsupported getDebugRegisters call.\n");
1579 #ifdef KVM_SET_DEBUGREGS
1580 if (
ioctl(KVM_SET_DEBUGREGS, (
void *)®s) == -1)
1581 panic(
"KVM: Failed to set guest debug registers\n");
1583 panic(
"KVM: Unsupported setDebugRegisters call.\n");
1590 if (
ioctl(KVM_GET_XCRS, ®s) == -1)
1591 panic(
"KVM: Failed to get guest debug registers\n");
1597 if (
ioctl(KVM_SET_XCRS, (
void *)®s) == -1)
1598 panic(
"KVM: Failed to set guest debug registers\n");
1604 if (
ioctl(KVM_GET_XSAVE, &xsave) == -1)
1605 panic(
"KVM: Failed to get guest debug registers\n");
1611 if (
ioctl(KVM_SET_XSAVE, (
void *)&xsave) == -1)
1612 panic(
"KVM: Failed to set guest debug registers\n");
1619 if (
ioctl(KVM_GET_VCPU_EVENTS, &events) == -1)
1620 panic(
"KVM: Failed to get guest debug registers\n");
1626 if (
ioctl(KVM_SET_VCPU_EVENTS, (
void *)&events) == -1)
1627 panic(
"KVM: Failed to set guest debug registers\n");
static void dumpKvm(const struct kvm_regs ®s)
void dumpDebugRegs() const
Status _status
CPU run state.
double loadFloat80(const void *_mem)
Load an 80-bit float from memory and convert it to double.
bool capSetTSSAddress() const
Support for KvmVM::setTSSAddress()
void setCPUID(const struct kvm_cpuid2 &cpuid)
Methods to access CPUID information using the extended API.
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.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
bool capUserNMI() const
Support for BaseKvmCPU::kvmNonMaskableInterrupt().
static MiscRegIndex MISCREG_SEG_SEL(int index)
static void updateKvmStateFPUCommon(ThreadContext *tc, T &fpu)
std::vector< BaseInterrupts * > interrupts
struct gem5::FXSave::@24::@27 ctrl64
void dumpSpecRegs() const
void startup() override
startup() is the final initialization call before simulation.
void dumpVCpuEvents() const
const MsrMap msrMap
Map between MSR addresses and their corresponding misc registers.
static void forceSegAccessed(struct kvm_segment &seg)
bool haveXSave
Kvm::capXSave() available?
EventQueue * eventQueue() const
virtual RegVal readFloatReg(RegIndex reg_idx) const =0
int ioctl(int request, long p1) const
vCPU ioctl interface.
void handleIOMiscReg32(int miscreg)
Handle a 32-bit IO access that should be mapped to a MiscReg.
void getDebugRegisters(struct kvm_debugregs ®s) const
Wrappers around KVM's state transfer methods.
EventQueue * deviceEventQueue()
Get a pointer to the event queue owning devices.
void kvmInterrupt(const struct kvm_interrupt &interrupt)
Send a normal interrupt to the guest.
void syncThreadContext()
Update a thread context if the KVM state is dirty with respect to the cached thread context.
void updateKvmStateFPU()
Update FPU and SIMD registers.
void updateKvmStateRegs()
Support routines to update the state of the KVM CPU from gem5's state representation.
static MiscRegIndex MISCREG_SEG_LIMIT(int index)
void setMSRs(const struct kvm_msrs &msrs)
Methods to access MSRs in the guest.
@ UNCACHEABLE
The request is to an uncacheable address.
void setDebugRegisters(const struct kvm_debugregs ®s)
static MiscRegIndex MISCREG_SEG_ATTR(int index)
static double bitsToFloat64(uint64_t val)
static STRUCT * newVarStruct(size_t entries)
void updateThreadContextXSave(const struct kvm_xsave &kxsave)
Update FPU and SIMD registers using the XSave API.
static SimObject * find(const char *name)
Find the SimObject with the given name and return a pointer to it.
static Addr x86PciConfigAddress(const uint32_t addr)
struct kvm_run * getKvmRunState()
Get a pointer to the kvm_run structure containing all the input and output parameters from kvmRun().
void updateCPUID()
Transfer gem5's CPUID values into the virtual CPU.
virtual ContextID contextId() const =0
static FloatRegIndex FLOATREG_XMM_LOW(int index)
uint64_t getRFlags(ThreadContext *tc)
Reconstruct the rflags register from the internal gem5 register state.
bool capExtendedCPUID() const
Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID().
void updateThreadContextFPU(const struct kvm_fpu &fpu)
Update FPU and SIMD registers using the legacy API.
virtual Addr instAddr() const =0
Kvm::MSRIndexVector cachedMsrIntersection
Cached intersection of supported MSRs.
void setFPUState(const struct kvm_fpu &state)
bool capXCRs() const
Support for getting and setting the x86 XCRs.
void storeFloat80(void *_mem, double value)
Convert and store a double as an 80-bit float.
bool capXSave() const
Support for getting and setting the kvm_xsave structure.
void setMSR(uint32_t index, uint64_t value)
void getFPUState(struct kvm_fpu &state) const
Get/Set the guest FPU/vector state.
Tick kvmRunDrain() override
Run the virtual CPU until draining completes.
void ioctlRun() override
Override for synchronizing state in kvm_run.
void kvmNonMaskableInterrupt()
Send a non-maskable interrupt to the guest.
bool archIsDrained() const override
Check if there are pending events in the vCPU that prevents it from being drained.
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
const Kvm::MSRIndexVector & getMsrIntersection() const
Get a list of MSRs supported by both gem5 and KVM.
SimpleThread * thread
A cached copy of a thread's state in the form of a SimpleThread object.
bool haveDebugRegs
Kvm::capDebugRegs() available?
void startup() override
startup() is the final initialization call before simulation.
virtual void ioctlRun()
Execute the KVM_RUN ioctl.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
bool capVCPUEvents() const
Support for getting and setting the kvm_vcpu_events structure.
uint64_t getMSR(uint32_t index) const
std::shared_ptr< FaultBase > Fault
void updateKvmStateSRegs()
Update control registers (CRx, segments, etc.)
#define SEG_TYPE_BIT_ACCESSED
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Base class for KVM based CPU models.
ThreadContext * tc
ThreadContext object, provides an interface for external objects to modify this thread's state.
GenericISA::DelaySlotPCState< 4 > PCState
ProbePointArg< PacketInfo > Packet
Packet probe point.
uint64_t Tick
Tick count type.
std::shared_ptr< Request > RequestPtr
static void setKvmSegmentReg(ThreadContext *tc, struct kvm_segment &kvm_seg, const int index)
virtual uint8_t getVector() const
Get the vector of an interrupt.
#define SEG_SYS_TYPE_TSS_BUSY
static void dumpFpuCommon(const T &fpu)
static FloatRegIndex FLOATREG_XMM_HIGH(int index)
void getSpecialRegisters(struct kvm_sregs ®s) const
@ MISCREG_PCI_CONFIG_ADDRESS
virtual void setFloatReg(RegIndex reg_idx, RegVal val)=0
static MiscRegIndex MISCREG_SEG_BASE(int index)
void updateKvmStateMSRs()
Update MSR registers.
void setXCRs(const struct kvm_xcrs ®s)
static struct kvm_cpuid_entry2 makeKvmCpuid(uint32_t function, uint32_t index, CpuidResult &result)
void setContextSegment(ThreadContext *tc, const struct kvm_segment &kvm_seg, const int index)
virtual TheISA::PCState pcState() const =0
static void updateThreadContextFPUCommon(ThreadContext *tc, const T &fpu)
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
void getMSRs(struct kvm_msrs &msrs) const
#define IO_PCI_CONF_DATA_BASE
uint16_t convX87XTagsToTags(uint8_t ftwx)
Convert an x87 xtag word to normal tags format.
#define SEG_CS_TYPE_ACCESSED
uint64_t getHostCycles() const override
Get the value of the hardware cycle counter in the guest.
#define SEG_CS_TYPE_READ_ACCESSED
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Tick handleKvmExitIO() override
Handle x86 legacy IO (in/out)
static void checkSeg(const char *name, const int idx, const struct kvm_segment &seg, struct kvm_sregs sregs)
void updateThreadContextMSRs()
Update MSR registers.
@ Idle
Context not scheduled in KVM.
const std::string & name()
void setRFlags(ThreadContext *tc, uint64_t val)
Set update the rflags register and internal gem5 state.
void setRegisters(const struct kvm_regs ®s)
Kvm * kvm
Global KVM interface.
bool doCpuid(ThreadContext *tc, uint32_t function, uint32_t index, CpuidResult &result)
uint8_t convX87TagsToXTags(uint16_t ftw)
Convert an x87 tag word to abridged tag format.
void updateKvmState() override
Update the KVM state from the current thread context.
static FloatRegIndex FLOATREG_FPR(int index)
void getVCpuEvents(struct kvm_vcpu_events &events) const
void getXSave(struct kvm_xsave &xsave) const
void deliverInterrupts()
Inject pending interrupts from gem5 into the virtual CPU.
void dump() const override
Dump the internal state to the terminal.
bool haveXCRs
Kvm::capXCRs() available?
void updateKvmStateFPUXSave()
Update FPU and SIMD registers using the XSave API.
#define FOREACH_SEGMENT()
bool capDebugRegs() const
Support for getting and setting the kvm_debugregs structure.
void suspend() override
Set the status to Suspended.
static uint64_t floatToBits64(double val)
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
static void dumpFpuSpec(const struct FXSave &xs)
void updateKvmStateFPULegacy()
Update FPU and SIMD registers using the legacy API.
Tick submitIO(PacketPtr pkt)
Interface to send Atomic or Timing IO request.
X86KvmCPU(const X86KvmCPUParams ¶ms)
Tick kvmRun(Tick ticks) override
Request KVM to run the guest for a given number of ticks.
Tick handleKvmExitIRQWindowOpen() override
The guest exited because an interrupt window was requested.
void setXSave(const struct kvm_xsave &xsave)
virtual Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
bool threadContextDirty
Is the gem5 context dirty? Set to true to force an update of the KVM vCPU state upon the next call to...
void getXCRs(struct kvm_xcrs ®s) const
void getRegisters(struct kvm_regs ®s) const
Get/Set the register state of the guest vCPU.
RequestorID dataRequestorId() const
Reads this CPU's unique data requestor ID.
void updateThreadContextSRegs(const struct kvm_sregs &sregs)
Update control registers (CRx, segments, etc.)
static bool isCanonicalAddress(uint64_t addr)
KVMCpuPort dataPort
Port for data requests.
uint8_t * getGuestData(uint64_t offset) const
Retrieve a pointer to guest data stored at the end of the kvm_run structure.
#define SEG_SYS_TYPE_TSS_AVAILABLE
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
void updateThreadContext() override
Update the current thread context with the KVM state.
static Addr x86IOAddress(const uint32_t port)
void setSpecialRegisters(const struct kvm_sregs ®s)
bool useXSave
Should the XSave interface be used to sync the FPU and SIMD registers?
#define panic(...)
This implements a cprintf based panic() function.
static void setKvmDTableReg(ThreadContext *tc, struct kvm_dtable &kvm_dtable, const int index)
void setVCpuEvents(const struct kvm_vcpu_events &events)
virtual void setMiscRegNoEffect(RegIndex misc_reg, RegVal val)=0
Generated on Tue Sep 21 2021 12:25:00 for gem5 by doxygen 1.8.17