2 * Copyright (c) 2013 Andreas Sandberg
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Andreas Sandberg
31 #ifndef __CPU_KVM_X86_CPU_HH__
32 #define __CPU_KVM_X86_CPU_HH__
34 #include "cpu/kvm/base.hh"
35 #include "cpu/kvm/vm.hh"
36 #include "params/X86KvmCPU.hh"
39 * x86 implementation of a KVM-based hardware virtualized CPU.
41 class X86KvmCPU : public BaseKvmCPU
44 X86KvmCPU(X86KvmCPUParams *params);
51 void dumpFpuRegs() const;
52 void dumpIntRegs() const;
53 void dumpSpecRegs() const;
54 void dumpDebugRegs() const;
55 void dumpXCRs() const;
56 void dumpXSave() const;
57 void dumpVCpuEvents() const;
58 void dumpMSRs() const;
62 typedef std::vector<struct kvm_msr_entry> KvmMSRVector;
64 Tick kvmRun(Tick ticks);
67 * Run the virtual CPU until draining completes.
69 * In addition to the base functionality provided by
70 * BaseKvmCPU::kvmRunDrain(), this method handles x86-specific
71 * cases where there are pending interrupt events in the virtual
72 * CPU. These are handled by requesting an interrupt window if
73 * interrupts are pending (causing the vCPU to execute until
74 * interrupts can be delivered again).
76 * @see BaseKvmCPU::kvmRunDrain()
77 * @see archIsDrained()
79 * @return Number of ticks executed
83 /** Wrapper that synchronizes state in kvm_run */
84 Tick kvmRunWrapper(Tick ticks);
86 uint64_t getHostCycles() const;
89 * Methods to access CPUID information using the extended
90 * API. Only available if Kvm::capExtendedCPUID() is true.
94 void setCPUID(const struct kvm_cpuid2 &cpuid);
95 void setCPUID(const Kvm::CPUIDVector &cpuid);
99 * Methods to access MSRs in the guest.
103 void setMSRs(const struct kvm_msrs &msrs);
104 void setMSRs(const KvmMSRVector &msrs);
105 void getMSRs(struct kvm_msrs &msrs) const;
106 void setMSR(uint32_t index, uint64_t value);
107 uint64_t getMSR(uint32_t index) const;
111 * Get a list of MSRs supported by both gem5 and KVM.
113 * @note This method uses an internal cache and only generates the
116 * @return reference to a list of msr indices
118 const Kvm::MSRIndexVector &getMsrIntersection() const;
121 * Wrappers around KVM's state transfer methods.
125 void getDebugRegisters(struct kvm_debugregs ®s) const;
126 void setDebugRegisters(const struct kvm_debugregs ®s);
127 void getXCRs(struct kvm_xcrs ®s) const;
128 void setXCRs(const struct kvm_xcrs ®s);
129 void getXSave(struct kvm_xsave &xsave) const;
130 void setXSave(const struct kvm_xsave &xsave);
131 void getVCpuEvents(struct kvm_vcpu_events &events) const;
132 void setVCpuEvents(const struct kvm_vcpu_events &events);
135 void updateKvmState();
136 void updateThreadContext();
139 * Inject pending interrupts from gem5 into the virtual CPU.
141 void deliverInterrupts();
144 * Handle x86 legacy IO (in/out)
146 Tick handleKvmExitIO();
148 Tick handleKvmExitIRQWindowOpen();
151 * Check if there are pending events in the vCPU that prevents it
152 * from being drained.
154 * There are cases after interrupt injection where the interrupt
155 * is still pending in the guest. This method detects such cases
156 * and requests additional draining.
158 * @return False if there are pending events in the guest, True
161 bool archIsDrained() const;
165 * Support routines to update the state of the KVM CPU from gem5's
166 * state representation.
170 /** Update integer registers */
171 void updateKvmStateRegs();
172 /** Update control registers (CRx, segments, etc.) */
173 void updateKvmStateSRegs();
175 * Update FPU and SIMD registers
177 * This method uses the appropriate (depending on availability and
178 * user configuration) kernel API by calling
179 * updateKvmStateFPULegacy() or updateKvmStateFPUXSave().
181 * @see updateKvmStateFPULegacy()
182 * @see updateKvmStateFPUXSave()
184 void updateKvmStateFPU();
186 * Update FPU and SIMD registers using the legacy API
188 * @note This method should normally only be called by
189 * updateKvmStateFPU() which automatically chooses between
192 void updateKvmStateFPULegacy();
194 * Update FPU and SIMD registers using the XSave API
196 * @note This method should normally only be called by
197 * updateKvmStateFPU() which automatically chooses between
200 void updateKvmStateFPUXSave();
201 /** Update MSR registers */
202 void updateKvmStateMSRs();
206 * Support routines to update the state of gem5's thread context from
207 * KVM's state representation.
211 /** Update integer registers */
212 void updateThreadContextRegs(const struct kvm_regs ®s,
213 const struct kvm_sregs &sregs);
214 /** Update control registers (CRx, segments, etc.) */
215 void updateThreadContextSRegs(const struct kvm_sregs &sregs);
216 /** Update FPU and SIMD registers using the legacy API */
217 void updateThreadContextFPU(const struct kvm_fpu &fpu);
218 /** Update FPU and SIMD registers using the XSave API */
219 void updateThreadContextXSave(const struct kvm_xsave &kxsave);
220 /** Update MSR registers */
221 void updateThreadContextMSRs();
224 /** Transfer gem5's CPUID values into the virtual CPU. */
228 * Handle a 32-bit IO access that should be mapped to a MiscReg.
230 * @note This method can only be called on when handling IO after
233 * @param miscreg Register to map the current IO access to.
235 void handleIOMiscReg32(int miscreg);
237 /** Cached intersection of supported MSRs */
238 mutable Kvm::MSRIndexVector cachedMsrIntersection;
241 /** Kvm::capDebugRegs() available? */
243 /** Kvm::capXSave() available? */
246 * Should the XSave interface be used to sync the FPU and SIMD
250 /** Kvm::capXCRs() available? */