summaryrefslogtreecommitdiff
path: root/src/cpu/kvm/base.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/kvm/base.hh')
-rw-r--r--src/cpu/kvm/base.hh56
1 files changed, 43 insertions, 13 deletions
diff --git a/src/cpu/kvm/base.hh b/src/cpu/kvm/base.hh
index 7ff0cab5c..ef500974f 100644
--- a/src/cpu/kvm/base.hh
+++ b/src/cpu/kvm/base.hh
@@ -44,6 +44,7 @@
#include <csignal>
#include <memory>
+#include <queue>
#include "base/statistics.hh"
#include "cpu/kvm/perfevent.hh"
@@ -110,6 +111,12 @@ class BaseKvmCPU : public BaseCPU
Counter totalInsts() const override;
Counter totalOps() const override;
+ /**
+ * Callback from KvmCPUPort to transition the CPU out of RunningMMIOPending
+ * when all timing requests have completed.
+ */
+ void finishMMIOPending();
+
/** Dump the internal state to the terminal. */
virtual void dump() const;
@@ -152,6 +159,7 @@ class BaseKvmCPU : public BaseCPU
* Running;
* RunningService;
* RunningServiceCompletion;
+ * RunningMMIOPending;
*
* Idle -> Idle;
* Idle -> Running [label="activateContext()", URL="\ref activateContext"];
@@ -161,6 +169,8 @@ class BaseKvmCPU : public BaseCPU
* Running -> Idle [label="drain()", URL="\ref drain"];
* Idle -> Running [label="drainResume()", URL="\ref drainResume"];
* RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"];
+ * RunningService -> RunningMMIOPending [label="handleKvmExit()", URL="\ref handleKvmExit"];
+ * RunningMMIOPending -> RunningServiceCompletion [label="finishMMIOPending()", URL="\ref finishMMIOPending"];
* RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"];
* RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"];
* }
@@ -190,12 +200,21 @@ class BaseKvmCPU : public BaseCPU
* after running service is determined in handleKvmExit() and
* depends on what kind of service the guest requested:
* <ul>
- * <li>IO/MMIO: RunningServiceCompletion
+ * <li>IO/MMIO (Atomic): RunningServiceCompletion
+ * <li>IO/MMIO (Timing): RunningMMIOPending
* <li>Halt: Idle
* <li>Others: Running
* </ul>
*/
RunningService,
+ /** Timing MMIO request in flight or stalled.
+ *
+ * The VM has requested IO/MMIO and we are in timing mode. A timing
+ * request is either stalled (and will be retried with recvReqRetry())
+ * or it is in flight. After the timing request is complete, the CPU
+ * will transition to the RunningServiceCompletion state.
+ */
+ RunningMMIOPending,
/** Service completion in progress.
*
* The VM has requested service that requires KVM to be
@@ -543,28 +562,39 @@ class BaseKvmCPU : public BaseCPU
/**
- * KVM memory port. Uses the default MasterPort behavior, but
- * panics on timing accesses.
+ * KVM memory port. Uses default MasterPort behavior and provides an
+ * interface for KVM to transparently submit atomic or timing requests.
*/
class KVMCpuPort : public MasterPort
{
public:
KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu)
- : MasterPort(_name, _cpu)
+ : MasterPort(_name, _cpu), cpu(_cpu), activeMMIOReqs(0)
{ }
+ /**
+ * Interface to send Atomic or Timing IO request. Assumes that the pkt
+ * and corresponding req have been dynamically allocated and deletes
+ * them both if the system is in atomic mode.
+ */
+ Tick submitIO(PacketPtr pkt);
+
+ /** Returns next valid state after one or more IO accesses */
+ Status nextIOState() const;
protected:
- bool recvTimingResp(PacketPtr pkt)
- {
- panic("The KVM CPU doesn't expect recvTimingResp!\n");
- return true;
- }
+ /** KVM cpu pointer for finishMMIOPending() callback */
+ BaseKvmCPU *cpu;
- void recvReqRetry()
- {
- panic("The KVM CPU doesn't expect recvReqRetry!\n");
- }
+ /** Pending MMIO packets */
+ std::queue<PacketPtr> pendingMMIOPkts;
+
+ /** Number of MMIO requests in flight */
+ unsigned int activeMMIOReqs;
+
+ bool recvTimingResp(PacketPtr pkt) override;
+
+ void recvReqRetry() override;
};