cpu, o3: consider split requests for LSQ checksnoop operations

This patch enables instructions in LSQ to track two physical addresses for
corresponding two split requests. Later, the information is used in
checksnoop() to search for/invalidate the corresponding LD instructions.

The current implementation has kept track of only the physical address that is
referenced by the first split request. Thus, for checksnoop(), the line
accessed by the second request has not been considered, causing potential
correctness issues.

Committed by: Nilay Vaish <nilay@cs.wisc.edu>
This commit is contained in:
Hongil Yoon 2015-09-15 08:14:06 -05:00
parent 6bee1d9124
commit fb0f9884e2
4 changed files with 32 additions and 12 deletions

View file

@ -215,7 +215,12 @@ class BaseDynInst : public ExecContext, public RefCounted
Addr effAddr;
/** The effective physical address. */
Addr physEffAddr;
Addr physEffAddrLow;
/** The effective physical address
* of the second request for a split request
*/
Addr physEffAddrHigh;
/** The memory request flags (from translation). */
unsigned memReqFlags;
@ -1056,7 +1061,15 @@ BaseDynInst<Impl>::finishTranslation(WholeTranslationState *state)
instFlags[IsStrictlyOrdered] = state->isStrictlyOrdered();
if (fault == NoFault) {
physEffAddr = state->getPaddr();
// save Paddr for a single req
physEffAddrLow = state->getPaddr();
// case for the request that has been split
if (state->isSplit) {
physEffAddrLow = state->sreqLow->getPaddr();
physEffAddrHigh = state->sreqHigh->getPaddr();
}
memReqFlags = state->getFlags();
if (state->mainReq->isCondSwap()) {

View file

@ -88,7 +88,8 @@ BaseDynInst<Impl>::initVars()
{
memData = NULL;
effAddr = 0;
physEffAddr = 0;
physEffAddrLow = 0;
physEffAddrHigh = 0;
readyRegs = 0;
memReqFlags = 0;

View file

@ -1347,7 +1347,7 @@ DefaultIEW<Impl>::executeInsts()
DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s "
"[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n",
violator->pcState(), violator->seqNum,
inst->pcState(), inst->seqNum, inst->physEffAddr);
inst->pcState(), inst->seqNum, inst->physEffAddrLow);
fetchRedirect[tid] = true;
@ -1370,7 +1370,7 @@ DefaultIEW<Impl>::executeInsts()
DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
"%s, inst PC: %s. Addr is: %#x.\n",
violator->pcState(), inst->pcState(),
inst->physEffAddr);
inst->physEffAddrLow);
DPRINTF(IEW, "Violation will not be handled because "
"already squashing\n");

View file

@ -453,10 +453,13 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
DynInstPtr ld_inst = loadQueue[load_idx];
if (ld_inst) {
Addr load_addr = ld_inst->physEffAddr & cacheBlockMask;
Addr load_addr_low = ld_inst->physEffAddrLow & cacheBlockMask;
Addr load_addr_high = ld_inst->physEffAddrHigh & cacheBlockMask;
// Check that this snoop didn't just invalidate our lock flag
if (ld_inst->effAddrValid() && load_addr == invalidate_addr &&
ld_inst->memReqFlags & Request::LLSC)
if (ld_inst->effAddrValid() && (load_addr_low == invalidate_addr
|| load_addr_high == invalidate_addr)
&& ld_inst->memReqFlags & Request::LLSC)
TheISA::handleLockedSnoopHit(ld_inst.get());
}
@ -476,11 +479,14 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
continue;
}
Addr load_addr = ld_inst->physEffAddr & cacheBlockMask;
DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n",
ld_inst->seqNum, load_addr, invalidate_addr);
Addr load_addr_low = ld_inst->physEffAddrLow & cacheBlockMask;
Addr load_addr_high = ld_inst->physEffAddrHigh & cacheBlockMask;
if (load_addr == invalidate_addr || force_squash) {
DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n",
ld_inst->seqNum, load_addr_low, invalidate_addr);
if ((load_addr_low == invalidate_addr
|| load_addr_high == invalidate_addr) || force_squash) {
if (needsTSO) {
// If we have a TSO system, as all loads must be ordered with
// all other loads, this load as well as *all* subsequent loads