ARM Linux 内核页表 [英] ARM Linux kernel page table

查看:42
本文介绍了ARM Linux 内核页表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考Linux 内核 ARM 转换表库(TTB0 和 TTB1)

我对上一个链接中讨论的主题有父亲的疑问/疑问:

<块引用>

  1. 0 到 0xbffffffff 是内存的较低部分(用于用户进程),由 TTB0 中的页表管理,它包含当前进程的页表<块引用>

    参考arm/include/asm/pgtable-2level.h : PTRS_PER_PGD =2048, PTRS_PER_PMD =1, PTRS_PER_PTE =512

  2. 0xc0000000 到 0xffffffff 是由 TTBR1 中的页表管理/转换的地址空间的上部(操作系统和内存映射 I/O).TTB1 表的大小和对齐方式是固定的(到 16k).每个级别 1 条目大小为 32 位,代表 1MB 页/段.这是swapper_pg_dir (ref System.map) 页表,在实际文本地址下方放置了 16K

  1. swapper_pg_dir = 0 中的第一个 768 条目(用户进程为 0x0 到 0xbfffffff)和从 768 到 1024 的有效条目(0xc0000000 到 0xffffffff 用于操作系统和内存映射 I/O)?

  2. 有人喜欢分享内核空间(内核模块)中的一些示例代码来浏览这个swapper_pg_dir PGD?

解决方案

由于 ARM MMU 的设计方式,两个转换表(TTB0 和 TTB1)只能在 1:1 映射内核映射中使用.

>

大多数 Linux 内核具有 3:1 映射(3GB 用户空间:ARM 的 1GB 内核空间).这意味着 0-0xBFFFFFFF 是用户空间,而 0xC0000000 - 0xFFFFFFFF 是内核空间.

现在对于 HW 内存转换,仅使用 TTBR0.TTBR1 只保存初始交换页面的地址(包含所有内核映射),并不真正用于虚拟地址转换.TTBR0 保存当前使用的页目录(硬件用于转换的页表)的地址.现在每个用户进程都有自己的页表,每次进程切换,TTBR0都会改变当前用户进程的页表(它们都位于内核空间).

例如,对于每一个新的用户进程,内核都会创建一个新的页目录,将所有内核映射从交换页(3-4GB的页框)复制到新的页表中,并清除用户页(页框)从 0-3GB).然后它将 TTB0 设置为此页目录的基地址并刷新缓存以安装新的地址空间.交换页面也总是随着映射的变化保持最新.

对于您的问题:

  1. 简化,硬件层面的第一级页面有 4096 个条目.每个条目代表 1MB 的虚拟地址,总共 4GB 的内存.条目 0-3071 代表用户空间,条目 3072-4095 代表内核空间.

  2. 交换页通常位于地址 0xC0004000 - 0xc0008000(4096 个条目 * 每个条目 4 字节 = 16384 = 16kb 十六进制 = 0x4000).通过检查 0xc0004000-0xc0007000 处的内存,您可以找到用户空间(空)的条目,并从 0xc0007000-0xc0008000 处找到内核条目.我将 gdb 与命令行 x/100x 0xc0007000 一起使用,以检查前 100 个内核条目.然后,您可以检查当前平台的技术参考手册,以破译页表属性.

如果想深入了解Linux内核,推荐使用Qemu模拟Beagleboard,结合gdb进行源码检查调试.我这样做是为了了解内核如何在初始化期间构建页表.

Ref. Linux kernel ARM Translation table base (TTB0 and TTB1)

I have father doubt/query on topic discussed in previous link:

  1. 0 to 0xbfffffff is a lower part of memory (for user processes) and managed by the page table in TTB0, it contains the page-table of the current process

    Ref. arm/include/asm/pgtable-2level.h : PTRS_PER_PGD =2048, PTRS_PER_PMD =1, PTRS_PER_PTE =512

  2. 0xc0000000 to 0xffffffff is upper part (OS and memory-mapped I/O) of the address space managed/translated by the page table in TTBR1. TTB1 table is fixed in size and alignment (to 16k). Each level 1 entry of size is 32bits and represents 1MB page/segment. This is swapper_pg_dir (ref System.map) page tables that placed 16K below the actual text address

  1. Is that the first 768 entry in swapper_pg_dir = 0 (0x0 to 0xbfffffff for user processes) and valid entry from 768 to 1024(0xc0000000 to 0xffffffff is for OS and memory-mapped I/O)?

  2. Anyone like to share some sample code in kernel space (kernel module) to browse this swapper_pg_dir PGD?

解决方案

Because of how the ARM MMU was designed, both the translations tables (TTB0 and TTB1) can only be used in a 1:1 mapping kernel mapping.

Most Linux Kernels have a 3:1 mapping (3GB User space : 1GB Kernel space for ARM). This means that 0-0xBFFFFFFF is user space while 0xC0000000 - 0xFFFFFFFF is kernel space.

Now for the HW memory translations, only TTBR0 is used. TTBR1 only holds the address of the initial swapper page (which contains all the kernel mappings) and isn't really used for virtual address translations. TTBR0 hold the address for the current used page directory (the page table that the HW is using for translations). Now each user process has their own page tables, and for each process switch, TTBR0 changes to the current user process page table (they are all located in kernel space).

For example, for each new user process, the kernel creates a new page directory, copies all the kernel mappings from the swapper page(page frames from 3-4GB) to the new page table and clears the user pages(page frames from 0-3GB). It then sets TTB0 to the base address of this page directory and flushes cache to install the new address space. The swapper page is also always kept up to date with changes to the mappings.

For your question:

  1. Simplified, hardwarewise the first level page have 4096 entries. Each entry represent 1MB of virtual address, totalling 4GB of ram. Entry 0-3071 represent user space and entry 3072-4095 represent kernel space.

  2. The swapper page is usually located at address 0xC0004000 - 0xc0008000 (4096 entries *4bytes each entry = 16384 =16kb in hex = 0x4000 ). By examing the memory at 0xc0004000-0xc0007000 you can find entries for user space (empty) and from 0xc0007000-0xc0008000 you can find kernel entries. I use gdb with the command line x /100x 0xc0007000 in order to examine the first 100 kernel entries. You can then examine the technical reference manual for your current platform in order to decipher the page table attributes.

If you want to learn more about the Linux kernel, I recommend you to use Qemu to simulate the Beagleboard together with gdb to examine and debug the source code. I did this to learn how the kernel builds the page table during initialization.

这篇关于ARM Linux 内核页表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