x86_cpu.hh revision 9883
12SN/A/*
21762SN/A * Copyright (c) 2013 Andreas Sandberg
32SN/A * All rights reserved
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Andreas Sandberg
292SN/A */
302SN/A
3111793Sbrandon.potter@amd.com#ifndef __CPU_KVM_X86_CPU_HH__
3211793Sbrandon.potter@amd.com#define __CPU_KVM_X86_CPU_HH__
338869SAli.Saidi@ARM.com
348869SAli.Saidi@ARM.com#include "cpu/kvm/base.hh"
352SN/A#include "cpu/kvm/vm.hh"
367840Snate@binkert.org#include "params/X86KvmCPU.hh"
372SN/A
3812334Sgabeblack@google.com/**
397840Snate@binkert.org * x86 implementation of a KVM-based hardware virtualized CPU.
407862Sgblack@eecs.umich.edu */
417870Sgblack@eecs.umich.educlass X86KvmCPU : public BaseKvmCPU
422SN/A{
432SN/A  public:
442SN/A    X86KvmCPU(X86KvmCPUParams *params);
457840Snate@binkert.org    virtual ~X86KvmCPU();
467840Snate@binkert.org
472SN/A    void startup();
487840Snate@binkert.org
497840Snate@binkert.org    /** @{ */
507840Snate@binkert.org    void dump();
51400SN/A    void dumpFpuRegs() const;
527840Snate@binkert.org    void dumpIntRegs() const;
537840Snate@binkert.org    void dumpSpecRegs() const;
547840Snate@binkert.org    void dumpDebugRegs() const;
55400SN/A    void dumpXCRs() const;
56400SN/A    void dumpXSave() const;
577862Sgblack@eecs.umich.edu    void dumpVCpuEvents() const;
587862Sgblack@eecs.umich.edu    void dumpMSRs() const;
597862Sgblack@eecs.umich.edu    /** @} */
607862Sgblack@eecs.umich.edu
617862Sgblack@eecs.umich.edu  protected:
627862Sgblack@eecs.umich.edu    typedef std::vector<struct kvm_msr_entry> KvmMSRVector;
637862Sgblack@eecs.umich.edu
647862Sgblack@eecs.umich.edu    Tick kvmRun(Tick ticks);
657862Sgblack@eecs.umich.edu
667862Sgblack@eecs.umich.edu    /**
677862Sgblack@eecs.umich.edu     * Run the virtual CPU until draining completes.
687862Sgblack@eecs.umich.edu     *
697862Sgblack@eecs.umich.edu     * In addition to the base functionality provided by
70400SN/A     * BaseKvmCPU::kvmRunDrain(), this method handles x86-specific
717840Snate@binkert.org     * cases where there are pending interrupt events in the virtual
72400SN/A     * CPU.  These are handled by requesting an interrupt window if
737840Snate@binkert.org     * interrupts are pending (causing the vCPU to execute until
74400SN/A     * interrupts can be delivered again).
75400SN/A     *
76400SN/A     * @see BaseKvmCPU::kvmRunDrain()
773918Ssaidi@eecs.umich.edu     * @see archIsDrained()
787840Snate@binkert.org     *
793918Ssaidi@eecs.umich.edu     * @return Number of ticks executed
80400SN/A     */
813918Ssaidi@eecs.umich.edu    Tick kvmRunDrain();
82400SN/A
83400SN/A    /** Wrapper that synchronizes state in kvm_run */
842SN/A    Tick kvmRunWrapper(Tick ticks);
852SN/A
86400SN/A    uint64_t getHostCycles() const;
87400SN/A
88400SN/A    /**
89400SN/A     * Methods to access CPUID information using the extended
902SN/A     * API. Only available if Kvm::capExtendedCPUID() is true.
917840Snate@binkert.org     *
927840Snate@binkert.org     * @{
93400SN/A     */
947840Snate@binkert.org    void setCPUID(const struct kvm_cpuid2 &cpuid);
957840Snate@binkert.org    void setCPUID(const Kvm::CPUIDVector &cpuid);
967840Snate@binkert.org    /** @} */
977840Snate@binkert.org
987840Snate@binkert.org    /**
997840Snate@binkert.org     * Methods to access MSRs in the guest.
1007840Snate@binkert.org     *
1017840Snate@binkert.org     * @{
1027840Snate@binkert.org     */
1037840Snate@binkert.org    void setMSRs(const struct kvm_msrs &msrs);
1047840Snate@binkert.org    void setMSRs(const KvmMSRVector &msrs);
1057840Snate@binkert.org    void getMSRs(struct kvm_msrs &msrs) const;
1067840Snate@binkert.org    void setMSR(uint32_t index, uint64_t value);
1077840Snate@binkert.org    uint64_t getMSR(uint32_t index) const;
1087840Snate@binkert.org    /** @} */
1097840Snate@binkert.org
1107840Snate@binkert.org    /**
1117840Snate@binkert.org     * Get a list of MSRs supported by both gem5 and KVM.
1127840Snate@binkert.org     *
1137840Snate@binkert.org     * @note This method uses an internal cache and only generates the
1147840Snate@binkert.org     * MSR list once.
1157840Snate@binkert.org     *
1167840Snate@binkert.org     * @return reference to a list of msr indices
1177840Snate@binkert.org     */
1187840Snate@binkert.org    const Kvm::MSRIndexVector &getMsrIntersection() const;
119400SN/A
1202SN/A    /**
1217840Snate@binkert.org     * Wrappers around KVM's state transfer methods.
12210905Sandreas.sandberg@arm.com     *
1237870Sgblack@eecs.umich.edu     * @{
12410905Sandreas.sandberg@arm.com     */
12510905Sandreas.sandberg@arm.com    void getDebugRegisters(struct kvm_debugregs &regs) const;
1267870Sgblack@eecs.umich.edu    void setDebugRegisters(const struct kvm_debugregs &regs);
1277870Sgblack@eecs.umich.edu    void getXCRs(struct kvm_xcrs &regs) const;
1287870Sgblack@eecs.umich.edu    void setXCRs(const struct kvm_xcrs &regs);
12910905Sandreas.sandberg@arm.com    void getXSave(struct kvm_xsave &xsave) const;
1307870Sgblack@eecs.umich.edu    void setXSave(const struct kvm_xsave &xsave);
1317870Sgblack@eecs.umich.edu    void getVCpuEvents(struct kvm_vcpu_events &events) const;
1327870Sgblack@eecs.umich.edu    void setVCpuEvents(const struct kvm_vcpu_events &events);
13310905Sandreas.sandberg@arm.com    /** @} */
13410905Sandreas.sandberg@arm.com
1357870Sgblack@eecs.umich.edu    void updateKvmState();
1367870Sgblack@eecs.umich.edu    void updateThreadContext();
1377870Sgblack@eecs.umich.edu
1387870Sgblack@eecs.umich.edu    /**
1397870Sgblack@eecs.umich.edu     * Inject pending interrupts from gem5 into the virtual CPU.
1407840Snate@binkert.org     */
141400SN/A    void deliverInterrupts();
1427840Snate@binkert.org
1437840Snate@binkert.org    /**
1447840Snate@binkert.org     * Handle x86 legacy IO (in/out)
1457840Snate@binkert.org     */
1467840Snate@binkert.org    Tick handleKvmExitIO();
1477840Snate@binkert.org
1487840Snate@binkert.org    Tick handleKvmExitIRQWindowOpen();
149400SN/A
1508869SAli.Saidi@ARM.com    /**
1518869SAli.Saidi@ARM.com     * Check if there are pending events in the vCPU that prevents it
1528869SAli.Saidi@ARM.com     * from being drained.
1538869SAli.Saidi@ARM.com     *
15410531Sandreas.hansson@arm.com     * There are cases after interrupt injection where the interrupt
15510531Sandreas.hansson@arm.com     * is still pending in the guest. This method detects such cases
15610531Sandreas.hansson@arm.com     * and requests additional draining.
15710531Sandreas.hansson@arm.com     *
15810531Sandreas.hansson@arm.com     * @return False if there are pending events in the guest, True
15910531Sandreas.hansson@arm.com     * otherwise.
16010531Sandreas.hansson@arm.com     */
16110531Sandreas.hansson@arm.com    bool archIsDrained() const;
16210531Sandreas.hansson@arm.com
16310531Sandreas.hansson@arm.com  private:
16410531Sandreas.hansson@arm.com    /**
16510531Sandreas.hansson@arm.com     * Support routines to update the state of the KVM CPU from gem5's
16610531Sandreas.hansson@arm.com     * state representation.
16710531Sandreas.hansson@arm.com     *
16810531Sandreas.hansson@arm.com     * @{
16910531Sandreas.hansson@arm.com     */
17010531Sandreas.hansson@arm.com    /** Update integer registers */
17110531Sandreas.hansson@arm.com    void updateKvmStateRegs();
17210531Sandreas.hansson@arm.com    /** Update control registers (CRx, segments, etc.) */
17310531Sandreas.hansson@arm.com    void updateKvmStateSRegs();
17410531Sandreas.hansson@arm.com    /** Update FPU and SIMD registers */
17510531Sandreas.hansson@arm.com    void updateKvmStateFPU();
17610531Sandreas.hansson@arm.com    /** Update MSR registers */
17710531Sandreas.hansson@arm.com    void updateKvmStateMSRs();
17810531Sandreas.hansson@arm.com    /** @} */
17910531Sandreas.hansson@arm.com
18010531Sandreas.hansson@arm.com    /**
1818869SAli.Saidi@ARM.com     * Support routines to update the state of gem5's thread context from
1828869SAli.Saidi@ARM.com     * 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