summaryrefslogtreecommitdiff
path: root/src/cpu/kvm/x86_cpu.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/kvm/x86_cpu.hh')
-rw-r--r--src/cpu/kvm/x86_cpu.hh225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/cpu/kvm/x86_cpu.hh b/src/cpu/kvm/x86_cpu.hh
new file mode 100644
index 000000000..602fc8416
--- /dev/null
+++ b/src/cpu/kvm/x86_cpu.hh
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2013 Andreas Sandberg
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andreas Sandberg
+ */
+
+#ifndef __CPU_KVM_X86_CPU_HH__
+#define __CPU_KVM_X86_CPU_HH__
+
+#include "cpu/kvm/base.hh"
+#include "cpu/kvm/vm.hh"
+#include "params/X86KvmCPU.hh"
+
+/**
+ * x86 implementation of a KVM-based hardware virtualized CPU.
+ */
+class X86KvmCPU : public BaseKvmCPU
+{
+ public:
+ X86KvmCPU(X86KvmCPUParams *params);
+ virtual ~X86KvmCPU();
+
+ void startup();
+
+ /** @{ */
+ void dump();
+ void dumpFpuRegs() const;
+ void dumpIntRegs() const;
+ void dumpSpecRegs() const;
+ void dumpDebugRegs() const;
+ void dumpXCRs() const;
+ void dumpXSave() const;
+ void dumpVCpuEvents() const;
+ void dumpMSRs() const;
+ /** @} */
+
+ protected:
+ typedef std::vector<struct kvm_msr_entry> KvmMSRVector;
+
+ Tick kvmRun(Tick ticks);
+
+ /**
+ * Run the virtual CPU until draining completes.
+ *
+ * In addition to the base functionality provided by
+ * BaseKvmCPU::kvmRunDrain(), this method handles x86-specific
+ * cases where there are pending interrupt events in the virtual
+ * CPU. These are handled by requesting an interrupt window if
+ * interrupts are pending (causing the vCPU to execute until
+ * interrupts can be delivered again).
+ *
+ * @see BaseKvmCPU::kvmRunDrain()
+ * @see archIsDrained()
+ *
+ * @return Number of ticks executed
+ */
+ Tick kvmRunDrain();
+
+ /** Wrapper that synchronizes state in kvm_run */
+ Tick kvmRunWrapper(Tick ticks);
+
+ uint64_t getHostCycles() const;
+
+ /**
+ * Methods to access CPUID information using the extended
+ * API. Only available if Kvm::capExtendedCPUID() is true.
+ *
+ * @{
+ */
+ void setCPUID(const struct kvm_cpuid2 &cpuid);
+ void setCPUID(const Kvm::CPUIDVector &cpuid);
+ /** @} */
+
+ /**
+ * Methods to access MSRs in the guest.
+ *
+ * @{
+ */
+ void setMSRs(const struct kvm_msrs &msrs);
+ void setMSRs(const KvmMSRVector &msrs);
+ void getMSRs(struct kvm_msrs &msrs) const;
+ void setMSR(uint32_t index, uint64_t value);
+ uint64_t getMSR(uint32_t index) const;
+ /** @} */
+
+ /**
+ * Get a list of MSRs supported by both gem5 and KVM.
+ *
+ * @note This method uses an internal cache and only generates the
+ * MSR list once.
+ *
+ * @return reference to a list of msr indices
+ */
+ const Kvm::MSRIndexVector &getMsrIntersection() const;
+
+ /**
+ * Wrappers around KVM's state transfer methods.
+ *
+ * @{
+ */
+ void getDebugRegisters(struct kvm_debugregs &regs) const;
+ void setDebugRegisters(const struct kvm_debugregs &regs);
+ void getXCRs(struct kvm_xcrs &regs) const;
+ void setXCRs(const struct kvm_xcrs &regs);
+ void getXSave(struct kvm_xsave &xsave) const;
+ void setXSave(const struct kvm_xsave &xsave);
+ void getVCpuEvents(struct kvm_vcpu_events &events) const;
+ void setVCpuEvents(const struct kvm_vcpu_events &events);
+ /** @} */
+
+ void updateKvmState();
+ void updateThreadContext();
+
+ /**
+ * Inject pending interrupts from gem5 into the virtual CPU.
+ */
+ void deliverInterrupts();
+
+ /**
+ * Handle x86 legacy IO (in/out)
+ */
+ Tick handleKvmExitIO();
+
+ Tick handleKvmExitIRQWindowOpen();
+
+ /**
+ * Check if there are pending events in the vCPU that prevents it
+ * from being drained.
+ *
+ * There are cases after interrupt injection where the interrupt
+ * is still pending in the guest. This method detects such cases
+ * and requests additional draining.
+ *
+ * @return False if there are pending events in the guest, True
+ * otherwise.
+ */
+ bool archIsDrained() const;
+
+ private:
+ /**
+ * Support routines to update the state of the KVM CPU from gem5's
+ * state representation.
+ *
+ * @{
+ */
+ /** Update integer registers */
+ void updateKvmStateRegs();
+ /** Update control registers (CRx, segments, etc.) */
+ void updateKvmStateSRegs();
+ /** Update FPU and SIMD registers */
+ void updateKvmStateFPU();
+ /** Update MSR registers */
+ void updateKvmStateMSRs();
+ /** @} */
+
+ /**
+ * Support routines to update the state of gem5's thread context from
+ * KVM's state representation.
+ *
+ * @{
+ */
+ /** Update integer registers */
+ void updateThreadContextRegs();
+ /** Update control registers (CRx, segments, etc.) */
+ void updateThreadContextSRegs();
+ /** Update FPU and SIMD registers */
+ void updateThreadContextFPU();
+ /** Update MSR registers */
+ void updateThreadContextMSRs();
+ /** @} */
+
+ /** Transfer gem5's CPUID values into the virtual CPU. */
+ void updateCPUID();
+
+ /**
+ * Handle a 32-bit IO access that should be mapped to a MiscReg.
+ *
+ * @note This method can only be called on when handling IO after
+ * a KVM_EXIT_IO.
+ *
+ * @param miscreg Register to map the current IO access to.
+ */
+ void handleIOMiscReg32(int miscreg);
+
+ /** Reusable IO request */
+ Request io_req;
+
+ /** Cached intersection of supported MSRs */
+ mutable Kvm::MSRIndexVector cachedMsrIntersection;
+
+ /** @{ */
+ /** Kvm::capDebugRegs() available? */
+ bool haveDebugRegs;
+ /** Kvm::capXSave() available? */
+ bool haveXSave;
+ /** Kvm::capXCRs() available? */
+ bool haveXCRs;
+ /** @} */
+};
+
+#endif