mem-ruby: Fix ReadShared hit handling on UD line
In case ReadShared hit on a UD line and there's no sharers, this chage makes the downstream respond with Unique even though it doesn't deallocate the line. This will make the requestor to UD and the downstream to UD_RU. In the previous implementation, loosely exclusive intermediate cache can cause loss of dirty data. Example sequence is as below. Configurations L2 cache: Roughly inclusive to L1 without back-invalidation - dealloc_on_* = false - dealloc_backinv_* = false L3 cache: Roughly exclusive to L2 without back-invalidation - alloc_on_readshared = tue - alloc_on_readunique = false - dealloc_on_shared = false - dealloc_on_unique = true - dealloc_backinv_* = false - is_HN = false LLC: Same clusivity as L3 except is_HN = true For all caches, allow_SD = true and fwd_unique_on_readshared = false Example problem sequence: 1. L1 sends ReadUnique then becomes UD. L2 is UC_RU. L3 and LLC are RU. 2. L1 evicts the line to L2 by WriteBackFull (UD_PD). L2 becomes UD. 3. L2 evicts the line to L3 using WriteBackFull (UD_PD). L3 becomes UD. 4. L1 reads the line with ReadShared which misses on L2. 5. L2 reads the line with ReadShared which hits on L3. L3 becomes UD_RSC because it doesn't deallocate the line (dataToBeInvalid=false) 6. L3 evicts the line to LLC by WriteCleanFull (UD_PD) because L3 doesn't back-invalidate and still has sharer. The local cache line is invalidated by Deallocate_CacheBlock. L3 becomes RUSC and LLC becomes UD_RU. 7. When UD_RU is evicted at LLC, the UD_RU line is dropped expecting the upstream to writeback, causing loss of dirty data. Change-Id: Ic9bee27f2ec8906dd5df8bd3be60e5a9a76c782f
This commit is contained in:
@@ -2600,11 +2600,18 @@ action(Send_CompData, desc="") {
|
||||
bool is_rd_nsd := tbe.reqType == CHIRequestType:ReadNotSharedDirty;
|
||||
bool is_rd_unique := tbe.reqType == CHIRequestType:ReadUnique;
|
||||
|
||||
// if the config allows (or not caching the data) and line has no sharers
|
||||
bool snd_unique_on_rs := (fwd_unique_on_readshared || tbe.dataToBeInvalid)
|
||||
// if the request type allows SD
|
||||
bool snd_dirty_on_rs := is_rd_shared && !is_rd_nsd;
|
||||
|
||||
// Send UC/UD on ReadShared or ReadNotSharedDirty if the line has no sharers
|
||||
// and one of the followings are met
|
||||
// 1) the config allows or
|
||||
// 2) local cache won't have the line or
|
||||
// 3) dirty will be passed
|
||||
bool snd_unique_on_rs := (fwd_unique_on_readshared ||
|
||||
tbe.dataToBeInvalid ||
|
||||
snd_dirty_on_rs)
|
||||
&& tbe.dataUnique && tbe.dir_sharers.isEmpty();
|
||||
// if the request type allows and we won't be caching the data
|
||||
bool snd_dirty_on_rs := is_rd_shared && !is_rd_nsd && tbe.dataToBeInvalid;
|
||||
|
||||
if (is_rd_once) {
|
||||
tbe.snd_msgType := CHIDataType:CompData_I;
|
||||
|
||||
Reference in New Issue
Block a user