summaryrefslogtreecommitdiff
path: root/src/mem/cache/cache_impl.hh
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:47 -0500
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:47 -0500
commit964aa49d1523787c06491453a85fad511b0a5883 (patch)
treef98a023bc20227f0a06d909df5f42053dd9218f1 /src/mem/cache/cache_impl.hh
parent1814a85a055732baf98fd030441bb4c5c5db9bdc (diff)
downloadgem5-964aa49d1523787c06491453a85fad511b0a5883.tar.xz
mem: Fix guest corruption when caches handle uncacheable accesses
When the classic gem5 cache sees an uncacheable memory access, it used to ignore it or silently drop the cache line in case of a write. Normally, there shouldn't be any data in the cache belonging to an uncacheable address range. However, since some architecture models don't implement cache maintenance instructions, there might be some dirty data in the cache that is discarded when this happens. The reason it has mostly worked before is because such cache lines were most likely evicted by normal memory activity before a TLB flush was requested by the OS. Previously, the cache model would invalidate cache lines when they were accessed by an uncacheable write. This changeset alters this behavior so all uncacheable memory accesses cause a cache flush with an associated writeback if necessary. This is implemented by reusing the cache flushing machinery used when draining the cache, which implies that writebacks are performed using functional accesses.
Diffstat (limited to 'src/mem/cache/cache_impl.hh')
-rw-r--r--src/mem/cache/cache_impl.hh40
1 files changed, 21 insertions, 19 deletions
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index fc01e2c06..a1d945103 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -279,16 +279,7 @@ Cache<TagStore>::access(PacketPtr pkt, BlkType *&blk,
Cycles &lat, PacketList &writebacks)
{
if (pkt->req->isUncacheable()) {
- if (pkt->req->isClearLL()) {
- tags->clearLocks();
- } else if (pkt->isWrite()) {
- blk = tags->findBlock(pkt->getAddr());
- if (blk != NULL) {
- tags->invalidate(blk);
- blk->invalidate();
- }
- }
-
+ uncacheableFlush(pkt);
blk = NULL;
lat = hitLatency;
return false;
@@ -444,15 +435,7 @@ Cache<TagStore>::timingAccess(PacketPtr pkt)
}
if (pkt->req->isUncacheable()) {
- if (pkt->req->isClearLL()) {
- tags->clearLocks();
- } else if (pkt->isWrite()) {
- BlkType *blk = tags->findBlock(pkt->getAddr());
- if (blk != NULL) {
- tags->invalidate(blk);
- blk->invalidate();
- }
- }
+ uncacheableFlush(pkt);
// writes go in write buffer, reads use MSHR
if (pkt->isWrite() && !pkt->isRead()) {
@@ -1104,6 +1087,25 @@ Cache<TagStore>::invalidateVisitor(BlkType &blk)
}
template<class TagStore>
+void
+Cache<TagStore>::uncacheableFlush(PacketPtr pkt)
+{
+ DPRINTF(Cache, "%s%s %x uncacheable\n", pkt->cmdString(),
+ pkt->req->isInstFetch() ? " (ifetch)" : "",
+ pkt->getAddr());
+
+ if (pkt->req->isClearLL())
+ tags->clearLocks();
+
+ BlkType *blk(tags->findBlock(pkt->getAddr()));
+ if (blk) {
+ writebackVisitor(*blk);
+ invalidateVisitor(*blk);
+ }
+}
+
+
+template<class TagStore>
typename Cache<TagStore>::BlkType*
Cache<TagStore>::allocateBlock(Addr addr, PacketList &writebacks)
{