description/memory: page cache readahead

This commit is contained in:
Cheng Jian
2022-01-26 18:58:26 +08:00
parent de0020907d
commit 7bb4bc447e
3 changed files with 90 additions and 30 deletions
+20 -2
View File
@@ -369,8 +369,14 @@ TLB entry shootdown 常常或多或少的带来一些性能问题.
[armv8/arm64 PAN 深入分析](https://cloud.tencent.com/developer/article/1413360)
[Arm64 架构安全 -- PAN](https://zhuanlan.zhihu.com/p/365701044)
[Learn the architecture: AArch64 memory model/Permissions attributes](https://developer.arm.com/documentation/102376/0100/Permissions-attributes)
### 2.5.1 ARMv8 页表权限控制
-------
一般控制一个内存的属性, 如 RWX 权限, 简单的想 3 个 bit 即可, 但是当前操作系统的设计 RWX 权限除了要表示内核的权限以外还要包括用户态的权限, 那么需要就需要 6 个 bit. 但是在 ARM v8 的设计中, 为了节省相应的页表设计 ARM 仅用了 4 个 bit.
| 控制位 | 描述 |
@@ -384,6 +390,15 @@ TLB entry shootdown 常常或多或少的带来一些性能问题.
这原本貌似也没什么问题, 但是后来安全研究人员发现, 由于内核态可以直接执行相应的用户态程序, 这样攻击者就可以在用户态准备好相应执行的代码, 如果内核里边有一个很小的漏洞, 比如 ROP, 攻击者通过 RetToUser Attrack 把相应的栈中的 ret 值修改为用户态准备好的地址, 那么就可以轻松做到任意代码执行.
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
| 2020/01/06 | James Morse <james.morse@arm.com> | [arm64: Revert support for execute-only user mappings](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=24cecc37746393432d994c0dbc251fb9ac7c5d72) | 实现 ARMv8.1-PAN, Privileged access never. | v1 ☑ 5.5-rc6 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=24cecc37746393432d994c0dbc251fb9ac7c5d72) |
### 2.5.2 ARMv8.1 引入 PAN 解决任意代码执行的漏洞
-------
为了解决这个问题, ARM v8.1 在修复这个问题的时候, 不得不在 pstate 中抠出来一个 bit 来设置 PAN(Privileged Access Never), 如果 PAN 为 1 的时候, 那么就限制在 EL1 里边不允许访问 EL0 的内存. 被称为 ARMv8.1-PAN, Privileged access never, 它的主要工作就是限制内核态不能访问用户态的数据. 如果启用了 CONFIG_ARM64_PAN, 内核试图访问用户空间的内存时, 则会报权限错误, 相反, [copy_from_user()](https://elixir.bootlin.com/linux/v4.3/source/arch/arm64/lib/copy_from_user.S#L34) 以及 [copy_to_user()](https://elixir.bootlin.com/linux/v4.3/source/arch/arm64/lib/copy_to_user.S#L35) 等接口中访问用户空间内存时必须清除 PAN 位(或使用 `ldt*/stt*` 指令), 在完成后则必须恢复.
[Arm Chips Vulnerable to PAN Bypass "We All Know its Broken"](https://techmonitor.ai/techonology/hardware/arm-pan-bypass)
@@ -396,14 +411,17 @@ TLB entry shootdown 常常或多或少的带来一些性能问题.
ARMv8.2-ATS1E1, AT S1E1R and AT S1E1W instruction variants, taking account of PSTATE.PAN
### 2.5.2 ARMv8.2 引入 UAO 解决任意代码执行的漏洞
-------
本来一切看起来貌似恢复平静了, 但是总有一些意外.
开启了 PAN 之后, 内核每次 copy_from_user/copy_to_user 需要访问用户态地址的时候, 不得不动态的禁用和使能 PAN. 于是, 在 ARM v8.2 又引入了 UAO(User Access Override). 与 LDR/STR 指令不同, UAO 提供了 LDTR/STTR 等非特权 load/store 指令, 不管在哪个 ELx 态(即使是 EL1 或 EL2) 运行, 它们都也会根据 EL0 权限检查进行检查. 并且不会被 PAN 阻止.
如果发现当前 CPU ARM64_HAS_UAO, 则会通过 alternative 机制将 [copy_from_user](https://elixir.bootlin.com/linux/v4.6/source/arch/arm64/lib/copy_from_user.S#L70) 以及 copy_to_user 等函数中访问用户态的指令[替换为 ldtr/sttr](https://elixir.bootlin.com/linux/v4.6/source/arch/arm64/include/asm/alternative.h#L148) 等. 而把[使能和禁用 PAN 的操作替换为 NOP](https://elixir.bootlin.com/linux/v4.6/source/arch/arm64/include/asm/uaccess.h#L75) 操作.
[Learn the architecture: AArch64 memory model/Permissions attributes](https://developer.arm.com/documentation/102376/0100/Permissions-attributes)
[UAO (User Access Override) as a mitigation against addr_limit overwrites](https://duasynt.com/blog/android-uao-kernel-expl-mitigation)
ARM v8.2 引入了 [UAO](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/armv8-a-architecture-evolution)
+55 -27
View File
@@ -2124,9 +2124,22 @@ swappiness 参数值可设置范围在 `0~100` 之间.
# 6 PageCache
-------
## 6.1 PAGE CACHE
-------
| 补丁 | 描述 |
|:---:|:---:|
| [Import 1.1.69](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/mm/filemap.c?id=ea8a68b948397fa9cd1c8a1a6b61a4dc4bc99ec5) | 引入 page cache |
| [Import 1.3.21](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/mm/filemap.c?id=13e539119b02e4af5daf6c55b31e6273c9a084a6) | 完善了 page cache 的功能 |
| [Import 1.3.50](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/mm/filemap.c?id=22accfc2b4fe4bc6a635c70c1a05a9a80abc81ea) | 引入了 shrink_mmap() 机制来释放 page cache 的空间. |
| [Import 1.3.53](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/mm/filemap.c?id=0e8625c7689bef9a38293aa927add4d9704e48be) | 引入了 page_cache_size, 统计 page cache 的大小. |
| [Linux 2.3.7pre1](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/mm/filemap.c?h=2.3.7pre1&id=344971f8de0ecf3fb7ea642e319aad5865b23529) |
统一了 page cache 和 buffer 的框架. |
| [Import 2.3.16pre1](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/mm/filemap.c?id=9aa2c66ac214f71cb051ba7c1adf313d9e160ee1) | 引入了 pagemap-LRU |
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
@@ -2139,15 +2152,16 @@ swappiness 参数值可设置范围在 `0~100` 之间.
| 2021/10/20 | Yang Shi <shy828301@gmail.com> | [Solve silent data loss caused by poisoned page cache (shmem/tmpfs)](https://patchwork.kernel.org/project/linux-mm/cover/20210930215311.240774-1-shy828301@gmail.com) | 为了让文件系统意识到有毒的(poisoned)页面.<br>在讨论拆分页面缓存 THP 以脱机有毒页面的补丁时, Noaya 提到了一个[更大的问题](https://lore.kernel.org/linux-mm/CAHbLzkqNPBh_sK09qfr4yu4WTFOzRy+MKj+PA7iG-adzi9zGsg@mail.gmail.com/T/#m0e959283380156f1d064456af01ae51fdff91265), 它阻止了这一工作的进行, 因为如果发生不可纠正的错误, 页面缓存页面将被截断. 深入研究后发现, 如果页面脏, 这种方法 (截断有毒页面) 可能导致所有非只读文件系统的静默数据丢失. 对于内存中的文件系统, 例如 shmem/tmpfs, 情况可能更糟, 因为数据块实际上已经消失了. 为了解决这个问题, 我们可以将有毒的脏页面保存在页面缓存中, 然后在任何后续访问时通知用户, 例如页面错误、读 / 写等. 可以按原样截断干净的页, 因为稍后可以从磁盘重新读取它们. 结果是, 文件系统可能会发现有毒的页面, 并将其作为健康页面进行操作, 因为除了页面错误之外, 所有文件系统实际上都不会检查页面是否有毒或是否在所有相关路径中. 通常, 在将有毒页面保存在页面缓存中以解决数据丢失问题之前, 我们需要让文件系统知道有毒页面. | v3 ☐ | [2021/09/30 PatchWork RFC,v3,0/5](https://patchwork.kernel.org/project/linux-mm/cover/20210930215311.240774-1-shy828301@gmail.com)<br>*-*-*-*-*-*-*-* <br>[2021/10/14 PatchWork RFC,v4,0/6](https://patchwork.kernel.org/project/linux-mm/cover/20211014191615.6674-1-shy828301@gmail.com)<br>*-*-*-*-*-*-*-* <br>[2021/10/20 PatchWork v5,0/6](https://patchwork.kernel.org/project/linux-mm/cover/20211020210755.23964-1-shy828301@gmail.com) |
https://lore.kernel.org/patchwork/cover/1324435/
## 6.2 页面预读(readahead)
-------
[linux文件预读发展过程](https://blog.csdn.net/jinking01/article/details/106541116)
kai_ding 的 [Linux 文件系统预读](https://blog.csdn.net/kai_ding/article/details/17322787) 以三个实际读取的实例程序讲解了 linux-3.12 的预读算法. [Linux 文件系统预读 (一)](https://blog.csdn.net/kai_ding/article/details/17322787) 讲解了单进程规则顺序读时预读算法的工作. [Linux 文件系统预读 (二)](https://blog.csdn.net/kai_ding/article/details/19957763) 讲解了单进程不规则顺序读(一共进行了三次读,顺序读,且读的大小不定,有超过最大预读量的,也有低于最大预读量的)下预读的工作行为. [Linux 文件系统预读 (三)](https://blog.csdn.net/kai_ding/article/details/20112753) 讲解了多进程交织顺序读行为下的预读是如何处理的.
[2.4.18 预读算法详解](https://blog.csdn.net/liuyuanqing2010/article/details/6705338)
[Linux readahead: less tricks for more](https://www.kernel.org/doc/ols/2007/ols2007v2-pages-273-284.pdf)
从用户角度来看, 这一节对了解 Linux 内核发展帮助不大, 可跳过不读; 但对于技术人员来说, 本节可以展现教材理论模型到工程实现的一些思考与折衷, 还有软件工程实践中由简单粗糙到复杂精细的演变过程
@@ -2169,36 +2183,56 @@ Linux内核的一大特色就是支持最多的文件系统, 并拥有一个虚
| 2003/02/03 | Andrew Morton <akpm@digeo.com> | [implement posix_fadvise64()](https://github.com/gatieme/linux-history/commit/fccbe3844c29beed4e665b1a5aafada44e133adc) | 引入 posix_fadvise64 | v1 ☑ 2.5.60 | [HISTORY commit](https://github.com/gatieme/linux-history/commit/fccbe3844c29beed4e665b1a5aafada44e133adc) |
### 6.2.2 预读算法及其优化
### 6.2.2 早期预读算法及其优化
-------
一开始, 内核的预读方案如你所想, 很简单. 就是在内核发觉可能在做顺序读操作时, 就把后面的 128 KB 的页面也读进来.
大约一年之后, Linus Torvalds 把 mmap 缺页 I/O 的预取算法单独列出, 从而形成了 read-around/read-ahead 两个独立算法(图4). read-around算法适用于那些以mmap方式访问的程序代码和数据, 它们具有很强的局域性(locality of reference)特征. 当有缺页事件发生时, 它以当前页面为中心, 往前往后预取共计128KB页面. 而readahead算法主要针对read()系统调用, 它们一般都具有很好的顺序特性. 但是随机和非典型的读取模式也大量存在, 因而readahead算法必须具有很好的智能和适应性.
大约一年之后, Linus Torvalds 把 mmap 缺页 I/O 的预取算法单独列出, 从而形成了 read-around/read-ahead 两个独立算法.
![Linux中的read-around, read-ahead和direct read](./images/0002-2-readahead_algorithm.gif)
1. read-around算法适用于那些以 mmap 方式访问的程序代码和数据, 它们具有很强的局域性(locality of reference)特征. 当有缺页事件发生时, 它以当前页面为中心, 往前往后预取共计 128KB 页面.
2. readahead 算法主要针对 read() 系统调用, 它们一般都具有很好的顺序特性. 但是随机和非典型的读取模式也大量存在, 因而 readahead 算法必须具有很好的智能和适应性.
* read-around 与 read-ahead 算法
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
| 2003/07/03 | Linus Torvalds <torvalds@home.osdl.org> | [Simplify and speed up mmap read-around handling](https://github.com/gatieme/linux-history/commit/82a333fa1948869322f32a67223ea8d0ae9ad8ba) | 引入 posix_fadvise64 | v1 ☑ 2.5.75 | [HISTORY commit](https://github.com/gatieme/linux-history/commit/82a333fa1948869322f32a67223ea8d0ae9ad8ba) |
| 2005/01/03 | Steven Pratt <slpratt@austin.ibm.com>, Ram Pai <linuxram@us.ibm.com> | [Simplified readahead](https://github.com/gatieme/linux-history/commit/6f734a1af323ab4690610ecd575198ae219b6fe8) | 引入读大小参数, 代码简化及优化; 支持随机读. | v1 ☑ 2.6.11 | [HISTORY commit 1](https://github.com/gatieme/linux-history/commit/6f734a1af323ab4690610ecd575198ae219b6fe8), [HISTORY commit 2](250c01d06ccb125519cc9958d938f41736868be9) |
| 2003/07/03 | Andrew Morton <akpm@zip.com.au> | [readahead optimisations](https://github.com/gatieme/linux-history/commit/82a333fa1948869322f32a67223ea8d0ae9ad8ba) | 最早的 read-around 思想实现 | v1 ☑ 2.5.27 | [HISTORY commit](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?h=v2.5.27&id=b6938a7bd23a74cfa7a81c0765ec255ea1c7e12e) |
| 2003/07/03 | Linus Torvalds <torvalds@home.osdl.org> | [Simplify and speed up mmap read-around handling](https://github.com/gatieme/linux-history/commit/82a333fa1948869322f32a67223ea8d0ae9ad8ba) | Linus Torvalds 把 mmap 缺页 I/O 的预取算法单独列出, 从而形成了 [read-around](https://elixir.bootlin.com/linux/v2.5.75/source/mm/filemap.c#L997)/read-ahead 两个独立算法 | v1 ☑ 2.5.75 | [HISTORY commit](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?h=v2.5.75&id=82a333fa1948869322f32a67223ea8d0ae9ad8ba) |
这种固定的128 KB预读方案显然不是最优的. 它没有考虑系统内存使用状况和进程读取情况. 当内存紧张时, 过度的预读其实是浪费, 预读的页面可能还没被访问就被踢出去了. 还有, 进程如果访问得凶猛的话, 且内存也足够宽裕的话, 128KB又显得太小家子气了.
* 顺序读与随机读
后续通过 Steven Pratt、Ram Pai 等人的大量工作, readahead 算法进一步完善. 其中最重要的一点是实现了对随机读的完好支持. 随机读在数据库应用中处于非常突出的地位. 在此之前, 预读算法以离散的读页面位置作为输入, 一个多页面的随机读会触发"顺序预读". 这导致了预读I/O数的增加和命中率的下降. 改进后的算法通过监控所有完整的 read() 调用, 同时得到读请求的页面偏移量和数量, 因而能够更好的区分顺序读和随机读.
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
| 2005/01/03 | Steven Pratt <slpratt@austin.ibm.com>, Ram Pai <linuxram@us.ibm.com> | [Simplified readahead](https://github.com/gatieme/linux-history/commit/6f734a1af323ab4690610ecd575198ae219b6fe8) | 引入读大小参数, 代码简化及优化; 支持随机读. | v1 ☑ 2.6.11 | [HISTORY commit 1](https://github.com/gatieme/linux-history/commit/6f734a1af323ab4690610ecd575198ae219b6fe8), [HISTORY commit 2](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?h=v2.6.11&id=250c01d06ccb125519cc9958d938f41736868be9) |
| 2005/03/07 | Oleg Nesterov <oleg@tv-sign.ru> | [readahead: improve sequential read detection](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=671ccb4b50a6ef21e8c0ed0ef9070098295e1e61) | 支持非对齐顺序读. | v1 ☑ [2.6.12](https://kernelnewbies.org/Linux_2_6_12) | [commit 1](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=671ccb4b50a6ef21e8c0ed0ef9070098295e1e61), [commit 2](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=577a3dd8fd68d24056075fdf479a1627586f8c46) |
* 顺序性检测
参见 [Linux 内核的文件预读机制详细详解](https://blog.csdn.net/kunyus/article/details/104620057)
为了保证预读命中率, Linux 只对顺序读 (sequential read) 进行预读. 内核通过验证如下两个条件来判定一个 read() 是否顺序读:
1. 这是文件被打开后的[第一次读](https://elixir.bootlin.com/linux/v2.6.22/source/mm/readahead.c#L476), 并且读的是[文件首部](https://elixir.bootlin.com/linux/v2.6.22/source/mm/readahead.c#L494);
2. 当前的读请求与前一 (记录的) 读请求在文件内的位置是连续的.
如果不满足上述顺序性条件, 就判定为随机读. 任何一个随机读都将终止当前的顺序序列, 从而终止预读行为 (而不是缩减预读大小). 注意这里的空间顺序性说的是文件内的偏移量, 而不是指物理磁盘扇区的连续性. 在这里 Linux 作了一种简化, 它行之有效的基本前提是文件在磁盘上是基本连续存储的, 没有严重的碎片化.
### 6.2.3 按需预读(On-demand Readahead)
-------
**2.6.23(2007年10月发布)**
这种固定的128 KB预读方案显然不是最优的. 它没有考虑系统内存使用状况和进程读取情况. 当内存紧张时, 过度的预读其实是浪费, 预读的页面可能还没被访问就被踢出去了. 还有, 进程如果访问得凶猛的话, 且内存也足够宽裕的话, 128KB又显得太小家子气了.
后续通过 Steven Pratt、Ram Pai 等人的大量工作, readahead算法进一步完善. 其中最重要的一点是实现了对随机读的完好支持. 随机读在数据库应用中处于非常突出的地位. 在此之前, 预读算法以离散的读页面位置作为输入, 一个多页面的随机读会触发"顺序预读". 这导致了预读I/O数的增加和命中率的下降. 改进后的算法通过监控所有完整的 read( )调用, 同时得到读请求的页面偏移量和数量, 因而能够更好的区分顺序读和随机读.
2.6.23的内核引入了在这个领域耕耘许久的吴峰光的一个[按需预读的算法]((https://lwn.net/Articles/235164). 所谓的按需预读, 就是内核在读取某页不在内存时, 同步把页从外设读入内存, 并且, 如果发现是顺序读取的话, 还会把后续若干页一起读进来, 这些预读的页叫预读窗口; 当内核读到预读窗口里的某一页时, 如果发现还是顺序读取的模式, 会再次启动预读, 异步地读入下一个预读窗口.
**2.6.23(2007年10月发布)** 的内核引入了在这个领域耕耘许久的吴峰光的一个[按需预读的算法]((https://lwn.net/Articles/235164). 所谓的按需预读, 就是内核在读取某页不在内存时, 同步把页从外设读入内存, 并且, 如果发现是顺序读取的话, 还会把后续若干页一起读进来, 这些预读的页叫预读窗口; 当内核读到预读窗口里的某一页时, 如果发现还是顺序读取的模式, 会再次启动预读, 异步地读入下一个预读窗口.
该算法关键就在于适当地决定这个预读窗口的大小,和哪一页做为异步预读的开始. 它的启发式逻辑也非常简单, 但取得不了错的效果. 此外, 对于两个进程在同一个文件上的交替预读, 2.6.24 增强了该算法, 使其能很好地侦测这一行为.
@@ -2206,6 +2240,8 @@ Linux内核的一大特色就是支持最多的文件系统, 并拥有一个虚
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
| 2005/10/06 | WU Fengguang <wfg@mail.ustc.edu.cn> | [Adaptive file readahead](https://lwn.net/Articles/155510) | 自适应预读算法 | v1 ☐ | [LWN](https://lwn.net/Articles/155097) |
| 2009/4/10 | Wu Fengguang <fengguang.wu@intel.com> | [filemap and readahead fixes for linux-next](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=d30a11004e3411909f2448546f036a011978062e) | bugfix | v1 ☑ 2.6.31-rc1 | [LORE v1,00/14](https://lore.kernel.org/lkml/20090407115039.780820496@intel.com)<br>*-*-*-*-*-*-*-* <br>[LORE v2,0/9](https://lore.kernel.org/lkml/20090410060957.442203404@intel.com), [LKML v2,0/9](https://lkml.org/lkml/2009/4/10/37) |
| 2009/4/10 | Wu Fengguang <fengguang.wu@intel.com> | [context readahead for concurrent IO](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=10be0b372cac50e2e7a477852f98bf069a97a3fa) | bugfix | v1 ☑ 2.6.31-rc1 | [LORE v1,0/3](https://lkml.kernel.org/lkml/20090410131247.764370473@intel.com) |
| 2011/05/17 | WU Fengguang <wfg@mail.ustc.edu.cn> | [512K readahead size with thrashing safe readahead](https://lwn.net/Articles/372384) | 将每次预读窗口大小的最大值从 128KB 增加到了 512KB, 其中增加了一个统计接口(tracepoint, stat 节点等). | v3 ☐ | [PatchWork](https://lore.kernel.org/patchwork/cover/190891), [LWN](https://lwn.net/Articles/234784) |
| 2011/05/17 | WU Fengguang <wfg@mail.ustc.edu.cn> | [on-demand readahead](https://lwn.net/Articles/235164) | on-demand 预读算法 | v1 ☑ [2.6.23-rc1](https://kernelnewbies.org/Linux_2_6_23#On-demand_read-ahead) | [LWN](https://lwn.net/Articles/234784) |
@@ -3249,15 +3285,7 @@ RMAP 反向映射是一种物理地址反向映射虚拟地址的方法.
| 2020/10/14 | Kalesh Singh <kaleshsingh@google.com> | [Speedup mremap on ppc64](https://patchwork.kernel.org/project/linux-mm/cover/20210616045735.374532-1-aneesh.kumar@linux.ibm.com) | NA | v8 ☑ 5.14-rc1 | [PatchWork v8,0/3](https://patchwork.kernel.org/project/linux-mm/cover/20201014005320.2233162-1-kaleshsingh@google.com) |
## 8.5 filemapping
-------
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
| 2020/10/25 | Kalesh Singh <kaleshsingh@google.com> | [generic_file_buffered_read() improvements](https://lore.kernel.org/patchwork/cover/1324435) | filemap 的批量内存分配和拷贝. | v4 ☑ [5.11-rc1](https://kernelnewbies.org/Linux_5.11#Memory_management) | [PatchWork v2,0/2](https://lore.kernel.org/patchwork/cover/1324435) |
## 8.6 ioremap
## 8.5 ioremap
-------
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
+15 -1
View File
@@ -441,7 +441,7 @@ linux 调度器定义了多个调度类, 不同调度类的调度优先级不同
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:----:|:---------:|:----:|
| 2010/6/8 | Michael Neuling <mikey@neuling.org> | [sched: asymmetrical packing for POWER7 SMT4](https://lkml.org/lkml/2010/6/8/6) | POWER7 是 SMT4, 并且支持动态 SMT 模式切换, 为内核调度器带来了挑战.<br>1. 首先是[对 CPU power 和 capacity 的处理](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9d5efe05eb0c904545a28b19c18b949f23334de0), 如果简单的认为每个 CPU power 为 total/4, 则值很小, 极容易被调度器认为 CPU capacity 为 0, 无法再容纳新的进程, 从而导致进程在核间来回跳跃.<br>2. POWER7 硬件动态 SMT 模式切换, 但是只有当更高编号的 CPU thread 处于空闲状态时, 它才能转移到 lower SMT 模式(比如从 SMT4 切换到 SMT2/SMT1). 在 lower SMT 模式下, 进程的性能会更好, 因为它们共享的核心资源更少. 为了解决 SMT4 上线程性能下降的问题, 倾向于将进程打包运行在编号小的 CPU 上. 通过 check_asym_packing() 来检查是否需要主动进行打包. 并增加了 [SD_ASYM_PACKING](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=532cb4c401e225b084c14d6bd6a2f8ee561de2f1) 标志, 从而可以以在任何调度域级别启用该特性. 当前[只在 SMT 域级别开启](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=76cbd8a8f8b0dddbff89a6708bd5bd13c0d21a00). | v1 ☑ 2.6.36-rc1 | [PatchWork 0/3](https://patchwork.ozlabs.org/project/linuxppc-dev/patch/20100608045702.2936CCC897@localhost.localdomain) |
| 2010/6/8 | Michael Neuling <mikey@neuling.org> | [sched: asymmetrical packing for POWER7 SMT4](https://lkml.org/lkml/2010/6/8/6) | POWER7 是 SMT4, 并且支持动态 SMT 模式切换, 为内核调度器带来了挑战.<br>1. 首先是[对 CPU power 和 capacity 的处理](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9d5efe05eb0c904545a28b19c18b949f23334de0), 如果简单的认为每个 CPU power 为 total/4, 则值很小, 极容易被调度器认为 CPU capacity 为 0, 无法再容纳新的进程, 从而导致进程在核间来回跳跃.<br>2. POWER7 硬件动态 SMT 模式切换, 但是只有当更高编号的 CPU thread 处于空闲状态时, 它才能转移到 lower SMT 模式(比如从 SMT4 切换到 SMT2/SMT1). 在 lower SMT 模式下, 进程的性能会更好, 因为它们共享的核心资源更少. 为了解决 SMT4 上线程性能下降的问题, 倾向于将进程打包运行在编号小的 CPU 上. 通过 check_asym_packing() 来检查是否需要主动进行打包. 并增加了 [SD_ASYM_PACKING](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=532cb4c401e225b084c14d6bd6a2f8ee561de2f1) 标志, 从而可以以在任何调度域级别启用该特性. 当前[只在 SMT 域级别开启](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=76cbd8a8f8b0dddbff89a6708bd5bd13c0d21a00). | v1 ☑ 2.6.36-rc1 | [PatchWork 0/3](https://patchwork.ozlabs.org/project/linuxppc-dev/patch/20100608045702.2936CCC897@localhost.localdomain), [LORE 0/3](https://lore.kernel.org/lkml/1275973022.91203.586435002889.qpush@pale) |
| 2016/11/11 | Tim Chen <tim.c.chen@linux.intel.com> | [Support Intel Turbo Boost Max Technology 3.0](https://lore.kernel.org/all/cover.1479844244.git.tim.c.chen@linux.intel.com) | 支持 [Intel Turbo Boost Max Technology 3.0 (ITMT)](http://www.intel.com/content/www/us/en/architecture-and-technology/turbo-boost/turbo-boost-max-technology.html) 技术, 通过 ITMT 技术硬件可以将 package 中的某些 CPU 提升到更高的 Turbo 频率, 调度器通过对非对称打包(ASYM_PACKING)功能进行扩展, 将关键任务等移动到 Turbo 的 CPU, 从而提升性能. | v8 ☑ 4.10-rc1 | [PatchWork v8,0/8](https://lore.kernel.org/all/cover.1479844244.git.tim.c.chen@linux.intel.com) |
| 2016/04/06 | Srikar Dronamraju <srikar@linux.vnet.ibm.com> | [sched/fair: Fix asym packing to select correct cpu](https://lore.kernel.org/all/1459948660-16073-1-git-send-email-srikar@linux.vnet.ibm.com) | NA | v2 ☑ 4.7-rc1 | [PatchWork v2](https://lore.kernel.org/all/1459948660-16073-1-git-send-email-srikar@linux.vnet.ibm.com) |
| 2016/12/29 | Peter Oskolkov <posk@google.com> | [sched/x86: Change CONFIG_SCHED_ITMT to CONFIG_SCHED_MC_PRIO](https://lore.kernel.org/all/2b2ee29d93e3f162922d72d0165a1405864fbb23.1480444902.git.tim.c.chen@linux.intel.com) | 将 ITMT 的 CONFIG_SCHED_ITMT 更新为 CONFIG_SCHED_MC_PRIO, 这使得该配置在将来可以扩展到希望在调度器中类似地建立 CPU 核心优先级支持的其他体系结构. | v1 ☑ 4.10-rc1 | [PatchWork](https://lore.kernel.org/all/2b2ee29d93e3f162922d72d0165a1405864fbb23.1480444902.git.tim.c.chen@linux.intel.com) |
@@ -935,6 +935,10 @@ max_idle_balance_cost 则跟踪了当前调度域最近一段时间执行 idle b
idle balance 中执行 update_blocked_average 是很费时费力的, 可以做不少优化.
[sched/fair: remote load updates for idle CPUs](https://lkml.org/lkml/2017/10/24/388)
[sched/fair: Rate limit calls to update_blocked_averages() for NOHZ](https://lkml.kernel.org/lkml/20210122154600.1722680-1-joel@joelfernandes.org)
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:---:|:----------:|:----:|
@@ -953,6 +957,16 @@ idle balance 中执行 update_blocked_average 是很费时费力的, 可以做
| 2013/08/29 | Jason Low <jason.low2@hp.com> | [steal tasks to improve CPU utilization](http://lwn.net/Articles/769225) | 限制 idle balance | v1 ☑ 4.13-rc1 | [PatchWork v1](https://lore.kernel.org/lkml/1540220381-424433-1-git-send-email-steven.sistare@oracle.com)<br>*-*-*-*-*-*-*-* <br>[PatchWork v4 00/10](https://lkml.org/lkml/2018/12/6/1253) |
### 4.6.4 nohz idle balance
-------
nohz_load_balance() 发生在其他 CPU 已经进入 IDLE, 但是本 CPU 任务依旧比较繁重, 这时候需要通过 IPI 将其他 IDLE CPU 唤醒来做负载均衡. 同样 nohz_idle_balance 就是通过 busy CPU 上 kick 其他 IDLE 的 CPU 来驱动的. 通过 GIC 发送 IPI 唤醒一个选中的 IDLE CPU, 他将代表系统所有的 IDLE CPU 们来做负载均衡.
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|:----:|:----:|:---:|:---:|:----------:|:----:|
| 2016/01/13 | Frederic Weisbecker <fweisbec@gmail.com> | [sched: Improve cpu load accounting with nohz](https://lkml.kernel.org/lkml/1452700891-21807-1-git-send-email-fweisbec@gmail.com) | NA | RFC ☐ | [LORE RFC,0/4](https://lkml.kernel.org/lkml/1452700891-21807-1-git-send-email-fweisbec@gmail.com) |
| 2010/05/17 | Suresh Siddha <suresh.b.siddha@intel.com> | [sched: change nohz idle load balancing logic to push model](https://lore.kernel.org/all/20100517182726.089700767@sbs-t61.sc.intel.com) | 现有的 nohz 空闲负载平衡逻辑使用拉模式, 在部分 CPU 空闲的系统上指定一个空闲的 CPU 来做负载均衡(balancer CPU), 并且该平衡器 CPU 不进入 nohz 模式. 通过周期性的 TICK, 平衡器在 nohz 模式下代表所有 CPU 进行空闲平衡. 另一种选择是使用推送模式, 在这种模式下, 所有空闲 CPU 都可以进入 nohz 模式, 任何忙碌的 CPU 都可以 kick 一个空闲 CPU, 以代表一组空闲 CPU 处理 idle balancing. 这个补丁就将 nohz idle balance 切换到了 push 模式. | RFC ☑ 2.6.36-rc1 | [LKML 0/7](https://lore.kernel.org/all/20100517184027.862696498@sbs-t61.sc.intel.com), [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=83cd4fe27ad8446619b2e030b171b858501de87d) |
## 4.7 active load_balance
-------