diff options
Diffstat (limited to 'src/cpu/kvm/base.hh')
-rw-r--r-- | src/cpu/kvm/base.hh | 147 |
1 files changed, 138 insertions, 9 deletions
diff --git a/src/cpu/kvm/base.hh b/src/cpu/kvm/base.hh index 81b24a378..42a7eca2b 100644 --- a/src/cpu/kvm/base.hh +++ b/src/cpu/kvm/base.hh @@ -41,6 +41,7 @@ #define __CPU_KVM_BASE_HH__ #include <memory> +#include <csignal> #include "base/statistics.hh" #include "cpu/kvm/perfevent.hh" @@ -133,11 +134,67 @@ class BaseKvmCPU : public BaseCPU KvmVM &vm; protected: + /** + * + * @dot + * digraph { + * Idle; + * Running; + * RunningService; + * RunningServiceCompletion; + * + * Idle -> Idle; + * Idle -> Running [label="activateContext()", URL="\ref activateContext"]; + * Running -> Running [label="tick()", URL="\ref tick"]; + * Running -> RunningService [label="tick()", URL="\ref tick"]; + * Running -> Idle [label="suspendContext()", URL="\ref suspendContext"]; + * Running -> Idle [label="drain()", URL="\ref drain"]; + * Idle -> Running [label="drainResume()", URL="\ref drainResume"]; + * RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"]; + * RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"]; + * RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"]; + * } + * @enddot + */ enum Status { - /** Context not scheduled in KVM */ + /** Context not scheduled in KVM. + * + * The CPU generally enters this state when the guest execute + * an instruction that halts the CPU (e.g., WFI on ARM or HLT + * on X86) if KVM traps this instruction. Ticks are not + * scheduled in this state. + * + * @see suspendContext() + */ Idle, - /** Running normally */ + /** Running normally. + * + * This is the normal run state of the CPU. KVM will be + * entered next time tick() is called. + */ Running, + /** Requiring service at the beginning of the next cycle. + * + * The virtual machine has exited and requires service, tick() + * will call handleKvmExit() on the next cycle. The next state + * after running service is determined in handleKvmExit() and + * depends on what kind of service the guest requested: + * <ul> + * <li>IO/MMIO: RunningServiceCompletion + * <li>Halt: Idle + * <li>Others: Running + * </ul> + */ + RunningService, + /** Service completion in progress. + * + * The VM has requested service that requires KVM to be + * entered once in order to get to a consistent state. This + * happens in handleKvmExit() or one of its friends after IO + * exits. After executing tick(), the CPU will transition into + * the Running or RunningService state. + */ + RunningServiceCompletion, }; /** CPU run state */ @@ -146,12 +203,8 @@ class BaseKvmCPU : public BaseCPU /** * Execute the CPU until the next event in the main event queue or * until the guest needs service from gem5. - * - * @note This method is virtual in order to allow implementations - * to check for architecture specific events (e.g., interrupts) - * before entering the VM. */ - virtual void tick(); + void tick(); /** * Get the value of the hardware cycle counter in the guest. @@ -177,10 +230,32 @@ class BaseKvmCPU : public BaseCPU * can, for example, occur when the guest executes MMIO. A larger * number is typically due to performance counter inaccuracies. * - * @param ticks Number of ticks to execute + * @note This method is virtual in order to allow implementations + * to check for architecture specific events (e.g., interrupts) + * before entering the VM. + * + * @note It is the response of the caller (normally tick()) to + * make sure that the KVM state is synchronized and that the TC is + * invalidated after entering KVM. + * + * @param ticks Number of ticks to execute, set to 0 to exit + * immediately after finishing pending operations. * @return Number of ticks executed (see note) */ - Tick kvmRun(Tick ticks); + virtual Tick kvmRun(Tick ticks); + + /** + * Request the CPU to run until draining completes. + * + * This function normally calls kvmRun(0) to make KVM finish + * pending MMIO operations. Architecures implementing + * archIsDrained() must override this method. + * + * @see BaseKvmCPU::archIsDrained() + * + * @return Number of ticks executed + */ + virtual Tick kvmRunDrain(); /** * Get a pointer to the kvm_run structure containing all the input @@ -385,6 +460,24 @@ class BaseKvmCPU : public BaseCPU /** @} */ /** + * Is the architecture specific code in a state that prevents + * draining? + * + * This method should return false if there are any pending events + * in the guest vCPU that won't be carried over to the gem5 state + * and thus will prevent correct checkpointing or CPU handover. It + * might, for example, check for pending interrupts that have been + * passed to the vCPU but not acknowledged by the OS. Architecures + * implementing this method <i>must</i> override + * kvmRunDrain(). + * + * @see BaseKvmCPU::kvmRunDrain() + * + * @return true if the vCPU is drained, false otherwise. + */ + virtual bool archIsDrained() const { return true; } + + /** * Inject a memory mapped IO request into gem5 * * @param paddr Physical address @@ -395,6 +488,21 @@ class BaseKvmCPU : public BaseCPU */ Tick doMMIOAccess(Addr paddr, void *data, int size, bool write); + /** @{ */ + /** + * Set the signal mask used in kvmRun() + * + * This method allows the signal mask of the thread executing + * kvmRun() to be overridden inside the actual system call. This + * allows us to mask timer signals used to force KVM exits while + * in gem5. + * + * The signal mask can be disabled by setting it to NULL. + * + * @param mask Signals to mask + */ + void setSignalMask(const sigset_t *mask); + /** @} */ /** * @addtogroup KvmIoctl @@ -499,9 +607,23 @@ class BaseKvmCPU : public BaseCPU */ void setupSignalHandler(); + /** + * Discard a (potentially) pending signal. + * + * @param signum Signal to discard + * @return true if the signal was pending, false otherwise. + */ + bool discardPendingSignal(int signum) const; + /** Setup hardware performance counters */ void setupCounters(); + /** Try to drain the CPU if a drain is pending */ + bool tryDrain(); + + /** Execute the KVM_RUN ioctl */ + void ioctlRun(); + /** KVM vCPU file descriptor */ int vcpuFD; /** Size of MMAPed kvm_run area */ @@ -550,6 +672,13 @@ class BaseKvmCPU : public BaseCPU float hostFactor; + /** + * Drain manager to use when signaling drain completion + * + * This pointer is non-NULL when draining and NULL otherwise. + */ + DrainManager *drainManager; + public: /* @{ */ Stats::Scalar numInsts; |