Peter Yuen has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/41933 )
Change subject: arch-riscv: Fixed CPU switching and PLIC issue with MinorCPU
......................................................................
arch-riscv: Fixed CPU switching and PLIC issue with MinorCPU
Added takeover methods for PMA Checker and RiscvTLB to ensure
that checkpoint restoration works. Also added logic in PLIC
to prevent posting interrupts to a CPU that has yet to complete
the current interrupt. PLIC's behaviour when a CPU claims another
interrupt before completion is also changed. Now PLIC will return
the uncompleted interrupt ID instead of return 0. This behaviour
is not documented in the specs but is designed this way to avoid
issues from CPU side (especially MinorCPU).
Change-Id: I68eaaf56d2c4d76cc1e0a1e2160f5abe184c2cd5
---
M src/arch/riscv/pma_checker.cc
M src/arch/riscv/pma_checker.hh
M src/arch/riscv/tlb.cc
M src/arch/riscv/tlb.hh
M src/dev/riscv/plic.cc
5 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/src/arch/riscv/pma_checker.cc b/src/arch/riscv/pma_checker.cc
index 32cb66d..d36dc1d 100644
--- a/src/arch/riscv/pma_checker.cc
+++ b/src/arch/riscv/pma_checker.cc
@@ -81,3 +81,9 @@
{
return isUncacheable(pkt->getAddrRange());
}
+
+void
+PMAChecker::takeOverFrom(PMAChecker *old)
+{
+ uncacheable = old->uncacheable;
+}
diff --git a/src/arch/riscv/pma_checker.hh b/src/arch/riscv/pma_checker.hh
index 5833dbe..298d4a0 100644
--- a/src/arch/riscv/pma_checker.hh
+++ b/src/arch/riscv/pma_checker.hh
@@ -74,6 +74,8 @@
bool isUncacheable(const AddrRange &range);
bool isUncacheable(const Addr &addr, const unsigned size);
bool isUncacheable(PacketPtr pkt);
+
+ void takeOverFrom(PMAChecker *old);
};
#endif // __ARCH_RISCV_PMA_CHECKER_HH__
diff --git a/src/arch/riscv/tlb.cc b/src/arch/riscv/tlb.cc
index 5109d2a..8d21fe3 100644
--- a/src/arch/riscv/tlb.cc
+++ b/src/arch/riscv/tlb.cc
@@ -87,6 +87,13 @@
}
void
+TLB::takeOverFrom(BaseTLB *_old)
+{
+ TLB *old = dynamic_cast<TLB*>(_old);
+ pma->takeOverFrom(old->pma);
+}
+
+void
TLB::evictLRU()
{
// Find the entry with the lowest (and hence least recently updated)
@@ -519,3 +526,9 @@
readAccesses + writeAccesses)
{
}
+
+Port *
+TLB::getTableWalkerPort()
+{
+ return &walker->getPort("port");
+}
\ No newline at end of file
diff --git a/src/arch/riscv/tlb.hh b/src/arch/riscv/tlb.hh
index 8dcf0fc..287d8e7 100644
--- a/src/arch/riscv/tlb.hh
+++ b/src/arch/riscv/tlb.hh
@@ -92,7 +92,7 @@
Walker *getWalker();
- void takeOverFrom(BaseTLB *otlb) override {}
+ void takeOverFrom(BaseTLB *old) override;
TlbEntry *insert(Addr vpn, const TlbEntry &entry);
void flushAll() override;
@@ -108,6 +108,18 @@
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
+ /**
+ * Get the table walker port. This is used for
+ * migrating port connections during a CPU takeOverFrom()
+ * call. For architectures that do not have a table walker,
+ * NULL is returned, hence the use of a pointer rather than a
+ * reference. For RISC-V this method will always return a valid
+ * port pointer.
+ *
+ * @return A pointer to the walker port
+ */
+ Port *getTableWalkerPort() override;
+
Addr translateWithTLB(Addr vaddr, uint16_t asid, Mode mode);
Fault translateAtomic(const RequestPtr &req,
diff --git a/src/dev/riscv/plic.cc b/src/dev/riscv/plic.cc
index 60ac192..2183183 100644
--- a/src/dev/riscv/plic.cc
+++ b/src/dev/riscv/plic.cc
@@ -354,17 +354,18 @@
context_id, max_int_id);
clear(max_int_id);
reg.update(max_int_id);
+ return reg.get();
} else {
DPRINTF(Plic,
"Claim already cleared - context: %d, interrupt ID: %d\n",
context_id, max_int_id);
- reg.update(0);
+ return 0;
}
} else {
- warn("PLIC claim failed (not completed) - context: %d",
context_id);
- reg.update(0);
+ warn("PLIC claim repeated (not completed) - context: %d, last: %d",
+ context_id, lastID[context_id]);
+ return lastID[context_id];
}
- return reg.get();
}
void
@@ -381,6 +382,7 @@
DPRINTF(Plic,
"Complete - context: %d, interrupt ID: %d\n",
context_id, reg.get());
+ updateInt();
}
void
@@ -445,11 +447,11 @@
uint32_t max_id = output.maxID[i];
uint32_t priority = output.maxPriority[i];
uint32_t threshold = registers.threshold[i].get();
- if (priority > threshold && max_id > 0) {
+ if (priority > threshold && max_id > 0 && lastID[i] == 0) {
DPRINTF(Plic,
"Int posted - thread: %d, int id: %d, ",
thread_id, int_id);
- DPRINTF(Plic,
+ DPRINTFR(Plic,
"pri: %d, thres: %d\n", priority, threshold);
intrctrl->post(thread_id, int_id, 0);
} else {
@@ -457,7 +459,7 @@
DPRINTF(Plic,
"Int filtered - thread: %d, int id: %d, ",
thread_id, int_id);
- DPRINTF(Plic,
+ DPRINTFR(Plic,
"pri: %d, thres: %d\n", priority, threshold);
}
intrctrl->clear(thread_id, int_id, 0);
@@ -499,6 +501,12 @@
SERIALIZE_SCALAR(n_outputs);
SERIALIZE_CONTAINER(output.maxID);
SERIALIZE_CONTAINER(output.maxPriority);
+ SERIALIZE_CONTAINER(pendingPriority);
+ for (int i=0; i < effPriority.size(); i++) {
+ arrayParamOut(cp, std::string("effPriority") +
+ std::to_string(i), effPriority[i]);
+ }
+ SERIALIZE_CONTAINER(lastID);
}
void
@@ -541,4 +549,11 @@
}
UNSERIALIZE_CONTAINER(output.maxID);
UNSERIALIZE_CONTAINER(output.maxPriority);
+ UNSERIALIZE_CONTAINER(pendingPriority);
+ for (int i=0; i < effPriority.size(); i++) {
+ arrayParamIn(cp, std::string("effPriority") +
+ std::to_string(i), effPriority[i]);
+ }
+ UNSERIALIZE_CONTAINER(lastID);
+ updateInt();
}
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/41933
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I68eaaf56d2c4d76cc1e0a1e2160f5abe184c2cd5
Gerrit-Change-Number: 41933
Gerrit-PatchSet: 1
Gerrit-Owner: Peter Yuen <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s