base.hh revision 11151:ca4ea9b5c052
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2012 ARM Limited
312027Sjungma@eit.uni-kl.de * All rights reserved
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * The license below extends only to copyright in the software and shall
612027Sjungma@eit.uni-kl.de * not be construed as granting a license to any other intellectual
712027Sjungma@eit.uni-kl.de * property including but not limited to intellectual property relating
812027Sjungma@eit.uni-kl.de * to a hardware implementation of the functionality of the software
912027Sjungma@eit.uni-kl.de * licensed hereunder.  You may use the software subject to the license
1012027Sjungma@eit.uni-kl.de * terms below provided that you ensure that this notice is replicated
1112027Sjungma@eit.uni-kl.de * unmodified and in its entirety in all distributions of the software,
1212027Sjungma@eit.uni-kl.de * modified or unmodified, in source code or in binary form.
1312027Sjungma@eit.uni-kl.de *
1412027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
1512027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
1612027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
1712027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
1812027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
1912027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
2012027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
2112027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
2212027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
2312027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
2412027Sjungma@eit.uni-kl.de *
2512027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612027Sjungma@eit.uni-kl.de *
3712027Sjungma@eit.uni-kl.de * Authors: Andreas Sandberg
3812027Sjungma@eit.uni-kl.de */
3912027Sjungma@eit.uni-kl.de
4012027Sjungma@eit.uni-kl.de#ifndef __CPU_KVM_BASE_HH__
4112027Sjungma@eit.uni-kl.de#define __CPU_KVM_BASE_HH__
4212027Sjungma@eit.uni-kl.de
4312027Sjungma@eit.uni-kl.de#include <pthread.h>
4412027Sjungma@eit.uni-kl.de
4512027Sjungma@eit.uni-kl.de#include <csignal>
4612027Sjungma@eit.uni-kl.de#include <memory>
4712027Sjungma@eit.uni-kl.de
4812027Sjungma@eit.uni-kl.de#include "base/statistics.hh"
4912027Sjungma@eit.uni-kl.de#include "cpu/kvm/perfevent.hh"
5012027Sjungma@eit.uni-kl.de#include "cpu/kvm/timer.hh"
5112027Sjungma@eit.uni-kl.de#include "cpu/kvm/vm.hh"
5212027Sjungma@eit.uni-kl.de#include "cpu/base.hh"
5312027Sjungma@eit.uni-kl.de#include "cpu/simple_thread.hh"
5412027Sjungma@eit.uni-kl.de
5512027Sjungma@eit.uni-kl.de/** Signal to use to trigger exits from KVM */
5612027Sjungma@eit.uni-kl.de#define KVM_KICK_SIGNAL SIGRTMIN
5712027Sjungma@eit.uni-kl.de
5812027Sjungma@eit.uni-kl.de// forward declarations
5912027Sjungma@eit.uni-kl.declass ThreadContext;
6012027Sjungma@eit.uni-kl.destruct BaseKvmCPUParams;
6112027Sjungma@eit.uni-kl.de
6212027Sjungma@eit.uni-kl.de/**
6312027Sjungma@eit.uni-kl.de * Base class for KVM based CPU models
6412027Sjungma@eit.uni-kl.de *
6512027Sjungma@eit.uni-kl.de * All architecture specific KVM implementation should inherit from
6612027Sjungma@eit.uni-kl.de * this class. The most basic CPU models only need to override the
6712027Sjungma@eit.uni-kl.de * updateKvmState() and updateThreadContext() methods to implement
6812027Sjungma@eit.uni-kl.de * state synchronization between gem5 and KVM.
6912027Sjungma@eit.uni-kl.de *
7012027Sjungma@eit.uni-kl.de * The architecture specific implementation is also responsible for
7112027Sjungma@eit.uni-kl.de * delivering interrupts into the VM. This is typically done by
7212027Sjungma@eit.uni-kl.de * overriding tick() and checking the thread context before entering
7312027Sjungma@eit.uni-kl.de * into the VM. In order to deliver an interrupt, the implementation
7412027Sjungma@eit.uni-kl.de * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt()
7512027Sjungma@eit.uni-kl.de * depending on the specifics of the underlying hardware/drivers.
7612027Sjungma@eit.uni-kl.de */
7712027Sjungma@eit.uni-kl.declass BaseKvmCPU : public BaseCPU
7812027Sjungma@eit.uni-kl.de{
7912027Sjungma@eit.uni-kl.de  public:
8012027Sjungma@eit.uni-kl.de    BaseKvmCPU(BaseKvmCPUParams *params);
8112027Sjungma@eit.uni-kl.de    virtual ~BaseKvmCPU();
8212027Sjungma@eit.uni-kl.de
8312027Sjungma@eit.uni-kl.de    void init();
8412027Sjungma@eit.uni-kl.de    void startup();
8512027Sjungma@eit.uni-kl.de    void regStats();
8612027Sjungma@eit.uni-kl.de
8712027Sjungma@eit.uni-kl.de    void serializeThread(CheckpointOut &cp,
8812027Sjungma@eit.uni-kl.de                         ThreadID tid) const M5_ATTR_OVERRIDE;
8912027Sjungma@eit.uni-kl.de    void unserializeThread(CheckpointIn &cp,
9012027Sjungma@eit.uni-kl.de                           ThreadID tid) M5_ATTR_OVERRIDE;
9112027Sjungma@eit.uni-kl.de
9212027Sjungma@eit.uni-kl.de    DrainState drain() M5_ATTR_OVERRIDE;
9312027Sjungma@eit.uni-kl.de    void drainResume() M5_ATTR_OVERRIDE;
9412027Sjungma@eit.uni-kl.de
9512027Sjungma@eit.uni-kl.de    void switchOut();
9612027Sjungma@eit.uni-kl.de    void takeOverFrom(BaseCPU *cpu);
9712027Sjungma@eit.uni-kl.de
9812027Sjungma@eit.uni-kl.de    void verifyMemoryMode() const;
9912027Sjungma@eit.uni-kl.de
10012027Sjungma@eit.uni-kl.de    MasterPort &getDataPort() { return dataPort; }
10112027Sjungma@eit.uni-kl.de    MasterPort &getInstPort() { return instPort; }
10212027Sjungma@eit.uni-kl.de
10312027Sjungma@eit.uni-kl.de    void wakeup(ThreadID tid = 0) M5_ATTR_OVERRIDE;
10412027Sjungma@eit.uni-kl.de    void activateContext(ThreadID thread_num);
10512027Sjungma@eit.uni-kl.de    void suspendContext(ThreadID thread_num);
10612027Sjungma@eit.uni-kl.de    void deallocateContext(ThreadID thread_num);
10712027Sjungma@eit.uni-kl.de    void haltContext(ThreadID thread_num);
10812027Sjungma@eit.uni-kl.de
10912027Sjungma@eit.uni-kl.de    ThreadContext *getContext(int tn);
11012027Sjungma@eit.uni-kl.de
11112027Sjungma@eit.uni-kl.de    Counter totalInsts() const;
11212027Sjungma@eit.uni-kl.de    Counter totalOps() const;
11312027Sjungma@eit.uni-kl.de
11412027Sjungma@eit.uni-kl.de    /** Dump the internal state to the terminal. */
11512027Sjungma@eit.uni-kl.de    virtual void dump() const;
11612027Sjungma@eit.uni-kl.de
11712027Sjungma@eit.uni-kl.de    /**
11812027Sjungma@eit.uni-kl.de     * Force an exit from KVM.
11912027Sjungma@eit.uni-kl.de     *
12012027Sjungma@eit.uni-kl.de     * Send a signal to the thread owning this vCPU to get it to exit
12112027Sjungma@eit.uni-kl.de     * from KVM. Ignored if the vCPU is not executing.
12212027Sjungma@eit.uni-kl.de     */
12312027Sjungma@eit.uni-kl.de    void kick() const { pthread_kill(vcpuThread, KVM_KICK_SIGNAL); }
12412027Sjungma@eit.uni-kl.de
12512027Sjungma@eit.uni-kl.de    /**
12612027Sjungma@eit.uni-kl.de     * A cached copy of a thread's state in the form of a SimpleThread
12712027Sjungma@eit.uni-kl.de     * object.
12812027Sjungma@eit.uni-kl.de     *
12912027Sjungma@eit.uni-kl.de     * Normally the actual thread state is stored in the KVM vCPU. If KVM has
13012027Sjungma@eit.uni-kl.de     * been running this copy is will be out of date. If we recently handled
13112027Sjungma@eit.uni-kl.de     * some events within gem5 that required state to be updated this could be
13212027Sjungma@eit.uni-kl.de     * the most up-to-date copy. When getContext() or updateThreadContext() is
13312027Sjungma@eit.uni-kl.de     * called this copy gets updated.  The method syncThreadContext can
13412027Sjungma@eit.uni-kl.de     * be used within a KVM CPU to update the thread context if the
13512027Sjungma@eit.uni-kl.de     * KVM state is dirty (i.e., the vCPU has been run since the last
13612027Sjungma@eit.uni-kl.de     * update).
13712027Sjungma@eit.uni-kl.de     */
13812027Sjungma@eit.uni-kl.de    SimpleThread *thread;
13912027Sjungma@eit.uni-kl.de
14012027Sjungma@eit.uni-kl.de    /** ThreadContext object, provides an interface for external
14112027Sjungma@eit.uni-kl.de     * objects to modify this thread's state.
14212027Sjungma@eit.uni-kl.de     */
14312027Sjungma@eit.uni-kl.de    ThreadContext *tc;
14412027Sjungma@eit.uni-kl.de
14512027Sjungma@eit.uni-kl.de    KvmVM &vm;
14612027Sjungma@eit.uni-kl.de
14712027Sjungma@eit.uni-kl.de  protected:
14812027Sjungma@eit.uni-kl.de    /**
14912027Sjungma@eit.uni-kl.de     *
15012027Sjungma@eit.uni-kl.de     * @dot
15112027Sjungma@eit.uni-kl.de     *   digraph {
15212027Sjungma@eit.uni-kl.de     *     Idle;
15312027Sjungma@eit.uni-kl.de     *     Running;
15412027Sjungma@eit.uni-kl.de     *     RunningService;
15512027Sjungma@eit.uni-kl.de     *     RunningServiceCompletion;
15612027Sjungma@eit.uni-kl.de     *
15712027Sjungma@eit.uni-kl.de     *     Idle -> Idle;
15812027Sjungma@eit.uni-kl.de     *     Idle -> Running [label="activateContext()", URL="\ref activateContext"];
15912027Sjungma@eit.uni-kl.de     *     Running -> Running [label="tick()", URL="\ref tick"];
16012027Sjungma@eit.uni-kl.de     *     Running -> RunningService [label="tick()", URL="\ref tick"];
16112027Sjungma@eit.uni-kl.de     *     Running -> Idle [label="suspendContext()", URL="\ref suspendContext"];
16212027Sjungma@eit.uni-kl.de     *     Running -> Idle [label="drain()", URL="\ref drain"];
16312027Sjungma@eit.uni-kl.de     *     Idle -> Running [label="drainResume()", URL="\ref drainResume"];
16412027Sjungma@eit.uni-kl.de     *     RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"];
16512027Sjungma@eit.uni-kl.de     *     RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"];
16612027Sjungma@eit.uni-kl.de     *     RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"];
16712027Sjungma@eit.uni-kl.de     *   }
16812027Sjungma@eit.uni-kl.de     * @enddot
16912027Sjungma@eit.uni-kl.de     */
17012027Sjungma@eit.uni-kl.de    enum Status {
17112027Sjungma@eit.uni-kl.de        /** Context not scheduled in KVM.
17212027Sjungma@eit.uni-kl.de         *
17312027Sjungma@eit.uni-kl.de         * The CPU generally enters this state when the guest execute
17412027Sjungma@eit.uni-kl.de         * an instruction that halts the CPU (e.g., WFI on ARM or HLT
17512027Sjungma@eit.uni-kl.de         * on X86) if KVM traps this instruction. Ticks are not
17612027Sjungma@eit.uni-kl.de         * scheduled in this state.
17712027Sjungma@eit.uni-kl.de         *
17812027Sjungma@eit.uni-kl.de         * @see suspendContext()
17912027Sjungma@eit.uni-kl.de         */
18012027Sjungma@eit.uni-kl.de        Idle,
18112027Sjungma@eit.uni-kl.de        /** Running normally.
18212027Sjungma@eit.uni-kl.de         *
18312027Sjungma@eit.uni-kl.de         * This is the normal run state of the CPU. KVM will be
18412027Sjungma@eit.uni-kl.de         * entered next time tick() is called.
18512027Sjungma@eit.uni-kl.de         */
18612027Sjungma@eit.uni-kl.de        Running,
18712027Sjungma@eit.uni-kl.de        /** Requiring service at the beginning of the next cycle.
18812027Sjungma@eit.uni-kl.de         *
18912027Sjungma@eit.uni-kl.de         * The virtual machine has exited and requires service, tick()
19012027Sjungma@eit.uni-kl.de         * will call handleKvmExit() on the next cycle. The next state
19112027Sjungma@eit.uni-kl.de         * after running service is determined in handleKvmExit() and
19212027Sjungma@eit.uni-kl.de         * depends on what kind of service the guest requested:
19312027Sjungma@eit.uni-kl.de         * <ul>
19412027Sjungma@eit.uni-kl.de         *   <li>IO/MMIO: RunningServiceCompletion
19512027Sjungma@eit.uni-kl.de         *   <li>Halt: Idle
19612027Sjungma@eit.uni-kl.de         *   <li>Others: Running
19712027Sjungma@eit.uni-kl.de         * </ul>
19812027Sjungma@eit.uni-kl.de         */
19912027Sjungma@eit.uni-kl.de        RunningService,
20012027Sjungma@eit.uni-kl.de        /** Service completion in progress.
20112027Sjungma@eit.uni-kl.de         *
20212027Sjungma@eit.uni-kl.de         * The VM has requested service that requires KVM to be
20312027Sjungma@eit.uni-kl.de         * entered once in order to get to a consistent state. This
20412027Sjungma@eit.uni-kl.de         * happens in handleKvmExit() or one of its friends after IO
20512027Sjungma@eit.uni-kl.de         * exits. After executing tick(), the CPU will transition into
20612027Sjungma@eit.uni-kl.de         * the Running or RunningService state.
20712027Sjungma@eit.uni-kl.de         */
20812027Sjungma@eit.uni-kl.de        RunningServiceCompletion,
20912027Sjungma@eit.uni-kl.de    };
21012027Sjungma@eit.uni-kl.de
21112027Sjungma@eit.uni-kl.de    /** CPU run state */
21212027Sjungma@eit.uni-kl.de    Status _status;
21312027Sjungma@eit.uni-kl.de
21412027Sjungma@eit.uni-kl.de    /**
21512027Sjungma@eit.uni-kl.de     * Execute the CPU until the next event in the main event queue or
21612027Sjungma@eit.uni-kl.de     * until the guest needs service from gem5.
21712027Sjungma@eit.uni-kl.de     */
21812027Sjungma@eit.uni-kl.de    void tick();
21912027Sjungma@eit.uni-kl.de
22012027Sjungma@eit.uni-kl.de    /**
22112027Sjungma@eit.uni-kl.de     * Get the value of the hardware cycle counter in the guest.
22212027Sjungma@eit.uni-kl.de     *
22312027Sjungma@eit.uni-kl.de     * This method is supposed to return the total number of cycles
22412027Sjungma@eit.uni-kl.de     * executed in hardware mode relative to some arbitrary point in
22512027Sjungma@eit.uni-kl.de     * the past. It's mainly used when estimating the number of cycles
22612027Sjungma@eit.uni-kl.de     * actually executed by the CPU in kvmRun(). The default behavior
22712027Sjungma@eit.uni-kl.de     * of this method is to use the cycles performance counter, but
22812027Sjungma@eit.uni-kl.de     * some architectures may want to use internal registers instead.
22912027Sjungma@eit.uni-kl.de     *
23012027Sjungma@eit.uni-kl.de     * @return Number of host cycles executed relative to an undefined
23112027Sjungma@eit.uni-kl.de     * point in the past.
23212027Sjungma@eit.uni-kl.de     */
23312027Sjungma@eit.uni-kl.de    virtual uint64_t getHostCycles() const;
23412027Sjungma@eit.uni-kl.de
23512027Sjungma@eit.uni-kl.de    /**
23612027Sjungma@eit.uni-kl.de     * Request KVM to run the guest for a given number of ticks. The
23712027Sjungma@eit.uni-kl.de     * method returns the approximate number of ticks executed.
23812027Sjungma@eit.uni-kl.de     *
23912027Sjungma@eit.uni-kl.de     * @note The returned number of ticks can be both larger or
24012027Sjungma@eit.uni-kl.de     * smaller than the requested number of ticks. A smaller number
24112027Sjungma@eit.uni-kl.de     * can, for example, occur when the guest executes MMIO. A larger
24212027Sjungma@eit.uni-kl.de     * number is typically due to performance counter inaccuracies.
24312027Sjungma@eit.uni-kl.de     *
24412027Sjungma@eit.uni-kl.de     * @note This method is virtual in order to allow implementations
24512027Sjungma@eit.uni-kl.de     * to check for architecture specific events (e.g., interrupts)
24612027Sjungma@eit.uni-kl.de     * before entering the VM.
24712027Sjungma@eit.uni-kl.de     *
24812027Sjungma@eit.uni-kl.de     * @note It is the response of the caller (normally tick()) to
24912027Sjungma@eit.uni-kl.de     * make sure that the KVM state is synchronized and that the TC is
25012027Sjungma@eit.uni-kl.de     * invalidated after entering KVM.
25112027Sjungma@eit.uni-kl.de     *
25212027Sjungma@eit.uni-kl.de     * @note This method does not normally cause any state
25312027Sjungma@eit.uni-kl.de     * transitions. However, if it may suspend the CPU by suspending
25412027Sjungma@eit.uni-kl.de     * the thread, which leads to a transition to the Idle state. In
25512027Sjungma@eit.uni-kl.de     * such a case, kvm <i>must not</i> be entered.
25612027Sjungma@eit.uni-kl.de     *
25712027Sjungma@eit.uni-kl.de     * @param ticks Number of ticks to execute, set to 0 to exit
25812027Sjungma@eit.uni-kl.de     * immediately after finishing pending operations.
25912027Sjungma@eit.uni-kl.de     * @return Number of ticks executed (see note)
26012027Sjungma@eit.uni-kl.de     */
26112027Sjungma@eit.uni-kl.de    virtual Tick kvmRun(Tick ticks);
26212027Sjungma@eit.uni-kl.de
26312027Sjungma@eit.uni-kl.de    /**
26412027Sjungma@eit.uni-kl.de     * Request the CPU to run until draining completes.
26512027Sjungma@eit.uni-kl.de     *
26612027Sjungma@eit.uni-kl.de     * This function normally calls kvmRun(0) to make KVM finish
26712027Sjungma@eit.uni-kl.de     * pending MMIO operations. Architecures implementing
26812027Sjungma@eit.uni-kl.de     * archIsDrained() must override this method.
26912027Sjungma@eit.uni-kl.de     *
27012027Sjungma@eit.uni-kl.de     * @see BaseKvmCPU::archIsDrained()
27112027Sjungma@eit.uni-kl.de     *
27212027Sjungma@eit.uni-kl.de     * @return Number of ticks executed
27312027Sjungma@eit.uni-kl.de     */
27412027Sjungma@eit.uni-kl.de    virtual Tick kvmRunDrain();
27512027Sjungma@eit.uni-kl.de
27612027Sjungma@eit.uni-kl.de    /**
27712027Sjungma@eit.uni-kl.de     * Get a pointer to the kvm_run structure containing all the input
27812027Sjungma@eit.uni-kl.de     * and output parameters from kvmRun().
27912027Sjungma@eit.uni-kl.de     */
28012027Sjungma@eit.uni-kl.de    struct kvm_run *getKvmRunState() { return _kvmRun; };
28112027Sjungma@eit.uni-kl.de
28212027Sjungma@eit.uni-kl.de    /**
28312027Sjungma@eit.uni-kl.de     * Retrieve a pointer to guest data stored at the end of the
28412027Sjungma@eit.uni-kl.de     * kvm_run structure. This is mainly used for PIO operations
28512027Sjungma@eit.uni-kl.de     * (KVM_EXIT_IO).
28612027Sjungma@eit.uni-kl.de     *
28712027Sjungma@eit.uni-kl.de     * @param offset Offset as specified by the kvm_run structure
28812027Sjungma@eit.uni-kl.de     * @return Pointer to guest data
28912027Sjungma@eit.uni-kl.de     */
29012027Sjungma@eit.uni-kl.de    uint8_t *getGuestData(uint64_t offset) const {
29112027Sjungma@eit.uni-kl.de        return (uint8_t *)_kvmRun + offset;
29212027Sjungma@eit.uni-kl.de    };
29312027Sjungma@eit.uni-kl.de
29412027Sjungma@eit.uni-kl.de    /**
29512027Sjungma@eit.uni-kl.de     * @addtogroup KvmInterrupts
29612027Sjungma@eit.uni-kl.de     * @{
29712027Sjungma@eit.uni-kl.de     */
29812027Sjungma@eit.uni-kl.de    /**
29912027Sjungma@eit.uni-kl.de     * Send a non-maskable interrupt to the guest
30012027Sjungma@eit.uni-kl.de     *
30112027Sjungma@eit.uni-kl.de     * @note The presence of this call depends on Kvm::capUserNMI().
30212027Sjungma@eit.uni-kl.de     */
30312027Sjungma@eit.uni-kl.de    void kvmNonMaskableInterrupt();
30412027Sjungma@eit.uni-kl.de
30512027Sjungma@eit.uni-kl.de    /**
30612027Sjungma@eit.uni-kl.de     * Send a normal interrupt to the guest
30712027Sjungma@eit.uni-kl.de     *
30812027Sjungma@eit.uni-kl.de     * @note Make sure that ready_for_interrupt_injection in kvm_run
30912027Sjungma@eit.uni-kl.de     * is set prior to calling this function. If not, an interrupt
31012027Sjungma@eit.uni-kl.de     * window must be requested by setting request_interrupt_window in
31112027Sjungma@eit.uni-kl.de     * kvm_run to 1 and restarting the guest.
31212027Sjungma@eit.uni-kl.de     *
31312027Sjungma@eit.uni-kl.de     * @param interrupt Structure describing the interrupt to send
31412027Sjungma@eit.uni-kl.de     */
31512027Sjungma@eit.uni-kl.de    void kvmInterrupt(const struct kvm_interrupt &interrupt);
31612027Sjungma@eit.uni-kl.de
31712027Sjungma@eit.uni-kl.de    /** @} */
31812027Sjungma@eit.uni-kl.de
31912027Sjungma@eit.uni-kl.de    /** @{ */
32012027Sjungma@eit.uni-kl.de    /**
32112027Sjungma@eit.uni-kl.de     * Get/Set the register state of the guest vCPU
32212027Sjungma@eit.uni-kl.de     *
32312027Sjungma@eit.uni-kl.de     * KVM has two different interfaces for accessing the state of the
32412027Sjungma@eit.uni-kl.de     * guest CPU. One interface updates 'normal' registers and one
32512027Sjungma@eit.uni-kl.de     * updates 'special' registers. The distinction between special
32612027Sjungma@eit.uni-kl.de     * and normal registers isn't very clear and is architecture
32712027Sjungma@eit.uni-kl.de     * dependent.
32812027Sjungma@eit.uni-kl.de     */
32912027Sjungma@eit.uni-kl.de    void getRegisters(struct kvm_regs &regs) const;
33012027Sjungma@eit.uni-kl.de    void setRegisters(const struct kvm_regs &regs);
33112027Sjungma@eit.uni-kl.de    void getSpecialRegisters(struct kvm_sregs &regs) const;
33212027Sjungma@eit.uni-kl.de    void setSpecialRegisters(const struct kvm_sregs &regs);
33312027Sjungma@eit.uni-kl.de    /** @} */
33412027Sjungma@eit.uni-kl.de
33512027Sjungma@eit.uni-kl.de    /** @{ */
33612027Sjungma@eit.uni-kl.de    /**
33712027Sjungma@eit.uni-kl.de     * Get/Set the guest FPU/vector state
33812027Sjungma@eit.uni-kl.de     */
33912027Sjungma@eit.uni-kl.de    void getFPUState(struct kvm_fpu &state) const;
34012027Sjungma@eit.uni-kl.de    void setFPUState(const struct kvm_fpu &state);
34112027Sjungma@eit.uni-kl.de    /** @} */
34212027Sjungma@eit.uni-kl.de
34312027Sjungma@eit.uni-kl.de    /** @{ */
34412027Sjungma@eit.uni-kl.de    /**
34512027Sjungma@eit.uni-kl.de     * Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
34612027Sjungma@eit.uni-kl.de     *
34712027Sjungma@eit.uni-kl.de     * @note The presence of this call depends on Kvm::capOneReg().
34812027Sjungma@eit.uni-kl.de     */
34912027Sjungma@eit.uni-kl.de    void setOneReg(uint64_t id, const void *addr);
35012027Sjungma@eit.uni-kl.de    void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); }
35112027Sjungma@eit.uni-kl.de    void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); }
35212027Sjungma@eit.uni-kl.de    void getOneReg(uint64_t id, void *addr) const;
35312027Sjungma@eit.uni-kl.de    uint64_t getOneRegU64(uint64_t id) const {
35412027Sjungma@eit.uni-kl.de        uint64_t value;
35512027Sjungma@eit.uni-kl.de        getOneReg(id, &value);
35612027Sjungma@eit.uni-kl.de        return value;
35712027Sjungma@eit.uni-kl.de    }
35812027Sjungma@eit.uni-kl.de    uint32_t getOneRegU32(uint64_t id) const {
35912027Sjungma@eit.uni-kl.de        uint32_t value;
36012027Sjungma@eit.uni-kl.de        getOneReg(id, &value);
36112027Sjungma@eit.uni-kl.de        return value;
36212027Sjungma@eit.uni-kl.de    }
36312027Sjungma@eit.uni-kl.de    /** @} */
36412027Sjungma@eit.uni-kl.de
36512027Sjungma@eit.uni-kl.de    /**
36612027Sjungma@eit.uni-kl.de     * Get and format one register for printout.
36712027Sjungma@eit.uni-kl.de     *
36812027Sjungma@eit.uni-kl.de     * This function call getOneReg() to retrieve the contents of one
36912027Sjungma@eit.uni-kl.de     * register and automatically formats it for printing.
37012027Sjungma@eit.uni-kl.de     *
37112027Sjungma@eit.uni-kl.de     * @note The presence of this call depends on Kvm::capOneReg().
37212027Sjungma@eit.uni-kl.de     */
37312027Sjungma@eit.uni-kl.de    std::string getAndFormatOneReg(uint64_t id) const;
37412027Sjungma@eit.uni-kl.de
37512027Sjungma@eit.uni-kl.de    /** @{ */
37612027Sjungma@eit.uni-kl.de    /**
37712027Sjungma@eit.uni-kl.de     * Update the KVM state from the current thread context
37812027Sjungma@eit.uni-kl.de     *
37912027Sjungma@eit.uni-kl.de     * The base CPU calls this method before starting the guest CPU
38012027Sjungma@eit.uni-kl.de     * when the contextDirty flag is set. The architecture dependent
38112027Sjungma@eit.uni-kl.de     * CPU implementation is expected to update all guest state
38212027Sjungma@eit.uni-kl.de     * (registers, special registers, and FPU state).
38312027Sjungma@eit.uni-kl.de     */
38412027Sjungma@eit.uni-kl.de    virtual void updateKvmState() = 0;
38512027Sjungma@eit.uni-kl.de
38612027Sjungma@eit.uni-kl.de    /**
38712027Sjungma@eit.uni-kl.de     * Update the current thread context with the KVM state
38812027Sjungma@eit.uni-kl.de     *
38912027Sjungma@eit.uni-kl.de     * The base CPU after the guest updates any of the KVM state. In
39012027Sjungma@eit.uni-kl.de     * practice, this happens after kvmRun is called. The architecture
39112027Sjungma@eit.uni-kl.de     * dependent code is expected to read the state of the guest CPU
39212027Sjungma@eit.uni-kl.de     * and update gem5's thread state.
39312027Sjungma@eit.uni-kl.de     */
39412027Sjungma@eit.uni-kl.de    virtual void updateThreadContext() = 0;
39512027Sjungma@eit.uni-kl.de
39612027Sjungma@eit.uni-kl.de    /**
39712027Sjungma@eit.uni-kl.de     * Update a thread context if the KVM state is dirty with respect
39812027Sjungma@eit.uni-kl.de     * to the cached thread context.
39912027Sjungma@eit.uni-kl.de     */
40012027Sjungma@eit.uni-kl.de    void syncThreadContext();
40112027Sjungma@eit.uni-kl.de
40212027Sjungma@eit.uni-kl.de    /**
40312027Sjungma@eit.uni-kl.de     * Update the KVM if the thread context is dirty.
40412027Sjungma@eit.uni-kl.de     */
40512027Sjungma@eit.uni-kl.de    void syncKvmState();
40612027Sjungma@eit.uni-kl.de    /** @} */
40712027Sjungma@eit.uni-kl.de
40812027Sjungma@eit.uni-kl.de    /** @{ */
40912027Sjungma@eit.uni-kl.de    /**
41012027Sjungma@eit.uni-kl.de     * Main kvmRun exit handler, calls the relevant handleKvmExit*
41112027Sjungma@eit.uni-kl.de     * depending on exit type.
41212027Sjungma@eit.uni-kl.de     *
41312027Sjungma@eit.uni-kl.de     * @return Number of ticks spent servicing the exit request
41412027Sjungma@eit.uni-kl.de     */
41512027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExit();
41612027Sjungma@eit.uni-kl.de
41712027Sjungma@eit.uni-kl.de    /**
41812027Sjungma@eit.uni-kl.de     * The guest performed a legacy IO request (out/inp on x86)
41912027Sjungma@eit.uni-kl.de     *
42012027Sjungma@eit.uni-kl.de     * @return Number of ticks spent servicing the IO request
42112027Sjungma@eit.uni-kl.de     */
42212027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExitIO();
42312027Sjungma@eit.uni-kl.de
42412027Sjungma@eit.uni-kl.de    /**
42512027Sjungma@eit.uni-kl.de     * The guest requested a monitor service using a hypercall
42612027Sjungma@eit.uni-kl.de     *
42712027Sjungma@eit.uni-kl.de     * @return Number of ticks spent servicing the hypercall
42812027Sjungma@eit.uni-kl.de     */
42912027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExitHypercall();
43012027Sjungma@eit.uni-kl.de
43112027Sjungma@eit.uni-kl.de    /**
43212027Sjungma@eit.uni-kl.de     * The guest exited because an interrupt window was requested
43312027Sjungma@eit.uni-kl.de     *
43412027Sjungma@eit.uni-kl.de     * The guest exited because an interrupt window was requested
43512027Sjungma@eit.uni-kl.de     * (request_interrupt_window in the kvm_run structure was set to 1
43612027Sjungma@eit.uni-kl.de     * before calling kvmRun) and it is now ready to receive
43712027Sjungma@eit.uni-kl.de     *
43812027Sjungma@eit.uni-kl.de     * @return Number of ticks spent servicing the IRQ
43912027Sjungma@eit.uni-kl.de     */
44012027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExitIRQWindowOpen();
44112027Sjungma@eit.uni-kl.de
44212027Sjungma@eit.uni-kl.de    /**
44312027Sjungma@eit.uni-kl.de     * An unknown architecture dependent error occurred when starting
44412027Sjungma@eit.uni-kl.de     * the vCPU
44512027Sjungma@eit.uni-kl.de     *
44612027Sjungma@eit.uni-kl.de     * The kvm_run data structure contains the hardware error
44712027Sjungma@eit.uni-kl.de     * code. The defaults behavior of this method just prints the HW
44812027Sjungma@eit.uni-kl.de     * error code and panics. Architecture dependent implementations
44912027Sjungma@eit.uni-kl.de     * may want to override this method to provide better,
45012027Sjungma@eit.uni-kl.de     * hardware-aware, error messages.
45112027Sjungma@eit.uni-kl.de     *
45212027Sjungma@eit.uni-kl.de     * @return Number of ticks delay the next CPU tick
45312027Sjungma@eit.uni-kl.de     */
45412027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExitUnknown();
45512027Sjungma@eit.uni-kl.de
45612027Sjungma@eit.uni-kl.de    /**
45712027Sjungma@eit.uni-kl.de     * An unhandled virtualization exception occured
45812027Sjungma@eit.uni-kl.de     *
45912027Sjungma@eit.uni-kl.de     * Some KVM virtualization drivers return unhandled exceptions to
46012027Sjungma@eit.uni-kl.de     * the user-space monitor. This interface is currently only used
46112027Sjungma@eit.uni-kl.de     * by the Intel VMX KVM driver.
46212027Sjungma@eit.uni-kl.de     *
46312027Sjungma@eit.uni-kl.de     * @return Number of ticks delay the next CPU tick
46412027Sjungma@eit.uni-kl.de     */
46512027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExitException();
46612027Sjungma@eit.uni-kl.de
46712027Sjungma@eit.uni-kl.de    /**
46812027Sjungma@eit.uni-kl.de     * KVM failed to start the virtualized CPU
46912027Sjungma@eit.uni-kl.de     *
47012027Sjungma@eit.uni-kl.de     * The kvm_run data structure contains the hardware-specific error
47112027Sjungma@eit.uni-kl.de     * code.
47212027Sjungma@eit.uni-kl.de     *
47312027Sjungma@eit.uni-kl.de     * @return Number of ticks delay the next CPU tick
47412027Sjungma@eit.uni-kl.de     */
47512027Sjungma@eit.uni-kl.de    virtual Tick handleKvmExitFailEntry();
47612027Sjungma@eit.uni-kl.de    /** @} */
47712027Sjungma@eit.uni-kl.de
47812027Sjungma@eit.uni-kl.de    /**
47912027Sjungma@eit.uni-kl.de     * Is the architecture specific code in a state that prevents
48012027Sjungma@eit.uni-kl.de     * draining?
48112027Sjungma@eit.uni-kl.de     *
48212027Sjungma@eit.uni-kl.de     * This method should return false if there are any pending events
48312027Sjungma@eit.uni-kl.de     * in the guest vCPU that won't be carried over to the gem5 state
48412027Sjungma@eit.uni-kl.de     * and thus will prevent correct checkpointing or CPU handover. It
48512027Sjungma@eit.uni-kl.de     * might, for example, check for pending interrupts that have been
48612027Sjungma@eit.uni-kl.de     * passed to the vCPU but not acknowledged by the OS. Architecures
48712027Sjungma@eit.uni-kl.de     * implementing this method <i>must</i> override
48812027Sjungma@eit.uni-kl.de     * kvmRunDrain().
48912027Sjungma@eit.uni-kl.de     *
49012027Sjungma@eit.uni-kl.de     * @see BaseKvmCPU::kvmRunDrain()
49112027Sjungma@eit.uni-kl.de     *
49212027Sjungma@eit.uni-kl.de     * @return true if the vCPU is drained, false otherwise.
49312027Sjungma@eit.uni-kl.de     */
49412027Sjungma@eit.uni-kl.de    virtual bool archIsDrained() const { return true; }
49512027Sjungma@eit.uni-kl.de
49612027Sjungma@eit.uni-kl.de    /**
49712027Sjungma@eit.uni-kl.de     * Inject a memory mapped IO request into gem5
49812027Sjungma@eit.uni-kl.de     *
49912027Sjungma@eit.uni-kl.de     * @param paddr Physical address
50012027Sjungma@eit.uni-kl.de     * @param data Pointer to the source/destination buffer
50112027Sjungma@eit.uni-kl.de     * @param size Memory access size
50212027Sjungma@eit.uni-kl.de     * @param write True if write, False if read
50312027Sjungma@eit.uni-kl.de     * @return Number of ticks spent servicing the memory access
50412027Sjungma@eit.uni-kl.de     */
50512027Sjungma@eit.uni-kl.de    Tick doMMIOAccess(Addr paddr, void *data, int size, bool write);
50612027Sjungma@eit.uni-kl.de
50712027Sjungma@eit.uni-kl.de    /** @{ */
50812027Sjungma@eit.uni-kl.de    /**
50912027Sjungma@eit.uni-kl.de     * Set the signal mask used in kvmRun()
51012027Sjungma@eit.uni-kl.de     *
51112027Sjungma@eit.uni-kl.de     * This method allows the signal mask of the thread executing
51212027Sjungma@eit.uni-kl.de     * kvmRun() to be overridden inside the actual system call. This
51312027Sjungma@eit.uni-kl.de     * allows us to mask timer signals used to force KVM exits while
51412027Sjungma@eit.uni-kl.de     * in gem5.
51512027Sjungma@eit.uni-kl.de     *
51612027Sjungma@eit.uni-kl.de     * The signal mask can be disabled by setting it to NULL.
51712027Sjungma@eit.uni-kl.de     *
51812027Sjungma@eit.uni-kl.de     * @param mask Signals to mask
51912027Sjungma@eit.uni-kl.de     */
52012027Sjungma@eit.uni-kl.de    void setSignalMask(const sigset_t *mask);
52112027Sjungma@eit.uni-kl.de    /** @} */
52212027Sjungma@eit.uni-kl.de
52312027Sjungma@eit.uni-kl.de    /**
52412027Sjungma@eit.uni-kl.de     * @addtogroup KvmIoctl
52512027Sjungma@eit.uni-kl.de     * @{
52612027Sjungma@eit.uni-kl.de     */
52712027Sjungma@eit.uni-kl.de    /**
52812027Sjungma@eit.uni-kl.de     * vCPU ioctl interface.
52912027Sjungma@eit.uni-kl.de     *
53012027Sjungma@eit.uni-kl.de     * @param request KVM vCPU request
53112027Sjungma@eit.uni-kl.de     * @param p1 Optional request parameter
53212027Sjungma@eit.uni-kl.de     *
53312027Sjungma@eit.uni-kl.de     * @return -1 on error (error number in errno), ioctl dependent
53412027Sjungma@eit.uni-kl.de     * value otherwise.
53512027Sjungma@eit.uni-kl.de     */
53612027Sjungma@eit.uni-kl.de    int ioctl(int request, long p1) const;
53712027Sjungma@eit.uni-kl.de    int ioctl(int request, void *p1) const {
53812027Sjungma@eit.uni-kl.de        return ioctl(request, (long)p1);
53912027Sjungma@eit.uni-kl.de    }
54012027Sjungma@eit.uni-kl.de    int ioctl(int request) const {
54112027Sjungma@eit.uni-kl.de        return ioctl(request, 0L);
54212027Sjungma@eit.uni-kl.de    }
54312027Sjungma@eit.uni-kl.de    /** @} */
54412027Sjungma@eit.uni-kl.de
54512027Sjungma@eit.uni-kl.de
54612027Sjungma@eit.uni-kl.de    /**
54712027Sjungma@eit.uni-kl.de     * KVM memory port. Uses the default MasterPort behavior, but
54812027Sjungma@eit.uni-kl.de     * panics on timing accesses.
54912027Sjungma@eit.uni-kl.de     */
55012027Sjungma@eit.uni-kl.de    class KVMCpuPort : public MasterPort
55112027Sjungma@eit.uni-kl.de    {
55212027Sjungma@eit.uni-kl.de
55312027Sjungma@eit.uni-kl.de      public:
55412027Sjungma@eit.uni-kl.de        KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu)
55512027Sjungma@eit.uni-kl.de            : MasterPort(_name, _cpu)
55612027Sjungma@eit.uni-kl.de        { }
55712027Sjungma@eit.uni-kl.de
55812027Sjungma@eit.uni-kl.de      protected:
55912027Sjungma@eit.uni-kl.de        bool recvTimingResp(PacketPtr pkt)
56012027Sjungma@eit.uni-kl.de        {
56112027Sjungma@eit.uni-kl.de            panic("The KVM CPU doesn't expect recvTimingResp!\n");
56212027Sjungma@eit.uni-kl.de            return true;
56312027Sjungma@eit.uni-kl.de        }
56412027Sjungma@eit.uni-kl.de
56512027Sjungma@eit.uni-kl.de        void recvReqRetry()
56612027Sjungma@eit.uni-kl.de        {
56712027Sjungma@eit.uni-kl.de            panic("The KVM CPU doesn't expect recvReqRetry!\n");
56812027Sjungma@eit.uni-kl.de        }
56912027Sjungma@eit.uni-kl.de
57012027Sjungma@eit.uni-kl.de    };
57112027Sjungma@eit.uni-kl.de
57212027Sjungma@eit.uni-kl.de    /** Port for data requests */
57312027Sjungma@eit.uni-kl.de    KVMCpuPort dataPort;
57412027Sjungma@eit.uni-kl.de
57512027Sjungma@eit.uni-kl.de    /** Unused dummy port for the instruction interface */
57612027Sjungma@eit.uni-kl.de    KVMCpuPort instPort;
57712027Sjungma@eit.uni-kl.de
57812027Sjungma@eit.uni-kl.de    /**
57912027Sjungma@eit.uni-kl.de     * Is the gem5 context dirty? Set to true to force an update of
58012027Sjungma@eit.uni-kl.de     * the KVM vCPU state upon the next call to kvmRun().
58112027Sjungma@eit.uni-kl.de     */
58212027Sjungma@eit.uni-kl.de    bool threadContextDirty;
58312027Sjungma@eit.uni-kl.de
58412027Sjungma@eit.uni-kl.de    /**
58512027Sjungma@eit.uni-kl.de     * Is the KVM state dirty? Set to true to force an update of
58612027Sjungma@eit.uni-kl.de     * the KVM vCPU state upon the next call to kvmRun().
58712027Sjungma@eit.uni-kl.de     */
58812027Sjungma@eit.uni-kl.de    bool kvmStateDirty;
58912027Sjungma@eit.uni-kl.de
59012027Sjungma@eit.uni-kl.de    /** KVM internal ID of the vCPU */
59112027Sjungma@eit.uni-kl.de    const long vcpuID;
59212027Sjungma@eit.uni-kl.de
59312027Sjungma@eit.uni-kl.de    /** ID of the vCPU thread */
59412027Sjungma@eit.uni-kl.de    pthread_t vcpuThread;
59512027Sjungma@eit.uni-kl.de
59612027Sjungma@eit.uni-kl.de  private:
59712027Sjungma@eit.uni-kl.de    struct TickEvent : public Event
59812027Sjungma@eit.uni-kl.de    {
59912027Sjungma@eit.uni-kl.de        BaseKvmCPU &cpu;
60012027Sjungma@eit.uni-kl.de
60112027Sjungma@eit.uni-kl.de        TickEvent(BaseKvmCPU &c)
60212027Sjungma@eit.uni-kl.de            : Event(CPU_Tick_Pri), cpu(c) {}
60312027Sjungma@eit.uni-kl.de
60412027Sjungma@eit.uni-kl.de        void process() { cpu.tick(); }
60512027Sjungma@eit.uni-kl.de
60612027Sjungma@eit.uni-kl.de        const char *description() const {
60712027Sjungma@eit.uni-kl.de            return "BaseKvmCPU tick";
60812027Sjungma@eit.uni-kl.de        }
60912027Sjungma@eit.uni-kl.de    };
61012027Sjungma@eit.uni-kl.de
61112027Sjungma@eit.uni-kl.de    /**
61212027Sjungma@eit.uni-kl.de     * Service MMIO requests in the mmioRing.
61312027Sjungma@eit.uni-kl.de     *
61412027Sjungma@eit.uni-kl.de     *
61512027Sjungma@eit.uni-kl.de     * @return Number of ticks spent servicing the MMIO requests in
61612027Sjungma@eit.uni-kl.de     * the MMIO ring buffer
61712027Sjungma@eit.uni-kl.de     */
61812027Sjungma@eit.uni-kl.de    Tick flushCoalescedMMIO();
61912027Sjungma@eit.uni-kl.de
62012027Sjungma@eit.uni-kl.de    /**
62112027Sjungma@eit.uni-kl.de     * Setup a signal handler to catch the timer signal used to
62212027Sjungma@eit.uni-kl.de     * switch back to the monitor.
62312027Sjungma@eit.uni-kl.de     */
62412027Sjungma@eit.uni-kl.de    void setupSignalHandler();
62512027Sjungma@eit.uni-kl.de
62612027Sjungma@eit.uni-kl.de    /**
62712027Sjungma@eit.uni-kl.de     * Discard a (potentially) pending signal.
62812027Sjungma@eit.uni-kl.de     *
62912027Sjungma@eit.uni-kl.de     * @param signum Signal to discard
63012027Sjungma@eit.uni-kl.de     * @return true if the signal was pending, false otherwise.
63112027Sjungma@eit.uni-kl.de     */
63212027Sjungma@eit.uni-kl.de    bool discardPendingSignal(int signum) const;
63312027Sjungma@eit.uni-kl.de
63412027Sjungma@eit.uni-kl.de    /**
63512027Sjungma@eit.uni-kl.de     * Thread-specific initialization.
63612027Sjungma@eit.uni-kl.de     *
63712027Sjungma@eit.uni-kl.de     * Some KVM-related initialization requires us to know the TID of
63812027Sjungma@eit.uni-kl.de     * the thread that is going to execute our event queue. For
63912027Sjungma@eit.uni-kl.de     * example, when setting up timers, we need to know the TID of the
64012027Sjungma@eit.uni-kl.de     * thread executing in KVM in order to deliver the timer signal to
64112027Sjungma@eit.uni-kl.de     * that thread. This method is called as the first event in this
64212027Sjungma@eit.uni-kl.de     * SimObject's event queue.
64312027Sjungma@eit.uni-kl.de     *
64412027Sjungma@eit.uni-kl.de     * @see startup
64512027Sjungma@eit.uni-kl.de     */
64612027Sjungma@eit.uni-kl.de    void startupThread();
64712027Sjungma@eit.uni-kl.de
64812027Sjungma@eit.uni-kl.de    /** Try to drain the CPU if a drain is pending */
64912027Sjungma@eit.uni-kl.de    bool tryDrain();
65012027Sjungma@eit.uni-kl.de
65112027Sjungma@eit.uni-kl.de    /** Execute the KVM_RUN ioctl */
65212027Sjungma@eit.uni-kl.de    void ioctlRun();
65312027Sjungma@eit.uni-kl.de
65412027Sjungma@eit.uni-kl.de    /** KVM vCPU file descriptor */
65512027Sjungma@eit.uni-kl.de    int vcpuFD;
65612027Sjungma@eit.uni-kl.de    /** Size of MMAPed kvm_run area */
65712027Sjungma@eit.uni-kl.de    int vcpuMMapSize;
65812027Sjungma@eit.uni-kl.de    /**
65912027Sjungma@eit.uni-kl.de     * Pointer to the kvm_run structure used to communicate parameters
66012027Sjungma@eit.uni-kl.de     * with KVM.
66112027Sjungma@eit.uni-kl.de     *
66212027Sjungma@eit.uni-kl.de     * @note This is the base pointer of the MMAPed KVM region. The
66312027Sjungma@eit.uni-kl.de     * first page contains the kvm_run structure. Subsequent pages may
66412027Sjungma@eit.uni-kl.de     * contain other data such as the MMIO ring buffer.
66512027Sjungma@eit.uni-kl.de     */
66612027Sjungma@eit.uni-kl.de    struct kvm_run *_kvmRun;
66712027Sjungma@eit.uni-kl.de    /**
66812027Sjungma@eit.uni-kl.de     * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not
66912027Sjungma@eit.uni-kl.de     * supported.
67012027Sjungma@eit.uni-kl.de     */
67112027Sjungma@eit.uni-kl.de    struct kvm_coalesced_mmio_ring *mmioRing;
67212027Sjungma@eit.uni-kl.de    /** Cached page size of the host */
67312027Sjungma@eit.uni-kl.de    const long pageSize;
67412027Sjungma@eit.uni-kl.de
67512027Sjungma@eit.uni-kl.de    TickEvent tickEvent;
67612027Sjungma@eit.uni-kl.de
67712027Sjungma@eit.uni-kl.de    /**
67812027Sjungma@eit.uni-kl.de     * Setup an instruction break if there is one pending.
67912027Sjungma@eit.uni-kl.de     *
68012027Sjungma@eit.uni-kl.de     * Check if there are pending instruction breaks in the CPU's
68112027Sjungma@eit.uni-kl.de     * instruction event queue and schedule an instruction break using
68212027Sjungma@eit.uni-kl.de     * PerfEvent.
68312027Sjungma@eit.uni-kl.de     *
68412027Sjungma@eit.uni-kl.de     * @note This method doesn't currently handle the main system
68512027Sjungma@eit.uni-kl.de     * instruction event queue.
68612027Sjungma@eit.uni-kl.de     */
68712027Sjungma@eit.uni-kl.de    void setupInstStop();
68812027Sjungma@eit.uni-kl.de
68912027Sjungma@eit.uni-kl.de    /** @{ */
69012027Sjungma@eit.uni-kl.de    /** Setup hardware performance counters */
69112027Sjungma@eit.uni-kl.de    void setupCounters();
69212027Sjungma@eit.uni-kl.de
69312027Sjungma@eit.uni-kl.de    /**
69412027Sjungma@eit.uni-kl.de     * Setup the guest instruction counter.
69512027Sjungma@eit.uni-kl.de     *
69612027Sjungma@eit.uni-kl.de     * Setup the guest instruction counter and optionally request a
69712027Sjungma@eit.uni-kl.de     * signal every N instructions executed by the guest. This method
69812027Sjungma@eit.uni-kl.de     * will re-attach the counter if the counter has already been
69912027Sjungma@eit.uni-kl.de     * attached and its sampling settings have changed.
70012027Sjungma@eit.uni-kl.de     *
70112027Sjungma@eit.uni-kl.de     * @param period Signal period, set to 0 to disable signaling.
70212027Sjungma@eit.uni-kl.de     */
70312027Sjungma@eit.uni-kl.de    void setupInstCounter(uint64_t period = 0);
70412027Sjungma@eit.uni-kl.de
70512027Sjungma@eit.uni-kl.de    /** Currently active instruction count breakpoint */
70612027Sjungma@eit.uni-kl.de    uint64_t activeInstPeriod;
70712027Sjungma@eit.uni-kl.de
70812027Sjungma@eit.uni-kl.de    /**
70912027Sjungma@eit.uni-kl.de     * Guest cycle counter.
71012027Sjungma@eit.uni-kl.de     *
71112027Sjungma@eit.uni-kl.de     * This is the group leader of all performance counters measuring
71212027Sjungma@eit.uni-kl.de     * the guest system. It can be used in conjunction with the
71312027Sjungma@eit.uni-kl.de     * PerfKvmTimer (see perfControlledByTimer) to trigger exits from
71412027Sjungma@eit.uni-kl.de     * KVM.
71512027Sjungma@eit.uni-kl.de     */
71612027Sjungma@eit.uni-kl.de    PerfKvmCounter hwCycles;
71712027Sjungma@eit.uni-kl.de
71812027Sjungma@eit.uni-kl.de    /**
71912027Sjungma@eit.uni-kl.de     * Guest instruction counter.
72012027Sjungma@eit.uni-kl.de     *
72112027Sjungma@eit.uni-kl.de     * This counter is typically only used to measure the number of
72212027Sjungma@eit.uni-kl.de     * instructions executed by the guest. However, it can also be
72312027Sjungma@eit.uni-kl.de     * used to trigger exits from KVM if the configuration script
72412027Sjungma@eit.uni-kl.de     * requests an exit after a certain number of instructions.
72512027Sjungma@eit.uni-kl.de     *
72612027Sjungma@eit.uni-kl.de     * @see setupInstBreak
72712027Sjungma@eit.uni-kl.de     * @see scheduleInstStop
72812027Sjungma@eit.uni-kl.de     */
72912027Sjungma@eit.uni-kl.de    PerfKvmCounter hwInstructions;
73012027Sjungma@eit.uni-kl.de
73112027Sjungma@eit.uni-kl.de    /**
73212027Sjungma@eit.uni-kl.de     * Does the runTimer control the performance counters?
73312027Sjungma@eit.uni-kl.de     *
73412027Sjungma@eit.uni-kl.de     * The run timer will automatically enable and disable performance
73512027Sjungma@eit.uni-kl.de     * counters if a PerfEvent-based timer is used to control KVM
73612027Sjungma@eit.uni-kl.de     * exits.
73712027Sjungma@eit.uni-kl.de     */
73812027Sjungma@eit.uni-kl.de    bool perfControlledByTimer;
73912027Sjungma@eit.uni-kl.de    /** @} */
74012027Sjungma@eit.uni-kl.de
74112027Sjungma@eit.uni-kl.de    /**
74212027Sjungma@eit.uni-kl.de     * Timer used to force execution into the monitor after a
74312027Sjungma@eit.uni-kl.de     * specified number of simulation tick equivalents have executed
74412027Sjungma@eit.uni-kl.de     * in the guest. This counter generates the signal specified by
74512027Sjungma@eit.uni-kl.de     * KVM_TIMER_SIGNAL.
74612027Sjungma@eit.uni-kl.de     */
74712027Sjungma@eit.uni-kl.de    std::unique_ptr<BaseKvmTimer> runTimer;
74812027Sjungma@eit.uni-kl.de
74912027Sjungma@eit.uni-kl.de    /** Host factor as specified in the configuration */
75012027Sjungma@eit.uni-kl.de    float hostFactor;
75112027Sjungma@eit.uni-kl.de
75212027Sjungma@eit.uni-kl.de  public:
75312027Sjungma@eit.uni-kl.de    /* @{ */
75412027Sjungma@eit.uni-kl.de    Stats::Scalar numInsts;
75512027Sjungma@eit.uni-kl.de    Stats::Scalar numVMExits;
75612027Sjungma@eit.uni-kl.de    Stats::Scalar numVMHalfEntries;
75712027Sjungma@eit.uni-kl.de    Stats::Scalar numExitSignal;
75812027Sjungma@eit.uni-kl.de    Stats::Scalar numMMIO;
75912027Sjungma@eit.uni-kl.de    Stats::Scalar numCoalescedMMIO;
76012027Sjungma@eit.uni-kl.de    Stats::Scalar numIO;
76112027Sjungma@eit.uni-kl.de    Stats::Scalar numHalt;
76212027Sjungma@eit.uni-kl.de    Stats::Scalar numInterrupts;
76312027Sjungma@eit.uni-kl.de    Stats::Scalar numHypercalls;
76412027Sjungma@eit.uni-kl.de    /* @} */
76512027Sjungma@eit.uni-kl.de
76612027Sjungma@eit.uni-kl.de    /** Number of instructions executed by the CPU */
76712027Sjungma@eit.uni-kl.de    Counter ctrInsts;
76812027Sjungma@eit.uni-kl.de};
76912027Sjungma@eit.uni-kl.de
77012027Sjungma@eit.uni-kl.de#endif
77112027Sjungma@eit.uni-kl.de