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 &section,
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 &regs) const;
32212472Sglenn.bergmans@arm.com    void setRegisters(const struct kvm_regs &regs);
32312472Sglenn.bergmans@arm.com    void getSpecialRegisters(struct kvm_sregs &regs) const;
32412472Sglenn.bergmans@arm.com    void setSpecialRegisters(const struct kvm_sregs &regs);
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