mem: Add support for a security bit in the memory system
This patch adds the basic building blocks required to support e.g. ARM TrustZone by discerning secure and non-secure memory accesses.
This commit is contained in:
6
src/mem/cache/base.hh
vendored
6
src/mem/cache/base.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -560,9 +560,9 @@ class BaseCache : public MemObject
|
||||
|
||||
virtual unsigned int drain(DrainManager *dm);
|
||||
|
||||
virtual bool inCache(Addr addr) const = 0;
|
||||
virtual bool inCache(Addr addr, bool is_secure) const = 0;
|
||||
|
||||
virtual bool inMissQueue(Addr addr) const = 0;
|
||||
virtual bool inMissQueue(Addr addr, bool is_secure) const = 0;
|
||||
|
||||
void incMissCount(PacketPtr pkt)
|
||||
{
|
||||
|
||||
17
src/mem/cache/blk.cc
vendored
17
src/mem/cache/blk.cc
vendored
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -33,9 +45,10 @@ void
|
||||
CacheBlkPrintWrapper::print(std::ostream &os, int verbosity,
|
||||
const std::string &prefix) const
|
||||
{
|
||||
ccprintf(os, "%sblk %c%c%c\n", prefix,
|
||||
ccprintf(os, "%sblk %c%c%c%c\n", prefix,
|
||||
blk->isValid() ? 'V' : '-',
|
||||
blk->isWritable() ? 'E' : '-',
|
||||
blk->isDirty() ? 'M' : '-');
|
||||
blk->isDirty() ? 'M' : '-',
|
||||
blk->isSecure() ? 'S' : '-');
|
||||
}
|
||||
|
||||
|
||||
15
src/mem/cache/blk.hh
vendored
15
src/mem/cache/blk.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -70,7 +70,9 @@ enum CacheBlkStatusBits {
|
||||
/** block was referenced */
|
||||
BlkReferenced = 0x10,
|
||||
/** block was a hardware prefetch yet unaccessed*/
|
||||
BlkHWPrefetched = 0x20
|
||||
BlkHWPrefetched = 0x20,
|
||||
/** block holds data from the secure memory space */
|
||||
BlkSecure = 0x40
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -262,6 +264,15 @@ class CacheBlk
|
||||
return (status & BlkHWPrefetched) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this block holds data from the secure memory space.
|
||||
* @return True if the block holds data from the secure memory space.
|
||||
*/
|
||||
bool isSecure() const
|
||||
{
|
||||
return (status & BlkSecure) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track the fact that a local locked was issued to the block. If
|
||||
* multiple LLs get issued from the same context we could have
|
||||
|
||||
23
src/mem/cache/cache.hh
vendored
23
src/mem/cache/cache.hh
vendored
@@ -209,12 +209,13 @@ class Cache : public BaseCache
|
||||
void cmpAndSwap(BlkType *blk, PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Find a block frame for new block at address addr, assuming that
|
||||
* the block is not currently in the cache. Append writebacks if
|
||||
* any to provided packet list. Return free block frame. May
|
||||
* return NULL if there are no replaceable blocks at the moment.
|
||||
* Find a block frame for new block at address addr targeting the
|
||||
* given security space, assuming that the block is not currently
|
||||
* in the cache. Append writebacks if any to provided packet
|
||||
* list. Return free block frame. May return NULL if there are
|
||||
* no replaceable blocks at the moment.
|
||||
*/
|
||||
BlkType *allocateBlock(Addr addr, PacketList &writebacks);
|
||||
BlkType *allocateBlock(Addr addr, bool is_secure, PacketList &writebacks);
|
||||
|
||||
/**
|
||||
* Populates a cache block and handles all outstanding requests for the
|
||||
@@ -384,16 +385,16 @@ class Cache : public BaseCache
|
||||
return mshrQueue.allocated != 0;
|
||||
}
|
||||
|
||||
CacheBlk *findBlock(Addr addr) const {
|
||||
return tags->findBlock(addr);
|
||||
CacheBlk *findBlock(Addr addr, bool is_secure) const {
|
||||
return tags->findBlock(addr, is_secure);
|
||||
}
|
||||
|
||||
bool inCache(Addr addr) const {
|
||||
return (tags->findBlock(addr) != 0);
|
||||
bool inCache(Addr addr, bool is_secure) const {
|
||||
return (tags->findBlock(addr, is_secure) != 0);
|
||||
}
|
||||
|
||||
bool inMissQueue(Addr addr) const {
|
||||
return (mshrQueue.findMatch(addr) != 0);
|
||||
bool inMissQueue(Addr addr, bool is_secure) const {
|
||||
return (mshrQueue.findMatch(addr, is_secure) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
134
src/mem/cache/cache_impl.hh
vendored
134
src/mem/cache/cache_impl.hh
vendored
@@ -301,11 +301,12 @@ Cache<TagStore>::access(PacketPtr pkt, BlkType *&blk,
|
||||
}
|
||||
|
||||
int id = pkt->req->hasContextId() ? pkt->req->contextId() : -1;
|
||||
blk = tags->accessBlock(pkt->getAddr(), lat, id);
|
||||
blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), lat, id);
|
||||
|
||||
DPRINTF(Cache, "%s%s %x %s %s\n", pkt->cmdString(),
|
||||
DPRINTF(Cache, "%s%s %x (%s) %s %s\n", pkt->cmdString(),
|
||||
pkt->req->isInstFetch() ? " (ifetch)" : "",
|
||||
pkt->getAddr(), blk ? "hit" : "miss", blk ? blk->print() : "");
|
||||
pkt->getAddr(), pkt->isSecure() ? "s" : "ns",
|
||||
blk ? "hit" : "miss", blk ? blk->print() : "");
|
||||
|
||||
if (blk != NULL) {
|
||||
|
||||
@@ -327,7 +328,7 @@ Cache<TagStore>::access(PacketPtr pkt, BlkType *&blk,
|
||||
assert(blkSize == pkt->getSize());
|
||||
if (blk == NULL) {
|
||||
// need to do a replacement
|
||||
blk = allocateBlock(pkt->getAddr(), writebacks);
|
||||
blk = allocateBlock(pkt->getAddr(), pkt->isSecure(), writebacks);
|
||||
if (blk == NULL) {
|
||||
// no replaceable block available, give up.
|
||||
// writeback will be forwarded to next level.
|
||||
@@ -390,8 +391,8 @@ Cache<TagStore>::recvTimingSnoopResp(PacketPtr pkt)
|
||||
assert(pkt->cmd == MemCmd::HardPFResp);
|
||||
// Check if it's a prefetch response and handle it. We shouldn't
|
||||
// get any other kinds of responses without FRRs.
|
||||
DPRINTF(Cache, "Got prefetch response from above for addr %#x\n",
|
||||
pkt->getAddr());
|
||||
DPRINTF(Cache, "Got prefetch response from above for addr %#x (%s)\n",
|
||||
pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
|
||||
recvTimingResp(pkt);
|
||||
return;
|
||||
}
|
||||
@@ -431,8 +432,8 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
|
||||
}
|
||||
|
||||
if (pkt->memInhibitAsserted()) {
|
||||
DPRINTF(Cache, "mem inhibited on 0x%x: not responding\n",
|
||||
pkt->getAddr());
|
||||
DPRINTF(Cache, "mem inhibited on 0x%x (%s): not responding\n",
|
||||
pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
|
||||
assert(!pkt->req->isUncacheable());
|
||||
// Special tweak for multilevel coherence: snoop downward here
|
||||
// on invalidates since there may be other caches below here
|
||||
@@ -489,7 +490,8 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
|
||||
(pkt->cmd == MemCmd::WriteReq
|
||||
|| pkt->cmd == MemCmd::WriteInvalidateReq) ) {
|
||||
// not outstanding misses, can do this
|
||||
MSHR *outstanding_miss = mshrQueue.findMatch(pkt->getAddr());
|
||||
MSHR *outstanding_miss = mshrQueue.findMatch(pkt->getAddr(),
|
||||
pkt->isSecure());
|
||||
if (pkt->cmd == MemCmd::WriteInvalidateReq || !outstanding_miss) {
|
||||
if (outstanding_miss) {
|
||||
warn("WriteInv doing a fastallocate"
|
||||
@@ -532,7 +534,7 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
|
||||
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
|
||||
|
||||
Addr blk_addr = blockAlign(pkt->getAddr());
|
||||
MSHR *mshr = mshrQueue.findMatch(blk_addr);
|
||||
MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure());
|
||||
|
||||
if (mshr) {
|
||||
/// MSHR hit
|
||||
@@ -672,16 +674,19 @@ Cache<TagStore>::recvAtomic(PacketPtr pkt)
|
||||
// have to invalidate ourselves and any lower caches even if
|
||||
// upper cache will be responding
|
||||
if (pkt->isInvalidate()) {
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
|
||||
if (blk && blk->isValid()) {
|
||||
tags->invalidate(blk);
|
||||
blk->invalidate();
|
||||
DPRINTF(Cache, "rcvd mem-inhibited %s on 0x%x: invalidating\n",
|
||||
pkt->cmdString(), pkt->getAddr());
|
||||
DPRINTF(Cache, "rcvd mem-inhibited %s on 0x%x (%s):"
|
||||
" invalidating\n",
|
||||
pkt->cmdString(), pkt->getAddr(),
|
||||
pkt->isSecure() ? "s" : "ns");
|
||||
}
|
||||
if (!last_level_cache) {
|
||||
DPRINTF(Cache, "forwarding mem-inhibited %s on 0x%x\n",
|
||||
pkt->cmdString(), pkt->getAddr());
|
||||
DPRINTF(Cache, "forwarding mem-inhibited %s on 0x%x (%s)\n",
|
||||
pkt->cmdString(), pkt->getAddr(),
|
||||
pkt->isSecure() ? "s" : "ns");
|
||||
lat += ticksToCycles(memSidePort->sendAtomic(pkt));
|
||||
}
|
||||
} else {
|
||||
@@ -711,8 +716,9 @@ Cache<TagStore>::recvAtomic(PacketPtr pkt)
|
||||
bus_pkt = pkt;
|
||||
}
|
||||
|
||||
DPRINTF(Cache, "Sending an atomic %s for %x\n",
|
||||
bus_pkt->cmdString(), bus_pkt->getAddr());
|
||||
DPRINTF(Cache, "Sending an atomic %s for %x (%s)\n",
|
||||
bus_pkt->cmdString(), bus_pkt->getAddr(),
|
||||
bus_pkt->isSecure() ? "s" : "ns");
|
||||
|
||||
#if TRACING_ON
|
||||
CacheBlk::State old_state = blk ? blk->status : 0;
|
||||
@@ -720,8 +726,10 @@ Cache<TagStore>::recvAtomic(PacketPtr pkt)
|
||||
|
||||
lat += ticksToCycles(memSidePort->sendAtomic(bus_pkt));
|
||||
|
||||
DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
|
||||
bus_pkt->cmdString(), bus_pkt->getAddr(), old_state);
|
||||
DPRINTF(Cache, "Receive response: %s for addr %x (%s) in state %i\n",
|
||||
bus_pkt->cmdString(), bus_pkt->getAddr(),
|
||||
bus_pkt->isSecure() ? "s" : "ns",
|
||||
old_state);
|
||||
|
||||
// If packet was a forward, the response (if any) is already
|
||||
// in place in the bus_pkt == pkt structure, so we don't need
|
||||
@@ -794,8 +802,9 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide)
|
||||
}
|
||||
|
||||
Addr blk_addr = blockAlign(pkt->getAddr());
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||
MSHR *mshr = mshrQueue.findMatch(blk_addr);
|
||||
bool is_secure = pkt->isSecure();
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr(), is_secure);
|
||||
MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
|
||||
|
||||
pkt->pushLabel(name());
|
||||
|
||||
@@ -808,7 +817,8 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide)
|
||||
|
||||
// see if we have data at all (owned or otherwise)
|
||||
bool have_data = blk && blk->isValid()
|
||||
&& pkt->checkFunctional(&cbpw, blk_addr, blkSize, blk->data);
|
||||
&& pkt->checkFunctional(&cbpw, blk_addr, is_secure, blkSize,
|
||||
blk->data);
|
||||
|
||||
// data we have is dirty if marked as such or if valid & ownership
|
||||
// pending due to outstanding UpgradeReq
|
||||
@@ -822,8 +832,8 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide)
|
||||
|| writeBuffer.checkFunctional(pkt, blk_addr)
|
||||
|| memSidePort->checkFunctional(pkt);
|
||||
|
||||
DPRINTF(Cache, "functional %s %x %s%s%s\n",
|
||||
pkt->cmdString(), pkt->getAddr(),
|
||||
DPRINTF(Cache, "functional %s %x (%s) %s%s%s\n",
|
||||
pkt->cmdString(), pkt->getAddr(), is_secure ? "s" : "ns",
|
||||
(blk && blk->isValid()) ? "valid " : "",
|
||||
have_data ? "data " : "", done ? "done " : "");
|
||||
|
||||
@@ -866,12 +876,13 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
|
||||
assert(mshr);
|
||||
|
||||
if (is_error) {
|
||||
DPRINTF(Cache, "Cache received packet with error for address %x, "
|
||||
"cmd: %s\n", pkt->getAddr(), pkt->cmdString());
|
||||
DPRINTF(Cache, "Cache received packet with error for address %x (%s), "
|
||||
"cmd: %s\n", pkt->getAddr(), pkt->isSecure() ? "s" : "ns",
|
||||
pkt->cmdString());
|
||||
}
|
||||
|
||||
DPRINTF(Cache, "Handling response to %s for address %x\n",
|
||||
pkt->cmdString(), pkt->getAddr());
|
||||
DPRINTF(Cache, "Handling response to %s for address %x (%s)\n",
|
||||
pkt->cmdString(), pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
|
||||
|
||||
MSHRQueue *mq = mshr->queue;
|
||||
bool wasFull = mq->isFull();
|
||||
@@ -884,7 +895,7 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
|
||||
|
||||
// Initial target is used just for stats
|
||||
MSHR::Target *initial_tgt = mshr->getTarget();
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
|
||||
int stats_cmd_idx = initial_tgt->pkt->cmdToIndex();
|
||||
Tick miss_latency = curTick() - initial_tgt->recvTime;
|
||||
PacketList writebacks;
|
||||
@@ -1074,6 +1085,8 @@ Cache<TagStore>::writebackBlk(BlkType *blk)
|
||||
Request *writebackReq =
|
||||
new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0,
|
||||
Request::wbMasterId);
|
||||
if (blk->isSecure())
|
||||
writebackReq->setFlags(Request::SECURE);
|
||||
|
||||
writebackReq->taskId(blk->task_id);
|
||||
blk->task_id= ContextSwitchTaskId::Unknown;
|
||||
@@ -1166,7 +1179,7 @@ Cache<TagStore>::uncacheableFlush(PacketPtr pkt)
|
||||
if (pkt->req->isClearLL())
|
||||
tags->clearLocks();
|
||||
|
||||
BlkType *blk(tags->findBlock(pkt->getAddr()));
|
||||
BlkType *blk(tags->findBlock(pkt->getAddr(), pkt->isSecure()));
|
||||
if (blk) {
|
||||
writebackVisitor(*blk);
|
||||
invalidateVisitor(*blk);
|
||||
@@ -1176,13 +1189,14 @@ Cache<TagStore>::uncacheableFlush(PacketPtr pkt)
|
||||
|
||||
template<class TagStore>
|
||||
typename Cache<TagStore>::BlkType*
|
||||
Cache<TagStore>::allocateBlock(Addr addr, PacketList &writebacks)
|
||||
Cache<TagStore>::allocateBlock(Addr addr, bool is_secure,
|
||||
PacketList &writebacks)
|
||||
{
|
||||
BlkType *blk = tags->findVictim(addr, writebacks);
|
||||
|
||||
if (blk->isValid()) {
|
||||
Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
|
||||
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr);
|
||||
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr, blk->isSecure());
|
||||
if (repl_mshr) {
|
||||
// must be an outstanding upgrade request on block
|
||||
// we're about to replace...
|
||||
@@ -1192,8 +1206,9 @@ Cache<TagStore>::allocateBlock(Addr addr, PacketList &writebacks)
|
||||
// allocation failed, block not inserted
|
||||
return NULL;
|
||||
} else {
|
||||
DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
|
||||
repl_addr, addr,
|
||||
DPRINTF(Cache, "replacement: replacing %x (%s) with %x (%s): %s\n",
|
||||
repl_addr, blk->isSecure() ? "s" : "ns",
|
||||
addr, is_secure ? "s" : "ns",
|
||||
blk->isDirty() ? "writeback" : "clean");
|
||||
|
||||
if (blk->isDirty()) {
|
||||
@@ -1218,6 +1233,7 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||
PacketList &writebacks)
|
||||
{
|
||||
Addr addr = pkt->getAddr();
|
||||
bool is_secure = pkt->isSecure();
|
||||
#if TRACING_ON
|
||||
CacheBlk::State old_state = blk ? blk->status : 0;
|
||||
#endif
|
||||
@@ -1226,7 +1242,7 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||
// better have read new data...
|
||||
assert(pkt->hasData());
|
||||
// need to do a replacement
|
||||
blk = allocateBlock(addr, writebacks);
|
||||
blk = allocateBlock(addr, is_secure, writebacks);
|
||||
if (blk == NULL) {
|
||||
// No replaceable block... just use temporary storage to
|
||||
// complete the current request and then get rid of it
|
||||
@@ -1234,7 +1250,9 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||
blk = tempBlock;
|
||||
tempBlock->set = tags->extractSet(addr);
|
||||
tempBlock->tag = tags->extractTag(addr);
|
||||
DPRINTF(Cache, "using temp block for %x\n", addr);
|
||||
// @todo: set security state as well...
|
||||
DPRINTF(Cache, "using temp block for %x (%s)\n", addr,
|
||||
is_secure ? "s" : "ns");
|
||||
} else {
|
||||
tags->insertBlock(pkt, blk);
|
||||
}
|
||||
@@ -1250,6 +1268,8 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||
// don't want to lose that
|
||||
}
|
||||
|
||||
if (is_secure)
|
||||
blk->status |= BlkSecure;
|
||||
blk->status |= BlkValid | BlkReadable;
|
||||
|
||||
if (!pkt->sharedAsserted()) {
|
||||
@@ -1265,8 +1285,8 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||
blk->status |= BlkDirty;
|
||||
}
|
||||
|
||||
DPRINTF(Cache, "Block addr %x moving from state %x to %s\n",
|
||||
addr, old_state, blk->print());
|
||||
DPRINTF(Cache, "Block addr %x (%s) moving from state %x to %s\n",
|
||||
addr, is_secure ? "s" : "ns", old_state, blk->print());
|
||||
|
||||
// if we got new data, copy it in
|
||||
if (pkt->isRead()) {
|
||||
@@ -1453,16 +1473,18 @@ Cache<TagStore>::recvTimingSnoopReq(PacketPtr pkt)
|
||||
return;
|
||||
}
|
||||
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||
bool is_secure = pkt->isSecure();
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr(), is_secure);
|
||||
|
||||
Addr blk_addr = blockAlign(pkt->getAddr());
|
||||
MSHR *mshr = mshrQueue.findMatch(blk_addr);
|
||||
MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
|
||||
|
||||
// Let the MSHR itself track the snoop and decide whether we want
|
||||
// to go ahead and do the regular cache snoop
|
||||
if (mshr && mshr->handleSnoop(pkt, order++)) {
|
||||
DPRINTF(Cache, "Deferring snoop on in-service MSHR to blk %x."
|
||||
"mshrs: %s\n", blk_addr, mshr->print());
|
||||
DPRINTF(Cache, "Deferring snoop on in-service MSHR to blk %x (%s)."
|
||||
"mshrs: %s\n", blk_addr, is_secure ? "s" : "ns",
|
||||
mshr->print());
|
||||
|
||||
if (mshr->getNumTargets() > numTarget)
|
||||
warn("allocating bonus target for snoop"); //handle later
|
||||
@@ -1471,9 +1493,9 @@ Cache<TagStore>::recvTimingSnoopReq(PacketPtr pkt)
|
||||
|
||||
//We also need to check the writeback buffers and handle those
|
||||
std::vector<MSHR *> writebacks;
|
||||
if (writeBuffer.findMatches(blk_addr, writebacks)) {
|
||||
DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n",
|
||||
pkt->getAddr());
|
||||
if (writeBuffer.findMatches(blk_addr, is_secure, writebacks)) {
|
||||
DPRINTF(Cache, "Snoop hit in writeback to addr: %x (%s)\n",
|
||||
pkt->getAddr(), is_secure ? "s" : "ns");
|
||||
|
||||
//Look through writebacks for any non-uncachable writes, use that
|
||||
if (writebacks.size()) {
|
||||
@@ -1538,7 +1560,7 @@ Cache<TagStore>::recvAtomicSnoop(PacketPtr pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||
BlkType *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
|
||||
handleSnoop(pkt, blk, false, false, false);
|
||||
return hitLatency * clockPeriod();
|
||||
}
|
||||
@@ -1567,7 +1589,8 @@ Cache<TagStore>::getNextMSHR()
|
||||
// Write buffer is full, so we'd like to issue a write;
|
||||
// need to search MSHR queue for conflicting earlier miss.
|
||||
MSHR *conflict_mshr =
|
||||
mshrQueue.findPending(write_mshr->addr, write_mshr->size);
|
||||
mshrQueue.findPending(write_mshr->addr, write_mshr->size,
|
||||
write_mshr->isSecure);
|
||||
|
||||
if (conflict_mshr && conflict_mshr->order < write_mshr->order) {
|
||||
// Service misses in order until conflict is cleared.
|
||||
@@ -1581,7 +1604,8 @@ Cache<TagStore>::getNextMSHR()
|
||||
// Write buffer isn't full, but need to check it for
|
||||
// conflicting earlier writeback
|
||||
MSHR *conflict_mshr =
|
||||
writeBuffer.findPending(miss_mshr->addr, miss_mshr->size);
|
||||
writeBuffer.findPending(miss_mshr->addr, miss_mshr->size,
|
||||
miss_mshr->isSecure);
|
||||
if (conflict_mshr) {
|
||||
// not sure why we don't check order here... it was in the
|
||||
// original code but commented out.
|
||||
@@ -1609,8 +1633,9 @@ Cache<TagStore>::getNextMSHR()
|
||||
PacketPtr pkt = prefetcher->getPacket();
|
||||
if (pkt) {
|
||||
Addr pf_addr = blockAlign(pkt->getAddr());
|
||||
if (!tags->findBlock(pf_addr) && !mshrQueue.findMatch(pf_addr) &&
|
||||
!writeBuffer.findMatch(pf_addr)) {
|
||||
if (!tags->findBlock(pf_addr, pkt->isSecure()) &&
|
||||
!mshrQueue.findMatch(pf_addr, pkt->isSecure()) &&
|
||||
!writeBuffer.findMatch(pf_addr, pkt->isSecure())) {
|
||||
// Update statistic on number of prefetches issued
|
||||
// (hwpf_mshr_misses)
|
||||
assert(pkt->req->masterId() < system->maxMasters());
|
||||
@@ -1659,10 +1684,10 @@ Cache<TagStore>::getTimingPacket()
|
||||
return NULL;
|
||||
} else if (mshr->isForwardNoResponse()) {
|
||||
// no response expected, just forward packet as it is
|
||||
assert(tags->findBlock(mshr->addr) == NULL);
|
||||
assert(tags->findBlock(mshr->addr, mshr->isSecure) == NULL);
|
||||
pkt = tgt_pkt;
|
||||
} else {
|
||||
BlkType *blk = tags->findBlock(mshr->addr);
|
||||
BlkType *blk = tags->findBlock(mshr->addr, mshr->isSecure);
|
||||
|
||||
if (tgt_pkt->cmd == MemCmd::HardPFReq) {
|
||||
// It might be possible for a writeback to arrive between
|
||||
@@ -1683,8 +1708,9 @@ Cache<TagStore>::getTimingPacket()
|
||||
|
||||
if (snoop_pkt.memInhibitAsserted()) {
|
||||
markInService(mshr, &snoop_pkt);
|
||||
DPRINTF(Cache, "Upward snoop of prefetch for addr %#x hit\n",
|
||||
tgt_pkt->getAddr());
|
||||
DPRINTF(Cache, "Upward snoop of prefetch for addr"
|
||||
" %#x (%s) hit\n",
|
||||
tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
16
src/mem/cache/mshr.cc
vendored
16
src/mem/cache/mshr.cc
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -64,8 +64,8 @@ using namespace std;
|
||||
MSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false),
|
||||
pendingDirty(false), postInvalidate(false),
|
||||
postDowngrade(false), queue(NULL), order(0), addr(0), size(0),
|
||||
inService(false), isForward(false), threadNum(InvalidThreadID),
|
||||
data(NULL)
|
||||
isSecure(false), inService(false), isForward(false),
|
||||
threadNum(InvalidThreadID), data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -201,11 +201,12 @@ print(std::ostream &os, int verbosity, const std::string &prefix) const
|
||||
|
||||
|
||||
void
|
||||
MSHR::allocate(Addr _addr, int _size, PacketPtr target,
|
||||
Tick whenReady, Counter _order)
|
||||
MSHR::allocate(Addr _addr, int _size, PacketPtr target, Tick whenReady,
|
||||
Counter _order)
|
||||
{
|
||||
addr = _addr;
|
||||
size = _size;
|
||||
isSecure = target->isSecure();
|
||||
readyTime = whenReady;
|
||||
order = _order;
|
||||
assert(target);
|
||||
@@ -440,7 +441,7 @@ MSHR::checkFunctional(PacketPtr pkt)
|
||||
// For other requests, we iterate over the individual targets
|
||||
// since that's where the actual data lies.
|
||||
if (pkt->isPrint()) {
|
||||
pkt->checkFunctional(this, addr, size, NULL);
|
||||
pkt->checkFunctional(this, addr, isSecure, size, NULL);
|
||||
return false;
|
||||
} else {
|
||||
return (targets.checkFunctional(pkt) ||
|
||||
@@ -452,8 +453,9 @@ MSHR::checkFunctional(PacketPtr pkt)
|
||||
void
|
||||
MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
|
||||
{
|
||||
ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s %s\n",
|
||||
ccprintf(os, "%s[%x:%x](%s) %s %s %s state: %s %s %s %s %s\n",
|
||||
prefix, addr, addr+size-1,
|
||||
isSecure ? "s" : "ns",
|
||||
isForward ? "Forward" : "",
|
||||
isForwardNoResponse() ? "ForwNoResp" : "",
|
||||
needsExclusive() ? "Excl" : "",
|
||||
|
||||
3
src/mem/cache/mshr.hh
vendored
3
src/mem/cache/mshr.hh
vendored
@@ -155,6 +155,9 @@ class MSHR : public Packet::SenderState, public Printable
|
||||
/** Size of the request. */
|
||||
int size;
|
||||
|
||||
/** True if the request targets the secure memory space. */
|
||||
bool isSecure;
|
||||
|
||||
/** True if the request has been sent to the bus. */
|
||||
bool inService;
|
||||
|
||||
|
||||
24
src/mem/cache/mshr_queue.cc
vendored
24
src/mem/cache/mshr_queue.cc
vendored
@@ -62,13 +62,13 @@ MSHRQueue::MSHRQueue(const std::string &_label,
|
||||
}
|
||||
|
||||
MSHR *
|
||||
MSHRQueue::findMatch(Addr addr) const
|
||||
MSHRQueue::findMatch(Addr addr, bool is_secure) const
|
||||
{
|
||||
MSHR::ConstIterator i = allocatedList.begin();
|
||||
MSHR::ConstIterator end = allocatedList.end();
|
||||
for (; i != end; ++i) {
|
||||
MSHR *mshr = *i;
|
||||
if (mshr->addr == addr) {
|
||||
if (mshr->addr == addr && mshr->isSecure == is_secure) {
|
||||
return mshr;
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ MSHRQueue::findMatch(Addr addr) const
|
||||
}
|
||||
|
||||
bool
|
||||
MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
|
||||
MSHRQueue::findMatches(Addr addr, bool is_secure, vector<MSHR*>& matches) const
|
||||
{
|
||||
// Need an empty vector
|
||||
assert(matches.empty());
|
||||
@@ -85,7 +85,7 @@ MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
|
||||
MSHR::ConstIterator end = allocatedList.end();
|
||||
for (; i != end; ++i) {
|
||||
MSHR *mshr = *i;
|
||||
if (mshr->addr == addr) {
|
||||
if (mshr->addr == addr && mshr->isSecure == is_secure) {
|
||||
retval = true;
|
||||
matches.push_back(mshr);
|
||||
}
|
||||
@@ -113,19 +113,19 @@ MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
|
||||
|
||||
|
||||
MSHR *
|
||||
MSHRQueue::findPending(Addr addr, int size) const
|
||||
MSHRQueue::findPending(Addr addr, int size, bool is_secure) const
|
||||
{
|
||||
MSHR::ConstIterator i = readyList.begin();
|
||||
MSHR::ConstIterator end = readyList.end();
|
||||
for (; i != end; ++i) {
|
||||
MSHR *mshr = *i;
|
||||
if (mshr->addr < addr) {
|
||||
if (mshr->addr + mshr->size > addr) {
|
||||
return mshr;
|
||||
}
|
||||
} else {
|
||||
if (addr + size > mshr->addr) {
|
||||
return mshr;
|
||||
if (mshr->isSecure == is_secure) {
|
||||
if (mshr->addr < addr) {
|
||||
if (mshr->addr + mshr->size > addr)
|
||||
return mshr;
|
||||
} else {
|
||||
if (addr + size > mshr->addr)
|
||||
return mshr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/mem/cache/mshr_queue.hh
vendored
10
src/mem/cache/mshr_queue.hh
vendored
@@ -113,25 +113,29 @@ class MSHRQueue : public Drainable
|
||||
/**
|
||||
* Find the first MSHR that matches the provided address.
|
||||
* @param addr The address to find.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @return Pointer to the matching MSHR, null if not found.
|
||||
*/
|
||||
MSHR *findMatch(Addr addr) const;
|
||||
MSHR *findMatch(Addr addr, bool is_secure) const;
|
||||
|
||||
/**
|
||||
* Find and return all the matching entries in the provided vector.
|
||||
* @param addr The address to find.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @param matches The vector to return pointers to the matching entries.
|
||||
* @return True if any matches are found, false otherwise.
|
||||
* @todo Typedef the vector??
|
||||
*/
|
||||
bool findMatches(Addr addr, std::vector<MSHR*>& matches) const;
|
||||
bool findMatches(Addr addr, bool is_secure,
|
||||
std::vector<MSHR*>& matches) const;
|
||||
|
||||
/**
|
||||
* Find any pending requests that overlap the given request.
|
||||
* @param pkt The request to find.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @return A pointer to the earliest matching MSHR.
|
||||
*/
|
||||
MSHR *findPending(Addr addr, int size) const;
|
||||
MSHR *findPending(Addr addr, int size, bool is_secure) const;
|
||||
|
||||
bool checkFunctional(PacketPtr pkt, Addr blk_addr);
|
||||
|
||||
|
||||
33
src/mem/cache/prefetch/base.cc
vendored
33
src/mem/cache/prefetch/base.cc
vendored
@@ -122,9 +122,9 @@ BasePrefetcher::regStats()
|
||||
}
|
||||
|
||||
inline bool
|
||||
BasePrefetcher::inCache(Addr addr)
|
||||
BasePrefetcher::inCache(Addr addr, bool is_secure)
|
||||
{
|
||||
if (cache->inCache(addr)) {
|
||||
if (cache->inCache(addr, is_secure)) {
|
||||
pfCacheHit++;
|
||||
return true;
|
||||
}
|
||||
@@ -132,9 +132,9 @@ BasePrefetcher::inCache(Addr addr)
|
||||
}
|
||||
|
||||
inline bool
|
||||
BasePrefetcher::inMissQueue(Addr addr)
|
||||
BasePrefetcher::inMissQueue(Addr addr, bool is_secure)
|
||||
{
|
||||
if (cache->inMissQueue(addr)) {
|
||||
if (cache->inMissQueue(addr, is_secure)) {
|
||||
pfMSHRHit++;
|
||||
return true;
|
||||
}
|
||||
@@ -157,12 +157,14 @@ BasePrefetcher::getPacket()
|
||||
pf.pop_front();
|
||||
|
||||
Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
|
||||
bool is_secure = pkt->isSecure();
|
||||
|
||||
if (!inCache(blk_addr) && !inMissQueue(blk_addr))
|
||||
if (!inCache(blk_addr, is_secure) && !inMissQueue(blk_addr, is_secure))
|
||||
// we found a prefetch, return it
|
||||
break;
|
||||
|
||||
DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", pkt->getAddr());
|
||||
DPRINTF(HWPrefetch, "addr 0x%x (%s) in cache, skipping\n",
|
||||
pkt->getAddr(), is_secure ? "s" : "ns");
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
@@ -174,7 +176,8 @@ BasePrefetcher::getPacket()
|
||||
|
||||
pfIssued++;
|
||||
assert(pkt != NULL);
|
||||
DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr());
|
||||
DPRINTF(HWPrefetch, "returning 0x%x (%s)\n", pkt->getAddr(),
|
||||
pkt->isSecure() ? "s" : "ns");
|
||||
return pkt;
|
||||
}
|
||||
|
||||
@@ -185,12 +188,15 @@ BasePrefetcher::notify(PacketPtr &pkt, Tick tick)
|
||||
if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData)) {
|
||||
// Calculate the blk address
|
||||
Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
|
||||
bool is_secure = pkt->isSecure();
|
||||
|
||||
// Check if miss is in pfq, if so remove it
|
||||
std::list<DeferredPacket>::iterator iter = inPrefetch(blk_addr);
|
||||
std::list<DeferredPacket>::iterator iter = inPrefetch(blk_addr,
|
||||
is_secure);
|
||||
if (iter != pf.end()) {
|
||||
DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: "
|
||||
"0x%x, removing it\n", blk_addr);
|
||||
"0x%x (%s), removing it\n", blk_addr,
|
||||
is_secure ? "s" : "ns");
|
||||
pfRemovedMSHR++;
|
||||
delete iter->pkt->req;
|
||||
delete iter->pkt;
|
||||
@@ -239,7 +245,7 @@ BasePrefetcher::notify(PacketPtr &pkt, Tick tick)
|
||||
addr, *delayIter, time);
|
||||
|
||||
// Check if it is already in the pf buffer
|
||||
if (inPrefetch(addr) != pf.end()) {
|
||||
if (inPrefetch(addr, is_secure) != pf.end()) {
|
||||
pfBufferHit++;
|
||||
DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n");
|
||||
continue;
|
||||
@@ -247,6 +253,8 @@ BasePrefetcher::notify(PacketPtr &pkt, Tick tick)
|
||||
|
||||
// create a prefetch memreq
|
||||
Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId);
|
||||
if (is_secure)
|
||||
prefetchReq->setFlags(Request::SECURE);
|
||||
prefetchReq->taskId(ContextSwitchTaskId::Prefetcher);
|
||||
PacketPtr prefetch =
|
||||
new Packet(prefetchReq, MemCmd::HardPFReq);
|
||||
@@ -274,12 +282,13 @@ BasePrefetcher::notify(PacketPtr &pkt, Tick tick)
|
||||
}
|
||||
|
||||
std::list<BasePrefetcher::DeferredPacket>::iterator
|
||||
BasePrefetcher::inPrefetch(Addr address)
|
||||
BasePrefetcher::inPrefetch(Addr address, bool is_secure)
|
||||
{
|
||||
// Guaranteed to only be one match, we always check before inserting
|
||||
std::list<DeferredPacket>::iterator iter;
|
||||
for (iter = pf.begin(); iter != pf.end(); iter++) {
|
||||
if ((iter->pkt->getAddr() & ~(Addr)(blkSize-1)) == address) {
|
||||
if (((*iter).pkt->getAddr() & ~(Addr)(blkSize-1)) == address &&
|
||||
(*iter).pkt->isSecure() == is_secure) {
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
6
src/mem/cache/prefetch/base.hh
vendored
6
src/mem/cache/prefetch/base.hh
vendored
@@ -137,9 +137,9 @@ class BasePrefetcher : public ClockedObject
|
||||
*/
|
||||
Tick notify(PacketPtr &pkt, Tick tick);
|
||||
|
||||
bool inCache(Addr addr);
|
||||
bool inCache(Addr addr, bool is_secure);
|
||||
|
||||
bool inMissQueue(Addr addr);
|
||||
bool inMissQueue(Addr addr, bool is_secure);
|
||||
|
||||
PacketPtr getPacket();
|
||||
|
||||
@@ -157,7 +157,7 @@ class BasePrefetcher : public ClockedObject
|
||||
std::list<Addr> &addresses,
|
||||
std::list<Cycles> &delays) = 0;
|
||||
|
||||
std::list<DeferredPacket>::iterator inPrefetch(Addr address);
|
||||
std::list<DeferredPacket>::iterator inPrefetch(Addr address, bool is_secure);
|
||||
|
||||
/**
|
||||
* Utility function: are addresses a and b on the same VM page?
|
||||
|
||||
24
src/mem/cache/prefetch/ghb.cc
vendored
24
src/mem/cache/prefetch/ghb.cc
vendored
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -43,16 +55,26 @@ GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
std::list<Cycles> &delays)
|
||||
{
|
||||
Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
|
||||
bool is_secure = pkt->isSecure();
|
||||
int master_id = useMasterId ? pkt->req->masterId() : 0;
|
||||
assert(master_id < Max_Masters);
|
||||
|
||||
bool same_sec_state = true;
|
||||
// Avoid activating prefetch if the security state is not
|
||||
// consistent across requests
|
||||
if (is_secure != lastMissIsSecure[master_id] ||
|
||||
is_secure != secondLastMissIsSecure[master_id])
|
||||
same_sec_state = false;
|
||||
|
||||
int new_stride = blk_addr - lastMissAddr[master_id];
|
||||
int old_stride = lastMissAddr[master_id] - secondLastMissAddr[master_id];
|
||||
|
||||
secondLastMissAddr[master_id] = lastMissAddr[master_id];
|
||||
secondLastMissIsSecure[master_id] = lastMissIsSecure[master_id];
|
||||
lastMissAddr[master_id] = blk_addr;
|
||||
lastMissIsSecure[master_id] = is_secure;
|
||||
|
||||
if (new_stride == old_stride) {
|
||||
if (same_sec_state && new_stride == old_stride) {
|
||||
for (int d = 1; d <= degree; d++) {
|
||||
Addr new_addr = blk_addr + d * new_stride;
|
||||
if (pageStop && !samePage(blk_addr, new_addr)) {
|
||||
|
||||
14
src/mem/cache/prefetch/ghb.hh
vendored
14
src/mem/cache/prefetch/ghb.hh
vendored
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -46,7 +58,9 @@ class GHBPrefetcher : public BasePrefetcher
|
||||
static const int Max_Masters = 64;
|
||||
|
||||
Addr secondLastMissAddr[Max_Masters];
|
||||
bool secondLastMissIsSecure[Max_Masters];
|
||||
Addr lastMissAddr[Max_Masters];
|
||||
bool lastMissIsSecure[Max_Masters];
|
||||
|
||||
public:
|
||||
GHBPrefetcher(const Params *p)
|
||||
|
||||
33
src/mem/cache/prefetch/stride.cc
vendored
33
src/mem/cache/prefetch/stride.cc
vendored
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -48,6 +60,7 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
}
|
||||
|
||||
Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
|
||||
bool is_secure = pkt->isSecure();
|
||||
MasterID master_id = useMasterId ? pkt->req->masterId() : 0;
|
||||
Addr pc = pkt->req->getPC();
|
||||
assert(master_id < Max_Contexts);
|
||||
@@ -56,7 +69,8 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
/* Scan Table for instAddr Match */
|
||||
std::list<StrideEntry*>::iterator iter;
|
||||
for (iter = tab.begin(); iter != tab.end(); iter++) {
|
||||
if ((*iter)->instAddr == pc)
|
||||
// Entries have to match on the security state as well
|
||||
if ((*iter)->instAddr == pc && (*iter)->isSecure == is_secure)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -75,11 +89,13 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
(*iter)->confidence = 0;
|
||||
}
|
||||
|
||||
DPRINTF(HWPrefetch, "hit: PC %x blk_addr %x stride %d (%s), conf %d\n",
|
||||
pc, blk_addr, new_stride, stride_match ? "match" : "change",
|
||||
DPRINTF(HWPrefetch, "hit: PC %x blk_addr %x (%s) stride %d (%s), "
|
||||
"conf %d\n", pc, blk_addr, is_secure ? "s" : "ns", new_stride,
|
||||
stride_match ? "match" : "change",
|
||||
(*iter)->confidence);
|
||||
|
||||
(*iter)->missAddr = blk_addr;
|
||||
(*iter)->isSecure = is_secure;
|
||||
|
||||
if ((*iter)->confidence <= 0)
|
||||
return;
|
||||
@@ -91,8 +107,8 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
pfSpanPage += degree - d + 1;
|
||||
return;
|
||||
} else {
|
||||
DPRINTF(HWPrefetch, " queuing prefetch to %x @ %d\n",
|
||||
new_addr, latency);
|
||||
DPRINTF(HWPrefetch, " queuing prefetch to %x (%s) @ %d\n",
|
||||
new_addr, is_secure ? "s" : "ns", latency);
|
||||
addresses.push_back(new_addr);
|
||||
delays.push_back(latency);
|
||||
}
|
||||
@@ -101,7 +117,8 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
// Miss in table
|
||||
// Find lowest confidence and replace
|
||||
|
||||
DPRINTF(HWPrefetch, "miss: PC %x blk_addr %x\n", pc, blk_addr);
|
||||
DPRINTF(HWPrefetch, "miss: PC %x blk_addr %x (%s)\n", pc, blk_addr,
|
||||
is_secure ? "s" : "ns");
|
||||
|
||||
if (tab.size() >= 256) { //set default table size is 256
|
||||
std::list<StrideEntry*>::iterator min_pos = tab.begin();
|
||||
@@ -112,7 +129,8 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
min_conf = (*iter)->confidence;
|
||||
}
|
||||
}
|
||||
DPRINTF(HWPrefetch, " replacing PC %x\n", (*min_pos)->instAddr);
|
||||
DPRINTF(HWPrefetch, " replacing PC %x (%s)\n",
|
||||
(*min_pos)->instAddr, (*min_pos)->isSecure ? "s" : "ns");
|
||||
|
||||
// free entry and delete it
|
||||
delete *min_pos;
|
||||
@@ -122,6 +140,7 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
|
||||
StrideEntry *new_entry = new StrideEntry;
|
||||
new_entry->instAddr = pc;
|
||||
new_entry->missAddr = blk_addr;
|
||||
new_entry->isSecure = is_secure;
|
||||
new_entry->stride = 0;
|
||||
new_entry->confidence = 0;
|
||||
tab.push_back(new_entry);
|
||||
|
||||
15
src/mem/cache/prefetch/stride.hh
vendored
15
src/mem/cache/prefetch/stride.hh
vendored
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -57,12 +69,11 @@ class StridePrefetcher : public BasePrefetcher
|
||||
public:
|
||||
Addr instAddr;
|
||||
Addr missAddr;
|
||||
bool isSecure;
|
||||
int stride;
|
||||
int confidence;
|
||||
};
|
||||
|
||||
Addr *lastMissAddr[Max_Contexts];
|
||||
|
||||
std::list<StrideEntry*> table[Max_Contexts];
|
||||
|
||||
public:
|
||||
|
||||
14
src/mem/cache/tags/cacheset.hh
vendored
14
src/mem/cache/tags/cacheset.hh
vendored
@@ -69,10 +69,11 @@ class CacheSet
|
||||
* Find a block matching the tag in this set.
|
||||
* @param way_id The id of the way that matches the tag.
|
||||
* @param tag The Tag to find.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @return Pointer to the block if found. Set way_id to assoc if none found
|
||||
*/
|
||||
Blktype* findBlk(Addr tag, int& way_id) const ;
|
||||
Blktype* findBlk(Addr tag) const ;
|
||||
Blktype* findBlk(Addr tag, bool is_secure, int& way_id) const ;
|
||||
Blktype* findBlk(Addr tag, bool is_secure) const ;
|
||||
|
||||
/**
|
||||
* Move the given block to the head of the list.
|
||||
@@ -90,7 +91,7 @@ class CacheSet
|
||||
|
||||
template <class Blktype>
|
||||
Blktype*
|
||||
CacheSet<Blktype>::findBlk(Addr tag, int& way_id) const
|
||||
CacheSet<Blktype>::findBlk(Addr tag, bool is_secure, int& way_id) const
|
||||
{
|
||||
/**
|
||||
* Way_id returns the id of the way that matches the block
|
||||
@@ -98,7 +99,8 @@ CacheSet<Blktype>::findBlk(Addr tag, int& way_id) const
|
||||
*/
|
||||
way_id = assoc;
|
||||
for (int i = 0; i < assoc; ++i) {
|
||||
if (blks[i]->tag == tag && blks[i]->isValid()) {
|
||||
if (blks[i]->tag == tag && blks[i]->isValid() &&
|
||||
blks[i]->isSecure() == is_secure) {
|
||||
way_id = i;
|
||||
return blks[i];
|
||||
}
|
||||
@@ -108,10 +110,10 @@ CacheSet<Blktype>::findBlk(Addr tag, int& way_id) const
|
||||
|
||||
template <class Blktype>
|
||||
Blktype*
|
||||
CacheSet<Blktype>::findBlk(Addr tag) const
|
||||
CacheSet<Blktype>::findBlk(Addr tag, bool is_secure) const
|
||||
{
|
||||
int ignored_way_id;
|
||||
return findBlk(tag, ignored_way_id);
|
||||
return findBlk(tag, is_secure, ignored_way_id);
|
||||
}
|
||||
|
||||
template <class Blktype>
|
||||
|
||||
5
src/mem/cache/tags/fa_lru.cc
vendored
5
src/mem/cache/tags/fa_lru.cc
vendored
@@ -171,7 +171,8 @@ FALRU::invalidate(FALRU::BlkType *blk)
|
||||
}
|
||||
|
||||
FALRUBlk*
|
||||
FALRU::accessBlock(Addr addr, Cycles &lat, int context_src, int *inCache)
|
||||
FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, int context_src,
|
||||
int *inCache)
|
||||
{
|
||||
accesses++;
|
||||
int tmp_in_cache = 0;
|
||||
@@ -209,7 +210,7 @@ FALRU::accessBlock(Addr addr, Cycles &lat, int context_src, int *inCache)
|
||||
|
||||
|
||||
FALRUBlk*
|
||||
FALRU::findBlock(Addr addr) const
|
||||
FALRU::findBlock(Addr addr, bool is_secure) const
|
||||
{
|
||||
Addr blkAddr = blkAlign(addr);
|
||||
FALRUBlk* blk = hashLookup(blkAddr);
|
||||
|
||||
7
src/mem/cache/tags/fa_lru.hh
vendored
7
src/mem/cache/tags/fa_lru.hh
vendored
@@ -182,20 +182,23 @@ public:
|
||||
* access and should only be used as such.
|
||||
* Returns the access latency and inCache flags as a side effect.
|
||||
* @param addr The address to look for.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @param asid The address space ID.
|
||||
* @param lat The latency of the access.
|
||||
* @param inCache The FALRUBlk::inCache flags.
|
||||
* @return Pointer to the cache block.
|
||||
*/
|
||||
FALRUBlk* accessBlock(Addr addr, Cycles &lat, int context_src, int *inCache = 0);
|
||||
FALRUBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat,
|
||||
int context_src, int *inCache = 0);
|
||||
|
||||
/**
|
||||
* Find the block in the cache, do not update the replacement data.
|
||||
* @param addr The address to look for.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @param asid The address space ID.
|
||||
* @return Pointer to the cache block.
|
||||
*/
|
||||
FALRUBlk* findBlock(Addr addr) const;
|
||||
FALRUBlk* findBlock(Addr addr, bool is_secure) const;
|
||||
|
||||
/**
|
||||
* Find a replacement block for the address provided.
|
||||
|
||||
15
src/mem/cache/tags/lru.cc
vendored
15
src/mem/cache/tags/lru.cc
vendored
@@ -127,11 +127,11 @@ LRU::~LRU()
|
||||
}
|
||||
|
||||
LRU::BlkType*
|
||||
LRU::accessBlock(Addr addr, Cycles &lat, int master_id)
|
||||
LRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, int master_id)
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned set = extractSet(addr);
|
||||
BlkType *blk = sets[set].findBlk(tag);
|
||||
BlkType *blk = sets[set].findBlk(tag, is_secure);
|
||||
lat = hitLatency;
|
||||
|
||||
// Access all tags in parallel, hence one in each way. The data side
|
||||
@@ -149,8 +149,8 @@ LRU::accessBlock(Addr addr, Cycles &lat, int master_id)
|
||||
if (blk != NULL) {
|
||||
// move this block to head of the MRU list
|
||||
sets[set].moveToHead(blk);
|
||||
DPRINTF(CacheRepl, "set %x: moving blk %x to MRU\n",
|
||||
set, regenerateBlkAddr(tag, set));
|
||||
DPRINTF(CacheRepl, "set %x: moving blk %x (%s) to MRU\n",
|
||||
set, regenerateBlkAddr(tag, set), is_secure ? "s" : "ns");
|
||||
if (blk->whenReady > curTick()
|
||||
&& cache->ticksToCycles(blk->whenReady - curTick()) > hitLatency) {
|
||||
lat = cache->ticksToCycles(blk->whenReady - curTick());
|
||||
@@ -163,11 +163,11 @@ LRU::accessBlock(Addr addr, Cycles &lat, int master_id)
|
||||
|
||||
|
||||
LRU::BlkType*
|
||||
LRU::findBlock(Addr addr) const
|
||||
LRU::findBlock(Addr addr, bool is_secure) const
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned set = extractSet(addr);
|
||||
BlkType *blk = sets[set].findBlk(tag);
|
||||
BlkType *blk = sets[set].findBlk(tag, is_secure);
|
||||
return blk;
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ LRU::insertBlock(PacketPtr pkt, BlkType *blk)
|
||||
Addr addr = pkt->getAddr();
|
||||
MasterID master_id = pkt->req->masterId();
|
||||
uint32_t task_id = pkt->req->taskId();
|
||||
bool is_secure = pkt->isSecure();
|
||||
if (!blk->isTouched) {
|
||||
tagsInUse++;
|
||||
blk->isTouched = true;
|
||||
@@ -220,6 +221,8 @@ LRU::insertBlock(PacketPtr pkt, BlkType *blk)
|
||||
blk->isTouched = true;
|
||||
// Set tag for new block. Caller is responsible for setting status.
|
||||
blk->tag = extractTag(addr);
|
||||
if (is_secure)
|
||||
blk->status |= BlkSecure;
|
||||
|
||||
// deal with what we are bringing in
|
||||
assert(master_id < cache->system->maxMasters());
|
||||
|
||||
7
src/mem/cache/tags/lru.hh
vendored
7
src/mem/cache/tags/lru.hh
vendored
@@ -148,20 +148,23 @@ public:
|
||||
* NULL pointer is returned. This has all the implications of a cache
|
||||
* access and should only be used as such. Returns the access latency as a side effect.
|
||||
* @param addr The address to find.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @param asid The address space ID.
|
||||
* @param lat The access latency.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
BlkType* accessBlock(Addr addr, Cycles &lat, int context_src);
|
||||
BlkType* accessBlock(Addr addr, bool is_secure, Cycles &lat,
|
||||
int context_src);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache, do not update replacement data.
|
||||
* i.e. This is a no-side-effect find of a block.
|
||||
* @param addr The address to find.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @param asid The address space ID.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
BlkType* findBlock(Addr addr) const;
|
||||
BlkType* findBlock(Addr addr, bool is_secure) const;
|
||||
|
||||
/**
|
||||
* Find a block to evict for the address provided.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012 ARM Limited
|
||||
* Copyright (c) 2011-2013 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -172,14 +172,16 @@ MemCmd::commandInfo[] =
|
||||
};
|
||||
|
||||
bool
|
||||
Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data)
|
||||
Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
|
||||
uint8_t *data)
|
||||
{
|
||||
Addr func_start = getAddr();
|
||||
Addr func_end = getAddr() + getSize() - 1;
|
||||
Addr val_start = addr;
|
||||
Addr val_end = val_start + size - 1;
|
||||
|
||||
if (func_start > val_end || val_start > func_end) {
|
||||
if (is_secure != _isSecure || func_start > val_end ||
|
||||
val_start > func_end) {
|
||||
// no intersection
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,6 +286,9 @@ class Packet : public Printable
|
||||
/// physical, depending on the system configuration.
|
||||
Addr addr;
|
||||
|
||||
/// True if the request targets the secure memory space.
|
||||
bool _isSecure;
|
||||
|
||||
/// The size of the request or transfer.
|
||||
unsigned size;
|
||||
|
||||
@@ -562,6 +565,12 @@ class Packet : public Printable
|
||||
unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; }
|
||||
Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
|
||||
|
||||
bool isSecure() const
|
||||
{
|
||||
assert(flags.isSet(VALID_ADDR));
|
||||
return _isSecure;
|
||||
}
|
||||
|
||||
/**
|
||||
* It has been determined that the SC packet should successfully update
|
||||
* memory. Therefore, convert this SC packet to a normal write.
|
||||
@@ -601,6 +610,7 @@ class Packet : public Printable
|
||||
if (req->hasPaddr()) {
|
||||
addr = req->getPaddr();
|
||||
flags.set(VALID_ADDR);
|
||||
_isSecure = req->isSecure();
|
||||
}
|
||||
if (req->hasSize()) {
|
||||
size = req->getSize();
|
||||
@@ -623,6 +633,7 @@ class Packet : public Printable
|
||||
if (req->hasPaddr()) {
|
||||
addr = req->getPaddr() & ~(_blkSize - 1);
|
||||
flags.set(VALID_ADDR);
|
||||
_isSecure = req->isSecure();
|
||||
}
|
||||
size = _blkSize;
|
||||
flags.set(VALID_SIZE);
|
||||
@@ -638,7 +649,8 @@ class Packet : public Printable
|
||||
Packet(Packet *pkt, bool clearFlags = false)
|
||||
: cmd(pkt->cmd), req(pkt->req),
|
||||
data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
|
||||
addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest),
|
||||
addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
|
||||
src(pkt->src), dest(pkt->dest),
|
||||
bytesValidStart(pkt->bytesValidStart),
|
||||
bytesValidEnd(pkt->bytesValidEnd),
|
||||
busFirstWordDelay(pkt->busFirstWordDelay),
|
||||
@@ -679,6 +691,7 @@ class Packet : public Printable
|
||||
assert(req->hasPaddr());
|
||||
flags = 0;
|
||||
addr = req->getPaddr();
|
||||
_isSecure = req->isSecure();
|
||||
size = req->getSize();
|
||||
|
||||
src = InvalidPortID;
|
||||
@@ -887,7 +900,8 @@ class Packet : public Printable
|
||||
* value. If the functional request is a write, it may update the
|
||||
* memory value.
|
||||
*/
|
||||
bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
|
||||
bool checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
|
||||
uint8_t *data);
|
||||
|
||||
/**
|
||||
* Check a functional request against a memory value stored in
|
||||
@@ -897,8 +911,8 @@ class Packet : public Printable
|
||||
checkFunctional(PacketPtr other)
|
||||
{
|
||||
uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
|
||||
return checkFunctional(other, other->getAddr(), other->getSize(),
|
||||
data);
|
||||
return checkFunctional(other, other->getAddr(), other->isSecure(),
|
||||
other->getSize(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,6 +140,9 @@ class Request
|
||||
* valid together with MMAPPED_IPR) */
|
||||
static const FlagsType GENERIC_IPR = 0x08000000;
|
||||
|
||||
/** The request targets the secure memory space. */
|
||||
static const FlagsType SECURE = 0x10000000;
|
||||
|
||||
/** These flags are *not* cleared when a Request object is reused
|
||||
(assigned a new address). */
|
||||
static const FlagsType STICKY_FLAGS = INST_FETCH;
|
||||
@@ -612,6 +615,7 @@ class Request
|
||||
bool isCondSwap() const { return _flags.isSet(MEM_SWAP_COND); }
|
||||
bool isMmappedIpr() const { return _flags.isSet(MMAPPED_IPR); }
|
||||
bool isClearLL() const { return _flags.isSet(CLEAR_LL); }
|
||||
bool isSecure() const { return _flags.isSet(SECURE); }
|
||||
};
|
||||
|
||||
#endif // __MEM_REQUEST_HH__
|
||||
|
||||
Reference in New Issue
Block a user