有两种明显的方式可以符合 ARMv6 的页面着色限制:
如果仅使用 4KB 页面,则可以构建维持颜色限制的映射,但该映射中第 12 和 13 位在虚拟和物理地址之间应不同;不过,加上这额外的复杂度是不太值得的。
请注意,ARM1136 和 ARM1176 都拥有固定为 4 的缓存,因此有 4KB 路数的此类系统将拥有 16KB 缓存。
ARMv7 和页面着色
ARMv7 处理器具有 PIPT 数据缓存(或者至少需要表现为拥有该缓存)。也就是说,它们拥有物理索引、物理标记的数据缓存,不适用任何页面着色限制。然而,它们可以有 VIPT 指令缓存,甚至在一定范围内还允许拥有 VIVT 指令缓存。它们也可以有 PIPT 指令缓存。(详情请见。)Cortex-A8 和 Cortex-A9 都有 VIPT 指令缓存。
对于大多数使用案例来说,VIPT 指令缓存的行为与 PIPT 指令缓存非常相似。指令缓存是只读的,因此不会出现最明显的连贯性问题。然而,在通过虚拟地址使缓存行无效时,VIPT 指令缓存可能依然需要特殊处理:具有不同颜色的别名条目将不会失效。实际上,中有如下陈述:
使 VIPT 指令缓存中某一物理地址的所有别名无效的唯一架构上有保证的方式是使整个指令缓存无效。
在实践中,你应该能够简单地使给定虚拟地址的所有可能的颜色变体失效。当然,如果不关心所有虚拟别名,那么其他别名的可能存在也不重要。自修改代码的作者(如 JIT 编译器)可以确保它们要执行(在修改后)的任何代码都通过用于运行它的地址(而不是使用别名)来失效,从而安全而高效地在这一系统中运作。
请注意,通过数据缓存对指令数据的写操作 — 例如,在自修改代码中 — 始终要求明示缓存维护操作,如我在中所述。这是因为 ARM 架构中的指令缓存和数据缓存之间没有连贯性。
ARMv6 用户空间示例:mmap
下列 序列在 ARMv7 上通常可正常运行(在 GNU/Linux 下),但在 ARMv6 上会失败:
请注意,第一个调用请求映射到颜色为 00 的虚拟地址,而第二个调用则请求映射到颜色为 01 的虚拟地址。
在 ARMv6 上,第二个 mmap 通常会失败(并返回 MAP_FAILED),但第一个将通过。在一些情形中,第一个调用可能也会失败,例如在物理页面已被分配了不同颜色时。用户进程对此没有任何控制,尽管似乎(实验性地,在 GNU/Linux 平台上)文件在 16KB 对齐上映射,因此有理由认为颜色为 00 的文件映射在 ARMv6 上是可靠的。
在 ARMv7 上,两个映射(通常)都将可行,而且可以指定任何用户可分配的虚拟地址,只要它在 4KB 页面界限上对齐。
请注意,这些 mmap 调用无法确保在任何平台上都成功。例如,某一给定平台可能会限制可以映射的区域数量,而一旦达到这一限制时,mmap 将返回 MAP_FAILED 并将 errno 设为 EMFILE。
每一缓存策略的属性
既然 VIPT 缓存有这一固有的页面着色限制,为何还要使用它们?
可以在 VIVT 缓存(即虚拟索引、虚拟标记的缓存)上进行最简单(或许最快速)的缓存查找。如果加载了缓存行,则完全不需要 MMU 查找。然而,VIVT 缓存有重复映射的连贯性问题,而且在更新分页表时(如上下文切换时)必须执行缓存维护操作。其中一些问题存在硬件解决办法,但最为高效的解决方案就是使用 VIPT 或 PIPT 缓存。
VIPT 缓存是 VIVT 缓存的自然演进。它们在进行任何存取时需要 MMU 转译,但物理标记意味着物理地址可以在缓存中进行唯一标识,因此重复映射是可能的(在页面着色限制中)并且上下文切换时不需要缓存维护操作。另外,尽管依然需要 MMU 转译,它可以和索引操作并行执行,如前文中所述。
ARMv7-A 指定数据缓存像 PIPT 缓存一样运作,所以给定的标记不会在标记 RAM 中重复,原因是缓存是通过物理地址索引的。其缺点在于,缓存查找无法与 MMU 转译并行执行,因为缓存查找的每一阶段中都需要物理地址。然而, 命中率良好时,这一缺点在某些程度上得到了缓减,因为成功的 TLB 查找速度很快。
但请注意,PIPT 缓存依然能够(在一些情形中)从页面着色中获益,因为它能够改善缓存行驱逐行为。这方面的详细信息可以单独组成一篇博文了,所以我不准备进一步详述。欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |