base.hh revision 10112:1a2f64842044
112598Snikos.nikoleris@arm.com/* 27090SN/A * Copyright (c) 2012 ARM Limited 37090SN/A * All rights reserved 47090SN/A * 57090SN/A * The license below extends only to copyright in the software and shall 67090SN/A * not be construed as granting a license to any other intellectual 77090SN/A * property including but not limited to intellectual property relating 87090SN/A * to a hardware implementation of the functionality of the software 97090SN/A * licensed hereunder. You may use the software subject to the license 107090SN/A * terms below provided that you ensure that this notice is replicated 117090SN/A * unmodified and in its entirety in all distributions of the software, 127090SN/A * modified or unmodified, in source code or in binary form. 134486SN/A * 144486SN/A * Redistribution and use in source and binary forms, with or without 154486SN/A * modification, are permitted provided that the following conditions are 164486SN/A * met: redistributions of source code must retain the above copyright 174486SN/A * notice, this list of conditions and the following disclaimer; 184486SN/A * redistributions in binary form must reproduce the above copyright 194486SN/A * notice, this list of conditions and the following disclaimer in the 204486SN/A * documentation and/or other materials provided with the distribution; 214486SN/A * neither the name of the copyright holders nor the names of its 224486SN/A * contributors may be used to endorse or promote products derived from 234486SN/A * this software without specific prior written permission. 244486SN/A * 254486SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 264486SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 274486SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 284486SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 294486SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 304486SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 314486SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 324486SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 334486SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 344486SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 354486SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 364486SN/A * 374486SN/A * Authors: Andreas Sandberg 384486SN/A */ 397584SAli.Saidi@arm.com 407584SAli.Saidi@arm.com#ifndef __CPU_KVM_BASE_HH__ 417754SWilliam.Wang@arm.com#define __CPU_KVM_BASE_HH__ 4212472Sglenn.bergmans@arm.com 434486SN/A#include <memory> 4412472Sglenn.bergmans@arm.com#include <csignal> 453630SN/A 463630SN/A#include "base/statistics.hh" 4712472Sglenn.bergmans@arm.com#include "cpu/kvm/perfevent.hh" 4813665Sandreas.sandberg@arm.com#include "cpu/kvm/timer.hh" 4913665Sandreas.sandberg@arm.com#include "cpu/kvm/vm.hh" 5013665Sandreas.sandberg@arm.com#include "cpu/base.hh" 5113665Sandreas.sandberg@arm.com#include "cpu/simple_thread.hh" 5213665Sandreas.sandberg@arm.com 5313665Sandreas.sandberg@arm.com/** Signal to use to trigger time-based exits from KVM */ 5413665Sandreas.sandberg@arm.com#define KVM_TIMER_SIGNAL SIGRTMIN 5513665Sandreas.sandberg@arm.com 5613665Sandreas.sandberg@arm.com/** Signal to use to trigger instruction-based exits from KVM */ 5713665Sandreas.sandberg@arm.com#define KVM_INST_SIGNAL (SIGRTMIN+1) 5813665Sandreas.sandberg@arm.com 5913665Sandreas.sandberg@arm.com// forward declarations 6013665Sandreas.sandberg@arm.comclass ThreadContext; 6113665Sandreas.sandberg@arm.comstruct BaseKvmCPUParams; 6213665Sandreas.sandberg@arm.com 6313665Sandreas.sandberg@arm.com/** 6413665Sandreas.sandberg@arm.com * Base class for KVM based CPU models 6513665Sandreas.sandberg@arm.com * 6613665Sandreas.sandberg@arm.com * All architecture specific KVM implementation should inherit from 6713665Sandreas.sandberg@arm.com * this class. The most basic CPU models only need to override the 683630SN/A * updateKvmState() and updateThreadContext() methods to implement 6911841Sandreas.sandberg@arm.com * state synchronization between gem5 and KVM. 7011841Sandreas.sandberg@arm.com * 7111841Sandreas.sandberg@arm.com * The architecture specific implementation is also responsible for 7211841Sandreas.sandberg@arm.com * delivering interrupts into the VM. This is typically done by 7313665Sandreas.sandberg@arm.com * overriding tick() and checking the thread context before entering 7411841Sandreas.sandberg@arm.com * into the VM. In order to deliver an interrupt, the implementation 7511841Sandreas.sandberg@arm.com * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt() 7611841Sandreas.sandberg@arm.com * depending on the specifics of the underlying hardware/drivers. 7711841Sandreas.sandberg@arm.com */ 7813505Sgiacomo.travaglini@arm.comclass BaseKvmCPU : public BaseCPU 7911841Sandreas.sandberg@arm.com{ 8011841Sandreas.sandberg@arm.com public: 819806Sstever@gmail.com BaseKvmCPU(BaseKvmCPUParams *params); 829806Sstever@gmail.com virtual ~BaseKvmCPU(); 837584SAli.Saidi@arm.com 849338SAndreas.Sandberg@arm.com void init(); 857584SAli.Saidi@arm.com void startup(); 863898SN/A void regStats(); 879806Sstever@gmail.com 887950SAli.Saidi@ARM.com void serializeThread(std::ostream &os, ThreadID tid); 897950SAli.Saidi@ARM.com void unserializeThread(Checkpoint *cp, const std::string §ion, 909338SAndreas.Sandberg@arm.com ThreadID tid); 919525SAndreas.Sandberg@ARM.com 927950SAli.Saidi@ARM.com unsigned int drain(DrainManager *dm); 937950SAli.Saidi@ARM.com void drainResume(); 947950SAli.Saidi@ARM.com 957950SAli.Saidi@ARM.com void switchOut(); 967587SAli.Saidi@arm.com void takeOverFrom(BaseCPU *cpu); 977587SAli.Saidi@arm.com 987587SAli.Saidi@arm.com void verifyMemoryMode() const; 999338SAndreas.Sandberg@arm.com 1007753SWilliam.Wang@arm.com MasterPort &getDataPort() { return dataPort; } 1017753SWilliam.Wang@arm.com MasterPort &getInstPort() { return instPort; } 1029525SAndreas.Sandberg@ARM.com 1037753SWilliam.Wang@arm.com void wakeup(); 1047587SAli.Saidi@arm.com void activateContext(ThreadID thread_num, Cycles delay); 1057587SAli.Saidi@arm.com void suspendContext(ThreadID thread_num); 1068282SAli.Saidi@ARM.com void deallocateContext(ThreadID thread_num); 1078282SAli.Saidi@ARM.com void haltContext(ThreadID thread_num); 1089338SAndreas.Sandberg@arm.com 1098282SAli.Saidi@ARM.com ThreadContext *getContext(int tn); 11011296Sandreas.sandberg@arm.com 11111296Sandreas.sandberg@arm.com Counter totalInsts() const; 11211296Sandreas.sandberg@arm.com Counter totalOps() const; 11311296Sandreas.sandberg@arm.com 11411296Sandreas.sandberg@arm.com /** Dump the internal state to the terminal. */ 11511296Sandreas.sandberg@arm.com virtual void dump(); 11611296Sandreas.sandberg@arm.com 11711296Sandreas.sandberg@arm.com /** 11811296Sandreas.sandberg@arm.com * A cached copy of a thread's state in the form of a SimpleThread 11911296Sandreas.sandberg@arm.com * object. 12011296Sandreas.sandberg@arm.com * 12111296Sandreas.sandberg@arm.com * Normally the actual thread state is stored in the KVM vCPU. If KVM has 12211296Sandreas.sandberg@arm.com * been running this copy is will be out of date. If we recently handled 12311296Sandreas.sandberg@arm.com * some events within gem5 that required state to be updated this could be 12413805Sgiacomo.travaglini@arm.com * the most up-to-date copy. When getContext() or updateThreadContext() is 12513805Sgiacomo.travaglini@arm.com * called this copy gets updated. The method syncThreadContext can 12613805Sgiacomo.travaglini@arm.com * be used within a KVM CPU to update the thread context if the 12713805Sgiacomo.travaglini@arm.com * KVM state is dirty (i.e., the vCPU has been run since the last 12812474Sglenn.bergmans@arm.com * update). 12912474Sglenn.bergmans@arm.com */ 13012474Sglenn.bergmans@arm.com SimpleThread *thread; 13112474Sglenn.bergmans@arm.com 13212474Sglenn.bergmans@arm.com /** ThreadContext object, provides an interface for external 13312474Sglenn.bergmans@arm.com * objects to modify this thread's state. 13412474Sglenn.bergmans@arm.com */ 13512474Sglenn.bergmans@arm.com ThreadContext *tc; 13612474Sglenn.bergmans@arm.com 13712474Sglenn.bergmans@arm.com KvmVM &vm; 13812474Sglenn.bergmans@arm.com 13912474Sglenn.bergmans@arm.com protected: 14012474Sglenn.bergmans@arm.com /** 14112474Sglenn.bergmans@arm.com * 14212474Sglenn.bergmans@arm.com * @dot 14312474Sglenn.bergmans@arm.com * digraph { 14412474Sglenn.bergmans@arm.com * Idle; 14512474Sglenn.bergmans@arm.com * Running; 14612474Sglenn.bergmans@arm.com * RunningService; 14712474Sglenn.bergmans@arm.com * RunningServiceCompletion; 14812474Sglenn.bergmans@arm.com * 14912474Sglenn.bergmans@arm.com * Idle -> Idle; 15012474Sglenn.bergmans@arm.com * Idle -> Running [label="activateContext()", URL="\ref activateContext"]; 15112474Sglenn.bergmans@arm.com * Running -> Running [label="tick()", URL="\ref tick"]; 15212474Sglenn.bergmans@arm.com * Running -> RunningService [label="tick()", URL="\ref tick"]; 15312474Sglenn.bergmans@arm.com * Running -> Idle [label="suspendContext()", URL="\ref suspendContext"]; 15412474Sglenn.bergmans@arm.com * Running -> Idle [label="drain()", URL="\ref drain"]; 15512474Sglenn.bergmans@arm.com * Idle -> Running [label="drainResume()", URL="\ref drainResume"]; 15612474Sglenn.bergmans@arm.com * RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"]; 15712474Sglenn.bergmans@arm.com * RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"]; 15812474Sglenn.bergmans@arm.com * RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"]; 15912474Sglenn.bergmans@arm.com * } 16012474Sglenn.bergmans@arm.com * @enddot 16112474Sglenn.bergmans@arm.com */ 16212474Sglenn.bergmans@arm.com enum Status { 16312474Sglenn.bergmans@arm.com /** Context not scheduled in KVM. 16412474Sglenn.bergmans@arm.com * 16512474Sglenn.bergmans@arm.com * The CPU generally enters this state when the guest execute 16612474Sglenn.bergmans@arm.com * an instruction that halts the CPU (e.g., WFI on ARM or HLT 16712474Sglenn.bergmans@arm.com * on X86) if KVM traps this instruction. Ticks are not 16812474Sglenn.bergmans@arm.com * scheduled in this state. 16912474Sglenn.bergmans@arm.com * 17012474Sglenn.bergmans@arm.com * @see suspendContext() 17112474Sglenn.bergmans@arm.com */ 17212474Sglenn.bergmans@arm.com Idle, 17312474Sglenn.bergmans@arm.com /** Running normally. 17412474Sglenn.bergmans@arm.com * 17512474Sglenn.bergmans@arm.com * This is the normal run state of the CPU. KVM will be 17612474Sglenn.bergmans@arm.com * entered next time tick() is called. 17712474Sglenn.bergmans@arm.com */ 17812474Sglenn.bergmans@arm.com Running, 17912474Sglenn.bergmans@arm.com /** Requiring service at the beginning of the next cycle. 18012474Sglenn.bergmans@arm.com * 18112474Sglenn.bergmans@arm.com * The virtual machine has exited and requires service, tick() 18212474Sglenn.bergmans@arm.com * will call handleKvmExit() on the next cycle. The next state 18312474Sglenn.bergmans@arm.com * after running service is determined in handleKvmExit() and 18412474Sglenn.bergmans@arm.com * depends on what kind of service the guest requested: 18512474Sglenn.bergmans@arm.com * <ul> 18612474Sglenn.bergmans@arm.com * <li>IO/MMIO: RunningServiceCompletion 18712474Sglenn.bergmans@arm.com * <li>Halt: Idle 18812474Sglenn.bergmans@arm.com * <li>Others: Running 18913805Sgiacomo.travaglini@arm.com * </ul> 19013805Sgiacomo.travaglini@arm.com */ 19112474Sglenn.bergmans@arm.com RunningService, 19212474Sglenn.bergmans@arm.com /** Service completion in progress. 19312474Sglenn.bergmans@arm.com * 1947584SAli.Saidi@arm.com * The VM has requested service that requires KVM to be 1957584SAli.Saidi@arm.com * entered once in order to get to a consistent state. This 1969338SAndreas.Sandberg@arm.com * happens in handleKvmExit() or one of its friends after IO 1978524SAli.Saidi@ARM.com * exits. After executing tick(), the CPU will transition into 1988524SAli.Saidi@ARM.com * the Running or RunningService state. 1998299Schander.sudanthi@arm.com */ 2007584SAli.Saidi@arm.com RunningServiceCompletion, 20112472Sglenn.bergmans@arm.com }; 20212472Sglenn.bergmans@arm.com 20312472Sglenn.bergmans@arm.com /** CPU run state */ 20412472Sglenn.bergmans@arm.com Status _status; 20512472Sglenn.bergmans@arm.com 20612472Sglenn.bergmans@arm.com /** 20712472Sglenn.bergmans@arm.com * Execute the CPU until the next event in the main event queue or 20812472Sglenn.bergmans@arm.com * until the guest needs service from gem5. 20912472Sglenn.bergmans@arm.com */ 21012472Sglenn.bergmans@arm.com void tick(); 21112472Sglenn.bergmans@arm.com 21212472Sglenn.bergmans@arm.com /** 21311011SAndreas.Sandberg@ARM.com * Get the value of the hardware cycle counter in the guest. 21411011SAndreas.Sandberg@ARM.com * 21511011SAndreas.Sandberg@ARM.com * This method is supposed to return the total number of cycles 21611011SAndreas.Sandberg@ARM.com * executed in hardware mode relative to some arbitrary point in 21711011SAndreas.Sandberg@ARM.com * the past. It's mainly used when estimating the number of cycles 21811011SAndreas.Sandberg@ARM.com * actually executed by the CPU in kvmRun(). The default behavior 21911011SAndreas.Sandberg@ARM.com * of this method is to use the cycles performance counter, but 22011011SAndreas.Sandberg@ARM.com * some architectures may want to use internal registers instead. 22111011SAndreas.Sandberg@ARM.com * 22211011SAndreas.Sandberg@ARM.com * @return Number of host cycles executed relative to an undefined 22311011SAndreas.Sandberg@ARM.com * point in the past. 22411011SAndreas.Sandberg@ARM.com */ 22511011SAndreas.Sandberg@ARM.com virtual uint64_t getHostCycles() const; 22611011SAndreas.Sandberg@ARM.com 22711011SAndreas.Sandberg@ARM.com /** 22811011SAndreas.Sandberg@ARM.com * Request KVM to run the guest for a given number of ticks. The 22911011SAndreas.Sandberg@ARM.com * method returns the approximate number of ticks executed. 23011011SAndreas.Sandberg@ARM.com * 23111011SAndreas.Sandberg@ARM.com * @note The returned number of ticks can be both larger or 23211011SAndreas.Sandberg@ARM.com * smaller than the requested number of ticks. A smaller number 23311011SAndreas.Sandberg@ARM.com * can, for example, occur when the guest executes MMIO. A larger 23411011SAndreas.Sandberg@ARM.com * number is typically due to performance counter inaccuracies. 23512472Sglenn.bergmans@arm.com * 23612472Sglenn.bergmans@arm.com * @note This method is virtual in order to allow implementations 23712472Sglenn.bergmans@arm.com * to check for architecture specific events (e.g., interrupts) 23812472Sglenn.bergmans@arm.com * before entering the VM. 23912472Sglenn.bergmans@arm.com * 24012472Sglenn.bergmans@arm.com * @note It is the response of the caller (normally tick()) to 24112472Sglenn.bergmans@arm.com * make sure that the KVM state is synchronized and that the TC is 24212472Sglenn.bergmans@arm.com * invalidated after entering KVM. 24312472Sglenn.bergmans@arm.com * 24412472Sglenn.bergmans@arm.com * @note This method does not normally cause any state 24512472Sglenn.bergmans@arm.com * transitions. However, if it may suspend the CPU by suspending 24612472Sglenn.bergmans@arm.com * the thread, which leads to a transition to the Idle state. In 24712472Sglenn.bergmans@arm.com * such a case, kvm <i>must not</i> be entered. 24812472Sglenn.bergmans@arm.com * 24911421Sdavid.guillen@arm.com * @param ticks Number of ticks to execute, set to 0 to exit 25011421Sdavid.guillen@arm.com * immediately after finishing pending operations. 25111421Sdavid.guillen@arm.com * @return Number of ticks executed (see note) 25211421Sdavid.guillen@arm.com */ 25311421Sdavid.guillen@arm.com virtual Tick kvmRun(Tick ticks); 25411421Sdavid.guillen@arm.com 25511421Sdavid.guillen@arm.com /** 25611421Sdavid.guillen@arm.com * Request the CPU to run until draining completes. 25711421Sdavid.guillen@arm.com * 25811421Sdavid.guillen@arm.com * This function normally calls kvmRun(0) to make KVM finish 25911421Sdavid.guillen@arm.com * pending MMIO operations. Architecures implementing 26011421Sdavid.guillen@arm.com * archIsDrained() must override this method. 26111421Sdavid.guillen@arm.com * 26211421Sdavid.guillen@arm.com * @see BaseKvmCPU::archIsDrained() 26311421Sdavid.guillen@arm.com * 26411421Sdavid.guillen@arm.com * @return Number of ticks executed 26511236Sandreas.sandberg@arm.com */ 26611236Sandreas.sandberg@arm.com virtual Tick kvmRunDrain(); 26711236Sandreas.sandberg@arm.com 26811236Sandreas.sandberg@arm.com /** 26911236Sandreas.sandberg@arm.com * Get a pointer to the kvm_run structure containing all the input 27011236Sandreas.sandberg@arm.com * and output parameters from kvmRun(). 27111236Sandreas.sandberg@arm.com */ 27211236Sandreas.sandberg@arm.com struct kvm_run *getKvmRunState() { return _kvmRun; }; 27311236Sandreas.sandberg@arm.com 27411011SAndreas.Sandberg@ARM.com /** 27511011SAndreas.Sandberg@ARM.com * Retrieve a pointer to guest data stored at the end of the 27611421Sdavid.guillen@arm.com * kvm_run structure. This is mainly used for PIO operations 27711421Sdavid.guillen@arm.com * (KVM_EXIT_IO). 27811421Sdavid.guillen@arm.com * 27911236Sandreas.sandberg@arm.com * @param offset Offset as specified by the kvm_run structure 28011236Sandreas.sandberg@arm.com * @return Pointer to guest data 28111236Sandreas.sandberg@arm.com */ 28211236Sandreas.sandberg@arm.com uint8_t *getGuestData(uint64_t offset) const { 28311236Sandreas.sandberg@arm.com return (uint8_t *)_kvmRun + offset; 28411421Sdavid.guillen@arm.com }; 28511421Sdavid.guillen@arm.com 28611421Sdavid.guillen@arm.com /** 28712472Sglenn.bergmans@arm.com * @addtogroup KvmInterrupts 28812472Sglenn.bergmans@arm.com * @{ 28912472Sglenn.bergmans@arm.com */ 29012472Sglenn.bergmans@arm.com /** 29112472Sglenn.bergmans@arm.com * Send a non-maskable interrupt to the guest 29212472Sglenn.bergmans@arm.com * 29312472Sglenn.bergmans@arm.com * @note The presence of this call depends on Kvm::capUserNMI(). 29412472Sglenn.bergmans@arm.com */ 29512472Sglenn.bergmans@arm.com void kvmNonMaskableInterrupt(); 29612472Sglenn.bergmans@arm.com 29712472Sglenn.bergmans@arm.com /** 29812472Sglenn.bergmans@arm.com * Send a normal interrupt to the guest 29912472Sglenn.bergmans@arm.com * 30012472Sglenn.bergmans@arm.com * @note Make sure that ready_for_interrupt_injection in kvm_run 30111236Sandreas.sandberg@arm.com * is set prior to calling this function. If not, an interrupt 30211236Sandreas.sandberg@arm.com * window must be requested by setting request_interrupt_window in 30311236Sandreas.sandberg@arm.com * kvm_run to 1 and restarting the guest. 30411236Sandreas.sandberg@arm.com * 30511236Sandreas.sandberg@arm.com * @param interrupt Structure describing the interrupt to send 30611236Sandreas.sandberg@arm.com */ 30711236Sandreas.sandberg@arm.com void kvmInterrupt(const struct kvm_interrupt &interrupt); 30811236Sandreas.sandberg@arm.com 30911236Sandreas.sandberg@arm.com /** @} */ 31011011SAndreas.Sandberg@ARM.com 31111011SAndreas.Sandberg@ARM.com /** @{ */ 31211236Sandreas.sandberg@arm.com /** 31311236Sandreas.sandberg@arm.com * Get/Set the register state of the guest vCPU 31411236Sandreas.sandberg@arm.com * 31511236Sandreas.sandberg@arm.com * KVM has two different interfaces for accessing the state of the 31611236Sandreas.sandberg@arm.com * guest CPU. One interface updates 'normal' registers and one 31711236Sandreas.sandberg@arm.com * updates 'special' registers. The distinction between special 31811236Sandreas.sandberg@arm.com * and normal registers isn't very clear and is architecture 31911011SAndreas.Sandberg@ARM.com * dependent. 32012472Sglenn.bergmans@arm.com */ 32112472Sglenn.bergmans@arm.com void getRegisters(struct kvm_regs ®s) const; 32212472Sglenn.bergmans@arm.com void setRegisters(const struct kvm_regs ®s); 32312472Sglenn.bergmans@arm.com void getSpecialRegisters(struct kvm_sregs ®s) const; 32412472Sglenn.bergmans@arm.com void setSpecialRegisters(const struct kvm_sregs ®s); 32512472Sglenn.bergmans@arm.com /** @} */ 32612472Sglenn.bergmans@arm.com 32712472Sglenn.bergmans@arm.com /** @{ */ 32812472Sglenn.bergmans@arm.com /** 32912472Sglenn.bergmans@arm.com * Get/Set the guest FPU/vector state 33012472Sglenn.bergmans@arm.com */ 33112472Sglenn.bergmans@arm.com void getFPUState(struct kvm_fpu &state) const; 33212472Sglenn.bergmans@arm.com void setFPUState(const struct kvm_fpu &state); 3339806Sstever@gmail.com /** @} */ 3347584SAli.Saidi@arm.com 3359338SAndreas.Sandberg@arm.com /** @{ */ 3367584SAli.Saidi@arm.com /** 3377584SAli.Saidi@arm.com * Get/Set single register using the KVM_(SET|GET)_ONE_REG API. 3387584SAli.Saidi@arm.com * 3397584SAli.Saidi@arm.com * @note The presence of this call depends on Kvm::capOneReg(). 3407584SAli.Saidi@arm.com */ 3419338SAndreas.Sandberg@arm.com void setOneReg(uint64_t id, const void *addr); 3429525SAndreas.Sandberg@ARM.com void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); } 3437584SAli.Saidi@arm.com void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); } 3447584SAli.Saidi@arm.com void getOneReg(uint64_t id, void *addr) const; 3457584SAli.Saidi@arm.com uint64_t getOneRegU64(uint64_t id) const { 3467584SAli.Saidi@arm.com uint64_t value; 34712472Sglenn.bergmans@arm.com getOneReg(id, &value); 34812472Sglenn.bergmans@arm.com return value; 34912472Sglenn.bergmans@arm.com } 35012472Sglenn.bergmans@arm.com uint32_t getOneRegU32(uint64_t id) const { 35112472Sglenn.bergmans@arm.com uint32_t value; 35212472Sglenn.bergmans@arm.com getOneReg(id, &value); 35312472Sglenn.bergmans@arm.com return value; 35412472Sglenn.bergmans@arm.com } 35512472Sglenn.bergmans@arm.com /** @} */ 35612472Sglenn.bergmans@arm.com 35712472Sglenn.bergmans@arm.com /** 35812472Sglenn.bergmans@arm.com * Get and format one register for printout. 35912472Sglenn.bergmans@arm.com * 36012472Sglenn.bergmans@arm.com * This function call getOneReg() to retrieve the contents of one 3619806Sstever@gmail.com * register and automatically formats it for printing. 3627584SAli.Saidi@arm.com * 3639338SAndreas.Sandberg@arm.com * @note The presence of this call depends on Kvm::capOneReg(). 3649525SAndreas.Sandberg@ARM.com */ 3657584SAli.Saidi@arm.com std::string getAndFormatOneReg(uint64_t id) const; 3667584SAli.Saidi@arm.com 3677584SAli.Saidi@arm.com /** @{ */ 3687584SAli.Saidi@arm.com /** 3697584SAli.Saidi@arm.com * Update the KVM state from the current thread context 3707584SAli.Saidi@arm.com * 37112077Sgedare@rtems.org * The base CPU calls this method before starting the guest CPU 37212077Sgedare@rtems.org * when the contextDirty flag is set. The architecture dependent 37312077Sgedare@rtems.org * CPU implementation is expected to update all guest state 37412077Sgedare@rtems.org * (registers, special registers, and FPU state). 37512077Sgedare@rtems.org */ 37612077Sgedare@rtems.org virtual void updateKvmState() = 0; 3778512Sgeoffrey.blake@arm.com 3788512Sgeoffrey.blake@arm.com /** 3799338SAndreas.Sandberg@arm.com * Update the current thread context with the KVM state 38013106Sgiacomo.travaglini@arm.com * 38113106Sgiacomo.travaglini@arm.com * The base CPU after the guest updates any of the KVM state. In 3828512Sgeoffrey.blake@arm.com * practice, this happens after kvmRun is called. The architecture 38312467SCurtis.Dunham@arm.com * dependent code is expected to read the state of the guest CPU 38410037SARM gem5 Developers * and update gem5's thread state. 38510037SARM gem5 Developers */ 38611668Sandreas.sandberg@arm.com virtual void updateThreadContext() = 0; 38712975Sgiacomo.travaglini@arm.com 38812975Sgiacomo.travaglini@arm.com /** 38912975Sgiacomo.travaglini@arm.com * Update a thread context if the KVM state is dirty with respect 39012975Sgiacomo.travaglini@arm.com * to the cached thread context. 39110037SARM gem5 Developers */ 39212472Sglenn.bergmans@arm.com void syncThreadContext(); 39312472Sglenn.bergmans@arm.com 39412472Sglenn.bergmans@arm.com /** 39512472Sglenn.bergmans@arm.com * Update the KVM if the thread context is dirty. 39612472Sglenn.bergmans@arm.com */ 39712472Sglenn.bergmans@arm.com void syncKvmState(); 39812733Sandreas.sandberg@arm.com /** @} */ 39912975Sgiacomo.travaglini@arm.com 40012975Sgiacomo.travaglini@arm.com /** @{ */ 40112975Sgiacomo.travaglini@arm.com /** 40212975Sgiacomo.travaglini@arm.com * Main kvmRun exit handler, calls the relevant handleKvmExit* 40312733Sandreas.sandberg@arm.com * depending on exit type. 40412472Sglenn.bergmans@arm.com * 40512472Sglenn.bergmans@arm.com * @return Number of ticks spent servicing the exit request 40612472Sglenn.bergmans@arm.com */ 40712472Sglenn.bergmans@arm.com virtual Tick handleKvmExit(); 40812472Sglenn.bergmans@arm.com 40910847Sandreas.sandberg@arm.com /** 41010847Sandreas.sandberg@arm.com * The guest performed a legacy IO request (out/inp on x86) 41110847Sandreas.sandberg@arm.com * 41210847Sandreas.sandberg@arm.com * @return Number of ticks spent servicing the IO request 41310847Sandreas.sandberg@arm.com */ 41410847Sandreas.sandberg@arm.com virtual Tick handleKvmExitIO(); 41512975Sgiacomo.travaglini@arm.com 41612975Sgiacomo.travaglini@arm.com /** 41710847Sandreas.sandberg@arm.com * The guest requested a monitor service using a hypercall 4188870SAli.Saidi@ARM.com * 4198870SAli.Saidi@ARM.com * @return Number of ticks spent servicing the hypercall 4209338SAndreas.Sandberg@arm.com */ 4218870SAli.Saidi@ARM.com virtual Tick handleKvmExitHypercall(); 4228870SAli.Saidi@ARM.com 4238870SAli.Saidi@ARM.com /** 42412472Sglenn.bergmans@arm.com * The guest exited because an interrupt window was requested 42512472Sglenn.bergmans@arm.com * 42612472Sglenn.bergmans@arm.com * The guest exited because an interrupt window was requested 42712472Sglenn.bergmans@arm.com * (request_interrupt_window in the kvm_run structure was set to 1 42812472Sglenn.bergmans@arm.com * before calling kvmRun) and it is now ready to receive 42912472Sglenn.bergmans@arm.com * 43012472Sglenn.bergmans@arm.com * @return Number of ticks spent servicing the IRQ 43112472Sglenn.bergmans@arm.com */ 43212472Sglenn.bergmans@arm.com virtual Tick handleKvmExitIRQWindowOpen(); 43312472Sglenn.bergmans@arm.com 4347950SAli.Saidi@ARM.com /** 4357754SWilliam.Wang@arm.com * An unknown architecture dependent error occurred when starting 4369338SAndreas.Sandberg@arm.com * the vCPU 4377754SWilliam.Wang@arm.com * 4387754SWilliam.Wang@arm.com * The kvm_run data structure contains the hardware error 43912659Sandreas.sandberg@arm.com * code. The defaults behavior of this method just prints the HW 44012659Sandreas.sandberg@arm.com * error code and panics. Architecture dependent implementations 44112472Sglenn.bergmans@arm.com * may want to override this method to provide better, 44212472Sglenn.bergmans@arm.com * hardware-aware, error messages. 44312472Sglenn.bergmans@arm.com * 44412472Sglenn.bergmans@arm.com * @return Number of ticks delay the next CPU tick 44512472Sglenn.bergmans@arm.com */ 44612472Sglenn.bergmans@arm.com virtual Tick handleKvmExitUnknown(); 44712472Sglenn.bergmans@arm.com 44812472Sglenn.bergmans@arm.com /** 44912472Sglenn.bergmans@arm.com * An unhandled virtualization exception occured 45012472Sglenn.bergmans@arm.com * 4517753SWilliam.Wang@arm.com * Some KVM virtualization drivers return unhandled exceptions to 4527753SWilliam.Wang@arm.com * the user-space monitor. This interface is currently only used 4539338SAndreas.Sandberg@arm.com * by the Intel VMX KVM driver. 4549394Sandreas.hansson@arm.com * 4559330Schander.sudanthi@arm.com * @return Number of ticks delay the next CPU tick 4567753SWilliam.Wang@arm.com */ 4579939Sdam.sunwoo@arm.com virtual Tick handleKvmExitException(); 4589939Sdam.sunwoo@arm.com 4599646SChris.Emmons@arm.com /** 4609646SChris.Emmons@arm.com * KVM failed to start the virtualized CPU 4619646SChris.Emmons@arm.com * 4629646SChris.Emmons@arm.com * The kvm_run data structure contains the hardware-specific error 4639646SChris.Emmons@arm.com * code. 4649646SChris.Emmons@arm.com * 46511237Sandreas.sandberg@arm.com * @return Number of ticks delay the next CPU tick 46610840Sandreas.sandberg@arm.com */ 46711090Sandreas.sandberg@arm.com virtual Tick handleKvmExitFailEntry(); 46811090Sandreas.sandberg@arm.com /** @} */ 46912232Sgiacomo.travaglini@arm.com 47012232Sgiacomo.travaglini@arm.com /** 47112232Sgiacomo.travaglini@arm.com * Is the architecture specific code in a state that prevents 47212232Sgiacomo.travaglini@arm.com * draining? 4739646SChris.Emmons@arm.com * 47411090Sandreas.sandberg@arm.com * This method should return false if there are any pending events 47511090Sandreas.sandberg@arm.com * in the guest vCPU that won't be carried over to the gem5 state 47611090Sandreas.sandberg@arm.com * and thus will prevent correct checkpointing or CPU handover. It 47711090Sandreas.sandberg@arm.com * might, for example, check for pending interrupts that have been 47811898Ssudhanshu.jha@arm.com * passed to the vCPU but not acknowledged by the OS. Architecures 47911898Ssudhanshu.jha@arm.com * implementing this method <i>must</i> override 48011090Sandreas.sandberg@arm.com * kvmRunDrain(). 48112472Sglenn.bergmans@arm.com * 48212472Sglenn.bergmans@arm.com * @see BaseKvmCPU::kvmRunDrain() 48312472Sglenn.bergmans@arm.com * 48412472Sglenn.bergmans@arm.com * @return true if the vCPU is drained, false otherwise. 48512472Sglenn.bergmans@arm.com */ 48612472Sglenn.bergmans@arm.com virtual bool archIsDrained() const { return true; } 48712472Sglenn.bergmans@arm.com 48812472Sglenn.bergmans@arm.com /** 48912472Sglenn.bergmans@arm.com * Inject a memory mapped IO request into gem5 49012472Sglenn.bergmans@arm.com * 49112472Sglenn.bergmans@arm.com * @param paddr Physical address 49212472Sglenn.bergmans@arm.com * @param data Pointer to the source/destination buffer 49312472Sglenn.bergmans@arm.com * @param size Memory access size 49412472Sglenn.bergmans@arm.com * @param write True if write, False if read 49512472Sglenn.bergmans@arm.com * @return Number of ticks spent servicing the memory access 49612472Sglenn.bergmans@arm.com */ 49712472Sglenn.bergmans@arm.com Tick doMMIOAccess(Addr paddr, void *data, int size, bool write); 4987584SAli.Saidi@arm.com 4997584SAli.Saidi@arm.com /** @{ */ 5009338SAndreas.Sandberg@arm.com /** 5013630SN/A * Set the signal mask used in kvmRun() 50213636Sgiacomo.travaglini@arm.com * 5038870SAli.Saidi@ARM.com * This method allows the signal mask of the thread executing 50411297Sandreas.sandberg@arm.com * kvmRun() to be overridden inside the actual system call. This 50511297Sandreas.sandberg@arm.com * allows us to mask timer signals used to force KVM exits while 50611297Sandreas.sandberg@arm.com * in gem5. 50711297Sandreas.sandberg@arm.com * 50811297Sandreas.sandberg@arm.com * The signal mask can be disabled by setting it to NULL. 50911297Sandreas.sandberg@arm.com * 51011297Sandreas.sandberg@arm.com * @param mask Signals to mask 51111297Sandreas.sandberg@arm.com */ 51211597Sandreas.sandberg@arm.com void setSignalMask(const sigset_t *mask); 51311597Sandreas.sandberg@arm.com /** @} */ 51411597Sandreas.sandberg@arm.com 51511597Sandreas.sandberg@arm.com /** 51611597Sandreas.sandberg@arm.com * @addtogroup KvmIoctl 51711597Sandreas.sandberg@arm.com * @{ 51811597Sandreas.sandberg@arm.com */ 51911597Sandreas.sandberg@arm.com /** 52011597Sandreas.sandberg@arm.com * vCPU ioctl interface. 52111597Sandreas.sandberg@arm.com * 52211297Sandreas.sandberg@arm.com * @param request KVM vCPU request 52311597Sandreas.sandberg@arm.com * @param p1 Optional request parameter 52411297Sandreas.sandberg@arm.com * 52511297Sandreas.sandberg@arm.com * @return -1 on error (error number in errno), ioctl dependent 52611297Sandreas.sandberg@arm.com * value otherwise. 52711297Sandreas.sandberg@arm.com */ 52811297Sandreas.sandberg@arm.com int ioctl(int request, long p1) const; 52911297Sandreas.sandberg@arm.com int ioctl(int request, void *p1) const { 53010353SGeoffrey.Blake@arm.com return ioctl(request, (long)p1); 53110353SGeoffrey.Blake@arm.com } 53210353SGeoffrey.Blake@arm.com int ioctl(int request) const { 53310353SGeoffrey.Blake@arm.com return ioctl(request, 0L); 53410353SGeoffrey.Blake@arm.com } 53510353SGeoffrey.Blake@arm.com /** @} */ 53610353SGeoffrey.Blake@arm.com 53711297Sandreas.sandberg@arm.com 53810353SGeoffrey.Blake@arm.com /** 53910353SGeoffrey.Blake@arm.com * KVM memory port. Uses the default MasterPort behavior, but 54011297Sandreas.sandberg@arm.com * panics on timing accesses. 54111297Sandreas.sandberg@arm.com */ 54212069Snikos.nikoleris@arm.com class KVMCpuPort : public MasterPort 54312069Snikos.nikoleris@arm.com { 54411297Sandreas.sandberg@arm.com 54511297Sandreas.sandberg@arm.com public: 54611297Sandreas.sandberg@arm.com KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu) 54711597Sandreas.sandberg@arm.com : MasterPort(_name, _cpu) 54811597Sandreas.sandberg@arm.com { } 54911297Sandreas.sandberg@arm.com 5508870SAli.Saidi@ARM.com protected: 55112598Snikos.nikoleris@arm.com bool recvTimingResp(PacketPtr pkt) 55212598Snikos.nikoleris@arm.com { 55312598Snikos.nikoleris@arm.com panic("The KVM CPU doesn't expect recvTimingResp!\n"); 55412598Snikos.nikoleris@arm.com return true; 55512598Snikos.nikoleris@arm.com } 5568870SAli.Saidi@ARM.com 55710037SARM gem5 Developers void recvRetry() 55810037SARM gem5 Developers { 5598870SAli.Saidi@ARM.com panic("The KVM CPU doesn't expect recvRetry!\n"); 56012472Sglenn.bergmans@arm.com } 56112472Sglenn.bergmans@arm.com 56212472Sglenn.bergmans@arm.com }; 56312472Sglenn.bergmans@arm.com 56412472Sglenn.bergmans@arm.com /** Port for data requests */ 56512785Sandreas.sandberg@arm.com KVMCpuPort dataPort; 56612785Sandreas.sandberg@arm.com 56712472Sglenn.bergmans@arm.com /** Unused dummy port for the instruction interface */ 56812472Sglenn.bergmans@arm.com KVMCpuPort instPort; 56912472Sglenn.bergmans@arm.com 57012472Sglenn.bergmans@arm.com /** Pre-allocated MMIO memory request */ 57112472Sglenn.bergmans@arm.com Request mmio_req; 57212472Sglenn.bergmans@arm.com 57312472Sglenn.bergmans@arm.com /** 5743630SN/A * Is the gem5 context dirty? Set to true to force an update of 5757753SWilliam.Wang@arm.com * the KVM vCPU state upon the next call to kvmRun(). 5767753SWilliam.Wang@arm.com */ 5777753SWilliam.Wang@arm.com bool threadContextDirty; 5787584SAli.Saidi@arm.com 5797584SAli.Saidi@arm.com /** 58011236Sandreas.sandberg@arm.com * Is the KVM state dirty? Set to true to force an update of 58111236Sandreas.sandberg@arm.com * the KVM vCPU state upon the next call to kvmRun(). 58211236Sandreas.sandberg@arm.com */ 58313505Sgiacomo.travaglini@arm.com bool kvmStateDirty; 58411244Sandreas.sandberg@arm.com 58511244Sandreas.sandberg@arm.com /** KVM internal ID of the vCPU */ 58611244Sandreas.sandberg@arm.com const long vcpuID; 5877584SAli.Saidi@arm.com 5887584SAli.Saidi@arm.com private: 58912077Sgedare@rtems.org struct TickEvent : public Event 59013106Sgiacomo.travaglini@arm.com { 59113106Sgiacomo.travaglini@arm.com BaseKvmCPU &cpu; 59212077Sgedare@rtems.org 5937753SWilliam.Wang@arm.com TickEvent(BaseKvmCPU &c) 59412659Sandreas.sandberg@arm.com : Event(CPU_Tick_Pri), cpu(c) {} 59512659Sandreas.sandberg@arm.com 5968282SAli.Saidi@ARM.com void process() { cpu.tick(); } 5978525SAli.Saidi@ARM.com 5988212SAli.Saidi@ARM.com const char *description() const { 5998212SAli.Saidi@ARM.com return "BaseKvmCPU tick"; 6008212SAli.Saidi@ARM.com } 6018212SAli.Saidi@ARM.com }; 6028212SAli.Saidi@ARM.com 6037584SAli.Saidi@arm.com /** 6047731SAli.Saidi@ARM.com * Service MMIO requests in the mmioRing. 6058461SAli.Saidi@ARM.com * 6068461SAli.Saidi@ARM.com * 6077696SAli.Saidi@ARM.com * @return Number of ticks spent servicing the MMIO requests in 6087696SAli.Saidi@ARM.com * the MMIO ring buffer 6097696SAli.Saidi@ARM.com */ 6107696SAli.Saidi@ARM.com Tick flushCoalescedMMIO(); 6117696SAli.Saidi@ARM.com 6127696SAli.Saidi@ARM.com /** 6137696SAli.Saidi@ARM.com * Setup a signal handler to catch the timer signal used to 6147696SAli.Saidi@ARM.com * switch back to the monitor. 6157696SAli.Saidi@ARM.com */ 6167696SAli.Saidi@ARM.com void setupSignalHandler(); 6177696SAli.Saidi@ARM.com 6187696SAli.Saidi@ARM.com /** 6197696SAli.Saidi@ARM.com * Discard a (potentially) pending signal. 6207696SAli.Saidi@ARM.com * 6218906Skoansin.tan@gmail.com * @param signum Signal to discard 62210397Sstephan.diestelhorst@arm.com * @return true if the signal was pending, false otherwise. 6237696SAli.Saidi@ARM.com */ 6247696SAli.Saidi@ARM.com bool discardPendingSignal(int signum) const; 6258713Sandreas.hansson@arm.com 6268713Sandreas.hansson@arm.com /** 6278713Sandreas.hansson@arm.com * Thread-specific initialization. 6288839Sandreas.hansson@arm.com * 6298839Sandreas.hansson@arm.com * Some KVM-related initialization requires us to know the TID of 6308839Sandreas.hansson@arm.com * the thread that is going to execute our event queue. For 63112077Sgedare@rtems.org * example, when setting up timers, we need to know the TID of the 6328839Sandreas.hansson@arm.com * thread executing in KVM in order to deliver the timer signal to 6338713Sandreas.hansson@arm.com * that thread. This method is called as the first event in this 6348713Sandreas.hansson@arm.com * SimObject's event queue. 6358713Sandreas.hansson@arm.com * 6368713Sandreas.hansson@arm.com * @see startup 6378870SAli.Saidi@ARM.com */ 6388870SAli.Saidi@ARM.com void startupThread(); 6398870SAli.Saidi@ARM.com 6407696SAli.Saidi@ARM.com /** Try to drain the CPU if a drain is pending */ 64110353SGeoffrey.Blake@arm.com bool tryDrain(); 64210353SGeoffrey.Blake@arm.com 64310353SGeoffrey.Blake@arm.com /** Execute the KVM_RUN ioctl */ 64410353SGeoffrey.Blake@arm.com void ioctlRun(); 64510353SGeoffrey.Blake@arm.com 64610353SGeoffrey.Blake@arm.com /** KVM vCPU file descriptor */ 64710353SGeoffrey.Blake@arm.com int vcpuFD; 64810353SGeoffrey.Blake@arm.com /** Size of MMAPed kvm_run area */ 6497696SAli.Saidi@ARM.com int vcpuMMapSize; 6507696SAli.Saidi@ARM.com /** 6517696SAli.Saidi@ARM.com * Pointer to the kvm_run structure used to communicate parameters 6527696SAli.Saidi@ARM.com * with KVM. 6538839Sandreas.hansson@arm.com * 6548839Sandreas.hansson@arm.com * @note This is the base pointer of the MMAPed KVM region. The 65511244Sandreas.sandberg@arm.com * first page contains the kvm_run structure. Subsequent pages may 6568839Sandreas.hansson@arm.com * contain other data such as the MMIO ring buffer. 6578839Sandreas.hansson@arm.com */ 6588839Sandreas.hansson@arm.com struct kvm_run *_kvmRun; 6598839Sandreas.hansson@arm.com /** 6608839Sandreas.hansson@arm.com * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not 6618839Sandreas.hansson@arm.com * supported. 6628839Sandreas.hansson@arm.com */ 6638839Sandreas.hansson@arm.com struct kvm_coalesced_mmio_ring *mmioRing; 6648839Sandreas.hansson@arm.com /** Cached page size of the host */ 6658839Sandreas.hansson@arm.com const long pageSize; 6668839Sandreas.hansson@arm.com 6678839Sandreas.hansson@arm.com TickEvent tickEvent; 6688839Sandreas.hansson@arm.com 6698839Sandreas.hansson@arm.com /** 6708839Sandreas.hansson@arm.com * Setup an instruction break if there is one pending. 6718839Sandreas.hansson@arm.com * 6728839Sandreas.hansson@arm.com * Check if there are pending instruction breaks in the CPU's 6738839Sandreas.hansson@arm.com * instruction event queue and schedule an instruction break using 6748839Sandreas.hansson@arm.com * PerfEvent. 6758839Sandreas.hansson@arm.com * 6768839Sandreas.hansson@arm.com * @note This method doesn't currently handle the main system 6778839Sandreas.hansson@arm.com * instruction event queue. 6788906Skoansin.tan@gmail.com */ 6798839Sandreas.hansson@arm.com void setupInstStop(); 68010397Sstephan.diestelhorst@arm.com 6817696SAli.Saidi@ARM.com /** @{ */ 68210353SGeoffrey.Blake@arm.com /** Setup hardware performance counters */ 68310353SGeoffrey.Blake@arm.com void setupCounters(); 68410353SGeoffrey.Blake@arm.com 68510353SGeoffrey.Blake@arm.com /** 68610353SGeoffrey.Blake@arm.com * Setup the guest instruction counter. 68710353SGeoffrey.Blake@arm.com * 68810353SGeoffrey.Blake@arm.com * Setup the guest instruction counter and optionally request a 68910353SGeoffrey.Blake@arm.com * signal every N instructions executed by the guest. This method 69010353SGeoffrey.Blake@arm.com * will re-attach the counter if the counter has already been 69110353SGeoffrey.Blake@arm.com * attached and its sampling settings have changed. 69210353SGeoffrey.Blake@arm.com * 69310353SGeoffrey.Blake@arm.com * @param period Signal period, set to 0 to disable signaling. 69410353SGeoffrey.Blake@arm.com */ 69510353SGeoffrey.Blake@arm.com void setupInstCounter(uint64_t period = 0); 69610353SGeoffrey.Blake@arm.com 69710353SGeoffrey.Blake@arm.com /** Currently active instruction count breakpoint */ 69810353SGeoffrey.Blake@arm.com uint64_t activeInstPeriod; 69910353SGeoffrey.Blake@arm.com 70010353SGeoffrey.Blake@arm.com /** 70110353SGeoffrey.Blake@arm.com * Guest cycle counter. 70210353SGeoffrey.Blake@arm.com * 70310353SGeoffrey.Blake@arm.com * This is the group leader of all performance counters measuring 70410353SGeoffrey.Blake@arm.com * the guest system. It can be used in conjunction with the 70510353SGeoffrey.Blake@arm.com * PerfKvmTimer (see perfControlledByTimer) to trigger exits from 70610353SGeoffrey.Blake@arm.com * KVM. 70710353SGeoffrey.Blake@arm.com */ 70810353SGeoffrey.Blake@arm.com PerfKvmCounter hwCycles; 70910397Sstephan.diestelhorst@arm.com 71010353SGeoffrey.Blake@arm.com /** 7118870SAli.Saidi@ARM.com * Guest instruction counter. 71213636Sgiacomo.travaglini@arm.com * 71312069Snikos.nikoleris@arm.com * This counter is typically only used to measure the number of 71412069Snikos.nikoleris@arm.com * instructions executed by the guest. However, it can also be 71512069Snikos.nikoleris@arm.com * used to trigger exits from KVM if the configuration script 71612069Snikos.nikoleris@arm.com * requests an exit after a certain number of instructions. 71712069Snikos.nikoleris@arm.com * 71812069Snikos.nikoleris@arm.com * @see setupInstBreak 71912069Snikos.nikoleris@arm.com * @see scheduleInstStop 72012069Snikos.nikoleris@arm.com */ 72112069Snikos.nikoleris@arm.com PerfKvmCounter hwInstructions; 72212069Snikos.nikoleris@arm.com 72312069Snikos.nikoleris@arm.com /** 72412069Snikos.nikoleris@arm.com * Does the runTimer control the performance counters? 72512069Snikos.nikoleris@arm.com * 72611236Sandreas.sandberg@arm.com * The run timer will automatically enable and disable performance 72711236Sandreas.sandberg@arm.com * counters if a PerfEvent-based timer is used to control KVM 72812069Snikos.nikoleris@arm.com * exits. 72912069Snikos.nikoleris@arm.com */ 73013505Sgiacomo.travaglini@arm.com bool perfControlledByTimer; 73113814Sgiacomo.travaglini@arm.com /** @} */ 73212069Snikos.nikoleris@arm.com 73313106Sgiacomo.travaglini@arm.com /** 73413106Sgiacomo.travaglini@arm.com * Timer used to force execution into the monitor after a 73512069Snikos.nikoleris@arm.com * specified number of simulation tick equivalents have executed 73612069Snikos.nikoleris@arm.com * in the guest. This counter generates the signal specified by 73712069Snikos.nikoleris@arm.com * KVM_TIMER_SIGNAL. 73812069Snikos.nikoleris@arm.com */ 73912069Snikos.nikoleris@arm.com std::unique_ptr<BaseKvmTimer> runTimer; 74012069Snikos.nikoleris@arm.com 74112069Snikos.nikoleris@arm.com /** Host factor as specified in the configuration */ 74212069Snikos.nikoleris@arm.com float hostFactor; 74312069Snikos.nikoleris@arm.com 74412069Snikos.nikoleris@arm.com /** 74512069Snikos.nikoleris@arm.com * Drain manager to use when signaling drain completion 74612069Snikos.nikoleris@arm.com * 74712069Snikos.nikoleris@arm.com * This pointer is non-NULL when draining and NULL otherwise. 74812069Snikos.nikoleris@arm.com */ 74912069Snikos.nikoleris@arm.com DrainManager *drainManager; 75012069Snikos.nikoleris@arm.com 75112069Snikos.nikoleris@arm.com public: 75212069Snikos.nikoleris@arm.com /* @{ */ 75311244Sandreas.sandberg@arm.com Stats::Scalar numInsts; 75411244Sandreas.sandberg@arm.com Stats::Scalar numVMExits; 75511244Sandreas.sandberg@arm.com Stats::Scalar numVMHalfEntries; 75612069Snikos.nikoleris@arm.com Stats::Scalar numExitSignal; 75712975Sgiacomo.travaglini@arm.com Stats::Scalar numMMIO; 75812975Sgiacomo.travaglini@arm.com Stats::Scalar numCoalescedMMIO; 75912975Sgiacomo.travaglini@arm.com Stats::Scalar numIO; 76012975Sgiacomo.travaglini@arm.com Stats::Scalar numHalt; 76112975Sgiacomo.travaglini@arm.com Stats::Scalar numInterrupts; 7629185SAli.Saidi@ARM.com Stats::Scalar numHypercalls; 7639185SAli.Saidi@ARM.com /* @} */ 7648870SAli.Saidi@ARM.com 76512659Sandreas.sandberg@arm.com /** Number of instructions executed by the CPU */ 76612659Sandreas.sandberg@arm.com Counter ctrInsts; 7678870SAli.Saidi@ARM.com}; 7688870SAli.Saidi@ARM.com 7698870SAli.Saidi@ARM.com#endif 7708870SAli.Saidi@ARM.com