base.hh revision 10905:a6ca6831e775
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 */
39
40#ifndef __CPU_KVM_BASE_HH__
41#define __CPU_KVM_BASE_HH__
42
43#include <pthread.h>
44
45#include <csignal>
46#include <memory>
47
48#include "base/statistics.hh"
49#include "cpu/kvm/perfevent.hh"
50#include "cpu/kvm/timer.hh"
51#include "cpu/kvm/vm.hh"
52#include "cpu/base.hh"
53#include "cpu/simple_thread.hh"
54
55/** Signal to use to trigger exits from KVM */
56#define KVM_KICK_SIGNAL SIGRTMIN
57
58// forward declarations
59class ThreadContext;
60struct BaseKvmCPUParams;
61
62/**
63 * Base class for KVM based CPU models
64 *
65 * All architecture specific KVM implementation should inherit from
66 * this class. The most basic CPU models only need to override the
67 * updateKvmState() and updateThreadContext() methods to implement
68 * state synchronization between gem5 and KVM.
69 *
70 * The architecture specific implementation is also responsible for
71 * delivering interrupts into the VM. This is typically done by
72 * overriding tick() and checking the thread context before entering
73 * into the VM. In order to deliver an interrupt, the implementation
74 * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt()
75 * depending on the specifics of the underlying hardware/drivers.
76 */
77class BaseKvmCPU : public BaseCPU
78{
79  public:
80    BaseKvmCPU(BaseKvmCPUParams *params);
81    virtual ~BaseKvmCPU();
82
83    void init();
84    void startup();
85    void regStats();
86
87    void serializeThread(CheckpointOut &cp,
88                         ThreadID tid) const M5_ATTR_OVERRIDE;
89    void unserializeThread(CheckpointIn &cp,
90                           ThreadID tid) M5_ATTR_OVERRIDE;
91
92    unsigned int drain(DrainManager *dm);
93    void drainResume();
94
95    void switchOut();
96    void takeOverFrom(BaseCPU *cpu);
97
98    void verifyMemoryMode() const;
99
100    MasterPort &getDataPort() { return dataPort; }
101    MasterPort &getInstPort() { return instPort; }
102
103    void wakeup();
104    void activateContext(ThreadID thread_num);
105    void suspendContext(ThreadID thread_num);
106    void deallocateContext(ThreadID thread_num);
107    void haltContext(ThreadID thread_num);
108
109    ThreadContext *getContext(int tn);
110
111    Counter totalInsts() const;
112    Counter totalOps() const;
113
114    /** Dump the internal state to the terminal. */
115    virtual void dump() const;
116
117    /**
118     * Force an exit from KVM.
119     *
120     * Send a signal to the thread owning this vCPU to get it to exit
121     * from KVM. Ignored if the vCPU is not executing.
122     */
123    void kick() const { pthread_kill(vcpuThread, KVM_KICK_SIGNAL); }
124
125    /**
126     * A cached copy of a thread's state in the form of a SimpleThread
127     * object.
128     *
129     * Normally the actual thread state is stored in the KVM vCPU. If KVM has
130     * been running this copy is will be out of date. If we recently handled
131     * some events within gem5 that required state to be updated this could be
132     * the most up-to-date copy. When getContext() or updateThreadContext() is
133     * called this copy gets updated.  The method syncThreadContext can
134     * be used within a KVM CPU to update the thread context if the
135     * KVM state is dirty (i.e., the vCPU has been run since the last
136     * update).
137     */
138    SimpleThread *thread;
139
140    /** ThreadContext object, provides an interface for external
141     * objects to modify this thread's state.
142     */
143    ThreadContext *tc;
144
145    KvmVM &vm;
146
147  protected:
148    /**
149     *
150     * @dot
151     *   digraph {
152     *     Idle;
153     *     Running;
154     *     RunningService;
155     *     RunningServiceCompletion;
156     *
157     *     Idle -> Idle;
158     *     Idle -> Running [label="activateContext()", URL="\ref activateContext"];
159     *     Running -> Running [label="tick()", URL="\ref tick"];
160     *     Running -> RunningService [label="tick()", URL="\ref tick"];
161     *     Running -> Idle [label="suspendContext()", URL="\ref suspendContext"];
162     *     Running -> Idle [label="drain()", URL="\ref drain"];
163     *     Idle -> Running [label="drainResume()", URL="\ref drainResume"];
164     *     RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"];
165     *     RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"];
166     *     RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"];
167     *   }
168     * @enddot
169     */
170    enum Status {
171        /** Context not scheduled in KVM.
172         *
173         * The CPU generally enters this state when the guest execute
174         * an instruction that halts the CPU (e.g., WFI on ARM or HLT
175         * on X86) if KVM traps this instruction. Ticks are not
176         * scheduled in this state.
177         *
178         * @see suspendContext()
179         */
180        Idle,
181        /** Running normally.
182         *
183         * This is the normal run state of the CPU. KVM will be
184         * entered next time tick() is called.
185         */
186        Running,
187        /** Requiring service at the beginning of the next cycle.
188         *
189         * The virtual machine has exited and requires service, tick()
190         * will call handleKvmExit() on the next cycle. The next state
191         * after running service is determined in handleKvmExit() and
192         * depends on what kind of service the guest requested:
193         * <ul>
194         *   <li>IO/MMIO: RunningServiceCompletion
195         *   <li>Halt: Idle
196         *   <li>Others: Running
197         * </ul>
198         */
199        RunningService,
200        /** Service completion in progress.
201         *
202         * The VM has requested service that requires KVM to be
203         * entered once in order to get to a consistent state. This
204         * happens in handleKvmExit() or one of its friends after IO
205         * exits. After executing tick(), the CPU will transition into
206         * the Running or RunningService state.
207         */
208        RunningServiceCompletion,
209    };
210
211    /** CPU run state */
212    Status _status;
213
214    /**
215     * Execute the CPU until the next event in the main event queue or
216     * until the guest needs service from gem5.
217     */
218    void tick();
219
220    /**
221     * Get the value of the hardware cycle counter in the guest.
222     *
223     * This method is supposed to return the total number of cycles
224     * executed in hardware mode relative to some arbitrary point in
225     * the past. It's mainly used when estimating the number of cycles
226     * actually executed by the CPU in kvmRun(). The default behavior
227     * of this method is to use the cycles performance counter, but
228     * some architectures may want to use internal registers instead.
229     *
230     * @return Number of host cycles executed relative to an undefined
231     * point in the past.
232     */
233    virtual uint64_t getHostCycles() const;
234
235    /**
236     * Request KVM to run the guest for a given number of ticks. The
237     * method returns the approximate number of ticks executed.
238     *
239     * @note The returned number of ticks can be both larger or
240     * smaller than the requested number of ticks. A smaller number
241     * can, for example, occur when the guest executes MMIO. A larger
242     * number is typically due to performance counter inaccuracies.
243     *
244     * @note This method is virtual in order to allow implementations
245     * to check for architecture specific events (e.g., interrupts)
246     * before entering the VM.
247     *
248     * @note It is the response of the caller (normally tick()) to
249     * make sure that the KVM state is synchronized and that the TC is
250     * invalidated after entering KVM.
251     *
252     * @note This method does not normally cause any state
253     * transitions. However, if it may suspend the CPU by suspending
254     * the thread, which leads to a transition to the Idle state. In
255     * such a case, kvm <i>must not</i> be entered.
256     *
257     * @param ticks Number of ticks to execute, set to 0 to exit
258     * immediately after finishing pending operations.
259     * @return Number of ticks executed (see note)
260     */
261    virtual Tick kvmRun(Tick ticks);
262
263    /**
264     * Request the CPU to run until draining completes.
265     *
266     * This function normally calls kvmRun(0) to make KVM finish
267     * pending MMIO operations. Architecures implementing
268     * archIsDrained() must override this method.
269     *
270     * @see BaseKvmCPU::archIsDrained()
271     *
272     * @return Number of ticks executed
273     */
274    virtual Tick kvmRunDrain();
275
276    /**
277     * Get a pointer to the kvm_run structure containing all the input
278     * and output parameters from kvmRun().
279     */
280    struct kvm_run *getKvmRunState() { return _kvmRun; };
281
282    /**
283     * Retrieve a pointer to guest data stored at the end of the
284     * kvm_run structure. This is mainly used for PIO operations
285     * (KVM_EXIT_IO).
286     *
287     * @param offset Offset as specified by the kvm_run structure
288     * @return Pointer to guest data
289     */
290    uint8_t *getGuestData(uint64_t offset) const {
291        return (uint8_t *)_kvmRun + offset;
292    };
293
294    /**
295     * @addtogroup KvmInterrupts
296     * @{
297     */
298    /**
299     * Send a non-maskable interrupt to the guest
300     *
301     * @note The presence of this call depends on Kvm::capUserNMI().
302     */
303    void kvmNonMaskableInterrupt();
304
305    /**
306     * Send a normal interrupt to the guest
307     *
308     * @note Make sure that ready_for_interrupt_injection in kvm_run
309     * is set prior to calling this function. If not, an interrupt
310     * window must be requested by setting request_interrupt_window in
311     * kvm_run to 1 and restarting the guest.
312     *
313     * @param interrupt Structure describing the interrupt to send
314     */
315    void kvmInterrupt(const struct kvm_interrupt &interrupt);
316
317    /** @} */
318
319    /** @{ */
320    /**
321     * Get/Set the register state of the guest vCPU
322     *
323     * KVM has two different interfaces for accessing the state of the
324     * guest CPU. One interface updates 'normal' registers and one
325     * updates 'special' registers. The distinction between special
326     * and normal registers isn't very clear and is architecture
327     * dependent.
328     */
329    void getRegisters(struct kvm_regs &regs) const;
330    void setRegisters(const struct kvm_regs &regs);
331    void getSpecialRegisters(struct kvm_sregs &regs) const;
332    void setSpecialRegisters(const struct kvm_sregs &regs);
333    /** @} */
334
335    /** @{ */
336    /**
337     * Get/Set the guest FPU/vector state
338     */
339    void getFPUState(struct kvm_fpu &state) const;
340    void setFPUState(const struct kvm_fpu &state);
341    /** @} */
342
343    /** @{ */
344    /**
345     * Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
346     *
347     * @note The presence of this call depends on Kvm::capOneReg().
348     */
349    void setOneReg(uint64_t id, const void *addr);
350    void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); }
351    void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); }
352    void getOneReg(uint64_t id, void *addr) const;
353    uint64_t getOneRegU64(uint64_t id) const {
354        uint64_t value;
355        getOneReg(id, &value);
356        return value;
357    }
358    uint32_t getOneRegU32(uint64_t id) const {
359        uint32_t value;
360        getOneReg(id, &value);
361        return value;
362    }
363    /** @} */
364
365    /**
366     * Get and format one register for printout.
367     *
368     * This function call getOneReg() to retrieve the contents of one
369     * register and automatically formats it for printing.
370     *
371     * @note The presence of this call depends on Kvm::capOneReg().
372     */
373    std::string getAndFormatOneReg(uint64_t id) const;
374
375    /** @{ */
376    /**
377     * Update the KVM state from the current thread context
378     *
379     * The base CPU calls this method before starting the guest CPU
380     * when the contextDirty flag is set. The architecture dependent
381     * CPU implementation is expected to update all guest state
382     * (registers, special registers, and FPU state).
383     */
384    virtual void updateKvmState() = 0;
385
386    /**
387     * Update the current thread context with the KVM state
388     *
389     * The base CPU after the guest updates any of the KVM state. In
390     * practice, this happens after kvmRun is called. The architecture
391     * dependent code is expected to read the state of the guest CPU
392     * and update gem5's thread state.
393     */
394    virtual void updateThreadContext() = 0;
395
396    /**
397     * Update a thread context if the KVM state is dirty with respect
398     * to the cached thread context.
399     */
400    void syncThreadContext();
401
402    /**
403     * Update the KVM if the thread context is dirty.
404     */
405    void syncKvmState();
406    /** @} */
407
408    /** @{ */
409    /**
410     * Main kvmRun exit handler, calls the relevant handleKvmExit*
411     * depending on exit type.
412     *
413     * @return Number of ticks spent servicing the exit request
414     */
415    virtual Tick handleKvmExit();
416
417    /**
418     * The guest performed a legacy IO request (out/inp on x86)
419     *
420     * @return Number of ticks spent servicing the IO request
421     */
422    virtual Tick handleKvmExitIO();
423
424    /**
425     * The guest requested a monitor service using a hypercall
426     *
427     * @return Number of ticks spent servicing the hypercall
428     */
429    virtual Tick handleKvmExitHypercall();
430
431    /**
432     * The guest exited because an interrupt window was requested
433     *
434     * The guest exited because an interrupt window was requested
435     * (request_interrupt_window in the kvm_run structure was set to 1
436     * before calling kvmRun) and it is now ready to receive
437     *
438     * @return Number of ticks spent servicing the IRQ
439     */
440    virtual Tick handleKvmExitIRQWindowOpen();
441
442    /**
443     * An unknown architecture dependent error occurred when starting
444     * the vCPU
445     *
446     * The kvm_run data structure contains the hardware error
447     * code. The defaults behavior of this method just prints the HW
448     * error code and panics. Architecture dependent implementations
449     * may want to override this method to provide better,
450     * hardware-aware, error messages.
451     *
452     * @return Number of ticks delay the next CPU tick
453     */
454    virtual Tick handleKvmExitUnknown();
455
456    /**
457     * An unhandled virtualization exception occured
458     *
459     * Some KVM virtualization drivers return unhandled exceptions to
460     * the user-space monitor. This interface is currently only used
461     * by the Intel VMX KVM driver.
462     *
463     * @return Number of ticks delay the next CPU tick
464     */
465    virtual Tick handleKvmExitException();
466
467    /**
468     * KVM failed to start the virtualized CPU
469     *
470     * The kvm_run data structure contains the hardware-specific error
471     * code.
472     *
473     * @return Number of ticks delay the next CPU tick
474     */
475    virtual Tick handleKvmExitFailEntry();
476    /** @} */
477
478    /**
479     * Is the architecture specific code in a state that prevents
480     * draining?
481     *
482     * This method should return false if there are any pending events
483     * in the guest vCPU that won't be carried over to the gem5 state
484     * and thus will prevent correct checkpointing or CPU handover. It
485     * might, for example, check for pending interrupts that have been
486     * passed to the vCPU but not acknowledged by the OS. Architecures
487     * implementing this method <i>must</i> override
488     * kvmRunDrain().
489     *
490     * @see BaseKvmCPU::kvmRunDrain()
491     *
492     * @return true if the vCPU is drained, false otherwise.
493     */
494    virtual bool archIsDrained() const { return true; }
495
496    /**
497     * Inject a memory mapped IO request into gem5
498     *
499     * @param paddr Physical address
500     * @param data Pointer to the source/destination buffer
501     * @param size Memory access size
502     * @param write True if write, False if read
503     * @return Number of ticks spent servicing the memory access
504     */
505    Tick doMMIOAccess(Addr paddr, void *data, int size, bool write);
506
507    /** @{ */
508    /**
509     * Set the signal mask used in kvmRun()
510     *
511     * This method allows the signal mask of the thread executing
512     * kvmRun() to be overridden inside the actual system call. This
513     * allows us to mask timer signals used to force KVM exits while
514     * in gem5.
515     *
516     * The signal mask can be disabled by setting it to NULL.
517     *
518     * @param mask Signals to mask
519     */
520    void setSignalMask(const sigset_t *mask);
521    /** @} */
522
523    /**
524     * @addtogroup KvmIoctl
525     * @{
526     */
527    /**
528     * vCPU ioctl interface.
529     *
530     * @param request KVM vCPU request
531     * @param p1 Optional request parameter
532     *
533     * @return -1 on error (error number in errno), ioctl dependent
534     * value otherwise.
535     */
536    int ioctl(int request, long p1) const;
537    int ioctl(int request, void *p1) const {
538        return ioctl(request, (long)p1);
539    }
540    int ioctl(int request) const {
541        return ioctl(request, 0L);
542    }
543    /** @} */
544
545
546    /**
547     * KVM memory port. Uses the default MasterPort behavior, but
548     * panics on timing accesses.
549     */
550    class KVMCpuPort : public MasterPort
551    {
552
553      public:
554        KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu)
555            : MasterPort(_name, _cpu)
556        { }
557
558      protected:
559        bool recvTimingResp(PacketPtr pkt)
560        {
561            panic("The KVM CPU doesn't expect recvTimingResp!\n");
562            return true;
563        }
564
565        void recvReqRetry()
566        {
567            panic("The KVM CPU doesn't expect recvReqRetry!\n");
568        }
569
570    };
571
572    /** Port for data requests */
573    KVMCpuPort dataPort;
574
575    /** Unused dummy port for the instruction interface */
576    KVMCpuPort instPort;
577
578    /**
579     * Is the gem5 context dirty? Set to true to force an update of
580     * the KVM vCPU state upon the next call to kvmRun().
581     */
582    bool threadContextDirty;
583
584    /**
585     * Is the KVM state dirty? Set to true to force an update of
586     * the KVM vCPU state upon the next call to kvmRun().
587     */
588    bool kvmStateDirty;
589
590    /** KVM internal ID of the vCPU */
591    const long vcpuID;
592
593    /** ID of the vCPU thread */
594    pthread_t vcpuThread;
595
596  private:
597    struct TickEvent : public Event
598    {
599        BaseKvmCPU &cpu;
600
601        TickEvent(BaseKvmCPU &c)
602            : Event(CPU_Tick_Pri), cpu(c) {}
603
604        void process() { cpu.tick(); }
605
606        const char *description() const {
607            return "BaseKvmCPU tick";
608        }
609    };
610
611    /**
612     * Service MMIO requests in the mmioRing.
613     *
614     *
615     * @return Number of ticks spent servicing the MMIO requests in
616     * the MMIO ring buffer
617     */
618    Tick flushCoalescedMMIO();
619
620    /**
621     * Setup a signal handler to catch the timer signal used to
622     * switch back to the monitor.
623     */
624    void setupSignalHandler();
625
626    /**
627     * Discard a (potentially) pending signal.
628     *
629     * @param signum Signal to discard
630     * @return true if the signal was pending, false otherwise.
631     */
632    bool discardPendingSignal(int signum) const;
633
634    /**
635     * Thread-specific initialization.
636     *
637     * Some KVM-related initialization requires us to know the TID of
638     * the thread that is going to execute our event queue. For
639     * example, when setting up timers, we need to know the TID of the
640     * thread executing in KVM in order to deliver the timer signal to
641     * that thread. This method is called as the first event in this
642     * SimObject's event queue.
643     *
644     * @see startup
645     */
646    void startupThread();
647
648    /** Try to drain the CPU if a drain is pending */
649    bool tryDrain();
650
651    /** Execute the KVM_RUN ioctl */
652    void ioctlRun();
653
654    /** KVM vCPU file descriptor */
655    int vcpuFD;
656    /** Size of MMAPed kvm_run area */
657    int vcpuMMapSize;
658    /**
659     * Pointer to the kvm_run structure used to communicate parameters
660     * with KVM.
661     *
662     * @note This is the base pointer of the MMAPed KVM region. The
663     * first page contains the kvm_run structure. Subsequent pages may
664     * contain other data such as the MMIO ring buffer.
665     */
666    struct kvm_run *_kvmRun;
667    /**
668     * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not
669     * supported.
670     */
671    struct kvm_coalesced_mmio_ring *mmioRing;
672    /** Cached page size of the host */
673    const long pageSize;
674
675    TickEvent tickEvent;
676
677    /**
678     * Setup an instruction break if there is one pending.
679     *
680     * Check if there are pending instruction breaks in the CPU's
681     * instruction event queue and schedule an instruction break using
682     * PerfEvent.
683     *
684     * @note This method doesn't currently handle the main system
685     * instruction event queue.
686     */
687    void setupInstStop();
688
689    /** @{ */
690    /** Setup hardware performance counters */
691    void setupCounters();
692
693    /**
694     * Setup the guest instruction counter.
695     *
696     * Setup the guest instruction counter and optionally request a
697     * signal every N instructions executed by the guest. This method
698     * will re-attach the counter if the counter has already been
699     * attached and its sampling settings have changed.
700     *
701     * @param period Signal period, set to 0 to disable signaling.
702     */
703    void setupInstCounter(uint64_t period = 0);
704
705    /** Currently active instruction count breakpoint */
706    uint64_t activeInstPeriod;
707
708    /**
709     * Guest cycle counter.
710     *
711     * This is the group leader of all performance counters measuring
712     * the guest system. It can be used in conjunction with the
713     * PerfKvmTimer (see perfControlledByTimer) to trigger exits from
714     * KVM.
715     */
716    PerfKvmCounter hwCycles;
717
718    /**
719     * Guest instruction counter.
720     *
721     * This counter is typically only used to measure the number of
722     * instructions executed by the guest. However, it can also be
723     * used to trigger exits from KVM if the configuration script
724     * requests an exit after a certain number of instructions.
725     *
726     * @see setupInstBreak
727     * @see scheduleInstStop
728     */
729    PerfKvmCounter hwInstructions;
730
731    /**
732     * Does the runTimer control the performance counters?
733     *
734     * The run timer will automatically enable and disable performance
735     * counters if a PerfEvent-based timer is used to control KVM
736     * exits.
737     */
738    bool perfControlledByTimer;
739    /** @} */
740
741    /**
742     * Timer used to force execution into the monitor after a
743     * specified number of simulation tick equivalents have executed
744     * in the guest. This counter generates the signal specified by
745     * KVM_TIMER_SIGNAL.
746     */
747    std::unique_ptr<BaseKvmTimer> runTimer;
748
749    /** Host factor as specified in the configuration */
750    float hostFactor;
751
752    /**
753     * Drain manager to use when signaling drain completion
754     *
755     * This pointer is non-NULL when draining and NULL otherwise.
756     */
757    DrainManager *drainManager;
758
759  public:
760    /* @{ */
761    Stats::Scalar numInsts;
762    Stats::Scalar numVMExits;
763    Stats::Scalar numVMHalfEntries;
764    Stats::Scalar numExitSignal;
765    Stats::Scalar numMMIO;
766    Stats::Scalar numCoalescedMMIO;
767    Stats::Scalar numIO;
768    Stats::Scalar numHalt;
769    Stats::Scalar numInterrupts;
770    Stats::Scalar numHypercalls;
771    /* @} */
772
773    /** Number of instructions executed by the CPU */
774    Counter ctrInsts;
775};
776
777#endif
778