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 §ion, 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 ®s) const; 3223888Ssaidi@eecs.umich.edu void setRegisters(const struct kvm_regs ®s); 3233888Ssaidi@eecs.umich.edu void getSpecialRegisters(struct kvm_sregs ®s) const; 3243888Ssaidi@eecs.umich.edu void setSpecialRegisters(const struct kvm_sregs ®s); 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