diff options
Diffstat (limited to 'src/cpu/kvm/x86_cpu.hh')
-rw-r--r-- | src/cpu/kvm/x86_cpu.hh | 225 |
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 ®s) const; + void setDebugRegisters(const struct kvm_debugregs ®s); + void getXCRs(struct kvm_xcrs ®s) const; + void setXCRs(const struct kvm_xcrs ®s); + 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 |