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:
Minje Jun
2024-01-31 17:48:29 +09:00
committed by Minje Jun
parent 1b5d92ee9c
commit 628be390a0

View File

@@ -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;