【问题标题】:Linux kernel ARM Translation table base (TTB0 and TTB1)Linux 内核 ARM 转换表库(TTB0 和 TTB1)
【发布时间】:2013-01-22 14:22:53
【问题描述】:

为 ARMv7 (Cortex-a8) 编译的 Linux 内核 2.6.34.3

我查看了内核代码,看起来 Linux 内核在 TTB1(转换表库)上为内核地址空间(0xC0000000 以上的所有内容)和 ttb0(0xC0000000 以下的所有内容)上的用户进程设置了硬件页表,每个进程上下文切换都会发生变化。它是否正确?我仍然很困惑 MMU 如何知道要查看哪个 ttb 进行翻译?

我读到 TTBCR(转换表基本控制寄存器)确定当未找到 MVA 时要遍历哪个 ttb 寄存器,但是该寄存器始终读取 0,这意味着始终使用 ARM 体系结构参考手册中的 TTBR0。这怎么可能?谁能向我解释一下 Linux 内核是如何使用这两个 ttb 的?

我从这个站点https://www.cs.rutgers.edu/~pxk/416/notes/10-paging.html 阅读了 ttb 的工作原理,但我仍然不明白内核如何使用这两个 ttb

(再次检查内核代码,由于某种原因,ttb0 和 ttb1 都已设置,但似乎从未使用过 ttb1,我将 TTB1 寄存器设置为 0,Linux 内核继续照常运行)

【问题讨论】:

  • 在你附上的链接上,TTBR0 will still contain the memory map for the operating system and memory-mapped I/O.,我猜他们的意思是说TTBR1 will still contain the memory map for the operating system and memory-mapped I/O.,这对 3G/1G (2G/2G) 内存拆分更有意义。 TTBR0 将地址从 0 的进程 AS 映射到 0xbfffffff,TTBR0 在每次进程切换期间切换。 TTBR1 永远不会被修改,因为它包含指向内核 AS 的链接(在具有 3G/1G 拆分的 Linux 上从 0xc000000 开始)。
  • 感谢您的回复,那么对于每张桌子行走,硬件仅使用 TTB0 是否正确?硬件不使用TTBCR来确定要走哪个ttb寄存器?那么TTB1只用于将OS页面复制到进程页面?

标签: linux-kernel operating-system arm


【解决方案1】:

TTBR 寄存器一起用于确定整个 32 位或 40 位地址空间的寻址。哪个寄存器用于哪个地址范围由 TTBCR 中的 tXsz 位控制。 t0sz 对应 TTBR0,t1sz 对应 TTBR1。

每个 TTBRx 寄存器寻址的页表都是独立的,但您通常会发现大多数 Linux 实现只使用 TTBR0。 Linux 期望能够使用 ARM 不支持的 3G/1G 地址空间分区方案。如果您查看 ARMv7 架构参考手册的 B3-1345 页,您会看到 t0sz 和 t1sz 的值分别决定了 TTBR0 和 TTBR1 支持的地址范围。为了使迷失方向更加混乱,甚至有可能在 TTBR0 和 TTBR1 支持的范围不连续的情况下出现脱节的地址空间,从而导致系统地址空间出现漏洞。好时光!

不过,为了回答您的主要问题,ARM 建议使用 TTBR0 来存储 USER 进程使用的页表的偏移量,而 TTBR1 用于存储 KERNEL 使用的页表的偏移量。我还没有看到一个真正做到这一点的实现。在所有情况下几乎都只使用 TTBR0,TTBR1 包含 L1 表的副本。

那么这是如何工作的呢? TTBR 的值作为进程状态的一部分存储,并且在每次进程关闭时简单地恢复。这就是预期的工作方式。最初,TTBR1 将保持内核表的恒定值并且永远不会被替换或换出,而 TTBR0 将在每次进程之间的上下文切换时更改。显然,大多数 ARM 的 Linux 实现已经决定基本上消除对 TTBR1 的使用,并坚持使用 TTBR0。

如果您想在您的设备上测试此理论,请尝试敲击 TTBR1,然后看什么都不会发生。然后尝试敲击 TTBR0 并观察您的系统崩溃。我还没有遇到一个没有产生完全相同结果的实例。长话短说,TTBR1 在 Linux 中是无用的,而 TTBR0 几乎完全被使用,只是被换掉了。

现在,一旦您获得了 LPAE 支持,就扔掉所有这些,重新开始。在这个实现中,您将开始看到 t0sz 和 t1sz 的值不是零,因此也不是零。

【讨论】:

【解决方案2】:

我对 ARM 架构知之甚少,但从我在您随附的链接中读到的内容,我猜 Linux 以这种方式实现其虚拟内存管理:

虚拟地址的高位决定使用哪一个。表的基址存储在两个基址寄存器之一(TTBR0 或 TTBR1)中,具体取决于虚拟地址的最高 n 位是否为 0(使用 TTBR0)或不(使用 TTBR1)。 n 的值由转换表基本控制寄存器 (TTBCR) 定义。

