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