Linux Mem -- MTE in AArch64 Linux
目录
1 介绍
2 用户空间支持
3 PROT_MTE内存属性
4 Tag Check Faults
5 排除IRG、ADDG和SUBG等指令产生的tag
6 每个CPU建议的tag check mode
7 初始进程状态
近期在深入了解AArch64 Linux MTE机制,本文是个人对于Linux org学习。原文来自 Memory Tagging Extension (MTE) in AArch64 Linux — The Linux Kernel documentation
1 介绍
ARMv8.5 版本的处理器介绍了MTE(memory tagging Extensio)特性。MTE是基于ARMv8.0的虚拟地址标签(TBI:top byte ignore)特性 ,允许软件访问4-bit的allocation tag 为16字节粒度物理空间。具有MTE特性的内存空间映射需要带Normal-Tagged内存属性。逻辑tag被应用于虚拟地址的59-56bit。使能MTE的处理器将比较logical tag 和 allocation tag,如果比较失败则根据系统寄存器配置上报响应异常。
2 用户空间支持
CONFIG_ARM64_MTE使能且硬件支持MTE,内核会通过HWCAP2_MTE向用户空间宣导支持MTE功能。
3 PROT_MTE内存属性
为了访问allocation tag,用户进程必须为使用tagged内存属性为其地址空间。
PROT-MTE --- 允许访问Page的MTE allocation tags
当这些page 首次映射到用户空间且保留 copy-on-write时,其对应的alloation tag被设置为0。支持MAP_SHARED 并且allocation tag 可以在多个进程间共享。
Note:a. PROT_MTE 仅仅支持匿名映射(MAP_ANONYMOS) 、基于Ram的文件映射(tmpfs、memfd)。传递该属性给其他的映射类型间返回 -EINVAL。
b. PROT_MTE不能够通过mprotect清除
c. 具有MADV_DONTNEED 和 MADV_FREE属性的通过madvise()获取的内存可以清除allocation tags。
4 Tag Check Faults
访问具有PROT_MTE属性的内存区域,当其logical tag 和allocation tag不匹配时,会有三种可配置的行为生发:
a.忽略 -- 默认配置,CPU将会略 tag check fault。
b. synchronous -- 内核将同步上报SIGSEGV, si_code = SEGV_MTESERR 和 si_addr = <fault-address>,该次系统访问不能执行。 如果SIGSEGV被违规进程忽略或者阻塞,对应的进程将执行coredump。
c. Asynchronous -- 在进程违规发生时,内核异步的发出SIGSEGV带有si_code= SEGV_MTEAERR, si_addr = 0的信号。
用户可以通过prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)系统调用为每个进程选择不同的行为。PR_MTE_TCF_MASK位域,对应的flags值如下:
PR_MTE_TCF_NONE <--> ignore tag check faults
PR_MTE_TCF_SYNC <--> synchronous tag check fault mode
PR_MTE_TCF_ASYNC <--> asynchronous tag check fault mode
如果没有模式指定,tag check fault将被忽略。如果一个模式被设置,tag check falut发生时则按照该改定模式运行。如果多中模式被设置,那种模式被选择需要看随后的“Per-CPU选择 tag 检测模式“。可以通过prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)系统函数获取当前的tag 检测模式。可以通过MSR TCO, #1指令设置PSTATE.TCO状态位关闭用户进程的tag check功能。
注意:a.不用考虑中断上下文,当PSTATE.TCO=0时信号处理程序总是被执行。TCO状态在sigreturn()过程恢复。
b.不可能匹配所有的逻辑tag为用户应用 ??
c.如果用户线程标记检查模式为PR_MTE_TCF_NONE或PR_MTE_TCF_ASYNC,则不检查内核访问用户地址空间。(例如,读取()系统调用)。如果标记检查模式为PR_MTE_TCF_SYNC,内核会尽最大努力检查其访问的用户地址,但它不能总是保证它。内核访问用户空间总视PSTATE.TCO值为零,无论用户配置如何。
5 排除IRG、ADDG和SUBG等指令产生的tag
架构允许通过设置GCR_EL1.Exclude寄存器位域来排除某些随机产生的tag。默认情况,Linux排除所有的非零tag。用户进程可以通过prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)系统函数指定特定的tag值,flag中包含了以PR_MTE_TAG_MASK为掩码的tag位域。
注意:GCR_EL1寄存器提供的排除tag的掩码,而prctl函数提供的是包含tag的掩码。
6 每个CPU建议的tag check mode
一些CPU在MTE严格tag check 模式下的性能和非严格tag check检模式下的性能是相似的,当非严格检测模式请求时这些CPU可以使用为严格tag check模式,这样即利于错误检测又没有太多性能下降。为了支持这种情况,特权用户可以将严格检测模式做为CPU的首选检测模式。
每个CPU的首选检测模式可以过/sys/devices/system/cpu/cpu<N>/mte_tcf_preferred控制,特权用户可以向该路径写入async 或者sync值。默认每个CPU的首选模式为async。
为了允许程序可能在CPU的首选标记检查模式下运行,用户程序可以设置多个tag check fault模式到prctl()的flag参数。如果CPU的首选模式是要设置的tag check模式的task检测子集,CPU的首先模式可能被选择。否则,将设置为task要设置的任一模式。
7 初始进程状态
execve()执行时,新进程将有如下配置:
a. PR_TAGGED_ADDR_ENABLE设置为0,即diable tag
b.Tag check fault被忽略
c.PSTATE.TC0设置为0 ,即disable tag check
d.初始映射的内存没有PROT_MTE属性
在fork()上,新进程继承父进程的配置和内存映射属性。除了使用MADV_WIPEONFORK的monust()范围,它将清除数据和标记。