summaryrefslogtreecommitdiff
path: root/src/cpu/kvm/base.hh
diff options
context:
space:
mode:
authorMichael LeBeane <michael.lebeane@amd.com>2016-09-13 23:20:03 -0400
committerMichael LeBeane <michael.lebeane@amd.com>2016-09-13 23:20:03 -0400
commit443da2c030c0ad5b22f86a471ae757cbbd491bc1 (patch)
tree5eba8c9e5382a721e4449fcefb4d3b8635c7f623 /src/cpu/kvm/base.hh
parent2c43a21687b861bae462bea555c5875a4d0a91c8 (diff)
downloadgem5-443da2c030c0ad5b22f86a471ae757cbbd491bc1.tar.xz
kvm: Support timing accesses for KVM cpu
This patch enables timing accesses for KVM cpu. A new state, RunningMMIOPending, is added to indicate that there are outstanding timing requests generated by KVM in the system. KVM's tick() is disabled and the simulation does not enter into KVM until all outstanding timing requests have completed. The main motivation for this is to allow KVM CPU to perform MMIO in Ruby, since Ruby does not support atomic accesses.
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;
};