VMM 需要识别 guest 内存的工作集
热页留在内存,冷页回收或下沉到分层、远端存储
userfaultfd 的写保护(uffd-wp)能跟踪写访问
但读访问完全不可见
工作集识别缺了一半
以读为主的热页,VMM 根本不知道它被碰过
看不见读,就分不清冷热
VMM 识别 guest 内存工作集
冷页下沉,热页留住
uffd-wp 只能跟踪写
读访问对 VMM 不可见
以读为主的热页被误判为冷页
下一步可能被下沉
只看写,等于只看了半个工作集
以读为主的热页被误判为冷页
可能被错误下沉
同步 fault 处理要阻塞 faulting 线程
每次碰页都停一次,等 VMM 解决
纯扫描场景下,这个代价过高
只想知道哪些页被碰过,却要停线程等 VMM
扫描要的是「碰过没有」,不是「当面拦下」
给 userfaultfd 增加 RWP(读写保护)跟踪
把 guest 内存的 PTE 设成 PAGE_NONE 并打上 uffd 位,读与写都会触发 fault
UFFDIO_RWPROTECT 把 PTE 设成 PAGE_NONE
并打上 uffd 位
读写都触发 fault
按 PTE、PMD、hugetlb 分级投递消息
async 模式内核就地恢复
VMM 事后用 PAGEMAP_SCAN 重建访问情况
UFFDIO_REGISTER_MODE_RWP
注册区间
把 VMA 挂进 RWP 模式
UFFDIO_RWPROTECT
安装或解除
在区间上开或关 RWP
UFFDIO_SET_MODE
运行时切换
同步与异步之间
RWP 与 WP 不能同挂一个区间
二者共用同一个 PTE 标记位,同挂就会互相踩踏
重复注册时若已有模式带 per-PTE 标记,返回 -EBUSY
免得标记悬空
PTE 级:do_uffd_rwp()
PMD 级:do_huge_pmd_uffd_rwp()
hugetlb 级:hugetlb_handle_userfault()
都向 VMM 送 UFFD_PAGEFAULT_FLAG_RWP 消息
VMM 侧只需要认这个 flag
uffd 位同时充当身份标记
把 RWP fault 与 mprotect(PROT_NONE)、NUMA hinting fault 区分开
同步模式
faulting 线程阻塞到 VMM 解决为止
异步模式 UFFD_FEATURE_RWP_ASYNC
内核就地恢复访问,线程不再停顿
VMM 事后用 PAGEMAP_SCAN 重建访问情况
uffd 位还在的页,就是上个周期没被再访问的
异步恢复时对可写私有匿名 PTE 顺手 pte_mkwrite() 升级,免得再吃 COW fault
UFFDIO_SET_MODE 免重新注册即可切换
扫描期用异步,驱逐期切同步拦截 fault
mm 侧的铺垫
protnone helper 与 CONFIG_NUMA_BALANCING 解耦
uffd-wp 的 PTE accessor 改名,归 uffd 公用
change_protection() 增加 MM_CP_UFFD_RWP
让 RWP 标记活下来
PTE 重写时保留 RWP 标记
khugepaged、rmap 与 GUP 识别 VM_UFFD_RWP
标记留得住,跟踪才连得上
工作集识别覆盖完整
读与写都可跟踪
冷页下沉不再误伤只读热页
两种模式各司其职
异步:扫描期零阻塞
同步:驱逐期精确拦截
RWP 与既有 WP、NUMA hinting 路径严格区分
互不误判:uffd 位就是身份标记
作者未提供性能数据,以上为代码逻辑推断的预期收益
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x