x86_cpu.cc revision 9884
19883Sandreas@sandberg.pp.se/*
29883Sandreas@sandberg.pp.se * Copyright (c) 2013 Andreas Sandberg
39883Sandreas@sandberg.pp.se * All rights reserved
49883Sandreas@sandberg.pp.se *
59883Sandreas@sandberg.pp.se * Redistribution and use in source and binary forms, with or without
69883Sandreas@sandberg.pp.se * modification, are permitted provided that the following conditions are
79883Sandreas@sandberg.pp.se * met: redistributions of source code must retain the above copyright
89883Sandreas@sandberg.pp.se * notice, this list of conditions and the following disclaimer;
99883Sandreas@sandberg.pp.se * redistributions in binary form must reproduce the above copyright
109883Sandreas@sandberg.pp.se * notice, this list of conditions and the following disclaimer in the
119883Sandreas@sandberg.pp.se * documentation and/or other materials provided with the distribution;
129883Sandreas@sandberg.pp.se * neither the name of the copyright holders nor the names of its
139883Sandreas@sandberg.pp.se * contributors may be used to endorse or promote products derived from
149883Sandreas@sandberg.pp.se * this software without specific prior written permission.
159883Sandreas@sandberg.pp.se *
169883Sandreas@sandberg.pp.se * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179883Sandreas@sandberg.pp.se * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189883Sandreas@sandberg.pp.se * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199883Sandreas@sandberg.pp.se * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209883Sandreas@sandberg.pp.se * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219883Sandreas@sandberg.pp.se * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229883Sandreas@sandberg.pp.se * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239883Sandreas@sandberg.pp.se * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249883Sandreas@sandberg.pp.se * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259883Sandreas@sandberg.pp.se * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269883Sandreas@sandberg.pp.se * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279883Sandreas@sandberg.pp.se *
289883Sandreas@sandberg.pp.se * Authors: Andreas Sandberg
299883Sandreas@sandberg.pp.se */
309883Sandreas@sandberg.pp.se
319883Sandreas@sandberg.pp.se#include <linux/kvm.h>
329883Sandreas@sandberg.pp.se
339883Sandreas@sandberg.pp.se#include <algorithm>
349883Sandreas@sandberg.pp.se#include <cerrno>
359883Sandreas@sandberg.pp.se#include <memory>
369883Sandreas@sandberg.pp.se
379883Sandreas@sandberg.pp.se#include "arch/x86/regs/msr.hh"
389883Sandreas@sandberg.pp.se#include "arch/x86/cpuid.hh"
399883Sandreas@sandberg.pp.se#include "arch/x86/utility.hh"
409883Sandreas@sandberg.pp.se#include "arch/registers.hh"
419883Sandreas@sandberg.pp.se#include "cpu/kvm/base.hh"
429883Sandreas@sandberg.pp.se#include "cpu/kvm/x86_cpu.hh"
439883Sandreas@sandberg.pp.se#include "debug/Drain.hh"
449883Sandreas@sandberg.pp.se#include "debug/Kvm.hh"
459883Sandreas@sandberg.pp.se#include "debug/KvmContext.hh"
469883Sandreas@sandberg.pp.se#include "debug/KvmIO.hh"
479883Sandreas@sandberg.pp.se#include "debug/KvmInt.hh"
489883Sandreas@sandberg.pp.se
499883Sandreas@sandberg.pp.seusing namespace X86ISA;
509883Sandreas@sandberg.pp.se
519883Sandreas@sandberg.pp.se#define MSR_TSC 0x10
529883Sandreas@sandberg.pp.se
539883Sandreas@sandberg.pp.se#define IO_PCI_CONF_ADDR 0xCF8
549883Sandreas@sandberg.pp.se#define IO_PCI_CONF_DATA_BASE 0xCFC
559883Sandreas@sandberg.pp.se
569883Sandreas@sandberg.pp.se#define FOREACH_IREG()                          \
579883Sandreas@sandberg.pp.se    do {                                        \
589883Sandreas@sandberg.pp.se        APPLY_IREG(rax, INTREG_RAX);            \
599883Sandreas@sandberg.pp.se        APPLY_IREG(rbx, INTREG_RBX);            \
609883Sandreas@sandberg.pp.se        APPLY_IREG(rcx, INTREG_RCX);            \
619883Sandreas@sandberg.pp.se        APPLY_IREG(rdx, INTREG_RDX);            \
629883Sandreas@sandberg.pp.se        APPLY_IREG(rsi, INTREG_RSI);            \
639883Sandreas@sandberg.pp.se        APPLY_IREG(rdi, INTREG_RDI);            \
649883Sandreas@sandberg.pp.se        APPLY_IREG(rsp, INTREG_RSP);            \
659883Sandreas@sandberg.pp.se        APPLY_IREG(rbp, INTREG_RBP);            \
669883Sandreas@sandberg.pp.se        APPLY_IREG(r8, INTREG_R8);              \
679883Sandreas@sandberg.pp.se        APPLY_IREG(r9, INTREG_R9);              \
689883Sandreas@sandberg.pp.se        APPLY_IREG(r10, INTREG_R10);            \
699883Sandreas@sandberg.pp.se        APPLY_IREG(r11, INTREG_R11);            \
709883Sandreas@sandberg.pp.se        APPLY_IREG(r12, INTREG_R12);            \
719883Sandreas@sandberg.pp.se        APPLY_IREG(r13, INTREG_R13);            \
729883Sandreas@sandberg.pp.se        APPLY_IREG(r14, INTREG_R14);            \
739883Sandreas@sandberg.pp.se        APPLY_IREG(r15, INTREG_R15);            \
749883Sandreas@sandberg.pp.se    } while(0)
759883Sandreas@sandberg.pp.se
769883Sandreas@sandberg.pp.se#define FOREACH_SREG()                                  \
779883Sandreas@sandberg.pp.se    do {                                                \
789883Sandreas@sandberg.pp.se        APPLY_SREG(cr0, MISCREG_CR0);                   \
799883Sandreas@sandberg.pp.se        APPLY_SREG(cr2, MISCREG_CR2);                   \
809883Sandreas@sandberg.pp.se        APPLY_SREG(cr3, MISCREG_CR3);                   \
819883Sandreas@sandberg.pp.se        APPLY_SREG(cr4, MISCREG_CR4);                   \
829883Sandreas@sandberg.pp.se        APPLY_SREG(cr8, MISCREG_CR8);                   \
839883Sandreas@sandberg.pp.se        APPLY_SREG(efer, MISCREG_EFER);                 \
849883Sandreas@sandberg.pp.se        APPLY_SREG(apic_base, MISCREG_APIC_BASE);       \
859883Sandreas@sandberg.pp.se    } while(0)
869883Sandreas@sandberg.pp.se
879883Sandreas@sandberg.pp.se#define FOREACH_DREG()                          \
889883Sandreas@sandberg.pp.se    do {                                        \
899883Sandreas@sandberg.pp.se        APPLY_DREG(db[0], MISCREG_DR0);         \
909883Sandreas@sandberg.pp.se        APPLY_DREG(db[1], MISCREG_DR1);         \
919883Sandreas@sandberg.pp.se        APPLY_DREG(db[2], MISCREG_DR2);         \
929883Sandreas@sandberg.pp.se        APPLY_DREG(db[3], MISCREG_DR3);         \
939883Sandreas@sandberg.pp.se        APPLY_DREG(dr6, MISCREG_DR6);           \
949883Sandreas@sandberg.pp.se        APPLY_DREG(dr7, MISCREG_DR7);           \
959883Sandreas@sandberg.pp.se    } while(0)
969883Sandreas@sandberg.pp.se
979883Sandreas@sandberg.pp.se#define FOREACH_SEGMENT()                                       \
989883Sandreas@sandberg.pp.se    do {                                                        \
999883Sandreas@sandberg.pp.se        APPLY_SEGMENT(cs, MISCREG_CS - MISCREG_SEG_SEL_BASE);   \
1009883Sandreas@sandberg.pp.se        APPLY_SEGMENT(ds, MISCREG_DS - MISCREG_SEG_SEL_BASE);   \
1019883Sandreas@sandberg.pp.se        APPLY_SEGMENT(es, MISCREG_ES - MISCREG_SEG_SEL_BASE);   \
1029883Sandreas@sandberg.pp.se        APPLY_SEGMENT(fs, MISCREG_FS - MISCREG_SEG_SEL_BASE);   \
1039883Sandreas@sandberg.pp.se        APPLY_SEGMENT(gs, MISCREG_GS - MISCREG_SEG_SEL_BASE);   \
1049883Sandreas@sandberg.pp.se        APPLY_SEGMENT(ss, MISCREG_SS - MISCREG_SEG_SEL_BASE);   \
1059883Sandreas@sandberg.pp.se        APPLY_SEGMENT(tr, MISCREG_TR - MISCREG_SEG_SEL_BASE);   \
1069883Sandreas@sandberg.pp.se        APPLY_SEGMENT(ldt, MISCREG_TSL - MISCREG_SEG_SEL_BASE); \
1079883Sandreas@sandberg.pp.se    } while(0)
1089883Sandreas@sandberg.pp.se
1099883Sandreas@sandberg.pp.se#define FOREACH_DTABLE()                                        \
1109883Sandreas@sandberg.pp.se    do {                                                        \
1119883Sandreas@sandberg.pp.se        APPLY_DTABLE(gdt, MISCREG_TSG - MISCREG_SEG_SEL_BASE);  \
1129883Sandreas@sandberg.pp.se        APPLY_DTABLE(idt, MISCREG_IDTR - MISCREG_SEG_SEL_BASE); \
1139883Sandreas@sandberg.pp.se    } while(0)
1149883Sandreas@sandberg.pp.se
1159883Sandreas@sandberg.pp.setemplate<typename STRUCT, typename ENTRY>
1169883Sandreas@sandberg.pp.sestatic STRUCT *newVarStruct(size_t entries)
1179883Sandreas@sandberg.pp.se{
1189883Sandreas@sandberg.pp.se    return (STRUCT *)operator new(sizeof(STRUCT) + entries * sizeof(ENTRY));
1199883Sandreas@sandberg.pp.se}
1209883Sandreas@sandberg.pp.se
1219883Sandreas@sandberg.pp.sestatic void
1229883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_regs &regs)
1239883Sandreas@sandberg.pp.se{
1249883Sandreas@sandberg.pp.se    inform("KVM register state:\n");
1259883Sandreas@sandberg.pp.se
1269883Sandreas@sandberg.pp.se#define APPLY_IREG(kreg, mreg)                  \
1279883Sandreas@sandberg.pp.se    inform("\t" # kreg ": 0x%llx\n", regs.kreg)
1289883Sandreas@sandberg.pp.se
1299883Sandreas@sandberg.pp.se    FOREACH_IREG();
1309883Sandreas@sandberg.pp.se
1319883Sandreas@sandberg.pp.se#undef APPLY_IREG
1329883Sandreas@sandberg.pp.se
1339883Sandreas@sandberg.pp.se    inform("\trip: 0x%llx\n", regs.rip);
1349883Sandreas@sandberg.pp.se    inform("\trflags: 0x%llx\n", regs.rflags);
1359883Sandreas@sandberg.pp.se}
1369883Sandreas@sandberg.pp.se
1379883Sandreas@sandberg.pp.sestatic void
1389883Sandreas@sandberg.pp.sedumpKvm(const char *reg_name, const struct kvm_segment &seg)
1399883Sandreas@sandberg.pp.se{
1409883Sandreas@sandberg.pp.se    inform("\t%s: @0x%llx+%x [sel: 0x%x, type: 0x%x]\n"
1419883Sandreas@sandberg.pp.se           "\t\tpres.: %u, dpl: %u, db: %u, s: %u, l: %u, g: %u, avl: %u, unus.: %u\n",
1429883Sandreas@sandberg.pp.se           reg_name,
1439883Sandreas@sandberg.pp.se           seg.base, seg.limit, seg.selector, seg.type,
1449883Sandreas@sandberg.pp.se           seg.present, seg.dpl, seg.db, seg.s, seg.l, seg.g, seg.avl, seg.unusable);
1459883Sandreas@sandberg.pp.se}
1469883Sandreas@sandberg.pp.se
1479883Sandreas@sandberg.pp.sestatic void
1489883Sandreas@sandberg.pp.sedumpKvm(const char *reg_name, const struct kvm_dtable &dtable)
1499883Sandreas@sandberg.pp.se{
1509883Sandreas@sandberg.pp.se    inform("\t%s: @0x%llx+%x\n",
1519883Sandreas@sandberg.pp.se           reg_name, dtable.base, dtable.limit);
1529883Sandreas@sandberg.pp.se}
1539883Sandreas@sandberg.pp.se
1549883Sandreas@sandberg.pp.sestatic void
1559883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_sregs &sregs)
1569883Sandreas@sandberg.pp.se{
1579883Sandreas@sandberg.pp.se#define APPLY_SREG(kreg, mreg)                          \
1589883Sandreas@sandberg.pp.se    inform("\t" # kreg ": 0x%llx\n", sregs.kreg);
1599883Sandreas@sandberg.pp.se#define APPLY_SEGMENT(kreg, idx)                \
1609883Sandreas@sandberg.pp.se    dumpKvm(# kreg, sregs.kreg);
1619883Sandreas@sandberg.pp.se#define APPLY_DTABLE(kreg, idx)                 \
1629883Sandreas@sandberg.pp.se    dumpKvm(# kreg, sregs.kreg);
1639883Sandreas@sandberg.pp.se
1649883Sandreas@sandberg.pp.se    inform("Special registers:\n");
1659883Sandreas@sandberg.pp.se    FOREACH_SEGMENT();
1669883Sandreas@sandberg.pp.se    FOREACH_SREG();
1679883Sandreas@sandberg.pp.se    FOREACH_DTABLE();
1689883Sandreas@sandberg.pp.se
1699883Sandreas@sandberg.pp.se    inform("Interrupt Bitmap:");
1709883Sandreas@sandberg.pp.se    for (int i = 0; i < KVM_NR_INTERRUPTS; i += 64)
1719883Sandreas@sandberg.pp.se        inform("  0x%.8x", sregs.interrupt_bitmap[i / 64]);
1729883Sandreas@sandberg.pp.se
1739883Sandreas@sandberg.pp.se#undef APPLY_SREG
1749883Sandreas@sandberg.pp.se#undef APPLY_SEGMENT
1759883Sandreas@sandberg.pp.se#undef APPLY_DTABLE
1769883Sandreas@sandberg.pp.se}
1779883Sandreas@sandberg.pp.se
1789883Sandreas@sandberg.pp.se#ifdef KVM_GET_DEBUGREGS
1799883Sandreas@sandberg.pp.sestatic void
1809883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_debugregs &regs)
1819883Sandreas@sandberg.pp.se{
1829883Sandreas@sandberg.pp.se    inform("KVM debug state:\n");
1839883Sandreas@sandberg.pp.se
1849883Sandreas@sandberg.pp.se#define APPLY_DREG(kreg, mreg)                  \
1859883Sandreas@sandberg.pp.se    inform("\t" # kreg ": 0x%llx\n", regs.kreg)
1869883Sandreas@sandberg.pp.se
1879883Sandreas@sandberg.pp.se    FOREACH_DREG();
1889883Sandreas@sandberg.pp.se
1899883Sandreas@sandberg.pp.se#undef APPLY_DREG
1909883Sandreas@sandberg.pp.se
1919883Sandreas@sandberg.pp.se    inform("\tflags: 0x%llx\n", regs.flags);
1929883Sandreas@sandberg.pp.se}
1939883Sandreas@sandberg.pp.se#endif
1949883Sandreas@sandberg.pp.se
1959883Sandreas@sandberg.pp.sestatic void
1969883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_fpu &fpu)
1979883Sandreas@sandberg.pp.se{
1989883Sandreas@sandberg.pp.se    inform("FPU registers:\n");
1999883Sandreas@sandberg.pp.se    inform("\tfcw: 0x%x\n", fpu.fcw);
2009883Sandreas@sandberg.pp.se    inform("\tfsw: 0x%x\n", fpu.fsw);
2019883Sandreas@sandberg.pp.se    inform("\tftwx: 0x%x\n", fpu.ftwx);
2029883Sandreas@sandberg.pp.se    inform("\tlast_opcode: 0x%x\n", fpu.last_opcode);
2039883Sandreas@sandberg.pp.se    inform("\tlast_ip: 0x%x\n", fpu.last_ip);
2049883Sandreas@sandberg.pp.se    inform("\tlast_dp: 0x%x\n", fpu.last_dp);
2059883Sandreas@sandberg.pp.se    inform("\tmxcsr: 0x%x\n", fpu.mxcsr);
2069883Sandreas@sandberg.pp.se    inform("\tFP Stack:\n");
2079883Sandreas@sandberg.pp.se    for (int i = 0; i < 8; ++i) {
2089883Sandreas@sandberg.pp.se        const bool empty(!((fpu.ftwx >> i) & 0x1));
2099883Sandreas@sandberg.pp.se        char hex[33];
2109883Sandreas@sandberg.pp.se        for (int j = 0; j < 16; ++j)
2119883Sandreas@sandberg.pp.se            snprintf(&hex[j*2], 3, "%.2x", fpu.fpr[i][j]);
2129883Sandreas@sandberg.pp.se        inform("\t\t%i: 0x%s%s\n", i, hex, empty ? " (e)" : "");
2139883Sandreas@sandberg.pp.se    }
2149883Sandreas@sandberg.pp.se    inform("\tXMM registers:\n");
2159883Sandreas@sandberg.pp.se    for (int i = 0; i < 16; ++i) {
2169883Sandreas@sandberg.pp.se        char hex[33];
2179883Sandreas@sandberg.pp.se        for (int j = 0; j < 16; ++j)
2189883Sandreas@sandberg.pp.se            snprintf(&hex[j*2], 3, "%.2x", fpu.xmm[i][j]);
2199883Sandreas@sandberg.pp.se        inform("\t\t%i: 0x%s\n", i, hex);
2209883Sandreas@sandberg.pp.se    }
2219883Sandreas@sandberg.pp.se}
2229883Sandreas@sandberg.pp.se
2239883Sandreas@sandberg.pp.sestatic void
2249883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_msrs &msrs)
2259883Sandreas@sandberg.pp.se{
2269883Sandreas@sandberg.pp.se    inform("MSRs:\n");
2279883Sandreas@sandberg.pp.se
2289883Sandreas@sandberg.pp.se    for (int i = 0; i < msrs.nmsrs; ++i) {
2299883Sandreas@sandberg.pp.se        const struct kvm_msr_entry &e(msrs.entries[i]);
2309883Sandreas@sandberg.pp.se
2319883Sandreas@sandberg.pp.se        inform("\t0x%x: 0x%x\n", e.index, e.data);
2329883Sandreas@sandberg.pp.se    }
2339883Sandreas@sandberg.pp.se}
2349883Sandreas@sandberg.pp.se
2359883Sandreas@sandberg.pp.sestatic void
2369883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_xcrs &regs)
2379883Sandreas@sandberg.pp.se{
2389883Sandreas@sandberg.pp.se    inform("KVM XCR registers:\n");
2399883Sandreas@sandberg.pp.se
2409883Sandreas@sandberg.pp.se    inform("\tFlags: 0x%x\n", regs.flags);
2419883Sandreas@sandberg.pp.se    for (int i = 0; i < regs.nr_xcrs; ++i) {
2429883Sandreas@sandberg.pp.se        inform("\tXCR[0x%x]: 0x%x\n",
2439883Sandreas@sandberg.pp.se               regs.xcrs[i].xcr,
2449883Sandreas@sandberg.pp.se               regs.xcrs[i].value);
2459883Sandreas@sandberg.pp.se    }
2469883Sandreas@sandberg.pp.se}
2479883Sandreas@sandberg.pp.se
2489883Sandreas@sandberg.pp.sestatic void
2499883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_xsave &xsave)
2509883Sandreas@sandberg.pp.se{
2519883Sandreas@sandberg.pp.se    inform("KVM XSAVE:\n");
2529883Sandreas@sandberg.pp.se
2539883Sandreas@sandberg.pp.se    Trace::dump((Tick)-1, "xsave.region",
2549883Sandreas@sandberg.pp.se                xsave.region, sizeof(xsave.region));
2559883Sandreas@sandberg.pp.se}
2569883Sandreas@sandberg.pp.se
2579883Sandreas@sandberg.pp.sestatic void
2589883Sandreas@sandberg.pp.sedumpKvm(const struct kvm_vcpu_events &events)
2599883Sandreas@sandberg.pp.se{
2609883Sandreas@sandberg.pp.se    inform("vCPU events:\n");
2619883Sandreas@sandberg.pp.se
2629883Sandreas@sandberg.pp.se    inform("\tException: [inj: %i, nr: %i, has_ec: %i, ec: %i]\n",
2639883Sandreas@sandberg.pp.se           events.exception.injected, events.exception.nr,
2649883Sandreas@sandberg.pp.se           events.exception.has_error_code, events.exception.error_code);
2659883Sandreas@sandberg.pp.se
2669883Sandreas@sandberg.pp.se    inform("\tInterrupt: [inj: %i, nr: %i, soft: %i]\n",
2679883Sandreas@sandberg.pp.se           events.interrupt.injected, events.interrupt.nr,
2689883Sandreas@sandberg.pp.se           events.interrupt.soft);
2699883Sandreas@sandberg.pp.se
2709883Sandreas@sandberg.pp.se    inform("\tNMI: [inj: %i, pending: %i, masked: %i]\n",
2719883Sandreas@sandberg.pp.se           events.nmi.injected, events.nmi.pending,
2729883Sandreas@sandberg.pp.se           events.nmi.masked);
2739883Sandreas@sandberg.pp.se
2749883Sandreas@sandberg.pp.se    inform("\tSIPI vector: 0x%x\n", events.sipi_vector);
2759883Sandreas@sandberg.pp.se    inform("\tFlags: 0x%x\n", events.flags);
2769883Sandreas@sandberg.pp.se}
2779883Sandreas@sandberg.pp.se
2789884Sandreas@sandberg.pp.sestatic bool
2799884Sandreas@sandberg.pp.seisCanonicalAddress(uint64_t addr)
2809884Sandreas@sandberg.pp.se{
2819884Sandreas@sandberg.pp.se    // x86-64 doesn't currently use the full 64-bit virtual address
2829884Sandreas@sandberg.pp.se    // space, instead it uses signed 48 bit addresses that are
2839884Sandreas@sandberg.pp.se    // sign-extended to 64 bits.  Such addresses are known as
2849884Sandreas@sandberg.pp.se    // "canonical".
2859884Sandreas@sandberg.pp.se    uint64_t upper_half(addr & 0xffff800000000000ULL);
2869884Sandreas@sandberg.pp.se    return upper_half == 0 || upper_half == 0xffff800000000000;
2879884Sandreas@sandberg.pp.se}
2889884Sandreas@sandberg.pp.se
2899884Sandreas@sandberg.pp.sestatic void
2909884Sandreas@sandberg.pp.secheckSeg(const char *name, const int idx, const struct kvm_segment &seg,
2919884Sandreas@sandberg.pp.se         struct kvm_sregs sregs)
2929884Sandreas@sandberg.pp.se{
2939884Sandreas@sandberg.pp.se    // Check the register base
2949884Sandreas@sandberg.pp.se    switch (idx) {
2959884Sandreas@sandberg.pp.se      case MISCREG_TSL:
2969884Sandreas@sandberg.pp.se      case MISCREG_TR:
2979884Sandreas@sandberg.pp.se      case MISCREG_FS:
2989884Sandreas@sandberg.pp.se      case MISCREG_GS:
2999884Sandreas@sandberg.pp.se        if (!isCanonicalAddress(seg.base))
3009884Sandreas@sandberg.pp.se            warn("Illegal %s base: 0x%x\n", name, seg.base);
3019884Sandreas@sandberg.pp.se        break;
3029884Sandreas@sandberg.pp.se
3039884Sandreas@sandberg.pp.se      case MISCREG_SS:
3049884Sandreas@sandberg.pp.se      case MISCREG_DS:
3059884Sandreas@sandberg.pp.se      case MISCREG_ES:
3069884Sandreas@sandberg.pp.se        if (seg.unusable)
3079884Sandreas@sandberg.pp.se            break;
3089884Sandreas@sandberg.pp.se      case MISCREG_CS:
3099884Sandreas@sandberg.pp.se        if (seg.base & 0xffffffff00000000ULL)
3109884Sandreas@sandberg.pp.se            warn("Illegal %s base: 0x%x\n", name, seg.base);
3119884Sandreas@sandberg.pp.se        break;
3129884Sandreas@sandberg.pp.se    }
3139884Sandreas@sandberg.pp.se
3149884Sandreas@sandberg.pp.se    // Check the type
3159884Sandreas@sandberg.pp.se    switch (idx) {
3169884Sandreas@sandberg.pp.se      case MISCREG_CS:
3179884Sandreas@sandberg.pp.se        switch (seg.type) {
3189884Sandreas@sandberg.pp.se          case 3:
3199884Sandreas@sandberg.pp.se            if (seg.dpl != 0)
3209884Sandreas@sandberg.pp.se                warn("CS type is 3 but dpl != 0.\n");
3219884Sandreas@sandberg.pp.se            break;
3229884Sandreas@sandberg.pp.se          case 9:
3239884Sandreas@sandberg.pp.se          case 11:
3249884Sandreas@sandberg.pp.se            if (seg.dpl != sregs.ss.dpl)
3259884Sandreas@sandberg.pp.se                warn("CS type is %i but CS DPL != SS DPL\n", seg.type);
3269884Sandreas@sandberg.pp.se            break;
3279884Sandreas@sandberg.pp.se          case 13:
3289884Sandreas@sandberg.pp.se          case 15:
3299884Sandreas@sandberg.pp.se            if (seg.dpl > sregs.ss.dpl)
3309884Sandreas@sandberg.pp.se                warn("CS type is %i but CS DPL > SS DPL\n", seg.type);
3319884Sandreas@sandberg.pp.se            break;
3329884Sandreas@sandberg.pp.se          default:
3339884Sandreas@sandberg.pp.se            warn("Illegal CS type: %i\n", seg.type);
3349884Sandreas@sandberg.pp.se            break;
3359884Sandreas@sandberg.pp.se        }
3369884Sandreas@sandberg.pp.se        break;
3379884Sandreas@sandberg.pp.se
3389884Sandreas@sandberg.pp.se      case MISCREG_SS:
3399884Sandreas@sandberg.pp.se        if (seg.unusable)
3409884Sandreas@sandberg.pp.se            break;
3419884Sandreas@sandberg.pp.se        switch (seg.type) {
3429884Sandreas@sandberg.pp.se          case 3:
3439884Sandreas@sandberg.pp.se            if (sregs.cs.type == 3 && seg.dpl != 0)
3449884Sandreas@sandberg.pp.se                warn("CS type is 3, but SS DPL is != 0.\n");
3459884Sandreas@sandberg.pp.se            /* FALLTHROUGH */
3469884Sandreas@sandberg.pp.se          case 7:
3479884Sandreas@sandberg.pp.se            if (!(sregs.cr0 & 1) && seg.dpl != 0)
3489884Sandreas@sandberg.pp.se                warn("SS DPL is %i, but CR0 PE is 0\n", seg.dpl);
3499884Sandreas@sandberg.pp.se            break;
3509884Sandreas@sandberg.pp.se          default:
3519884Sandreas@sandberg.pp.se            warn("Illegal SS type: %i\n", seg.type);
3529884Sandreas@sandberg.pp.se            break;
3539884Sandreas@sandberg.pp.se        }
3549884Sandreas@sandberg.pp.se        break;
3559884Sandreas@sandberg.pp.se
3569884Sandreas@sandberg.pp.se      case MISCREG_DS:
3579884Sandreas@sandberg.pp.se      case MISCREG_ES:
3589884Sandreas@sandberg.pp.se      case MISCREG_FS:
3599884Sandreas@sandberg.pp.se      case MISCREG_GS:
3609884Sandreas@sandberg.pp.se        if (seg.unusable)
3619884Sandreas@sandberg.pp.se            break;
3629884Sandreas@sandberg.pp.se        if (!(seg.type & 0x1) ||
3639884Sandreas@sandberg.pp.se            ((seg.type & 0x8) && !(seg.type & 0x2)))
3649884Sandreas@sandberg.pp.se            warn("%s has an illegal type field: %i\n", name, seg.type);
3659884Sandreas@sandberg.pp.se        break;
3669884Sandreas@sandberg.pp.se
3679884Sandreas@sandberg.pp.se      case MISCREG_TR:
3689884Sandreas@sandberg.pp.se        // TODO: We should check the CPU mode
3699884Sandreas@sandberg.pp.se        if (seg.type != 3 && seg.type != 11)
3709884Sandreas@sandberg.pp.se            warn("%s: Illegal segment type (%i)\n", name, seg.type);
3719884Sandreas@sandberg.pp.se        break;
3729884Sandreas@sandberg.pp.se
3739884Sandreas@sandberg.pp.se      case MISCREG_TSL:
3749884Sandreas@sandberg.pp.se        if (seg.unusable)
3759884Sandreas@sandberg.pp.se            break;
3769884Sandreas@sandberg.pp.se        if (seg.type != 2)
3779884Sandreas@sandberg.pp.se            warn("%s: Illegal segment type (%i)\n", name, seg.type);
3789884Sandreas@sandberg.pp.se        break;
3799884Sandreas@sandberg.pp.se    }
3809884Sandreas@sandberg.pp.se
3819884Sandreas@sandberg.pp.se    switch (idx) {
3829884Sandreas@sandberg.pp.se      case MISCREG_SS:
3839884Sandreas@sandberg.pp.se      case MISCREG_DS:
3849884Sandreas@sandberg.pp.se      case MISCREG_ES:
3859884Sandreas@sandberg.pp.se      case MISCREG_FS:
3869884Sandreas@sandberg.pp.se      case MISCREG_GS:
3879884Sandreas@sandberg.pp.se        if (seg.unusable)
3889884Sandreas@sandberg.pp.se            break;
3899884Sandreas@sandberg.pp.se      case MISCREG_CS:
3909884Sandreas@sandberg.pp.se        if (!seg.s)
3919884Sandreas@sandberg.pp.se            warn("%s: S flag not set\n", name);
3929884Sandreas@sandberg.pp.se        break;
3939884Sandreas@sandberg.pp.se
3949884Sandreas@sandberg.pp.se      case MISCREG_TSL:
3959884Sandreas@sandberg.pp.se        if (seg.unusable)
3969884Sandreas@sandberg.pp.se            break;
3979884Sandreas@sandberg.pp.se      case MISCREG_TR:
3989884Sandreas@sandberg.pp.se        if (seg.s)
3999884Sandreas@sandberg.pp.se            warn("%s: S flag is set\n", name);
4009884Sandreas@sandberg.pp.se        break;
4019884Sandreas@sandberg.pp.se    }
4029884Sandreas@sandberg.pp.se
4039884Sandreas@sandberg.pp.se    switch (idx) {
4049884Sandreas@sandberg.pp.se      case MISCREG_SS:
4059884Sandreas@sandberg.pp.se      case MISCREG_DS:
4069884Sandreas@sandberg.pp.se      case MISCREG_ES:
4079884Sandreas@sandberg.pp.se      case MISCREG_FS:
4089884Sandreas@sandberg.pp.se      case MISCREG_GS:
4099884Sandreas@sandberg.pp.se      case MISCREG_TSL:
4109884Sandreas@sandberg.pp.se        if (seg.unusable)
4119884Sandreas@sandberg.pp.se            break;
4129884Sandreas@sandberg.pp.se      case MISCREG_TR:
4139884Sandreas@sandberg.pp.se      case MISCREG_CS:
4149884Sandreas@sandberg.pp.se        if (!seg.present)
4159884Sandreas@sandberg.pp.se            warn("%s: P flag not set\n", name);
4169884Sandreas@sandberg.pp.se
4179884Sandreas@sandberg.pp.se        if (((seg.limit & 0xFFF) == 0 && seg.g) ||
4189884Sandreas@sandberg.pp.se            ((seg.limit & 0xFFF00000) != 0 && !seg.g)) {
4199884Sandreas@sandberg.pp.se            warn("%s limit (0x%x) and g (%i) combination is illegal.\n",
4209884Sandreas@sandberg.pp.se                 name, seg.limit, seg.g);
4219884Sandreas@sandberg.pp.se        }
4229884Sandreas@sandberg.pp.se        break;
4239884Sandreas@sandberg.pp.se    }
4249884Sandreas@sandberg.pp.se
4259884Sandreas@sandberg.pp.se    // TODO: Check CS DB
4269884Sandreas@sandberg.pp.se}
4279884Sandreas@sandberg.pp.se
4289883Sandreas@sandberg.pp.seX86KvmCPU::X86KvmCPU(X86KvmCPUParams *params)
4299883Sandreas@sandberg.pp.se    : BaseKvmCPU(params)
4309883Sandreas@sandberg.pp.se{
4319883Sandreas@sandberg.pp.se    Kvm &kvm(vm.kvm);
4329883Sandreas@sandberg.pp.se
4339883Sandreas@sandberg.pp.se    if (!kvm.capSetTSSAddress())
4349883Sandreas@sandberg.pp.se        panic("KVM: Missing capability (KVM_CAP_SET_TSS_ADDR)\n");
4359883Sandreas@sandberg.pp.se    if (!kvm.capExtendedCPUID())
4369883Sandreas@sandberg.pp.se        panic("KVM: Missing capability (KVM_CAP_EXT_CPUID)\n");
4379883Sandreas@sandberg.pp.se    if (!kvm.capUserNMI())
4389883Sandreas@sandberg.pp.se        warn("KVM: Missing capability (KVM_CAP_USER_NMI)\n");
4399883Sandreas@sandberg.pp.se    if (!kvm.capVCPUEvents())
4409883Sandreas@sandberg.pp.se        warn("KVM: Missing capability (KVM_CAP_VCPU_EVENTS)\n");
4419883Sandreas@sandberg.pp.se
4429883Sandreas@sandberg.pp.se    haveDebugRegs = kvm.capDebugRegs();
4439883Sandreas@sandberg.pp.se    haveXSave = kvm.capXSave();
4449883Sandreas@sandberg.pp.se    haveXCRs = kvm.capXCRs();
4459883Sandreas@sandberg.pp.se}
4469883Sandreas@sandberg.pp.se
4479883Sandreas@sandberg.pp.seX86KvmCPU::~X86KvmCPU()
4489883Sandreas@sandberg.pp.se{
4499883Sandreas@sandberg.pp.se}
4509883Sandreas@sandberg.pp.se
4519883Sandreas@sandberg.pp.sevoid
4529883Sandreas@sandberg.pp.seX86KvmCPU::startup()
4539883Sandreas@sandberg.pp.se{
4549883Sandreas@sandberg.pp.se    BaseKvmCPU::startup();
4559883Sandreas@sandberg.pp.se
4569883Sandreas@sandberg.pp.se    updateCPUID();
4579883Sandreas@sandberg.pp.se
4589883Sandreas@sandberg.pp.se    io_req.setThreadContext(tc->contextId(), 0);
4599883Sandreas@sandberg.pp.se
4609883Sandreas@sandberg.pp.se    // TODO: Do we need to create an identity mapped TSS area? We
4619883Sandreas@sandberg.pp.se    // should call kvm.vm.setTSSAddress() here in that case. It should
4629883Sandreas@sandberg.pp.se    // only be needed for old versions of the virtualization
4639883Sandreas@sandberg.pp.se    // extensions. We should make sure that the identity range is
4649883Sandreas@sandberg.pp.se    // reserved in the e820 memory map in that case.
4659883Sandreas@sandberg.pp.se}
4669883Sandreas@sandberg.pp.se
4679883Sandreas@sandberg.pp.sevoid
4689883Sandreas@sandberg.pp.seX86KvmCPU::dump()
4699883Sandreas@sandberg.pp.se{
4709883Sandreas@sandberg.pp.se    dumpIntRegs();
4719883Sandreas@sandberg.pp.se    dumpFpuRegs();
4729883Sandreas@sandberg.pp.se    dumpSpecRegs();
4739883Sandreas@sandberg.pp.se    dumpDebugRegs();
4749883Sandreas@sandberg.pp.se    dumpXCRs();
4759883Sandreas@sandberg.pp.se    dumpVCpuEvents();
4769883Sandreas@sandberg.pp.se    dumpMSRs();
4779883Sandreas@sandberg.pp.se    dumpXSave();
4789883Sandreas@sandberg.pp.se}
4799883Sandreas@sandberg.pp.se
4809883Sandreas@sandberg.pp.sevoid
4819883Sandreas@sandberg.pp.seX86KvmCPU::dumpFpuRegs() const
4829883Sandreas@sandberg.pp.se{
4839883Sandreas@sandberg.pp.se    struct kvm_fpu fpu;
4849883Sandreas@sandberg.pp.se    getFPUState(fpu);
4859883Sandreas@sandberg.pp.se    dumpKvm(fpu);
4869883Sandreas@sandberg.pp.se}
4879883Sandreas@sandberg.pp.se
4889883Sandreas@sandberg.pp.sevoid
4899883Sandreas@sandberg.pp.seX86KvmCPU::dumpIntRegs() const
4909883Sandreas@sandberg.pp.se{
4919883Sandreas@sandberg.pp.se    struct kvm_regs regs;
4929883Sandreas@sandberg.pp.se    getRegisters(regs);
4939883Sandreas@sandberg.pp.se    dumpKvm(regs);
4949883Sandreas@sandberg.pp.se}
4959883Sandreas@sandberg.pp.se
4969883Sandreas@sandberg.pp.sevoid
4979883Sandreas@sandberg.pp.seX86KvmCPU::dumpSpecRegs() const
4989883Sandreas@sandberg.pp.se{
4999883Sandreas@sandberg.pp.se    struct kvm_sregs sregs;
5009883Sandreas@sandberg.pp.se    getSpecialRegisters(sregs);
5019883Sandreas@sandberg.pp.se    dumpKvm(sregs);
5029883Sandreas@sandberg.pp.se}
5039883Sandreas@sandberg.pp.se
5049883Sandreas@sandberg.pp.sevoid
5059883Sandreas@sandberg.pp.seX86KvmCPU::dumpDebugRegs() const
5069883Sandreas@sandberg.pp.se{
5079883Sandreas@sandberg.pp.se    if (haveDebugRegs) {
5089883Sandreas@sandberg.pp.se#ifdef KVM_GET_DEBUGREGS
5099883Sandreas@sandberg.pp.se        struct kvm_debugregs dregs;
5109883Sandreas@sandberg.pp.se        getDebugRegisters(dregs);
5119883Sandreas@sandberg.pp.se        dumpKvm(dregs);
5129883Sandreas@sandberg.pp.se#endif
5139883Sandreas@sandberg.pp.se    } else {
5149883Sandreas@sandberg.pp.se        inform("Debug registers not supported by kernel.\n");
5159883Sandreas@sandberg.pp.se    }
5169883Sandreas@sandberg.pp.se}
5179883Sandreas@sandberg.pp.se
5189883Sandreas@sandberg.pp.sevoid
5199883Sandreas@sandberg.pp.seX86KvmCPU::dumpXCRs() const
5209883Sandreas@sandberg.pp.se{
5219883Sandreas@sandberg.pp.se    if (haveXCRs) {
5229883Sandreas@sandberg.pp.se        struct kvm_xcrs xcrs;
5239883Sandreas@sandberg.pp.se        getXCRs(xcrs);
5249883Sandreas@sandberg.pp.se        dumpKvm(xcrs);
5259883Sandreas@sandberg.pp.se    } else {
5269883Sandreas@sandberg.pp.se        inform("XCRs not supported by kernel.\n");
5279883Sandreas@sandberg.pp.se    }
5289883Sandreas@sandberg.pp.se}
5299883Sandreas@sandberg.pp.se
5309883Sandreas@sandberg.pp.sevoid
5319883Sandreas@sandberg.pp.seX86KvmCPU::dumpXSave() const
5329883Sandreas@sandberg.pp.se{
5339883Sandreas@sandberg.pp.se    if (haveXSave) {
5349883Sandreas@sandberg.pp.se        struct kvm_xsave xsave;
5359883Sandreas@sandberg.pp.se        getXSave(xsave);
5369883Sandreas@sandberg.pp.se        dumpKvm(xsave);
5379883Sandreas@sandberg.pp.se    } else {
5389883Sandreas@sandberg.pp.se        inform("XSave not supported by kernel.\n");
5399883Sandreas@sandberg.pp.se    }
5409883Sandreas@sandberg.pp.se}
5419883Sandreas@sandberg.pp.se
5429883Sandreas@sandberg.pp.sevoid
5439883Sandreas@sandberg.pp.seX86KvmCPU::dumpVCpuEvents() const
5449883Sandreas@sandberg.pp.se{
5459883Sandreas@sandberg.pp.se    struct kvm_vcpu_events events;
5469883Sandreas@sandberg.pp.se    getVCpuEvents(events);
5479883Sandreas@sandberg.pp.se    dumpKvm(events);
5489883Sandreas@sandberg.pp.se}
5499883Sandreas@sandberg.pp.se
5509883Sandreas@sandberg.pp.sevoid
5519883Sandreas@sandberg.pp.seX86KvmCPU::dumpMSRs() const
5529883Sandreas@sandberg.pp.se{
5539883Sandreas@sandberg.pp.se    const Kvm::MSRIndexVector &supported_msrs(vm.kvm.getSupportedMSRs());
5549883Sandreas@sandberg.pp.se    std::unique_ptr<struct kvm_msrs> msrs(
5559883Sandreas@sandberg.pp.se        newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(
5569883Sandreas@sandberg.pp.se            supported_msrs.size()));
5579883Sandreas@sandberg.pp.se
5589883Sandreas@sandberg.pp.se    msrs->nmsrs = supported_msrs.size();
5599883Sandreas@sandberg.pp.se    for (int i = 0; i < supported_msrs.size(); ++i) {
5609883Sandreas@sandberg.pp.se        struct kvm_msr_entry &e(msrs->entries[i]);
5619883Sandreas@sandberg.pp.se        e.index = supported_msrs[i];
5629883Sandreas@sandberg.pp.se        e.reserved = 0;
5639883Sandreas@sandberg.pp.se        e.data = 0;
5649883Sandreas@sandberg.pp.se    }
5659883Sandreas@sandberg.pp.se    getMSRs(*msrs.get());
5669883Sandreas@sandberg.pp.se
5679883Sandreas@sandberg.pp.se    dumpKvm(*msrs.get());
5689883Sandreas@sandberg.pp.se}
5699883Sandreas@sandberg.pp.se
5709883Sandreas@sandberg.pp.sevoid
5719883Sandreas@sandberg.pp.seX86KvmCPU::updateKvmState()
5729883Sandreas@sandberg.pp.se{
5739883Sandreas@sandberg.pp.se    updateKvmStateRegs();
5749883Sandreas@sandberg.pp.se    updateKvmStateSRegs();
5759883Sandreas@sandberg.pp.se    updateKvmStateFPU();
5769883Sandreas@sandberg.pp.se    updateKvmStateMSRs();
5779883Sandreas@sandberg.pp.se
5789883Sandreas@sandberg.pp.se    DPRINTF(KvmContext, "X86KvmCPU::updateKvmState():\n");
5799883Sandreas@sandberg.pp.se    if (DTRACE(KvmContext))
5809883Sandreas@sandberg.pp.se        dump();
5819883Sandreas@sandberg.pp.se}
5829883Sandreas@sandberg.pp.se
5839883Sandreas@sandberg.pp.sevoid
5849883Sandreas@sandberg.pp.seX86KvmCPU::updateKvmStateRegs()
5859883Sandreas@sandberg.pp.se{
5869883Sandreas@sandberg.pp.se    struct kvm_regs regs;
5879883Sandreas@sandberg.pp.se
5889883Sandreas@sandberg.pp.se#define APPLY_IREG(kreg, mreg) regs.kreg = tc->readIntReg(mreg)
5899883Sandreas@sandberg.pp.se    FOREACH_IREG();
5909883Sandreas@sandberg.pp.se#undef APPLY_IREG
5919883Sandreas@sandberg.pp.se
5929883Sandreas@sandberg.pp.se    regs.rip = tc->instAddr();
5939883Sandreas@sandberg.pp.se
5949883Sandreas@sandberg.pp.se    /* You might think that setting regs.rflags to the contents
5959883Sandreas@sandberg.pp.se     * MISCREG_RFLAGS here would suffice. In that case you're
5969883Sandreas@sandberg.pp.se     * mistaken. We need to reconstruct it from a bunch of ucode
5979883Sandreas@sandberg.pp.se     * registers and wave a dead chicken over it (aka mask out and set
5989883Sandreas@sandberg.pp.se     * reserved bits) to get it to work.
5999883Sandreas@sandberg.pp.se     */
6009883Sandreas@sandberg.pp.se    regs.rflags = X86ISA::getRFlags(tc);
6019883Sandreas@sandberg.pp.se
6029883Sandreas@sandberg.pp.se    setRegisters(regs);
6039883Sandreas@sandberg.pp.se}
6049883Sandreas@sandberg.pp.se
6059883Sandreas@sandberg.pp.sestatic inline void
6069883Sandreas@sandberg.pp.sesetKvmSegmentReg(ThreadContext *tc, struct kvm_segment &kvm_seg,
6079883Sandreas@sandberg.pp.se                 const int index)
6089883Sandreas@sandberg.pp.se{
6099883Sandreas@sandberg.pp.se    SegAttr attr(tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(index)));
6109883Sandreas@sandberg.pp.se
6119883Sandreas@sandberg.pp.se    kvm_seg.base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(index));
6129883Sandreas@sandberg.pp.se    kvm_seg.limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(index));
6139883Sandreas@sandberg.pp.se    kvm_seg.selector = tc->readMiscRegNoEffect(MISCREG_SEG_SEL(index));
6149883Sandreas@sandberg.pp.se    kvm_seg.type = attr.type;
6159883Sandreas@sandberg.pp.se    kvm_seg.present = attr.present;
6169883Sandreas@sandberg.pp.se    kvm_seg.dpl = attr.dpl;
6179883Sandreas@sandberg.pp.se    kvm_seg.db = attr.defaultSize;
6189883Sandreas@sandberg.pp.se    kvm_seg.s = attr.system;
6199883Sandreas@sandberg.pp.se    kvm_seg.l = attr.longMode;
6209883Sandreas@sandberg.pp.se    kvm_seg.g = attr.granularity;
6219883Sandreas@sandberg.pp.se    kvm_seg.avl = attr.avl;
6229883Sandreas@sandberg.pp.se
6239883Sandreas@sandberg.pp.se    // A segment is unusable when the selector is zero. There is a
6249883Sandreas@sandberg.pp.se    // attr.unusable flag in gem5, but it seems unused.
6259883Sandreas@sandberg.pp.se    //
6269883Sandreas@sandberg.pp.se    // TODO: Are there corner cases where this doesn't work?
6279883Sandreas@sandberg.pp.se    kvm_seg.unusable = (kvm_seg.selector == 0);
6289883Sandreas@sandberg.pp.se}
6299883Sandreas@sandberg.pp.se
6309883Sandreas@sandberg.pp.sestatic inline void
6319883Sandreas@sandberg.pp.sesetKvmDTableReg(ThreadContext *tc, struct kvm_dtable &kvm_dtable,
6329883Sandreas@sandberg.pp.se                const int index)
6339883Sandreas@sandberg.pp.se{
6349883Sandreas@sandberg.pp.se    kvm_dtable.base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(index));
6359883Sandreas@sandberg.pp.se    kvm_dtable.limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(index));
6369883Sandreas@sandberg.pp.se}
6379883Sandreas@sandberg.pp.se
6389883Sandreas@sandberg.pp.sevoid
6399883Sandreas@sandberg.pp.seX86KvmCPU::updateKvmStateSRegs()
6409883Sandreas@sandberg.pp.se{
6419883Sandreas@sandberg.pp.se    struct kvm_sregs sregs;
6429883Sandreas@sandberg.pp.se
6439883Sandreas@sandberg.pp.se#define APPLY_SREG(kreg, mreg) sregs.kreg = tc->readMiscRegNoEffect(mreg)
6449883Sandreas@sandberg.pp.se#define APPLY_SEGMENT(kreg, idx) setKvmSegmentReg(tc, sregs.kreg, idx)
6459883Sandreas@sandberg.pp.se#define APPLY_DTABLE(kreg, idx) setKvmDTableReg(tc, sregs.kreg, idx)
6469883Sandreas@sandberg.pp.se
6479883Sandreas@sandberg.pp.se    FOREACH_SREG();
6489883Sandreas@sandberg.pp.se    FOREACH_SEGMENT();
6499883Sandreas@sandberg.pp.se    FOREACH_DTABLE();
6509883Sandreas@sandberg.pp.se
6519883Sandreas@sandberg.pp.se#undef APPLY_SREG
6529883Sandreas@sandberg.pp.se#undef APPLY_SEGMENT
6539883Sandreas@sandberg.pp.se#undef APPLY_DTABLE
6549883Sandreas@sandberg.pp.se
6559883Sandreas@sandberg.pp.se    // Clear the interrupt bitmap
6569883Sandreas@sandberg.pp.se    memset(&sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
6579883Sandreas@sandberg.pp.se
6589884Sandreas@sandberg.pp.se    RFLAGS rflags_nocc(tc->readMiscReg(MISCREG_RFLAGS));
6599884Sandreas@sandberg.pp.se    if (!rflags_nocc.vm) {
6609884Sandreas@sandberg.pp.se        // Do segment verification if the CPU isn't entering virtual
6619884Sandreas@sandberg.pp.se        // 8086 mode.  We currently assume that unrestricted guest
6629884Sandreas@sandberg.pp.se        // mode is available.
6639884Sandreas@sandberg.pp.se
6649884Sandreas@sandberg.pp.se#define APPLY_SEGMENT(kreg, idx) \
6659884Sandreas@sandberg.pp.se        checkSeg(# kreg, idx + MISCREG_SEG_SEL_BASE, sregs.kreg, sregs)
6669884Sandreas@sandberg.pp.se
6679884Sandreas@sandberg.pp.se        FOREACH_SEGMENT();
6689884Sandreas@sandberg.pp.se#undef APPLY_SEGMENT
6699884Sandreas@sandberg.pp.se    }
6709883Sandreas@sandberg.pp.se    setSpecialRegisters(sregs);
6719883Sandreas@sandberg.pp.se}
6729883Sandreas@sandberg.pp.sevoid
6739883Sandreas@sandberg.pp.seX86KvmCPU::updateKvmStateFPU()
6749883Sandreas@sandberg.pp.se{
6759883Sandreas@sandberg.pp.se    warn_once("X86KvmCPU::updateKvmStateFPU not implemented\n");
6769883Sandreas@sandberg.pp.se}
6779883Sandreas@sandberg.pp.se
6789883Sandreas@sandberg.pp.sevoid
6799883Sandreas@sandberg.pp.seX86KvmCPU::updateKvmStateMSRs()
6809883Sandreas@sandberg.pp.se{
6819883Sandreas@sandberg.pp.se    KvmMSRVector msrs;
6829883Sandreas@sandberg.pp.se
6839883Sandreas@sandberg.pp.se    const Kvm::MSRIndexVector &indices(getMsrIntersection());
6849883Sandreas@sandberg.pp.se
6859883Sandreas@sandberg.pp.se    for (auto it = indices.cbegin(); it != indices.cend(); ++it) {
6869883Sandreas@sandberg.pp.se        struct kvm_msr_entry e;
6879883Sandreas@sandberg.pp.se
6889883Sandreas@sandberg.pp.se        e.index = *it;
6899883Sandreas@sandberg.pp.se        e.reserved = 0;
6909883Sandreas@sandberg.pp.se        e.data = tc->readMiscReg(msrMap.at(*it));
6919883Sandreas@sandberg.pp.se        DPRINTF(KvmContext, "Adding MSR: idx: 0x%x, data: 0x%x\n",
6929883Sandreas@sandberg.pp.se                e.index, e.data);
6939883Sandreas@sandberg.pp.se
6949883Sandreas@sandberg.pp.se        msrs.push_back(e);
6959883Sandreas@sandberg.pp.se    }
6969883Sandreas@sandberg.pp.se
6979883Sandreas@sandberg.pp.se    setMSRs(msrs);
6989883Sandreas@sandberg.pp.se}
6999883Sandreas@sandberg.pp.se
7009883Sandreas@sandberg.pp.sevoid
7019883Sandreas@sandberg.pp.seX86KvmCPU::updateThreadContext()
7029883Sandreas@sandberg.pp.se{
7039883Sandreas@sandberg.pp.se    DPRINTF(KvmContext, "X86KvmCPU::updateThreadContext():\n");
7049883Sandreas@sandberg.pp.se    if (DTRACE(KvmContext))
7059883Sandreas@sandberg.pp.se        dump();
7069883Sandreas@sandberg.pp.se
7079883Sandreas@sandberg.pp.se    updateThreadContextRegs();
7089883Sandreas@sandberg.pp.se    updateThreadContextSRegs();
7099883Sandreas@sandberg.pp.se    updateThreadContextFPU();
7109883Sandreas@sandberg.pp.se    updateThreadContextMSRs();
7119883Sandreas@sandberg.pp.se
7129883Sandreas@sandberg.pp.se    // The M5 misc reg caches some values from other
7139883Sandreas@sandberg.pp.se    // registers. Writing to it with side effects causes it to be
7149883Sandreas@sandberg.pp.se    // updated from its source registers.
7159883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_M5_REG, 0);
7169883Sandreas@sandberg.pp.se}
7179883Sandreas@sandberg.pp.se
7189883Sandreas@sandberg.pp.sevoid
7199883Sandreas@sandberg.pp.seX86KvmCPU::updateThreadContextRegs()
7209883Sandreas@sandberg.pp.se{
7219883Sandreas@sandberg.pp.se    struct kvm_regs regs;
7229883Sandreas@sandberg.pp.se    getRegisters(regs);
7239883Sandreas@sandberg.pp.se
7249883Sandreas@sandberg.pp.se#define APPLY_IREG(kreg, mreg) tc->setIntReg(mreg, regs.kreg)
7259883Sandreas@sandberg.pp.se
7269883Sandreas@sandberg.pp.se    FOREACH_IREG();
7279883Sandreas@sandberg.pp.se
7289883Sandreas@sandberg.pp.se#undef APPLY_IREG
7299883Sandreas@sandberg.pp.se
7309883Sandreas@sandberg.pp.se    tc->pcState(PCState(regs.rip));
7319883Sandreas@sandberg.pp.se
7329883Sandreas@sandberg.pp.se    // Flags are spread out across multiple semi-magic registers so we
7339883Sandreas@sandberg.pp.se    // need some special care when updating them.
7349883Sandreas@sandberg.pp.se    X86ISA::setRFlags(tc, regs.rflags);
7359883Sandreas@sandberg.pp.se}
7369883Sandreas@sandberg.pp.se
7379883Sandreas@sandberg.pp.se
7389883Sandreas@sandberg.pp.seinline void
7399883Sandreas@sandberg.pp.sesetContextSegment(ThreadContext *tc, const struct kvm_segment &kvm_seg,
7409883Sandreas@sandberg.pp.se                  const int index)
7419883Sandreas@sandberg.pp.se{
7429883Sandreas@sandberg.pp.se    SegAttr attr(0);
7439883Sandreas@sandberg.pp.se
7449883Sandreas@sandberg.pp.se    attr.type = kvm_seg.type;
7459883Sandreas@sandberg.pp.se    attr.present = kvm_seg.present;
7469883Sandreas@sandberg.pp.se    attr.dpl = kvm_seg.dpl;
7479883Sandreas@sandberg.pp.se    attr.defaultSize = kvm_seg.db;
7489883Sandreas@sandberg.pp.se    attr.system = kvm_seg.s;
7499883Sandreas@sandberg.pp.se    attr.longMode = kvm_seg.l;
7509883Sandreas@sandberg.pp.se    attr.granularity = kvm_seg.g;
7519883Sandreas@sandberg.pp.se    attr.avl = kvm_seg.avl;
7529883Sandreas@sandberg.pp.se    attr.unusable = kvm_seg.unusable;
7539883Sandreas@sandberg.pp.se
7549883Sandreas@sandberg.pp.se    // We need some setMiscReg magic here to keep the effective base
7559883Sandreas@sandberg.pp.se    // addresses in sync. We need an up-to-date version of EFER, so
7569883Sandreas@sandberg.pp.se    // make sure this is called after the sregs have been synced.
7579883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_SEG_BASE(index), kvm_seg.base);
7589883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_SEG_LIMIT(index), kvm_seg.limit);
7599883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_SEG_SEL(index), kvm_seg.selector);
7609883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_SEG_ATTR(index), attr);
7619883Sandreas@sandberg.pp.se}
7629883Sandreas@sandberg.pp.se
7639883Sandreas@sandberg.pp.seinline void
7649883Sandreas@sandberg.pp.sesetContextSegment(ThreadContext *tc, const struct kvm_dtable &kvm_dtable,
7659883Sandreas@sandberg.pp.se                  const int index)
7669883Sandreas@sandberg.pp.se{
7679883Sandreas@sandberg.pp.se    // We need some setMiscReg magic here to keep the effective base
7689883Sandreas@sandberg.pp.se    // addresses in sync. We need an up-to-date version of EFER, so
7699883Sandreas@sandberg.pp.se    // make sure this is called after the sregs have been synced.
7709883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_SEG_BASE(index), kvm_dtable.base);
7719883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_SEG_LIMIT(index), kvm_dtable.limit);
7729883Sandreas@sandberg.pp.se}
7739883Sandreas@sandberg.pp.se
7749883Sandreas@sandberg.pp.sevoid
7759883Sandreas@sandberg.pp.seX86KvmCPU::updateThreadContextSRegs()
7769883Sandreas@sandberg.pp.se{
7779883Sandreas@sandberg.pp.se    struct kvm_sregs sregs;
7789883Sandreas@sandberg.pp.se    getSpecialRegisters(sregs);
7799883Sandreas@sandberg.pp.se
7809883Sandreas@sandberg.pp.se    assert(getKvmRunState()->apic_base == sregs.apic_base);
7819883Sandreas@sandberg.pp.se    assert(getKvmRunState()->cr8 == sregs.cr8);
7829883Sandreas@sandberg.pp.se
7839883Sandreas@sandberg.pp.se#define APPLY_SREG(kreg, mreg) tc->setMiscRegNoEffect(mreg, sregs.kreg)
7849883Sandreas@sandberg.pp.se#define APPLY_SEGMENT(kreg, idx) setContextSegment(tc, sregs.kreg, idx)
7859883Sandreas@sandberg.pp.se#define APPLY_DTABLE(kreg, idx) setContextSegment(tc, sregs.kreg, idx)
7869883Sandreas@sandberg.pp.se    FOREACH_SREG();
7879883Sandreas@sandberg.pp.se    FOREACH_SEGMENT();
7889883Sandreas@sandberg.pp.se    FOREACH_DTABLE();
7899883Sandreas@sandberg.pp.se#undef APPLY_SREG
7909883Sandreas@sandberg.pp.se#undef APPLY_SEGMENT
7919883Sandreas@sandberg.pp.se#undef APPLY_DTABLE
7929883Sandreas@sandberg.pp.se}
7939883Sandreas@sandberg.pp.se
7949883Sandreas@sandberg.pp.sevoid
7959883Sandreas@sandberg.pp.seX86KvmCPU::updateThreadContextFPU()
7969883Sandreas@sandberg.pp.se{
7979883Sandreas@sandberg.pp.se    warn_once("X86KvmCPU::updateThreadContextFPU not implemented\n");
7989883Sandreas@sandberg.pp.se}
7999883Sandreas@sandberg.pp.se
8009883Sandreas@sandberg.pp.sevoid
8019883Sandreas@sandberg.pp.seX86KvmCPU::updateThreadContextMSRs()
8029883Sandreas@sandberg.pp.se{
8039883Sandreas@sandberg.pp.se    const Kvm::MSRIndexVector &msrs(getMsrIntersection());
8049883Sandreas@sandberg.pp.se
8059883Sandreas@sandberg.pp.se    std::unique_ptr<struct kvm_msrs> kvm_msrs(
8069883Sandreas@sandberg.pp.se        newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(msrs.size()));
8079883Sandreas@sandberg.pp.se    struct kvm_msr_entry *entry;
8089883Sandreas@sandberg.pp.se
8099883Sandreas@sandberg.pp.se    // Create a list of MSRs to read
8109883Sandreas@sandberg.pp.se    kvm_msrs->nmsrs = msrs.size();
8119883Sandreas@sandberg.pp.se    entry = &kvm_msrs->entries[0];
8129883Sandreas@sandberg.pp.se    for (auto it = msrs.cbegin(); it != msrs.cend(); ++it, ++entry) {
8139883Sandreas@sandberg.pp.se        entry->index = *it;
8149883Sandreas@sandberg.pp.se        entry->reserved = 0;
8159883Sandreas@sandberg.pp.se        entry->data = 0;
8169883Sandreas@sandberg.pp.se    }
8179883Sandreas@sandberg.pp.se
8189883Sandreas@sandberg.pp.se    getMSRs(*kvm_msrs.get());
8199883Sandreas@sandberg.pp.se
8209883Sandreas@sandberg.pp.se    // Update M5's state
8219883Sandreas@sandberg.pp.se    entry = &kvm_msrs->entries[0];
8229883Sandreas@sandberg.pp.se    for (int i = 0; i < kvm_msrs->nmsrs; ++i, ++entry) {
8239883Sandreas@sandberg.pp.se        DPRINTF(KvmContext, "Setting M5 MSR: idx: 0x%x, data: 0x%x\n",
8249883Sandreas@sandberg.pp.se                entry->index, entry->data);
8259883Sandreas@sandberg.pp.se
8269883Sandreas@sandberg.pp.se        tc->setMiscReg(X86ISA::msrMap.at(entry->index), entry->data);
8279883Sandreas@sandberg.pp.se    }
8289883Sandreas@sandberg.pp.se}
8299883Sandreas@sandberg.pp.se
8309883Sandreas@sandberg.pp.sevoid
8319883Sandreas@sandberg.pp.seX86KvmCPU::deliverInterrupts()
8329883Sandreas@sandberg.pp.se{
8339883Sandreas@sandberg.pp.se    syncThreadContext();
8349883Sandreas@sandberg.pp.se
8359883Sandreas@sandberg.pp.se    Fault fault(interrupts->getInterrupt(tc));
8369883Sandreas@sandberg.pp.se    interrupts->updateIntrInfo(tc);
8379883Sandreas@sandberg.pp.se
8389883Sandreas@sandberg.pp.se    X86Interrupt *x86int(dynamic_cast<X86Interrupt *>(fault.get()));
8399883Sandreas@sandberg.pp.se    if (x86int) {
8409883Sandreas@sandberg.pp.se        struct kvm_interrupt kvm_int;
8419883Sandreas@sandberg.pp.se        kvm_int.irq = x86int->getVector();
8429883Sandreas@sandberg.pp.se
8439883Sandreas@sandberg.pp.se        DPRINTF(KvmInt, "Delivering interrupt: %s (%u)\n",
8449883Sandreas@sandberg.pp.se                fault->name(), kvm_int.irq);
8459883Sandreas@sandberg.pp.se
8469883Sandreas@sandberg.pp.se        kvmInterrupt(kvm_int);
8479883Sandreas@sandberg.pp.se    } else if (dynamic_cast<NonMaskableInterrupt *>(fault.get())) {
8489883Sandreas@sandberg.pp.se        DPRINTF(KvmInt, "Delivering NMI\n");
8499883Sandreas@sandberg.pp.se        kvmNonMaskableInterrupt();
8509883Sandreas@sandberg.pp.se    } else {
8519883Sandreas@sandberg.pp.se        panic("KVM: Unknown interrupt type\n");
8529883Sandreas@sandberg.pp.se    }
8539883Sandreas@sandberg.pp.se
8549883Sandreas@sandberg.pp.se}
8559883Sandreas@sandberg.pp.se
8569883Sandreas@sandberg.pp.seTick
8579883Sandreas@sandberg.pp.seX86KvmCPU::kvmRun(Tick ticks)
8589883Sandreas@sandberg.pp.se{
8599883Sandreas@sandberg.pp.se    struct kvm_run &kvm_run(*getKvmRunState());
8609883Sandreas@sandberg.pp.se
8619883Sandreas@sandberg.pp.se    if (interrupts->checkInterruptsRaw()) {
8629883Sandreas@sandberg.pp.se        if (kvm_run.ready_for_interrupt_injection) {
8639883Sandreas@sandberg.pp.se            // KVM claims that it is ready for an interrupt. It might
8649883Sandreas@sandberg.pp.se            // be lying if we just updated rflags and disabled
8659883Sandreas@sandberg.pp.se            // interrupts (e.g., by doing a CPU handover). Let's sync
8669883Sandreas@sandberg.pp.se            // the thread context and check if there are /really/
8679883Sandreas@sandberg.pp.se            // interrupts that should be delivered now.
8689883Sandreas@sandberg.pp.se            syncThreadContext();
8699883Sandreas@sandberg.pp.se            if (interrupts->checkInterrupts(tc)) {
8709883Sandreas@sandberg.pp.se                DPRINTF(KvmInt,
8719883Sandreas@sandberg.pp.se                        "M5 has pending interrupts, delivering interrupt.\n");
8729883Sandreas@sandberg.pp.se
8739883Sandreas@sandberg.pp.se                deliverInterrupts();
8749883Sandreas@sandberg.pp.se            } else {
8759883Sandreas@sandberg.pp.se                DPRINTF(KvmInt,
8769883Sandreas@sandberg.pp.se                        "Interrupt delivery delayed due to KVM confusion.\n");
8779883Sandreas@sandberg.pp.se                kvm_run.request_interrupt_window = 1;
8789883Sandreas@sandberg.pp.se            }
8799883Sandreas@sandberg.pp.se        } else if (!kvm_run.request_interrupt_window) {
8809883Sandreas@sandberg.pp.se            DPRINTF(KvmInt,
8819883Sandreas@sandberg.pp.se                    "M5 has pending interrupts, requesting interrupt "
8829883Sandreas@sandberg.pp.se                    "window.\n");
8839883Sandreas@sandberg.pp.se            kvm_run.request_interrupt_window = 1;
8849883Sandreas@sandberg.pp.se        }
8859883Sandreas@sandberg.pp.se    } else {
8869883Sandreas@sandberg.pp.se        kvm_run.request_interrupt_window = 0;
8879883Sandreas@sandberg.pp.se    }
8889883Sandreas@sandberg.pp.se
8899883Sandreas@sandberg.pp.se    return kvmRunWrapper(ticks);
8909883Sandreas@sandberg.pp.se}
8919883Sandreas@sandberg.pp.se
8929883Sandreas@sandberg.pp.seTick
8939883Sandreas@sandberg.pp.seX86KvmCPU::kvmRunDrain()
8949883Sandreas@sandberg.pp.se{
8959883Sandreas@sandberg.pp.se    struct kvm_run &kvm_run(*getKvmRunState());
8969883Sandreas@sandberg.pp.se
8979883Sandreas@sandberg.pp.se    if (!archIsDrained()) {
8989883Sandreas@sandberg.pp.se        DPRINTF(Drain, "kvmRunDrain: Architecture code isn't drained\n");
8999883Sandreas@sandberg.pp.se
9009883Sandreas@sandberg.pp.se        // Tell KVM to find a suitable place to deliver interrupts. This
9019883Sandreas@sandberg.pp.se        // should ensure that pending interrupts have been delivered and
9029883Sandreas@sandberg.pp.se        // things are reasonably consistent (i.e., no interrupts pending
9039883Sandreas@sandberg.pp.se        // in the guest).
9049883Sandreas@sandberg.pp.se        kvm_run.request_interrupt_window = 1;
9059883Sandreas@sandberg.pp.se
9069883Sandreas@sandberg.pp.se        // Limit the run to 1 millisecond. That is hopefully enough to
9079883Sandreas@sandberg.pp.se        // reach an interrupt window. Otherwise, we'll just try again
9089883Sandreas@sandberg.pp.se        // later.
9099883Sandreas@sandberg.pp.se        return kvmRunWrapper(1 * SimClock::Float::ms);
9109883Sandreas@sandberg.pp.se    } else {
9119883Sandreas@sandberg.pp.se        DPRINTF(Drain, "kvmRunDrain: Delivering pending IO\n");
9129883Sandreas@sandberg.pp.se
9139883Sandreas@sandberg.pp.se        return kvmRunWrapper(0);
9149883Sandreas@sandberg.pp.se    }
9159883Sandreas@sandberg.pp.se}
9169883Sandreas@sandberg.pp.se
9179883Sandreas@sandberg.pp.seTick
9189883Sandreas@sandberg.pp.seX86KvmCPU::kvmRunWrapper(Tick ticks)
9199883Sandreas@sandberg.pp.se{
9209883Sandreas@sandberg.pp.se    struct kvm_run &kvm_run(*getKvmRunState());
9219883Sandreas@sandberg.pp.se
9229883Sandreas@sandberg.pp.se    // Synchronize the APIC base and CR8 here since they are present
9239883Sandreas@sandberg.pp.se    // in the kvm_run struct, which makes the synchronization really
9249883Sandreas@sandberg.pp.se    // cheap.
9259883Sandreas@sandberg.pp.se    kvm_run.apic_base = tc->readMiscReg(MISCREG_APIC_BASE);
9269883Sandreas@sandberg.pp.se    kvm_run.cr8 = tc->readMiscReg(MISCREG_CR8);
9279883Sandreas@sandberg.pp.se
9289883Sandreas@sandberg.pp.se    const Tick run_ticks(BaseKvmCPU::kvmRun(ticks));
9299883Sandreas@sandberg.pp.se
9309883Sandreas@sandberg.pp.se    tc->setMiscReg(MISCREG_APIC_BASE, kvm_run.apic_base);
9319883Sandreas@sandberg.pp.se    kvm_run.cr8 = tc->readMiscReg(MISCREG_CR8);
9329883Sandreas@sandberg.pp.se
9339883Sandreas@sandberg.pp.se    return run_ticks;
9349883Sandreas@sandberg.pp.se}
9359883Sandreas@sandberg.pp.se
9369883Sandreas@sandberg.pp.seuint64_t
9379883Sandreas@sandberg.pp.seX86KvmCPU::getHostCycles() const
9389883Sandreas@sandberg.pp.se{
9399883Sandreas@sandberg.pp.se    return getMSR(MSR_TSC);
9409883Sandreas@sandberg.pp.se}
9419883Sandreas@sandberg.pp.se
9429883Sandreas@sandberg.pp.sevoid
9439883Sandreas@sandberg.pp.seX86KvmCPU::handleIOMiscReg32(int miscreg)
9449883Sandreas@sandberg.pp.se{
9459883Sandreas@sandberg.pp.se    struct kvm_run &kvm_run(*getKvmRunState());
9469883Sandreas@sandberg.pp.se    const uint16_t port(kvm_run.io.port);
9479883Sandreas@sandberg.pp.se
9489883Sandreas@sandberg.pp.se    assert(kvm_run.exit_reason == KVM_EXIT_IO);
9499883Sandreas@sandberg.pp.se
9509883Sandreas@sandberg.pp.se    if (kvm_run.io.size != 4) {
9519883Sandreas@sandberg.pp.se        panic("Unexpected IO size (%u) for address 0x%x.\n",
9529883Sandreas@sandberg.pp.se              kvm_run.io.size, port);
9539883Sandreas@sandberg.pp.se    }
9549883Sandreas@sandberg.pp.se
9559883Sandreas@sandberg.pp.se    if (kvm_run.io.count != 1) {
9569883Sandreas@sandberg.pp.se        panic("Unexpected IO count (%u) for address 0x%x.\n",
9579883Sandreas@sandberg.pp.se              kvm_run.io.count, port);
9589883Sandreas@sandberg.pp.se    }
9599883Sandreas@sandberg.pp.se
9609883Sandreas@sandberg.pp.se    uint32_t *data((uint32_t *)getGuestData(kvm_run.io.data_offset));
9619883Sandreas@sandberg.pp.se    if (kvm_run.io.direction == KVM_EXIT_IO_OUT)
9629883Sandreas@sandberg.pp.se        tc->setMiscReg(miscreg, *data);
9639883Sandreas@sandberg.pp.se    else
9649883Sandreas@sandberg.pp.se        *data = tc->readMiscRegNoEffect(miscreg);
9659883Sandreas@sandberg.pp.se}
9669883Sandreas@sandberg.pp.se
9679883Sandreas@sandberg.pp.seTick
9689883Sandreas@sandberg.pp.seX86KvmCPU::handleKvmExitIO()
9699883Sandreas@sandberg.pp.se{
9709883Sandreas@sandberg.pp.se    struct kvm_run &kvm_run(*getKvmRunState());
9719883Sandreas@sandberg.pp.se    bool isWrite(kvm_run.io.direction == KVM_EXIT_IO_OUT);
9729883Sandreas@sandberg.pp.se    unsigned char *guestData(getGuestData(kvm_run.io.data_offset));
9739883Sandreas@sandberg.pp.se    Tick delay(0);
9749883Sandreas@sandberg.pp.se    uint16_t port(kvm_run.io.port);
9759883Sandreas@sandberg.pp.se    Addr pAddr;
9769883Sandreas@sandberg.pp.se    const int count(kvm_run.io.count);
9779883Sandreas@sandberg.pp.se
9789883Sandreas@sandberg.pp.se    assert(kvm_run.io.direction == KVM_EXIT_IO_IN ||
9799883Sandreas@sandberg.pp.se           kvm_run.io.direction == KVM_EXIT_IO_OUT);
9809883Sandreas@sandberg.pp.se
9819883Sandreas@sandberg.pp.se    DPRINTF(KvmIO, "KVM-x86: Handling IO instruction (%s) (port: 0x%x)\n",
9829883Sandreas@sandberg.pp.se            (isWrite ? "out" : "in"), kvm_run.io.port);
9839883Sandreas@sandberg.pp.se
9849883Sandreas@sandberg.pp.se    /* Vanilla gem5 handles PCI discovery in the TLB(!). Since we
9859883Sandreas@sandberg.pp.se     * don't use the TLB component, we need to intercept and handle
9869883Sandreas@sandberg.pp.se     * the PCI configuration space IO ports here.
9879883Sandreas@sandberg.pp.se     *
9889883Sandreas@sandberg.pp.se     * The IO port PCI discovery mechanism uses one address register
9899883Sandreas@sandberg.pp.se     * and one data register. We map the address register to a misc
9909883Sandreas@sandberg.pp.se     * reg and use that to re-route data register accesses to the
9919883Sandreas@sandberg.pp.se     * right location in the PCI configuration space.
9929883Sandreas@sandberg.pp.se     */
9939883Sandreas@sandberg.pp.se    if (port == IO_PCI_CONF_ADDR) {
9949883Sandreas@sandberg.pp.se        handleIOMiscReg32(MISCREG_PCI_CONFIG_ADDRESS);
9959883Sandreas@sandberg.pp.se        return 0;
9969883Sandreas@sandberg.pp.se    } else if ((port & ~0x3) == IO_PCI_CONF_DATA_BASE) {
9979883Sandreas@sandberg.pp.se        Addr pciConfigAddr(tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS));
9989883Sandreas@sandberg.pp.se        if (pciConfigAddr & 0x80000000) {
9999883Sandreas@sandberg.pp.se            pAddr = X86ISA::x86PciConfigAddress((pciConfigAddr & 0x7ffffffc) |
10009883Sandreas@sandberg.pp.se                                                (port & 0x3));
10019883Sandreas@sandberg.pp.se        } else {
10029883Sandreas@sandberg.pp.se            pAddr = X86ISA::x86IOAddress(port);
10039883Sandreas@sandberg.pp.se        }
10049883Sandreas@sandberg.pp.se    } else {
10059883Sandreas@sandberg.pp.se        pAddr = X86ISA::x86IOAddress(port);
10069883Sandreas@sandberg.pp.se    }
10079883Sandreas@sandberg.pp.se
10089883Sandreas@sandberg.pp.se    io_req.setPhys(pAddr, kvm_run.io.size, Request::UNCACHEABLE,
10099883Sandreas@sandberg.pp.se                   dataMasterId());
10109883Sandreas@sandberg.pp.se
10119883Sandreas@sandberg.pp.se    const MemCmd cmd(isWrite ? MemCmd::WriteReq : MemCmd::ReadReq);
10129883Sandreas@sandberg.pp.se    for (int i = 0; i < count; ++i) {
10139883Sandreas@sandberg.pp.se        Packet pkt(&io_req, cmd);
10149883Sandreas@sandberg.pp.se
10159883Sandreas@sandberg.pp.se        pkt.dataStatic(guestData);
10169883Sandreas@sandberg.pp.se        delay += dataPort.sendAtomic(&pkt);
10179883Sandreas@sandberg.pp.se
10189883Sandreas@sandberg.pp.se        guestData += kvm_run.io.size;
10199883Sandreas@sandberg.pp.se    }
10209883Sandreas@sandberg.pp.se
10219883Sandreas@sandberg.pp.se    return delay;
10229883Sandreas@sandberg.pp.se}
10239883Sandreas@sandberg.pp.se
10249883Sandreas@sandberg.pp.seTick
10259883Sandreas@sandberg.pp.seX86KvmCPU::handleKvmExitIRQWindowOpen()
10269883Sandreas@sandberg.pp.se{
10279883Sandreas@sandberg.pp.se    // We don't need to do anything here since this is caught the next
10289883Sandreas@sandberg.pp.se    // time we execute kvmRun(). We still overload the exit event to
10299883Sandreas@sandberg.pp.se    // silence the warning about an unhandled exit event.
10309883Sandreas@sandberg.pp.se    return 0;
10319883Sandreas@sandberg.pp.se}
10329883Sandreas@sandberg.pp.se
10339883Sandreas@sandberg.pp.sebool
10349883Sandreas@sandberg.pp.seX86KvmCPU::archIsDrained() const
10359883Sandreas@sandberg.pp.se{
10369883Sandreas@sandberg.pp.se    struct kvm_vcpu_events events;
10379883Sandreas@sandberg.pp.se
10389883Sandreas@sandberg.pp.se    getVCpuEvents(events);
10399883Sandreas@sandberg.pp.se
10409883Sandreas@sandberg.pp.se    // We could probably handle this in a by re-inserting interrupts
10419883Sandreas@sandberg.pp.se    // that are pending into gem5 on a drain. However, that would
10429883Sandreas@sandberg.pp.se    // probably be tricky to do reliably, so we'll just prevent a
10439883Sandreas@sandberg.pp.se    // drain if there is anything pending in the
10449883Sandreas@sandberg.pp.se    // guest. X86KvmCPU::kvmRunDrain() minimizes the amount of code
10459883Sandreas@sandberg.pp.se    // executed in the guest by requesting an interrupt window if
10469883Sandreas@sandberg.pp.se    // there are pending interrupts.
10479883Sandreas@sandberg.pp.se    const bool pending_events(events.exception.injected ||
10489883Sandreas@sandberg.pp.se                              events.interrupt.injected ||
10499883Sandreas@sandberg.pp.se                              events.nmi.injected || events.nmi.pending);
10509883Sandreas@sandberg.pp.se
10519883Sandreas@sandberg.pp.se    if (pending_events) {
10529883Sandreas@sandberg.pp.se        DPRINTF(Drain, "archIsDrained: Pending events: %s %s %s %s\n",
10539883Sandreas@sandberg.pp.se                events.exception.injected ? "exception" : "",
10549883Sandreas@sandberg.pp.se                events.interrupt.injected ? "interrupt" : "",
10559883Sandreas@sandberg.pp.se                events.nmi.injected ? "nmi[i]" : "",
10569883Sandreas@sandberg.pp.se                events.nmi.pending ? "nmi[p]" : "");
10579883Sandreas@sandberg.pp.se    }
10589883Sandreas@sandberg.pp.se
10599883Sandreas@sandberg.pp.se    return !pending_events;
10609883Sandreas@sandberg.pp.se}
10619883Sandreas@sandberg.pp.se
10629883Sandreas@sandberg.pp.sestatic struct kvm_cpuid_entry2
10639883Sandreas@sandberg.pp.semakeKvmCpuid(uint32_t function, uint32_t index,
10649883Sandreas@sandberg.pp.se             CpuidResult &result)
10659883Sandreas@sandberg.pp.se{
10669883Sandreas@sandberg.pp.se    struct kvm_cpuid_entry2 e;
10679883Sandreas@sandberg.pp.se    e.function = function;
10689883Sandreas@sandberg.pp.se    e.index = index;
10699883Sandreas@sandberg.pp.se    e.flags = 0;
10709883Sandreas@sandberg.pp.se    e.eax = (uint32_t)result.rax;
10719883Sandreas@sandberg.pp.se    e.ebx = (uint32_t)result.rbx;
10729883Sandreas@sandberg.pp.se    e.ecx = (uint32_t)result.rcx;
10739883Sandreas@sandberg.pp.se    e.edx = (uint32_t)result.rdx;
10749883Sandreas@sandberg.pp.se
10759883Sandreas@sandberg.pp.se    return e;
10769883Sandreas@sandberg.pp.se}
10779883Sandreas@sandberg.pp.se
10789883Sandreas@sandberg.pp.sevoid
10799883Sandreas@sandberg.pp.seX86KvmCPU::updateCPUID()
10809883Sandreas@sandberg.pp.se{
10819883Sandreas@sandberg.pp.se    Kvm::CPUIDVector m5_supported;
10829883Sandreas@sandberg.pp.se
10839883Sandreas@sandberg.pp.se    /* TODO: We currently don't support any of the functions that
10849883Sandreas@sandberg.pp.se     * iterate through data structures in the CPU using an index. It's
10859883Sandreas@sandberg.pp.se     * currently not a problem since M5 doesn't expose any of them at
10869883Sandreas@sandberg.pp.se     * the moment.
10879883Sandreas@sandberg.pp.se     */
10889883Sandreas@sandberg.pp.se
10899883Sandreas@sandberg.pp.se    /* Basic features */
10909883Sandreas@sandberg.pp.se    CpuidResult func0;
10919883Sandreas@sandberg.pp.se    X86ISA::doCpuid(tc, 0x0, 0, func0);
10929883Sandreas@sandberg.pp.se    for (uint32_t function = 0; function <= func0.rax; ++function) {
10939883Sandreas@sandberg.pp.se        CpuidResult cpuid;
10949883Sandreas@sandberg.pp.se        uint32_t idx(0);
10959883Sandreas@sandberg.pp.se
10969883Sandreas@sandberg.pp.se        X86ISA::doCpuid(tc, function, idx, cpuid);
10979883Sandreas@sandberg.pp.se        m5_supported.push_back(makeKvmCpuid(function, idx, cpuid));
10989883Sandreas@sandberg.pp.se    }
10999883Sandreas@sandberg.pp.se
11009883Sandreas@sandberg.pp.se    /* Extended features */
11019883Sandreas@sandberg.pp.se    CpuidResult efunc0;
11029883Sandreas@sandberg.pp.se    X86ISA::doCpuid(tc, 0x80000000, 0, efunc0);
11039883Sandreas@sandberg.pp.se    for (uint32_t function = 0x80000000; function <= efunc0.rax; ++function) {
11049883Sandreas@sandberg.pp.se        CpuidResult cpuid;
11059883Sandreas@sandberg.pp.se        uint32_t idx(0);
11069883Sandreas@sandberg.pp.se
11079883Sandreas@sandberg.pp.se        X86ISA::doCpuid(tc, function, idx, cpuid);
11089883Sandreas@sandberg.pp.se        m5_supported.push_back(makeKvmCpuid(function, idx, cpuid));
11099883Sandreas@sandberg.pp.se    }
11109883Sandreas@sandberg.pp.se
11119883Sandreas@sandberg.pp.se    setCPUID(m5_supported);
11129883Sandreas@sandberg.pp.se}
11139883Sandreas@sandberg.pp.se
11149883Sandreas@sandberg.pp.sevoid
11159883Sandreas@sandberg.pp.seX86KvmCPU::setCPUID(const struct kvm_cpuid2 &cpuid)
11169883Sandreas@sandberg.pp.se{
11179883Sandreas@sandberg.pp.se    if (ioctl(KVM_SET_CPUID2, (void *)&cpuid) == -1)
11189883Sandreas@sandberg.pp.se        panic("KVM: Failed to set guest CPUID2 (errno: %i)\n",
11199883Sandreas@sandberg.pp.se              errno);
11209883Sandreas@sandberg.pp.se}
11219883Sandreas@sandberg.pp.se
11229883Sandreas@sandberg.pp.sevoid
11239883Sandreas@sandberg.pp.seX86KvmCPU::setCPUID(const Kvm::CPUIDVector &cpuid)
11249883Sandreas@sandberg.pp.se{
11259883Sandreas@sandberg.pp.se    std::unique_ptr<struct kvm_cpuid2> kvm_cpuid(
11269883Sandreas@sandberg.pp.se        newVarStruct<struct kvm_cpuid2, struct kvm_cpuid_entry2>(cpuid.size()));
11279883Sandreas@sandberg.pp.se
11289883Sandreas@sandberg.pp.se    kvm_cpuid->nent = cpuid.size();
11299883Sandreas@sandberg.pp.se    std::copy(cpuid.begin(), cpuid.end(), kvm_cpuid->entries);
11309883Sandreas@sandberg.pp.se
11319883Sandreas@sandberg.pp.se    setCPUID(*kvm_cpuid);
11329883Sandreas@sandberg.pp.se}
11339883Sandreas@sandberg.pp.se
11349883Sandreas@sandberg.pp.sevoid
11359883Sandreas@sandberg.pp.seX86KvmCPU::setMSRs(const struct kvm_msrs &msrs)
11369883Sandreas@sandberg.pp.se{
11379883Sandreas@sandberg.pp.se    if (ioctl(KVM_SET_MSRS, (void *)&msrs) == -1)
11389883Sandreas@sandberg.pp.se        panic("KVM: Failed to set guest MSRs (errno: %i)\n",
11399883Sandreas@sandberg.pp.se              errno);
11409883Sandreas@sandberg.pp.se}
11419883Sandreas@sandberg.pp.se
11429883Sandreas@sandberg.pp.sevoid
11439883Sandreas@sandberg.pp.seX86KvmCPU::setMSRs(const KvmMSRVector &msrs)
11449883Sandreas@sandberg.pp.se{
11459883Sandreas@sandberg.pp.se    std::unique_ptr<struct kvm_msrs> kvm_msrs(
11469883Sandreas@sandberg.pp.se        newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(msrs.size()));
11479883Sandreas@sandberg.pp.se
11489883Sandreas@sandberg.pp.se    kvm_msrs->nmsrs = msrs.size();
11499883Sandreas@sandberg.pp.se    std::copy(msrs.begin(), msrs.end(), kvm_msrs->entries);
11509883Sandreas@sandberg.pp.se
11519883Sandreas@sandberg.pp.se    setMSRs(*kvm_msrs);
11529883Sandreas@sandberg.pp.se}
11539883Sandreas@sandberg.pp.se
11549883Sandreas@sandberg.pp.sevoid
11559883Sandreas@sandberg.pp.seX86KvmCPU::getMSRs(struct kvm_msrs &msrs) const
11569883Sandreas@sandberg.pp.se{
11579883Sandreas@sandberg.pp.se    if (ioctl(KVM_GET_MSRS, (void *)&msrs) == -1)
11589883Sandreas@sandberg.pp.se        panic("KVM: Failed to get guest MSRs (errno: %i)\n",
11599883Sandreas@sandberg.pp.se              errno);
11609883Sandreas@sandberg.pp.se}
11619883Sandreas@sandberg.pp.se
11629883Sandreas@sandberg.pp.se
11639883Sandreas@sandberg.pp.sevoid
11649883Sandreas@sandberg.pp.seX86KvmCPU::setMSR(uint32_t index, uint64_t value)
11659883Sandreas@sandberg.pp.se{
11669883Sandreas@sandberg.pp.se    std::unique_ptr<struct kvm_msrs> kvm_msrs(
11679883Sandreas@sandberg.pp.se        newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(1));
11689883Sandreas@sandberg.pp.se    struct kvm_msr_entry &entry(kvm_msrs->entries[0]);
11699883Sandreas@sandberg.pp.se
11709883Sandreas@sandberg.pp.se    kvm_msrs->nmsrs = 1;
11719883Sandreas@sandberg.pp.se    entry.index = index;
11729883Sandreas@sandberg.pp.se    entry.reserved = 0;
11739883Sandreas@sandberg.pp.se    entry.data = value;
11749883Sandreas@sandberg.pp.se
11759883Sandreas@sandberg.pp.se    setMSRs(*kvm_msrs.get());
11769883Sandreas@sandberg.pp.se}
11779883Sandreas@sandberg.pp.se
11789883Sandreas@sandberg.pp.seuint64_t
11799883Sandreas@sandberg.pp.seX86KvmCPU::getMSR(uint32_t index) const
11809883Sandreas@sandberg.pp.se{
11819883Sandreas@sandberg.pp.se    std::unique_ptr<struct kvm_msrs> kvm_msrs(
11829883Sandreas@sandberg.pp.se        newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(1));
11839883Sandreas@sandberg.pp.se    struct kvm_msr_entry &entry(kvm_msrs->entries[0]);
11849883Sandreas@sandberg.pp.se
11859883Sandreas@sandberg.pp.se    kvm_msrs->nmsrs = 1;
11869883Sandreas@sandberg.pp.se    entry.index = index;
11879883Sandreas@sandberg.pp.se    entry.reserved = 0;
11889883Sandreas@sandberg.pp.se    entry.data = 0;
11899883Sandreas@sandberg.pp.se
11909883Sandreas@sandberg.pp.se    getMSRs(*kvm_msrs.get());
11919883Sandreas@sandberg.pp.se    return entry.data;
11929883Sandreas@sandberg.pp.se}
11939883Sandreas@sandberg.pp.se
11949883Sandreas@sandberg.pp.seconst Kvm::MSRIndexVector &
11959883Sandreas@sandberg.pp.seX86KvmCPU::getMsrIntersection() const
11969883Sandreas@sandberg.pp.se{
11979883Sandreas@sandberg.pp.se    if (cachedMsrIntersection.empty()) {
11989883Sandreas@sandberg.pp.se        const Kvm::MSRIndexVector &kvm_msrs(vm.kvm.getSupportedMSRs());
11999883Sandreas@sandberg.pp.se
12009883Sandreas@sandberg.pp.se        DPRINTF(Kvm, "kvm-x86: Updating MSR intersection\n");
12019883Sandreas@sandberg.pp.se        for (auto it = kvm_msrs.cbegin(); it != kvm_msrs.cend(); ++it) {
12029883Sandreas@sandberg.pp.se            if (X86ISA::msrMap.find(*it) != X86ISA::msrMap.end()) {
12039883Sandreas@sandberg.pp.se                cachedMsrIntersection.push_back(*it);
12049883Sandreas@sandberg.pp.se                DPRINTF(Kvm, "kvm-x86: Adding MSR 0x%x\n", *it);
12059883Sandreas@sandberg.pp.se            } else {
12069883Sandreas@sandberg.pp.se                warn("kvm-x86: MSR (0x%x) unsupported by gem5. Skipping.\n",
12079883Sandreas@sandberg.pp.se                     *it);
12089883Sandreas@sandberg.pp.se            }
12099883Sandreas@sandberg.pp.se        }
12109883Sandreas@sandberg.pp.se    }
12119883Sandreas@sandberg.pp.se
12129883Sandreas@sandberg.pp.se    return cachedMsrIntersection;
12139883Sandreas@sandberg.pp.se}
12149883Sandreas@sandberg.pp.se
12159883Sandreas@sandberg.pp.sevoid
12169883Sandreas@sandberg.pp.seX86KvmCPU::getDebugRegisters(struct kvm_debugregs &regs) const
12179883Sandreas@sandberg.pp.se{
12189883Sandreas@sandberg.pp.se#ifdef KVM_GET_DEBUGREGS
12199883Sandreas@sandberg.pp.se    if (ioctl(KVM_GET_DEBUGREGS, &regs) == -1)
12209883Sandreas@sandberg.pp.se        panic("KVM: Failed to get guest debug registers\n");
12219883Sandreas@sandberg.pp.se#else
12229883Sandreas@sandberg.pp.se    panic("KVM: Unsupported getDebugRegisters call.\n");
12239883Sandreas@sandberg.pp.se#endif
12249883Sandreas@sandberg.pp.se}
12259883Sandreas@sandberg.pp.se
12269883Sandreas@sandberg.pp.sevoid
12279883Sandreas@sandberg.pp.seX86KvmCPU::setDebugRegisters(const struct kvm_debugregs &regs)
12289883Sandreas@sandberg.pp.se{
12299883Sandreas@sandberg.pp.se#ifdef KVM_SET_DEBUGREGS
12309883Sandreas@sandberg.pp.se    if (ioctl(KVM_SET_DEBUGREGS, (void *)&regs) == -1)
12319883Sandreas@sandberg.pp.se        panic("KVM: Failed to set guest debug registers\n");
12329883Sandreas@sandberg.pp.se#else
12339883Sandreas@sandberg.pp.se    panic("KVM: Unsupported setDebugRegisters call.\n");
12349883Sandreas@sandberg.pp.se#endif
12359883Sandreas@sandberg.pp.se}
12369883Sandreas@sandberg.pp.se
12379883Sandreas@sandberg.pp.sevoid
12389883Sandreas@sandberg.pp.seX86KvmCPU::getXCRs(struct kvm_xcrs &regs) const
12399883Sandreas@sandberg.pp.se{
12409883Sandreas@sandberg.pp.se    if (ioctl(KVM_GET_XCRS, &regs) == -1)
12419883Sandreas@sandberg.pp.se        panic("KVM: Failed to get guest debug registers\n");
12429883Sandreas@sandberg.pp.se}
12439883Sandreas@sandberg.pp.se
12449883Sandreas@sandberg.pp.sevoid
12459883Sandreas@sandberg.pp.seX86KvmCPU::setXCRs(const struct kvm_xcrs &regs)
12469883Sandreas@sandberg.pp.se{
12479883Sandreas@sandberg.pp.se    if (ioctl(KVM_SET_XCRS, (void *)&regs) == -1)
12489883Sandreas@sandberg.pp.se        panic("KVM: Failed to set guest debug registers\n");
12499883Sandreas@sandberg.pp.se}
12509883Sandreas@sandberg.pp.se
12519883Sandreas@sandberg.pp.sevoid
12529883Sandreas@sandberg.pp.seX86KvmCPU::getXSave(struct kvm_xsave &xsave) const
12539883Sandreas@sandberg.pp.se{
12549883Sandreas@sandberg.pp.se    if (ioctl(KVM_GET_XSAVE, &xsave) == -1)
12559883Sandreas@sandberg.pp.se        panic("KVM: Failed to get guest debug registers\n");
12569883Sandreas@sandberg.pp.se}
12579883Sandreas@sandberg.pp.se
12589883Sandreas@sandberg.pp.sevoid
12599883Sandreas@sandberg.pp.seX86KvmCPU::setXSave(const struct kvm_xsave &xsave)
12609883Sandreas@sandberg.pp.se{
12619883Sandreas@sandberg.pp.se    if (ioctl(KVM_SET_XSAVE, (void *)&xsave) == -1)
12629883Sandreas@sandberg.pp.se        panic("KVM: Failed to set guest debug registers\n");
12639883Sandreas@sandberg.pp.se}
12649883Sandreas@sandberg.pp.se
12659883Sandreas@sandberg.pp.se
12669883Sandreas@sandberg.pp.sevoid
12679883Sandreas@sandberg.pp.seX86KvmCPU::getVCpuEvents(struct kvm_vcpu_events &events) const
12689883Sandreas@sandberg.pp.se{
12699883Sandreas@sandberg.pp.se    if (ioctl(KVM_GET_VCPU_EVENTS, &events) == -1)
12709883Sandreas@sandberg.pp.se        panic("KVM: Failed to get guest debug registers\n");
12719883Sandreas@sandberg.pp.se}
12729883Sandreas@sandberg.pp.se
12739883Sandreas@sandberg.pp.sevoid
12749883Sandreas@sandberg.pp.seX86KvmCPU::setVCpuEvents(const struct kvm_vcpu_events &events)
12759883Sandreas@sandberg.pp.se{
12769883Sandreas@sandberg.pp.se    if (ioctl(KVM_SET_VCPU_EVENTS, (void *)&events) == -1)
12779883Sandreas@sandberg.pp.se        panic("KVM: Failed to set guest debug registers\n");
12789883Sandreas@sandberg.pp.se}
12799883Sandreas@sandberg.pp.se
12809883Sandreas@sandberg.pp.seX86KvmCPU *
12819883Sandreas@sandberg.pp.seX86KvmCPUParams::create()
12829883Sandreas@sandberg.pp.se{
12839883Sandreas@sandberg.pp.se    return new X86KvmCPU(this);
12849883Sandreas@sandberg.pp.se}
1285