Linux 内核修复办法:内核页表隔离KPTl(kernel page table isolation)
-
每个进程一张页表变成两张:运行在内核态和运行在用户态时分别使用各自分离的页表
-
Kernel页表包含了进程用户空间地址的映射和Kernel使用的内存映射
-
用户页表仅仅包含了用户空间的内存映射以及内核跳板的内存映射
-
当进程运行在用户空间时,使用的是用户页表
-
当发生中断或者是异常时,需要陷入到内核,进入内核空间后,有一小段内核跳板将页表切换到内核页表
-
KPTI最早是运用在x86上
-
KPTI补丁已经合并到Linux 4.15-rc4上
x86上的KPTI补丁主要工作:
- 内核页表和用户态页表的分离和切换
- 进程切换的优化:
- 因为内核态的页表包含了所有地址空间的页表,所以可以安全的访问到用户态页表
- 进程中用户态到内核态之间的切换,需要切换CR3寄存器
- 采用per-cpu的PCID来优化
ARM上的KPTI
- ARM64 只有Cortex-A75中招Meltdown漏洞
ARM64上早已经采用了双页表的设计,但是。 - ARM64上KPTI 的优化:
- A75上虽然有两个页表寄存器,但是TLB上依然没法做到完全隔离,用户进程在meltdown情况下依然有可能访问内核空间映射的TLB entry
- -个给当进程跑在内核态的使用,另外一个给进程跑在用户态每个进程上的ASID设置两份时使用。这样原本内核空间属于global TLB,就变成Process-Specific类型的TLB。
- ARM64上TLB示意图
ASID的简介
- 进程切换需要flush TLB,导致性能下降
- TLB优化:(ASID)Address Space ID
- Gobal类型的TLB:内核空间是所有进程共享的空间,因此这部分空间的虚拟地址到物理地址的翻译是不会变化的,可以理解为Global的。
- Process-specific类型的TLB:用户地址空间是每个进程独立的地址空间。prev进程切换到next进程时,TLB中缓存的prev进程的相关数据对于next进程是无用的,因此可以冲刷掉,这就是所谓的process-specific的TLB。
ASID 优化
KPTI之前:
KPTI之后:
标签:用户,TLB,熔断,页表,KPTI,Meltdown,进程,内核 From: https://www.cnblogs.com/linhaostudy/p/18240520