寄存器TTBCR 告诉哪些地址将从TTBR0TTBR1 指向的页表中转换。如果TTBCR 包含0xc000000,则从00xbfffffff 的任何地址都由TTBR0 指向的页表翻译,而从@​​987654329@ 到0xffffffff 的任何地址都由该页翻译- TTBR1 指向的表。这与用户进程 3GB/内核 1GB 的 Linux 内存分割相匹配。

这允许一个设计,其中操作系统和内存映射 I/O 位于地址空间的上部并由 TTBR1 中的页表管理,而用户进程位于内存的下部,并且由 TTB0 中的页表管理。在上下文切换时,操作系统必须更改 TTBR0 以指向新进程的第一级表。 TTBR1 仍将包含操作系统的内存映射和内存映射 I/O。

因此,TTBR1 的值不应该改变,因为您希望内核被永久映射(想想当一个中断被引发时会发生什么)。另一方面,TTBR0 在每次进程切换时都会被修改,它包含当前进程的页表。

【讨论】:

  • "如果Virtual Address的bits [31:32-N]全为0,则使用Translation Table Base Register 0否则使用Translation Table Base Register 1" 没有可以分离内核的N值地址(> = 0xC0000000)和用户地址(
  • 您对如何使用 TTBCR 来确定 TTBR0 或 TTBR1 是否适用的描述不正确。 MrGigu 的评论是正确的。 TTBR0(同时使用 TTBR1 时)可用的最大虚拟地址为 0x7fffffff。
【解决方案3】:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/Bihgfcgf.html

对于 ARM5 及更低版本,TTB 表的大小和对齐方式是固定的(至 16k)。每个级别 1 条目代表 1MB。表项为 32bits (16k*1M/(32bit/8) = 4GB)。 TTBCR 控制 TTBR0 表的大小。从上面的网址,

选择使用哪个翻译表基址寄存器
转换表基址寄存器选择如下:
如果 N = 0,则始终使用转换表基址寄存器 0。
- 这是重置时的默认情况。它向后兼容 ARMv5 或更早的处理器。
如果 N 大于 0,则:
- 如果虚拟地址的 [31:32-N] 位全为 0,则使用转换表基址寄存器 0,否则使用转换表基址寄存器 1。

所以 TTBR0 的大小也设置了内存分割。对于 traditional Linux 3G/1G 1G/3G,应选择值 2。 4kB 表 == 1G 内存 == 位 31..30 为零。对于 6 的值,该表为 256byte == 64MB == 位 31..26 为零。

在 Linux 用语中,这些是 page global 条目(这会拆分此 page global 目录)。这些条目可以指向另一个表或只是一个 1MB 。下一个表条目是 page middle Linux 目录,然后是最后的 page table 条目。我认为 page middle 条目在 ARM 上未使用。

MMU 硬件并非每次都走在桌子上。有一个 TLB(翻译后备缓冲区)。它就像 MMU 表的缓存。当操作系统更新这些表时,TLB 必须被刷新,否则处理器将使用 stale 条目。同样,ARM 缓存是虚拟标记,因此更改映射也可能意味着必须刷新缓存。由于这些原因,您从不希望在上下文切换时更改内容。共享库文本(比如 libc.so)在上下文切换时应该相同。希望每个进程都有 libc.so 映射到相同的虚拟地址。这样做有很大的收获;更少的内存使用和良好的 I-cache 使用。

domainPID 寄存器以及主管/用户模式也可以控制内存访问。这些是可以在上下文切换时切换的单个寄存器。

有关 ARMV5 上的 PID 和域使用的信息,请参阅 http://lwn.net/images/conf/rtlws11/papers/proc/p01.pdf。当前的 Linux 源代码与论文描述的不完全一样。 Linux 完全有可能不需要使用这种机制并将 TTBCR 设置为零,以便 ARM 子架构的 VM 代码类似。

编辑:相信 TTBCR 功能可用于实现 3G/1G 分离。我认为 Rutger 的页面是在泛泛地讨论 TTBCR 而不是在 Linux 上下文中。此外,至少 2.6.38 Linux 使用 domainsDACR 但不使用 pidfcse 因为它支持有限数量的进程。

http://lwn.net/Articles/106177/ - 在罗格斯页面上也有引用。

【讨论】:

  • 有趣的论文,但是使用 FCSE 将每个进程限制为 32MB,我认为普通的 Linux 发行版不会强制用户使用。然而,对于受限的嵌入式设备来说,这似乎是可行的。
  • 我仍然很困惑,将 N 位设置为 2,如果意味着所有虚拟地址
  • 分割为 1G/3G(根据编辑),Linux 很可能未使用此功能。此外,fcse 在较新的 ARM CPU 上已弃用。
  • 请参阅:Catalin Marinas's ARM LPAE paper 以了解在 Linux LPAE 中使用 TTBR1。
【解决方案4】:

TTBR0 保存着转换表 0 的基地址,以及它所占用的内存信息。

这是从 Hyp 模式以外的模式进行内存访问的第一阶段转换的转换表之一

【讨论】:

    猜你喜欢
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多