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