base.hh revision 10112
12650Ssaidi@eecs.umich.edu/*
22650Ssaidi@eecs.umich.edu * Copyright (c) 2012 ARM Limited
32650Ssaidi@eecs.umich.edu * All rights reserved
42650Ssaidi@eecs.umich.edu *
52650Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall
62650Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual
72650Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating
82650Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software
92650Ssaidi@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
102650Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
112650Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
122650Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form.
132650Ssaidi@eecs.umich.edu *
142650Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
152650Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
162650Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
172650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
182650Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
192650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
202650Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
212650Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
222650Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
232650Ssaidi@eecs.umich.edu * this software without specific prior written permission.
242650Ssaidi@eecs.umich.edu *
252650Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262650Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272650Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282650Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
294194Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
303817Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
313817Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
323817Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
333817Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
343817Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
354194Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362650Ssaidi@eecs.umich.edu *
373817Ssaidi@eecs.umich.edu * Authors: Andreas Sandberg
385946Sgblack@eecs.umich.edu */
393817Ssaidi@eecs.umich.edu
404103Ssaidi@eecs.umich.edu#ifndef __CPU_KVM_BASE_HH__
414103Ssaidi@eecs.umich.edu#define __CPU_KVM_BASE_HH__
424103Ssaidi@eecs.umich.edu
434103Ssaidi@eecs.umich.edu#include <memory>
445531Snate@binkert.org#include <csignal>
455531Snate@binkert.org
464103Ssaidi@eecs.umich.edu#include "base/statistics.hh"
474103Ssaidi@eecs.umich.edu#include "cpu/kvm/perfevent.hh"
485704Snate@binkert.org#include "cpu/kvm/timer.hh"
494103Ssaidi@eecs.umich.edu#include "cpu/kvm/vm.hh"
505704Snate@binkert.org#include "cpu/base.hh"
514103Ssaidi@eecs.umich.edu#include "cpu/simple_thread.hh"
525704Snate@binkert.org
534103Ssaidi@eecs.umich.edu/** Signal to use to trigger time-based exits from KVM */
545704Snate@binkert.org#define KVM_TIMER_SIGNAL SIGRTMIN
554103Ssaidi@eecs.umich.edu
564103Ssaidi@eecs.umich.edu/** Signal to use to trigger instruction-based exits from KVM */
574103Ssaidi@eecs.umich.edu#define KVM_INST_SIGNAL (SIGRTMIN+1)
584103Ssaidi@eecs.umich.edu
595704Snate@binkert.org// forward declarations
604103Ssaidi@eecs.umich.educlass ThreadContext;
615704Snate@binkert.orgstruct BaseKvmCPUParams;
624103Ssaidi@eecs.umich.edu
634103Ssaidi@eecs.umich.edu/**
644103Ssaidi@eecs.umich.edu * Base class for KVM based CPU models
655946Sgblack@eecs.umich.edu *
665946Sgblack@eecs.umich.edu * All architecture specific KVM implementation should inherit from
675946Sgblack@eecs.umich.edu * this class. The most basic CPU models only need to override the
685946Sgblack@eecs.umich.edu * updateKvmState() and updateThreadContext() methods to implement
695946Sgblack@eecs.umich.edu * state synchronization between gem5 and KVM.
705946Sgblack@eecs.umich.edu *
715946Sgblack@eecs.umich.edu * The architecture specific implementation is also responsible for
725946Sgblack@eecs.umich.edu * delivering interrupts into the VM. This is typically done by
735946Sgblack@eecs.umich.edu * overriding tick() and checking the thread context before entering
745946Sgblack@eecs.umich.edu * into the VM. In order to deliver an interrupt, the implementation
755946Sgblack@eecs.umich.edu * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt()
765946Sgblack@eecs.umich.edu * depending on the specifics of the underlying hardware/drivers.
775946Sgblack@eecs.umich.edu */
785946Sgblack@eecs.umich.educlass BaseKvmCPU : public BaseCPU
795946Sgblack@eecs.umich.edu{
805946Sgblack@eecs.umich.edu  public:
815946Sgblack@eecs.umich.edu    BaseKvmCPU(BaseKvmCPUParams *params);
825946Sgblack@eecs.umich.edu    virtual ~BaseKvmCPU();
835946Sgblack@eecs.umich.edu
845946Sgblack@eecs.umich.edu    void init();
854103Ssaidi@eecs.umich.edu    void startup();
863817Ssaidi@eecs.umich.edu    void regStats();
874185Ssaidi@eecs.umich.edu
882650Ssaidi@eecs.umich.edu    void serializeThread(std::ostream &os, ThreadID tid);
895531Snate@binkert.org    void unserializeThread(Checkpoint *cp, const std::string &section,
905531Snate@binkert.org                           ThreadID tid);
912650Ssaidi@eecs.umich.edu
922650Ssaidi@eecs.umich.edu    unsigned int drain(DrainManager *dm);
932982Sstever@eecs.umich.edu    void drainResume();
943919Shsul@eecs.umich.edu
954172Ssaidi@eecs.umich.edu    void switchOut();
964103Ssaidi@eecs.umich.edu    void takeOverFrom(BaseCPU *cpu);
973919Shsul@eecs.umich.edu
983919Shsul@eecs.umich.edu    void verifyMemoryMode() const;
994172Ssaidi@eecs.umich.edu
1003919Shsul@eecs.umich.edu    MasterPort &getDataPort() { return dataPort; }
1014172Ssaidi@eecs.umich.edu    MasterPort &getInstPort() { return instPort; }
1022650Ssaidi@eecs.umich.edu
1033919Shsul@eecs.umich.edu    void wakeup();
1043919Shsul@eecs.umich.edu    void activateContext(ThreadID thread_num, Cycles delay);
1053919Shsul@eecs.umich.edu    void suspendContext(ThreadID thread_num);
1064172Ssaidi@eecs.umich.edu    void deallocateContext(ThreadID thread_num);
1074103Ssaidi@eecs.umich.edu    void haltContext(ThreadID thread_num);
1085606Snate@binkert.org
1093919Shsul@eecs.umich.edu    ThreadContext *getContext(int tn);
1104103Ssaidi@eecs.umich.edu
1114103Ssaidi@eecs.umich.edu    Counter totalInsts() const;
1125606Snate@binkert.org    Counter totalOps() const;
1135606Snate@binkert.org
1144103Ssaidi@eecs.umich.edu    /** Dump the internal state to the terminal. */
1153919Shsul@eecs.umich.edu    virtual void dump();
1163919Shsul@eecs.umich.edu
1172650Ssaidi@eecs.umich.edu    /**
1183919Shsul@eecs.umich.edu     * A cached copy of a thread's state in the form of a SimpleThread
1193919Shsul@eecs.umich.edu     * object.
1203919Shsul@eecs.umich.edu     *
1214172Ssaidi@eecs.umich.edu     * Normally the actual thread state is stored in the KVM vCPU. If KVM has
1223919Shsul@eecs.umich.edu     * been running this copy is will be out of date. If we recently handled
1235606Snate@binkert.org     * some events within gem5 that required state to be updated this could be
1243919Shsul@eecs.umich.edu     * the most up-to-date copy. When getContext() or updateThreadContext() is
1255531Snate@binkert.org     * called this copy gets updated.  The method syncThreadContext can
1264103Ssaidi@eecs.umich.edu     * be used within a KVM CPU to update the thread context if the
1274103Ssaidi@eecs.umich.edu     * KVM state is dirty (i.e., the vCPU has been run since the last
1285606Snate@binkert.org     * update).
1295606Snate@binkert.org     */
1304103Ssaidi@eecs.umich.edu    SimpleThread *thread;
1313919Shsul@eecs.umich.edu
1323919Shsul@eecs.umich.edu    /** ThreadContext object, provides an interface for external
1332650Ssaidi@eecs.umich.edu     * objects to modify this thread's state.
1343919Shsul@eecs.umich.edu     */
1354172Ssaidi@eecs.umich.edu    ThreadContext *tc;
1363827Shsul@eecs.umich.edu
1373919Shsul@eecs.umich.edu    KvmVM &vm;
1384172Ssaidi@eecs.umich.edu
1394103Ssaidi@eecs.umich.edu  protected:
1403919Shsul@eecs.umich.edu    /**
1412650Ssaidi@eecs.umich.edu     *
1423919Shsul@eecs.umich.edu     * @dot
1433919Shsul@eecs.umich.edu     *   digraph {
1442650Ssaidi@eecs.umich.edu     *     Idle;
1453921Shsul@eecs.umich.edu     *     Running;
1464172Ssaidi@eecs.umich.edu     *     RunningService;
1474103Ssaidi@eecs.umich.edu     *     RunningServiceCompletion;
1485704Snate@binkert.org     *
1494103Ssaidi@eecs.umich.edu     *     Idle -> Idle;
1505704Snate@binkert.org     *     Idle -> Running [label="activateContext()", URL="\ref activateContext"];
1514103Ssaidi@eecs.umich.edu     *     Running -> Running [label="tick()", URL="\ref tick"];
1523921Shsul@eecs.umich.edu     *     Running -> RunningService [label="tick()", URL="\ref tick"];
1533919Shsul@eecs.umich.edu     *     Running -> Idle [label="suspendContext()", URL="\ref suspendContext"];
1543919Shsul@eecs.umich.edu     *     Running -> Idle [label="drain()", URL="\ref drain"];
1554172Ssaidi@eecs.umich.edu     *     Idle -> Running [label="drainResume()", URL="\ref drainResume"];
1563919Shsul@eecs.umich.edu     *     RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"];
1572650Ssaidi@eecs.umich.edu     *     RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"];
1583919Shsul@eecs.umich.edu     *     RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"];
1593919Shsul@eecs.umich.edu     *   }
1604172Ssaidi@eecs.umich.edu     * @enddot
1614103Ssaidi@eecs.umich.edu     */
1625704Snate@binkert.org    enum Status {
1634103Ssaidi@eecs.umich.edu        /** Context not scheduled in KVM.
1645704Snate@binkert.org         *
1654103Ssaidi@eecs.umich.edu         * The CPU generally enters this state when the guest execute
1663919Shsul@eecs.umich.edu         * an instruction that halts the CPU (e.g., WFI on ARM or HLT
1673919Shsul@eecs.umich.edu         * on X86) if KVM traps this instruction. Ticks are not
1684172Ssaidi@eecs.umich.edu         * scheduled in this state.
1694103Ssaidi@eecs.umich.edu         *
1705704Snate@binkert.org         * @see suspendContext()
1714103Ssaidi@eecs.umich.edu         */
1725704Snate@binkert.org        Idle,
1734103Ssaidi@eecs.umich.edu        /** Running normally.
1743919Shsul@eecs.umich.edu         *
1753919Shsul@eecs.umich.edu         * This is the normal run state of the CPU. KVM will be
1764172Ssaidi@eecs.umich.edu         * entered next time tick() is called.
1774103Ssaidi@eecs.umich.edu         */
1785704Snate@binkert.org        Running,
1794103Ssaidi@eecs.umich.edu        /** Requiring service at the beginning of the next cycle.
1805704Snate@binkert.org         *
1814103Ssaidi@eecs.umich.edu         * The virtual machine has exited and requires service, tick()
1823919Shsul@eecs.umich.edu         * will call handleKvmExit() on the next cycle. The next state
1833919Shsul@eecs.umich.edu         * after running service is determined in handleKvmExit() and
1844172Ssaidi@eecs.umich.edu         * depends on what kind of service the guest requested:
1854103Ssaidi@eecs.umich.edu         * <ul>
1863919Shsul@eecs.umich.edu         *   <li>IO/MMIO: RunningServiceCompletion
1873828Shsul@eecs.umich.edu         *   <li>Halt: Idle
1883919Shsul@eecs.umich.edu         *   <li>Others: Running
1893919Shsul@eecs.umich.edu         * </ul>
1903919Shsul@eecs.umich.edu         */
1914172Ssaidi@eecs.umich.edu        RunningService,
1923919Shsul@eecs.umich.edu        /** Service completion in progress.
1935606Snate@binkert.org         *
1943919Shsul@eecs.umich.edu         * The VM has requested service that requires KVM to be
1955531Snate@binkert.org         * entered once in order to get to a consistent state. This
1964103Ssaidi@eecs.umich.edu         * happens in handleKvmExit() or one of its friends after IO
1974103Ssaidi@eecs.umich.edu         * exits. After executing tick(), the CPU will transition into
1985606Snate@binkert.org         * the Running or RunningService state.
1995606Snate@binkert.org         */
2004103Ssaidi@eecs.umich.edu        RunningServiceCompletion,
2013919Shsul@eecs.umich.edu    };
2023919Shsul@eecs.umich.edu
2033817Ssaidi@eecs.umich.edu    /** CPU run state */
2043919Shsul@eecs.umich.edu    Status _status;
2053919Shsul@eecs.umich.edu
2064172Ssaidi@eecs.umich.edu    /**
2074103Ssaidi@eecs.umich.edu     * Execute the CPU until the next event in the main event queue or
2084103Ssaidi@eecs.umich.edu     * until the guest needs service from gem5.
2095704Snate@binkert.org     */
2104103Ssaidi@eecs.umich.edu    void tick();
2115704Snate@binkert.org
2124103Ssaidi@eecs.umich.edu    /**
2133919Shsul@eecs.umich.edu     * Get the value of the hardware cycle counter in the guest.
2143919Shsul@eecs.umich.edu     *
2154194Ssaidi@eecs.umich.edu     * This method is supposed to return the total number of cycles
2164194Ssaidi@eecs.umich.edu     * executed in hardware mode relative to some arbitrary point in
2174194Ssaidi@eecs.umich.edu     * the past. It's mainly used when estimating the number of cycles
2183919Shsul@eecs.umich.edu     * actually executed by the CPU in kvmRun(). The default behavior
2194194Ssaidi@eecs.umich.edu     * of this method is to use the cycles performance counter, but
2204194Ssaidi@eecs.umich.edu     * some architectures may want to use internal registers instead.
2214194Ssaidi@eecs.umich.edu     *
2224194Ssaidi@eecs.umich.edu     * @return Number of host cycles executed relative to an undefined
2234216Ssaidi@eecs.umich.edu     * point in the past.
2244194Ssaidi@eecs.umich.edu     */
2254194Ssaidi@eecs.umich.edu    virtual uint64_t getHostCycles() const;
2264194Ssaidi@eecs.umich.edu
2274194Ssaidi@eecs.umich.edu    /**
2285531Snate@binkert.org     * Request KVM to run the guest for a given number of ticks. The
2293919Shsul@eecs.umich.edu     * method returns the approximate number of ticks executed.
2303817Ssaidi@eecs.umich.edu     *
2313919Shsul@eecs.umich.edu     * @note The returned number of ticks can be both larger or
2325531Snate@binkert.org     * smaller than the requested number of ticks. A smaller number
2335531Snate@binkert.org     * can, for example, occur when the guest executes MMIO. A larger
2342650Ssaidi@eecs.umich.edu     * number is typically due to performance counter inaccuracies.
2352650Ssaidi@eecs.umich.edu     *
2362650Ssaidi@eecs.umich.edu     * @note This method is virtual in order to allow implementations
2372650Ssaidi@eecs.umich.edu     * to check for architecture specific events (e.g., interrupts)
2384185Ssaidi@eecs.umich.edu     * before entering the VM.
2392650Ssaidi@eecs.umich.edu     *
2404194Ssaidi@eecs.umich.edu     * @note It is the response of the caller (normally tick()) to
2414194Ssaidi@eecs.umich.edu     * make sure that the KVM state is synchronized and that the TC is
2422650Ssaidi@eecs.umich.edu     * invalidated after entering KVM.
2433919Shsul@eecs.umich.edu     *
2443825Ssaidi@eecs.umich.edu     * @note This method does not normally cause any state
2453825Ssaidi@eecs.umich.edu     * transitions. However, if it may suspend the CPU by suspending
2463825Ssaidi@eecs.umich.edu     * the thread, which leads to a transition to the Idle state. In
2473825Ssaidi@eecs.umich.edu     * such a case, kvm <i>must not</i> be entered.
2483825Ssaidi@eecs.umich.edu     *
2493825Ssaidi@eecs.umich.edu     * @param ticks Number of ticks to execute, set to 0 to exit
2503825Ssaidi@eecs.umich.edu     * immediately after finishing pending operations.
2513825Ssaidi@eecs.umich.edu     * @return Number of ticks executed (see note)
2523825Ssaidi@eecs.umich.edu     */
2533825Ssaidi@eecs.umich.edu    virtual Tick kvmRun(Tick ticks);
2543825Ssaidi@eecs.umich.edu
2553825Ssaidi@eecs.umich.edu    /**
2563825Ssaidi@eecs.umich.edu     * Request the CPU to run until draining completes.
2573825Ssaidi@eecs.umich.edu     *
2583825Ssaidi@eecs.umich.edu     * This function normally calls kvmRun(0) to make KVM finish
2593825Ssaidi@eecs.umich.edu     * pending MMIO operations. Architecures implementing
2604172Ssaidi@eecs.umich.edu     * archIsDrained() must override this method.
2612650Ssaidi@eecs.umich.edu     *
2623825Ssaidi@eecs.umich.edu     * @see BaseKvmCPU::archIsDrained()
2634172Ssaidi@eecs.umich.edu     *
2643825Ssaidi@eecs.umich.edu     * @return Number of ticks executed
2654207Ssaidi@eecs.umich.edu     */
2664207Ssaidi@eecs.umich.edu    virtual Tick kvmRunDrain();
2674207Ssaidi@eecs.umich.edu
2684207Ssaidi@eecs.umich.edu    /**
2694207Ssaidi@eecs.umich.edu     * Get a pointer to the kvm_run structure containing all the input
2704207Ssaidi@eecs.umich.edu     * and output parameters from kvmRun().
2714207Ssaidi@eecs.umich.edu     */
2722650Ssaidi@eecs.umich.edu    struct kvm_run *getKvmRunState() { return _kvmRun; };
2734194Ssaidi@eecs.umich.edu
2744194Ssaidi@eecs.umich.edu    /**
2754194Ssaidi@eecs.umich.edu     * Retrieve a pointer to guest data stored at the end of the
2764194Ssaidi@eecs.umich.edu     * kvm_run structure. This is mainly used for PIO operations
2774194Ssaidi@eecs.umich.edu     * (KVM_EXIT_IO).
2784194Ssaidi@eecs.umich.edu     *
2795531Snate@binkert.org     * @param offset Offset as specified by the kvm_run structure
2805531Snate@binkert.org     * @return Pointer to guest data
2815720Snate@binkert.org     */
2824194Ssaidi@eecs.umich.edu    uint8_t *getGuestData(uint64_t offset) const {
2835714Shsul@eecs.umich.edu        return (uint8_t *)_kvmRun + offset;
2844194Ssaidi@eecs.umich.edu    };
2855714Shsul@eecs.umich.edu
2864194Ssaidi@eecs.umich.edu    /**
2874194Ssaidi@eecs.umich.edu     * @addtogroup KvmInterrupts
2884194Ssaidi@eecs.umich.edu     * @{
2894194Ssaidi@eecs.umich.edu     */
2904194Ssaidi@eecs.umich.edu    /**
2914194Ssaidi@eecs.umich.edu     * Send a non-maskable interrupt to the guest
2924194Ssaidi@eecs.umich.edu     *
2934194Ssaidi@eecs.umich.edu     * @note The presence of this call depends on Kvm::capUserNMI().
2944194Ssaidi@eecs.umich.edu     */
2954194Ssaidi@eecs.umich.edu    void kvmNonMaskableInterrupt();
2964194Ssaidi@eecs.umich.edu
2974194Ssaidi@eecs.umich.edu    /**
2984194Ssaidi@eecs.umich.edu     * Send a normal interrupt to the guest
2994194Ssaidi@eecs.umich.edu     *
3004194Ssaidi@eecs.umich.edu     * @note Make sure that ready_for_interrupt_injection in kvm_run
3014194Ssaidi@eecs.umich.edu     * is set prior to calling this function. If not, an interrupt
3024194Ssaidi@eecs.umich.edu     * window must be requested by setting request_interrupt_window in
3034194Ssaidi@eecs.umich.edu     * kvm_run to 1 and restarting the guest.
3044194Ssaidi@eecs.umich.edu     *
3054194Ssaidi@eecs.umich.edu     * @param interrupt Structure describing the interrupt to send
3063825Ssaidi@eecs.umich.edu     */
3073825Ssaidi@eecs.umich.edu    void kvmInterrupt(const struct kvm_interrupt &interrupt);
3082650Ssaidi@eecs.umich.edu
3092650Ssaidi@eecs.umich.edu    /** @} */
3102650Ssaidi@eecs.umich.edu
3112651Ssaidi@eecs.umich.edu    /** @{ */
3122680Sktlim@umich.edu    /**
3132651Ssaidi@eecs.umich.edu     * Get/Set the register state of the guest vCPU
3142651Ssaidi@eecs.umich.edu     *
3152651Ssaidi@eecs.umich.edu     * KVM has two different interfaces for accessing the state of the
3162651Ssaidi@eecs.umich.edu     * guest CPU. One interface updates 'normal' registers and one
3172651Ssaidi@eecs.umich.edu     * updates 'special' registers. The distinction between special
3182680Sktlim@umich.edu     * and normal registers isn't very clear and is architecture
3192651Ssaidi@eecs.umich.edu     * dependent.
3205606Snate@binkert.org     */
3215606Snate@binkert.org    void getRegisters(struct kvm_regs &regs) const;
3223888Ssaidi@eecs.umich.edu    void setRegisters(const struct kvm_regs &regs);
3233888Ssaidi@eecs.umich.edu    void getSpecialRegisters(struct kvm_sregs &regs) const;
3243888Ssaidi@eecs.umich.edu    void setSpecialRegisters(const struct kvm_sregs &regs);
3253888Ssaidi@eecs.umich.edu    /** @} */
3263890Ssaidi@eecs.umich.edu
3275606Snate@binkert.org    /** @{ */
3283888Ssaidi@eecs.umich.edu    /**
3293888Ssaidi@eecs.umich.edu     * Get/Set the guest FPU/vector state
3304216Ssaidi@eecs.umich.edu     */
3313888Ssaidi@eecs.umich.edu    void getFPUState(struct kvm_fpu &state) const;
3323888Ssaidi@eecs.umich.edu    void setFPUState(const struct kvm_fpu &state);
3334172Ssaidi@eecs.umich.edu    /** @} */
3344172Ssaidi@eecs.umich.edu
3353921Shsul@eecs.umich.edu    /** @{ */
3363888Ssaidi@eecs.umich.edu    /**
3375606Snate@binkert.org     * Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
3382651Ssaidi@eecs.umich.edu     *
3392651Ssaidi@eecs.umich.edu     * @note The presence of this call depends on Kvm::capOneReg().
3402651Ssaidi@eecs.umich.edu     */
3412680Sktlim@umich.edu    void setOneReg(uint64_t id, const void *addr);
3422651Ssaidi@eecs.umich.edu    void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); }
3435606Snate@binkert.org    void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); }
3445606Snate@binkert.org    void getOneReg(uint64_t id, void *addr) const;
3453891Ssaidi@eecs.umich.edu    uint64_t getOneRegU64(uint64_t id) const {
3463891Ssaidi@eecs.umich.edu        uint64_t value;
3473891Ssaidi@eecs.umich.edu        getOneReg(id, &value);
3483891Ssaidi@eecs.umich.edu        return value;
3496029Ssteve.reinhardt@amd.com    }
3504216Ssaidi@eecs.umich.edu    uint32_t getOneRegU32(uint64_t id) const {
3514216Ssaidi@eecs.umich.edu        uint32_t value;
3523891Ssaidi@eecs.umich.edu        getOneReg(id, &value);
3535606Snate@binkert.org        return value;
3543891Ssaidi@eecs.umich.edu    }
3553891Ssaidi@eecs.umich.edu    /** @} */
3564216Ssaidi@eecs.umich.edu
3573891Ssaidi@eecs.umich.edu    /**
3583891Ssaidi@eecs.umich.edu     * Get and format one register for printout.
3594172Ssaidi@eecs.umich.edu     *
3604172Ssaidi@eecs.umich.edu     * This function call getOneReg() to retrieve the contents of one
3613921Shsul@eecs.umich.edu     * register and automatically formats it for printing.
3623891Ssaidi@eecs.umich.edu     *
3633891Ssaidi@eecs.umich.edu     * @note The presence of this call depends on Kvm::capOneReg().
3645606Snate@binkert.org     */
3652651Ssaidi@eecs.umich.edu    std::string getAndFormatOneReg(uint64_t id) const;
3662650Ssaidi@eecs.umich.edu
367    /** @{ */
368    /**
369     * Update the KVM state from the current thread context
370     *
371     * The base CPU calls this method before starting the guest CPU
372     * when the contextDirty flag is set. The architecture dependent
373     * CPU implementation is expected to update all guest state
374     * (registers, special registers, and FPU state).
375     */
376    virtual void updateKvmState() = 0;
377
378    /**
379     * Update the current thread context with the KVM state
380     *
381     * The base CPU after the guest updates any of the KVM state. In
382     * practice, this happens after kvmRun is called. The architecture
383     * dependent code is expected to read the state of the guest CPU
384     * and update gem5's thread state.
385     */
386    virtual void updateThreadContext() = 0;
387
388    /**
389     * Update a thread context if the KVM state is dirty with respect
390     * to the cached thread context.
391     */
392    void syncThreadContext();
393
394    /**
395     * Update the KVM if the thread context is dirty.
396     */
397    void syncKvmState();
398    /** @} */
399
400    /** @{ */
401    /**
402     * Main kvmRun exit handler, calls the relevant handleKvmExit*
403     * depending on exit type.
404     *
405     * @return Number of ticks spent servicing the exit request
406     */
407    virtual Tick handleKvmExit();
408
409    /**
410     * The guest performed a legacy IO request (out/inp on x86)
411     *
412     * @return Number of ticks spent servicing the IO request
413     */
414    virtual Tick handleKvmExitIO();
415
416    /**
417     * The guest requested a monitor service using a hypercall
418     *
419     * @return Number of ticks spent servicing the hypercall
420     */
421    virtual Tick handleKvmExitHypercall();
422
423    /**
424     * The guest exited because an interrupt window was requested
425     *
426     * The guest exited because an interrupt window was requested
427     * (request_interrupt_window in the kvm_run structure was set to 1
428     * before calling kvmRun) and it is now ready to receive
429     *
430     * @return Number of ticks spent servicing the IRQ
431     */
432    virtual Tick handleKvmExitIRQWindowOpen();
433
434    /**
435     * An unknown architecture dependent error occurred when starting
436     * the vCPU
437     *
438     * The kvm_run data structure contains the hardware error
439     * code. The defaults behavior of this method just prints the HW
440     * error code and panics. Architecture dependent implementations
441     * may want to override this method to provide better,
442     * hardware-aware, error messages.
443     *
444     * @return Number of ticks delay the next CPU tick
445     */
446    virtual Tick handleKvmExitUnknown();
447
448    /**
449     * An unhandled virtualization exception occured
450     *
451     * Some KVM virtualization drivers return unhandled exceptions to
452     * the user-space monitor. This interface is currently only used
453     * by the Intel VMX KVM driver.
454     *
455     * @return Number of ticks delay the next CPU tick
456     */
457    virtual Tick handleKvmExitException();
458
459    /**
460     * KVM failed to start the virtualized CPU
461     *
462     * The kvm_run data structure contains the hardware-specific error
463     * code.
464     *
465     * @return Number of ticks delay the next CPU tick
466     */
467    virtual Tick handleKvmExitFailEntry();
468    /** @} */
469
470    /**
471     * Is the architecture specific code in a state that prevents
472     * draining?
473     *
474     * This method should return false if there are any pending events
475     * in the guest vCPU that won't be carried over to the gem5 state
476     * and thus will prevent correct checkpointing or CPU handover. It
477     * might, for example, check for pending interrupts that have been
478     * passed to the vCPU but not acknowledged by the OS. Architecures
479     * implementing this method <i>must</i> override
480     * kvmRunDrain().
481     *
482     * @see BaseKvmCPU::kvmRunDrain()
483     *
484     * @return true if the vCPU is drained, false otherwise.
485     */
486    virtual bool archIsDrained() const { return true; }
487
488    /**
489     * Inject a memory mapped IO request into gem5
490     *
491     * @param paddr Physical address
492     * @param data Pointer to the source/destination buffer
493     * @param size Memory access size
494     * @param write True if write, False if read
495     * @return Number of ticks spent servicing the memory access
496     */
497    Tick doMMIOAccess(Addr paddr, void *data, int size, bool write);
498
499    /** @{ */
500    /**
501     * Set the signal mask used in kvmRun()
502     *
503     * This method allows the signal mask of the thread executing
504     * kvmRun() to be overridden inside the actual system call. This
505     * allows us to mask timer signals used to force KVM exits while
506     * in gem5.
507     *
508     * The signal mask can be disabled by setting it to NULL.
509     *
510     * @param mask Signals to mask
511     */
512    void setSignalMask(const sigset_t *mask);
513    /** @} */
514
515    /**
516     * @addtogroup KvmIoctl
517     * @{
518     */
519    /**
520     * vCPU ioctl interface.
521     *
522     * @param request KVM vCPU request
523     * @param p1 Optional request parameter
524     *
525     * @return -1 on error (error number in errno), ioctl dependent
526     * value otherwise.
527     */
528    int ioctl(int request, long p1) const;
529    int ioctl(int request, void *p1) const {
530        return ioctl(request, (long)p1);
531    }
532    int ioctl(int request) const {
533        return ioctl(request, 0L);
534    }
535    /** @} */
536
537
538    /**
539     * KVM memory port. Uses the default MasterPort behavior, but
540     * panics on timing accesses.
541     */
542    class KVMCpuPort : public MasterPort
543    {
544
545      public:
546        KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu)
547            : MasterPort(_name, _cpu)
548        { }
549
550      protected:
551        bool recvTimingResp(PacketPtr pkt)
552        {
553            panic("The KVM CPU doesn't expect recvTimingResp!\n");
554            return true;
555        }
556
557        void recvRetry()
558        {
559            panic("The KVM CPU doesn't expect recvRetry!\n");
560        }
561
562    };
563
564    /** Port for data requests */
565    KVMCpuPort dataPort;
566
567    /** Unused dummy port for the instruction interface */
568    KVMCpuPort instPort;
569
570    /** Pre-allocated MMIO memory request */
571    Request mmio_req;
572
573    /**
574     * Is the gem5 context dirty? Set to true to force an update of
575     * the KVM vCPU state upon the next call to kvmRun().
576     */
577    bool threadContextDirty;
578
579    /**
580     * Is the KVM state dirty? Set to true to force an update of
581     * the KVM vCPU state upon the next call to kvmRun().
582     */
583    bool kvmStateDirty;
584
585    /** KVM internal ID of the vCPU */
586    const long vcpuID;
587
588  private:
589    struct TickEvent : public Event
590    {
591        BaseKvmCPU &cpu;
592
593        TickEvent(BaseKvmCPU &c)
594            : Event(CPU_Tick_Pri), cpu(c) {}
595
596        void process() { cpu.tick(); }
597
598        const char *description() const {
599            return "BaseKvmCPU tick";
600        }
601    };
602
603    /**
604     * Service MMIO requests in the mmioRing.
605     *
606     *
607     * @return Number of ticks spent servicing the MMIO requests in
608     * the MMIO ring buffer
609     */
610    Tick flushCoalescedMMIO();
611
612    /**
613     * Setup a signal handler to catch the timer signal used to
614     * switch back to the monitor.
615     */
616    void setupSignalHandler();
617
618    /**
619     * Discard a (potentially) pending signal.
620     *
621     * @param signum Signal to discard
622     * @return true if the signal was pending, false otherwise.
623     */
624    bool discardPendingSignal(int signum) const;
625
626    /**
627     * Thread-specific initialization.
628     *
629     * Some KVM-related initialization requires us to know the TID of
630     * the thread that is going to execute our event queue. For
631     * example, when setting up timers, we need to know the TID of the
632     * thread executing in KVM in order to deliver the timer signal to
633     * that thread. This method is called as the first event in this
634     * SimObject's event queue.
635     *
636     * @see startup
637     */
638    void startupThread();
639
640    /** Try to drain the CPU if a drain is pending */
641    bool tryDrain();
642
643    /** Execute the KVM_RUN ioctl */
644    void ioctlRun();
645
646    /** KVM vCPU file descriptor */
647    int vcpuFD;
648    /** Size of MMAPed kvm_run area */
649    int vcpuMMapSize;
650    /**
651     * Pointer to the kvm_run structure used to communicate parameters
652     * with KVM.
653     *
654     * @note This is the base pointer of the MMAPed KVM region. The
655     * first page contains the kvm_run structure. Subsequent pages may
656     * contain other data such as the MMIO ring buffer.
657     */
658    struct kvm_run *_kvmRun;
659    /**
660     * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not
661     * supported.
662     */
663    struct kvm_coalesced_mmio_ring *mmioRing;
664    /** Cached page size of the host */
665    const long pageSize;
666
667    TickEvent tickEvent;
668
669    /**
670     * Setup an instruction break if there is one pending.
671     *
672     * Check if there are pending instruction breaks in the CPU's
673     * instruction event queue and schedule an instruction break using
674     * PerfEvent.
675     *
676     * @note This method doesn't currently handle the main system
677     * instruction event queue.
678     */
679    void setupInstStop();
680
681    /** @{ */
682    /** Setup hardware performance counters */
683    void setupCounters();
684
685    /**
686     * Setup the guest instruction counter.
687     *
688     * Setup the guest instruction counter and optionally request a
689     * signal every N instructions executed by the guest. This method
690     * will re-attach the counter if the counter has already been
691     * attached and its sampling settings have changed.
692     *
693     * @param period Signal period, set to 0 to disable signaling.
694     */
695    void setupInstCounter(uint64_t period = 0);
696
697    /** Currently active instruction count breakpoint */
698    uint64_t activeInstPeriod;
699
700    /**
701     * Guest cycle counter.
702     *
703     * This is the group leader of all performance counters measuring
704     * the guest system. It can be used in conjunction with the
705     * PerfKvmTimer (see perfControlledByTimer) to trigger exits from
706     * KVM.
707     */
708    PerfKvmCounter hwCycles;
709
710    /**
711     * Guest instruction counter.
712     *
713     * This counter is typically only used to measure the number of
714     * instructions executed by the guest. However, it can also be
715     * used to trigger exits from KVM if the configuration script
716     * requests an exit after a certain number of instructions.
717     *
718     * @see setupInstBreak
719     * @see scheduleInstStop
720     */
721    PerfKvmCounter hwInstructions;
722
723    /**
724     * Does the runTimer control the performance counters?
725     *
726     * The run timer will automatically enable and disable performance
727     * counters if a PerfEvent-based timer is used to control KVM
728     * exits.
729     */
730    bool perfControlledByTimer;
731    /** @} */
732
733    /**
734     * Timer used to force execution into the monitor after a
735     * specified number of simulation tick equivalents have executed
736     * in the guest. This counter generates the signal specified by
737     * KVM_TIMER_SIGNAL.
738     */
739    std::unique_ptr<BaseKvmTimer> runTimer;
740
741    /** Host factor as specified in the configuration */
742    float hostFactor;
743
744    /**
745     * Drain manager to use when signaling drain completion
746     *
747     * This pointer is non-NULL when draining and NULL otherwise.
748     */
749    DrainManager *drainManager;
750
751  public:
752    /* @{ */
753    Stats::Scalar numInsts;
754    Stats::Scalar numVMExits;
755    Stats::Scalar numVMHalfEntries;
756    Stats::Scalar numExitSignal;
757    Stats::Scalar numMMIO;
758    Stats::Scalar numCoalescedMMIO;
759    Stats::Scalar numIO;
760    Stats::Scalar numHalt;
761    Stats::Scalar numInterrupts;
762    Stats::Scalar numHypercalls;
763    /* @} */
764
765    /** Number of instructions executed by the CPU */
766    Counter ctrInsts;
767};
768
769#endif
770