x86_cpu.hh revision 9883
1/*
2 * Copyright (c) 2013 Andreas Sandberg
3 * All rights reserved
4 *
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.
15 *
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.
27 *
28 * Authors: Andreas Sandberg
29 */
30
31#ifndef __CPU_KVM_X86_CPU_HH__
32#define __CPU_KVM_X86_CPU_HH__
33
34#include "cpu/kvm/base.hh"
35#include "cpu/kvm/vm.hh"
36#include "params/X86KvmCPU.hh"
37
38/**
39 * x86 implementation of a KVM-based hardware virtualized CPU.
40 */
41class X86KvmCPU : public BaseKvmCPU
42{
43  public:
44    X86KvmCPU(X86KvmCPUParams *params);
45    virtual ~X86KvmCPU();
46
47    void startup();
48
49    /** @{ */
50    void dump();
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;
59    /** @} */
60
61  protected:
62    typedef std::vector<struct kvm_msr_entry> KvmMSRVector;
63
64    Tick kvmRun(Tick ticks);
65
66    /**
67     * Run the virtual CPU until draining completes.
68     *
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).
75     *
76     * @see BaseKvmCPU::kvmRunDrain()
77     * @see archIsDrained()
78     *
79     * @return Number of ticks executed
80     */
81    Tick kvmRunDrain();
82
83    /** Wrapper that synchronizes state in kvm_run */
84    Tick kvmRunWrapper(Tick ticks);
85
86    uint64_t getHostCycles() const;
87
88    /**
89     * Methods to access CPUID information using the extended
90     * API. Only available if Kvm::capExtendedCPUID() is true.
91     *
92     * @{
93     */
94    void setCPUID(const struct kvm_cpuid2 &cpuid);
95    void setCPUID(const Kvm::CPUIDVector &cpuid);
96    /** @} */
97
98    /**
99     * Methods to access MSRs in the guest.
100     *
101     * @{
102     */
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;
108    /** @} */
109
110    /**
111     * Get a list of MSRs supported by both gem5 and KVM.
112     *
113     * @note This method uses an internal cache and only generates the
114     * MSR list once.
115     *
116     * @return reference to a list of msr indices
117     */
118    const Kvm::MSRIndexVector &getMsrIntersection() const;
119
120    /**
121     * Wrappers around KVM's state transfer methods.
122     *
123     * @{
124     */
125    void getDebugRegisters(struct kvm_debugregs &regs) const;
126    void setDebugRegisters(const struct kvm_debugregs &regs);
127    void getXCRs(struct kvm_xcrs &regs) const;
128    void setXCRs(const struct kvm_xcrs &regs);
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);
133    /** @} */
134
135    void updateKvmState();
136    void updateThreadContext();
137
138    /**
139     * Inject pending interrupts from gem5 into the virtual CPU.
140     */
141    void deliverInterrupts();
142
143    /**
144     * Handle x86 legacy IO (in/out)
145     */
146    Tick handleKvmExitIO();
147
148    Tick handleKvmExitIRQWindowOpen();
149
150    /**
151     * Check if there are pending events in the vCPU that prevents it
152     * from being drained.
153     *
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.
157     *
158     * @return False if there are pending events in the guest, True
159     * otherwise.
160     */
161    bool archIsDrained() const;
162
163  private:
164    /**
165     * Support routines to update the state of the KVM CPU from gem5's
166     * state representation.
167     *
168     * @{
169     */
170    /** Update integer registers */
171    void updateKvmStateRegs();
172    /** Update control registers (CRx, segments, etc.) */
173    void updateKvmStateSRegs();
174    /** Update FPU and SIMD registers */
175    void updateKvmStateFPU();
176    /** Update MSR registers */
177    void updateKvmStateMSRs();
178    /** @} */
179
180    /**
181     * Support routines to update the state of gem5's thread context from
182     * KVM's state representation.
183     *
184     * @{
185     */
186    /** Update integer registers */
187    void updateThreadContextRegs();
188    /** Update control registers (CRx, segments, etc.) */
189    void updateThreadContextSRegs();
190    /** Update FPU and SIMD registers */
191    void updateThreadContextFPU();
192    /** Update MSR registers */
193    void updateThreadContextMSRs();
194    /** @} */
195
196    /** Transfer gem5's CPUID values into the virtual CPU. */
197    void updateCPUID();
198
199    /**
200     * Handle a 32-bit IO access that should be mapped to a MiscReg.
201     *
202     * @note This method can only be called on when handling IO after
203     * a KVM_EXIT_IO.
204     *
205     * @param miscreg Register to map the current IO access to.
206     */
207    void handleIOMiscReg32(int miscreg);
208
209    /** Reusable IO request */
210    Request io_req;
211
212    /** Cached intersection of supported MSRs */
213    mutable Kvm::MSRIndexVector cachedMsrIntersection;
214
215    /** @{ */
216    /** Kvm::capDebugRegs() available? */
217    bool haveDebugRegs;
218    /** Kvm::capXSave() available? */
219    bool haveXSave;
220    /** Kvm::capXCRs() available? */
221    bool haveXCRs;
222    /** @} */
223};
224
225#endif
226