TLB一致性维护
TLB 是页表项的物理 cache,用于加速虚拟地址到物理地址的转换。CPU 在访问一个虚拟地址时,首先会在 TLB 中查找,如果找不到对应的表项,那么就称之为 TLB miss,此时就需要去内存里查询页表,如果页表项是合法的,那么就会把它添加到 TLB 中。如果内核修改了页表,那么就需要主动的去清空一下当前的 TLB。
在 ARM64 上,清空 TLB 的指令是 TLBI,在 Linux 中,与 TLB 清空相关的宏都在 arch/arm64/include/asm/tlbflush.h 文件中定义。清空 TLB 的一般流程在文件开头的注视里有说明:
* DSB ISHST // Ensure prior page-table updates have completed
* TLBI ... // Invalidate the TLB
* DSB ISH // Ensure the TLB invalidation has completed
* if (invalidated kernel mappings)
* ISB // Discard any instructions fetched from the old mapping
在 TLBI 指令执行前后需要几个内存屏障指令的辅助,来防止在 TLB 清空过程中发生的不确定情况。主要的几个宏如下所示:
| 名称 | 说明 |
|---|---|
| flush_tlb_all() | 内核+用户空间的地址在所有的CPU上都清空 |
| flush_tlb_mm(mm) | 把用户空间的地址在所有的CPU上都清空 |
| flush_tlb_range(vma, start, end) | 用户空间的一段范围地址清空 |
| flush_tlb_kernel_range(start, end) | 内核空间的一段范围地址清空 |
| flush_tlb_page(vma, adds) | 用户空间的一个 page 地址映射清空 |
flush_tlb_kernel_range使用
以flush_tlb_kernel_range 为例:
flush_tlb_kernel_range 是 Linux 内核中的一个函数,用于使一段范围内的翻译后备缓冲区 (TLB) 条目失效。TLB 是一个缓存,用于存储最近的从虚拟内存地址到物理内存地址的转换,这有助于加快使用虚拟内存系统的内存访问速度。
主要作用:
- 使 TLB 条目失效:
flush_tlb_kernel_range的主要作用是确保指定范围内的 TLB 中任何过时或无效的条目都被移除。当内核修改页表(例如在内存管理操作中)时,需要将这些变化反映到 TLB 中。
使用场景:
- 内核内存管理:该函数特别用于内核内存管理的上下文中。当内核在自己的地址空间(内核虚拟内存)中更改映射时,必须确保 TLB 不包含指向旧映射的陈旧条目。
使用方法:
- 参数:该函数通常接受两个参数,指定要刷新的地址范围的开始和结束。
start:要刷新的范围的起始虚拟地址。end:要刷新的范围的结束虚拟地址。
操作方式:
- 与架构相关:
flush_tlb_kernel_range的实现与具体的 CPU 架构相关,因为不同的 CPU 架构(例如 x86,ARM)的 TLB 结构和操作方式不同。 - 使 TLB 条目失效:该函数使用特定的 CPU 指令使对应地址范围的 TLB 条目失效。
示例使用场景:
当内核更新其页表时,例如重新映射内核内存、添加新页面或更改访问权限时,需要使受影响的 TLB 条目失效,以确保 CPU 不会使用过时的转换。如果不这样做,可能会导致内存访问错误,带来潜在的安全风险或系统不稳定性。
代码示例:
一个函数原型的示例可能如下所示(实际实现细节因架构而异):
void flush_tlb_kernel_range(unsigned long start, unsigned long end);
总结:
总之,flush_tlb_kernel_range 是维护 TLB 一致性的重要函数,用于内核内存管理的上下文中。它确保内核页表中的变化准确反映到 TLB 中,从而防止陈旧条目导致错误的内存访问。
flush_tlb_kernel_range 实现
flush_tlb_kernel_range 的实现是与具体的 CPU 架构密切相关的。不同的架构有不同的 TLB 管理方式,因此该函数的实现方式也会有所不同。下面我们以 x86 架构为例,简单介绍一下 flush_tlb_kernel_range 的可能实现方式。
x86 架构实现示例
在 x86 架构上,TLB 刷新可以通过重新加载控制寄存器 CR3 来实现,这会导致整个 TLB 被刷新。对于特定范围的 TLB 刷新,可以使用页表条目无效(INVLPG)指令。
示例代码:
以下是一个可能的 flush_tlb_kernel_range 实现,针对 x86 架构:
#include <linux/mm.h>
#include <linux/smp.h>
#include <asm/tlbflush.h>
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
unsigned long addr;
// 对于每个地址,使用INVLPG指令
for (addr = start; addr < end; addr += PAGE_SIZE) {
__flush_tlb_one(addr);
}
// 同时在多处理器系统上处理
smp_mb();
smp_call_function(flush_tlb_mm_range, ¤t->mm, 1);
}
解释:
循环刷新每个页:
- 使用
INVLPG指令刷新指定范围内的每个页。 __flush_tlb_one(addr)是一个内联汇编函数,使用INVLPG指令刷新指定的地址。
- 使用
处理多处理器系统:
smp_mb()确保内存屏障,确保前面的 TLB 刷新操作在后续操作之前完成。smp_call_function(flush_tlb_mm_range, ¤t->mm, 1)在多处理器系统上调用,以确保所有 CPU 都执行 TLB 刷新操作。
通用实现框架
对于不同的架构,具体实现方式会有所不同,但总体的实现框架大致如下:
- 识别要刷新的地址范围:确定起始地址和结束地址。
- 使用架构特定的指令:使用特定的指令来刷新对应的 TLB 条目。
- 考虑多核处理器的同步:在多处理器系统上同步 TLB 刷新操作,以确保所有 CPU 的 TLB 都被刷新。
参考资料
可以参考 Linux 内核源代码中的实际实现。例如,可以查看 arch/x86/include/asm/tlbflush.h 文件中的实现细节。不同架构的实现可以在相应的架构目录中找到。
总结
flush_tlb_kernel_range 的具体实现依赖于 CPU 架构,x86 架构通常通过 INVLPG 指令和 CR3 寄存器重新加载来实现 TLB 刷新。上述示例展示了一个基本实现,具体实现应参考 Linux 内核源码,并根据具体需求和架构进行调整。
TLB一致性维护的更多相关文章
- ARM Linux 内核 panic 之cache 一致性 ——Cortex-A9多核cache和TLB一致性广播
ARM Linux 内核 panic 之cache 一致性 ——Cortex-A9多核cache和TLB一致性广播 Cortex-A9的多喝CPU可以接收和执行一致性广播操作,当其使能并处于SMP模式 ...
- Improving cache consistency redis和db的一致性维护
From http://simongui.github.io/2016/12/02/improving-cache-consistency.html A typically web applicat ...
- Linux X86在下面TLB机制
TLB - translation lookaside buffer 快表.直译为翻译后备缓冲器,也能够理解为页表缓冲.地址变换快速缓存. 因为页表存放在主存中,因此程序每次訪存至少须要两次:一次訪存 ...
- Linux 中的零拷贝技术,第 2 部分
技术实现 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.第一部分主要介绍了一些零拷贝技术的相关背景知识,简要概 ...
- [转帖]Linux 中的零拷贝技术,第 2 部分
Linux 中的零拷贝技术,第 2 部分 https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy2/index.html Linux 中 ...
- DDD实践问题之 - 关于论坛的帖子回复统计信息的更新的思考
之前,在用ENode开发forum案例时,遇到了关于如何实现论坛帖子的回复的统计信息如何更新的问题.后来找到了自己认为比较合理的解决方案,分享给大家.也希望能和大家交流,擦出更多的火花. 论坛核心领域 ...
- 基于redis分布式缓存实现(新浪微博案例)
第一:Redis 是什么? Redis是基于内存.可持久化的日志型.Key-Value数据库 高性能存储系统,并提供多种语言的API. 第二:出现背景 数据结构(Data Structure)需求越来 ...
- Zookeeper(一)从抽屉算法到Quorum (NRW)算法
一.抽屉算法 抽屉算法,又名鸽巢原理,它是德国数学家狄利克雷首先明确的提出来并用以证明一些数论中的问题,因此,也称为狄利克雷原则.它是组合数学中一个重要的原理. 具体算法讲的是: 第一抽屉算法: 如果 ...
- MST 001
一.String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的? 答: 1.String是字符串常量,StringBuffer和StringB ...
- RDD:基于内存的集群计算容错抽象(转)
原文:http://shiyanjun.cn/archives/744.html 该论文来自Berkeley实验室,英文标题为:Resilient Distributed Datasets: A Fa ...
随机推荐
- 【Vue】动态方法调用
JS的动态方法调用是通过eval函数实现 但是在Vue中是通过组件的$options.methods实现, 写这篇的随笔的原因是因为今天为了封装面包屑组件,花了一下午折腾这个动态方法调用 调用DEMO ...
- 【Mybatis】09 日志工厂配置 & Log4J
什么是日志 Log? 系统日志是记录系统中硬件.软件和系统问题的信息,同时还可以监视系统中发生的事件. 用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹. 系统日志包括系统日志. ...
- 乌克兰学者的学术图谱case3
============================================ 背景: 弗兰采维奇材料问题研究是欧洲最大的材料科研院所,在核电.航空.航天.军工及其他装备制造领域的先进材料研 ...
- Linux共享内存通信的C语言Demo代码
重点注明: 本文代码来源于: https://blog.csdn.net/github_38294679/article/details/122360026 ===================== ...
- 代码随想录Day7
454.四数相加Ⅱ 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, j, k ...
- 讲师招募 | Apache DolphinScheduler Meetup诚邀您共建开源!
随着Apache DolphinScheduler在全球范围内的快速发展,我们的用户群体和社区活动也在不断扩大. 为了进一步丰富我们的社区内容,分享更多有价值的知识和经验,我们诚挚地邀请您加入我们,成 ...
- 基于 token 的登陆系统的实现
这是一段防爬代码块,我不介意文章被爬取,但请注明出处 console.log("作者主页:https://www.cnblogs.com/Go-Solo"); console.lo ...
- Camera | 7.瑞芯微rk3568平台摄像头控制器MIPI-CSI驱动架构梳理
因为有拍照.录制视频.直播等刚需,现在手机的摄像头基本都是高清,支持高清摄像头的SoC都支持MIPI-CSI. 不同SoC的MIPI-CSI在实现上有一定差别,即使同一厂家设计生产的芯片也都不尽相同. ...
- Docker简单使用总结
写在前面 最近在部署前后端分离的SpringBoot项目,发现使用Docker技术很方便,特此记录一下Docker常用命令 1.常用网站 Docker docs :https://docs.docke ...
- Java微信授权登录小程序接口
1.微信授权登录小程序的流程是什么 微信授权登录小程序的流程是一个涉及前端和后端交互的过程,主要目的是让用户能够使用微信账号快速登录小程序,避免重复输入用户名和密码.以下是该流程的详细步骤: 1.1前 ...