arch-riscv: fix load reserved store conditional

* According to the manual, load reservations must be cleared on a
    failed or a successful SC attempt.
  * A load reservation can be arbitrarily large. The current
    implementation was reserving something different than cacheBlockSize
    which could lead to problems if snoop addresses are cache block
    aligned. This patch implementation assumes a cacheBlock granularity.
  * Load reservations should also be cleared on faults

Change-Id: I64513534710b5f269260fcb204f717801913e2f5
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71520
Maintainer: Bobby Bruce <bbruce@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu>
This commit is contained in:
Adrià Armejach
2023-06-07 17:01:03 +02:00
committed by Bobby Bruce
parent b182b15f93
commit d54b8f8475
4 changed files with 34 additions and 11 deletions

View File

@@ -70,6 +70,7 @@ class BaseISA : public SimObject
public:
virtual PCStateBase *newPCState(Addr new_inst_addr=0) const = 0;
virtual void clear() {}
virtual void clearLoadReservation(ContextID cid) {}
virtual RegVal readMiscRegNoEffect(RegIndex idx) const = 0;
virtual RegVal readMiscReg(RegIndex idx) = 0;

View File

@@ -153,6 +153,9 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
tc->setMiscReg(MISCREG_NMIE, 0);
}
// Clear load reservation address
tc->getIsaPtr()->clearLoadReservation(tc->contextId());
// Set PC to fault handler address
Addr addr = mbits(tc->readMiscReg(tvec), 63, 2);
if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1)

View File

@@ -672,11 +672,6 @@ ISA::unserialize(CheckpointIn &cp)
UNSERIALIZE_CONTAINER(miscRegFile);
}
const int WARN_FAILURE = 10000;
const Addr INVALID_RESERVATION_ADDR = (Addr) -1;
std::unordered_map<int, Addr> load_reservation_addrs;
void
ISA::handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
{
@@ -696,9 +691,9 @@ ISA::handleLockedRead(const RequestPtr &req)
{
Addr& load_reservation_addr = load_reservation_addrs[tc->contextId()];
load_reservation_addr = req->getPaddr() & ~0xF;
load_reservation_addr = req->getPaddr();
DPRINTF(LLSC, "[cid:%d]: Reserved address %x.\n",
req->contextId(), req->getPaddr() & ~0xF);
req->contextId(), req->getPaddr());
}
bool
@@ -717,12 +712,13 @@ ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
lr_addr_empty ? "yes" : "no");
if (!lr_addr_empty) {
DPRINTF(LLSC, "[cid:%d]: addr = %x.\n", req->contextId(),
req->getPaddr() & ~0xF);
req->getPaddr() & cacheBlockMask);
DPRINTF(LLSC, "[cid:%d]: last locked addr = %x.\n", req->contextId(),
load_reservation_addr);
load_reservation_addr & cacheBlockMask);
}
if (lr_addr_empty
|| load_reservation_addr != ((req->getPaddr() & ~0xF))) {
if (lr_addr_empty ||
(load_reservation_addr & cacheBlockMask)
!= ((req->getPaddr() & cacheBlockMask))) {
req->setExtraData(0);
int stCondFailures = tc->readStCondFailures();
tc->setStCondFailures(++stCondFailures);
@@ -730,12 +726,21 @@ ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
warn("%i: context %d: %d consecutive SC failures.\n",
curTick(), tc->contextId(), stCondFailures);
}
// Must clear any reservations
load_reservation_addr = INVALID_RESERVATION_ADDR;
return false;
}
if (req->isUncacheable()) {
req->setExtraData(2);
}
// Must clear any reservations
load_reservation_addr = INVALID_RESERVATION_ADDR;
DPRINTF(LLSC, "[cid:%d]: SC success! Current locked addr = %x.\n",
req->contextId(), load_reservation_addr & cacheBlockMask);
return true;
}
@@ -743,6 +748,8 @@ void
ISA::globalClearExclusive()
{
tc->getCpuPtr()->wakeup(tc->threadId());
Addr& load_reservation_addr = load_reservation_addrs[tc->contextId()];
load_reservation_addr = INVALID_RESERVATION_ADDR;
}
void

View File

@@ -76,6 +76,11 @@ class ISA : public BaseISA
bool hpmCounterEnabled(int counter) const;
// Load reserve - store conditional monitor
const int WARN_FAILURE = 10000;
const Addr INVALID_RESERVATION_ADDR = (Addr)-1;
std::unordered_map<int, Addr> load_reservation_addrs;
public:
using Params = RiscvISAParams;
@@ -87,6 +92,13 @@ class ISA : public BaseISA
return new PCState(new_inst_addr, rv_type);
}
void
clearLoadReservation(ContextID cid) override
{
Addr& load_reservation_addr = load_reservation_addrs[cid];
load_reservation_addr = INVALID_RESERVATION_ADDR;
}
public:
RegVal readMiscRegNoEffect(RegIndex idx) const override;
RegVal readMiscReg(RegIndex idx) override;