目录
4.2 Permitted initial MTE tag states
1. Introduction
内存标签扩展(MTE:Memory Tagging Extension)是一种用于检查内存中数据的正确使用情况的机制。当内存位置分配给特定用途时,还可以为其分配一个存储器标签。
此内存标签与内存中的数据一起保存,称为“分配标签”。以后访问内存位置时,请求者使用位置的地址和它认为与位置相关联的标签值。
此标签称为物理地址标签(Physical Address Tag)或物理标签(Physical Tag)。
对于启用标签检查的任何访问,将根据分配标签检查物理标签。访问始终按正常进行,标签检查结果决定是否发出错误条件信号。
此机制可确保内存访问用于其预期目的,而不是错误或恶意访问。它可以在运行时用于识别许多常见的编程存储器错误,例如缓冲区溢出和use-after-free。
注:计算机安全领域中的"use-after-free"漏洞是一种常见的内存安全问题,指的是在释放(free)了某块内存后,程序继续使用了已释放的内存区域,可能导致严重的安全问题。漏洞发生的主要原因之一是内存管理不当。
存储器标签包括与内存中的每个16字节对齐数据相关联的4-bit标签。
支持以下行为:
- 只在请求Normal WriteBack内存时允许内存标记。
- Read transactions请求中有一个指示(TagOp),确定是否必须与数据一起返回分配标签值。
- 由请求者执行根据分配标签检查返回的物理标签。举个例子,如果缓存保存数据值但不保存分配标签值,则Read事务必须执行同时返回数据data和标签tag,返回的数据不要求有效。
- 需要提取标签的读取请求不得使用转发监听 Forwarding snoops。
- StashOnce transactions请求分配标签。分配标签预计会随着数据的存储而被积存。
- Write transactions有一个物理标签和必须根据分配标签检查的写数据一起提供。由Completer执行对分配标签进行检查物理标签。如果不匹配,则需要发出失败通知。
- Write transactions将分配标签更新为新值。这些写事务通常会同时更新数据。但是,允许没有字节使能置位,以便仅更新标签。
- Write transactions将Dirty或clean的cache line刷到下级cache line,无需更新或检查标签。这些写入事务始终包括数据,并指示分配标签值是否也随数据一起传递。
- 返回数据的Snoop transactions也可以返回关联的分配标签。如果标签是Dirty,则必须返回标签。如果标签为“Clean”,则返回标签是可选的。
- CMO缓存维护操作必须在数据和相应的内存标签上运行。
2. Message extensions
CHI消息定义的以下扩展用于支持Memory Tagging:
Tag |
提供4-bit标签集,每个标签都与16字节对齐的数据相关联。
|
TU |
Tag Update。指示必须更新哪些分配标签。
|
TagOp |
Tag Operation。指示要对相应DAT通道中存在的标签执行的操作。
|
TagOp的编码如下:
TagOp[1:0] |
Tag operation |
0b00 |
Invalid |
0b01 |
Transfer |
0b10 |
Update |
0b11 |
Match or Fetch |
3. Tag coherency
本节总结标签一致性特性。
缓存的分配标签保持和硬件一致。一致性机制与数据一致性相同。
适用的标签缓存状态为:Invalid, Clean,Dirty。Clean,Dirty的缓存行都是有效的。
数据缓存状态和标签缓存状态组合的约束如下:
- 仅当数据为有效时,标签才能有效。
- 数据有效时标签可能无效。
- 当高速缓存行处于“Unique”状态时,它同时适用于数据和标签。
- 当高速缓存行处于“Shared”状态时,它同时适用于数据和标签。
- 当带有Dirty标签的缓存行被逐出 evict时,则:
——数据和标签都必须被视为Dirty。
——必须将标签回写到内存中,或者通过HNF将Dirty数据传递给其他缓存[_PD] 。
- 从缓存中evict干净标签时,可以将其发送到其他缓存,也可以静默丢弃。
- 当脏数据和干净标签一起被evict时,干净标签可以和脏数据一起传递到下游PoC。
4. Read transaction rules
Read可以选择随同数据提取标签。
根据请求中的TagOp值确定是否需要随读取的数据返回标签。
4.1 TagOp values
当请求中的TagOp值为Transfer(0b01)时:
- 标签必须随数据一起返回。
- 返回的标签的状态必须是正在使用的请求所允许的适当缓存状态。
- 要返回的标签数量取决于返回的数据大小。对于所有snoopable requests,每次访问必须返回4个标签。(即,对应一个cacheline的大小)
- 当访问需要时,requester将物理标签与随读取数据一起接收的分配标签进行匹配。
当请求中的TagOp值为Fetch(0b11)时:
- 标签必须随数据一起返回。
- 返回的数据不要求有效。无论标签匹配结果如何,请求者都必须忽略接收到的数据。
- 必须返回与缓存行相对应的所有标签。
- 返回的标签的状态必须是“干净”或“脏”。
- 如果返回Dirty标签,则必须保留这些标签,除非更新并写入内存。
请求中的TagOp值为无效时:
- 允许(但不要求)随数据一起返回标签。
- 如果标签与数据一起返回,则它们必须是“干净”。
转换标签从Shared到Unique
如果数据和标签都存在于“共享”状态的请求者处,并且请求者要求将缓存行移动到“Unique”状态,则应使用TagOp值为“Transfer”的MakeReadUnique事务。
允许请求者使用TagOp值为“Transfer”的ReadUnique事务。
Data存在时获取标签
如果请求者拥有缓存行的缓存副本且数据有效但分配标签无效,并且请求者要求执行标签匹配,则请求者必须使用读取请求来获取所需标签。
读取请求的类型和请求中的TagOp值取决于:
- 由请求者执行的操作,即Load或Store操作。
- Store操作的大小。
- 目标内存位置。
在上述场景中,Requester必须使用:
- 如果是Load操作,使用ReadClean with Transfer。请求可以从任何初始数据状态发送。初始MTE标签状态是无效的,但允许为任何状态。
- 如果是Store操作,使用ReadUnique with Transfer。请求可以从任何初始数据状态发送。初始MTE标签状态无效,但允许为任何状态。不论是否存在MTE,ReadUnique都可以从任何初始数据状态发送。
- 如果目标内存位置为Non-snoopable,而且无论Tag匹配结果如何,Requester都保证写入完整的cacheline,则使用ReadNoSnp with Fetch。必须删除返回的数据。返回的数据不要求有效。必须返回干净标签。缓存行内的所有标签都必须是有效的。
如果目标内存位置为Snoopable,而且无论Tag匹配结果如何,Requester都保证写入完整的cacheline,则使用ReadUnique with Fetch。必须删除返回的数据。返回的数据不要求有效。必须返回干净或脏标签。缓存行内的所有标签都必须是有效的。
当响应ReadClean时,使用Snoop Filter来跟踪请求者缓存状态的Home,不能基于响应请求者的状态降低Snoop Filter中缓存行的状态。
注意:
在以前的版本中,I和UCE是ReadClean事务的唯一允许初始高速缓存行状态。
使用Snoop Filter跟踪缓存状态的Home被允许根据响应中的状态设置缓存行状态。
允许的响应和tag状态
必须适当处理使用分配标签接收的缓存行的数据和状态,以免破坏一致性。
当请求TagOp值为Transfer时,允许的响应字段值为:
- Transfer. 指示返回的标签为“干净”。
- Update.指示返回的标签是Dirty。数据响应必须pass Dirty [_PD]。
当请求TagOp值为Fetch时,允许的响应字段值为:
- Transfer. 指示返回的标签为“干净”。
- Update.指示返回的标签是Dirty。数据响应必须pass Dirty [_PD]。
当请求TagOp值为“无效”时,允许的响应字段值为:
- Invalid. 表示返回的标签无效。
- Transfer. 指示返回的标签为“干净”。
当Read data中的TagOp值无效时,TU必须为全零。Tag不适用,并且可以是任意值。
在读事务中单独返回数据和响应时,TagOp字段仅在Data-only消息中适用,在Non-data响应消息中不适用,必须设置为零。
必须保持标签的缓存状态与读取请求的类型一致:
- 对于TagOp值为 Invalid的所有Read requests,Invalid 或Clean的标签必须返回。
- 对于TagOp值为Transfer或Fetch的ReadNoSnp,必须返回Clean标签。
- 对于TagOp值为Transfer的ReadClean、Readonce、ReadOnce CleanInvalid和ReadOnce MakeInvalid,必须返回Clean标签。
- 对于TagOp值为Transfer的ReadNotSharedDirty,必须返回Clean或Dirty标签。仅当缓存行状态为“ Unique”时,才允许返回Dirty标签。
- 对于TagOp值为Transfer的ReadShared,必须返回 Clean 或Dirty标签。
- 对于TagOp值为Transfer或Fetch的ReadUnique,必须返回Clean或Dirty标签。返回的缓存行状态必须是Unique的。
- 对于TagOp值为Invalid的MakeReadUnique,Invalid 或 Clean的标签必须返回。只允许在响应数据时使用Clean标签。
- 对于TagOp值为Transfer的MakeReadUnique,如果响应中包含数据,则必须返回Clean或Dirty标记。
——Clean标签允许在带数据的响应以及不带数据的响应 (Comp_UC andComp_SC)中使用。
——只有当响应是[UD_PD],才允许使用Dirty标签。
- 在返回Dirty标签的情况下,返回的缓存行必须包含pass Dirty[UD_PD]。
当目标地址不支持MTE时,响应必须使用TagOp of Invalid。
对于独占访问序列,在执行独占store事务之前,必须避免使用使缓存行的其他副本无效的请求来获取tag。这通常是通过在执行独占Load事务的同时提取标记来实现的。
4.2 Permitted initial MTE tag states
下表展示了允许的初始数据状态以及不同Read事务的标记状态和相应请求中允许的TagOp值。
5. Write transactions
在Write事务的Request和Data消息之间分配不同的支持MTE的字段。
Request和WriteData消息中都包含TagOp字段,指示要对WriteData消息中的标记执行的操作。Request还包括Tag GroupID字段,用于为需要标记匹配操作的请求提供通过/失败响应的标识符。
注意:TagGroupID字段是实现时自定义的,通常可用于标识响应相关的异常级别和TTBR。
WriteData消息中的TagOp值通常与Request消息中的值相同,但监听写入数据或取消写入时除外。当Write Data和Write请求中的Tag Op值不同时,必须根据Write Data中的Tag Op值来决定是否执行Tag Match。
WriteData消息还包括每个标签的标签更新(TU)位,适用于Tag Op为Update的情况。
5.1 Permitted TagOp values
本节描述写入请求消息中每个允许的TagOp值的Write Data TagOp值。
当请求中的TagOp字段为Invalid时,WriteData中的Memory Tagging字段必须设置为0,并被Completer忽略。
当Request请求中的TagOp字段为Transfer时,WriteData中的TagOp字段可以是:
- Transfer:标签是干净的,必须由Completer适当处理。
- Invalid:只有当缓存副本无效或写入事务被取消时才有可能。
在请求TagOp为Transfer的Write clean事务中,写入数据中的TagOp不允许更改为Update。
当请求中的TagOp字段为Update时,WriteData中的TagOp字段可以是:
- Update:Dirty标签必须缓存或写入内存。
- Transfer:标签是干净的。当Dirty标签已经被侦听出来,就可能发生这种情况。
- Invalid:只有当缓存副本无效或写入事务被取消时才有可能。
当请求中的TagOp字段为Match时,WriteData中的TagOp字段可以是:
- Match:必须在Completer中执行相应的标记匹配。
- Invalid:只有当Write事务被取消时才有可能。
5.2 TagOp, TU, and tags relationship
本节介绍不同write事务中TagOp、TU和Tag之间的关系。
- 对于TagOp为Invalid的所有Write请求,必须将Memory Tagging字段设置为0,并被Completer忽略。
- 对于WriteBackFull和WriteCleanFull的 TagOp:
——Transfer:必须返回干净标签。TU位不适用,必须设置为0。
——Update:必须置位所有TU位。
——Match:不允许
- 对于WriteBackPtl的TagOp:
——Transfer:不允许
——Update:不允许
——Match:不允许
- 对于WriteNoSnpFull的TagOp:
——Transfer:TU位不适用,必须为0。允许干净的标签传输从RN到HN和HN到SN。
——Update:必须置位所有TU位。
——Match:TU位不适用,必须设置为0。
- 对于WriteNoSnpDef的TagOP:
——Transfer:不允许
——Update:不允许
——Match:不允许
- 对于WriteUniqueFull和WriteUniqueFull Stash的TagOP:
——Transfer:不允许
——Update:必须置位所有TU位
——Match:TU位不适用,必须设置为0
- 对于带TagOpp的WriteNoSnpPtl、WriteUniquePtl和WriteUniquePtl Stash,
——Transfer:不允许
——Update:TU和BE位的任何组合,包括无或所有,都可以置位
——Match:TU位不适用,必须设置为0。当所有BE位为零时,不能执行标记匹配。
- 对于WriteEvict Full、WriteEvict OrEvict的TagOp:
——Transfer:必须返回干净标签。TU位不适用,必须设置为0
——Update:不允许
——Match:不允许
- 对于WriteNoSnpZero和WriteUniqueZero,TagOp只能是Invalid。
对于TagOp为Match的Write请求,tag在size范围内可以取任何值。
在Write DataCancel WriteData响应中,无论Write请求中的TagOp值如何,MTE字段都不适用,必须设置为0。
在写数据时,如果TagOp无效,则所有TU位和所有Tag位必须设置为0。
6. Dataless transactions
MakeUnique是唯一支持使用TagOp字段的dataless事务。
其他dataless事务,TagOp字段不适用,必须设置为0。
MakeUnique请求中的TagOp值只能为Invalid或Update。
Update的Request TagOp值指示请求者将随数据一起更新标记。当Request TagOp值为Update或Home知道Snoopee没有Dirty标记时,才允许Home使用SnpMakeInvalid响应MakeUnique。
响应MakeUnique的唯一允许的TagOp值为Invalid。
CMO必须在数据和相应的内存标签上运行。
MakeInvalid允许丢弃Dirty数据而不写入内存,但必须将Dirty标签写入内存。
7. Atomic transactions
TagOp适用于原子事务。此字段的允许值为“Invalid”和“Match”。
AtomicLoad, AtomicStore, and AtomicSwap事务要匹配的物理标签在写入数据中提供,并与有效数据字节相对应。
这些原子事务中只适用一组标记位,因为最大数据大小为8字节。其余标记位不适用,必须设置为0。
在数据达16字节的AtomicCompare中,有效数据仍然只对应于一组标记位。
在数据达32字节的AtomicCompare中,CMP和SWAP数据各自只有16字节。当Tag Op设置为Match有效时,只需要匹配一组Physical Tag位。必须复制物理标签,以覆盖比较和交换数据。允许completer使用一组物理标记执行标记匹配。
对于Non-store Atomic transactions,CompData响应中允许的TagOp值Invalid 和 Transfer。
TagOp为Invalid的原子事务的写数据必须具有所有TU位和所有Tag位设为0。