2. ARM64 虚拟地址空间布局:用户空间与内核空间划分
ARM64 架构下,虚拟地址空间被划分为两个主要区域:用户空间(User Space)和内核空间(Kernel Space)。这种划分是操作系统实现进程隔离与内核保护的基础。Linux 内核在 ARM64 上采用经典的“3:1”或“1:1”分割模型,具体取决于配置的地址位宽。
2.1 地址空间大小:48位与52位
ARMv8.0 架构定义了 48 位虚拟地址(VA)和 48 位物理地址(PA)的支持。ARMv8.2 引入了 52 位地址扩展(LVA/LPA),允许使用 52 位虚拟地址和 52 位物理地址。Linux 内核通过配置选项选择支持的地址位数。
| 特性 | 48位地址空间 | 52位地址空间 |
|---|---|---|
| 虚拟地址宽度 | 48 bits | 52 bits |
| 总虚拟地址空间 | 256 TB | 4 PB |
| 用户空间大小 | 128 TB | 2 PB |
| 内核空间大小 | 128 TB | 2 PB |
| 页表层级 | 3级(4KB页)/ 2级(64KB页) | 4级(4KB页)/ 3级(64KB页) |
| Linux 配置宏 | CONFIG_ARM64_VA_BITS_48 |
CONFIG_ARM64_VA_BITS_52 |
关键点: 52 位地址空间需要硬件支持(ARMv8.2 及以上),并且需要启用
CONFIG_ARM64_VA_BITS_52。目前大多数通用硬件仍使用 48 位地址空间。
2.2 用户空间与内核空间的划分
在 ARM64 Linux 中,虚拟地址空间的高位决定区域归属:
- 用户空间:地址范围从
0x0000_0000_0000_0000到0x0000_FFFF_FFFF_FFFF(48位)或0x0000_FFFF_FFFF_FFFF_FFFF(52位)。 - 内核空间:地址范围从
0xFFFF_0000_0000_0000到0xFFFF_FFFF_FFFF_FFFF(48位)或0xFFFF_FFFF_FFFF_FFFF_FFFF(52位)。
内核空间与用户空间之间有一个巨大的“空洞”(Non-canonical 区域),用于捕获非法访问。
划分原则: 地址的最高有效位(MSB)决定空间归属。对于 48 位地址,如果 bit[47] = 0,则为用户空间;如果 bit[47] = 1,则为内核空间。对于 52 位地址,检查 bit[51]。
2.3 内核镜像映射区域
内核镜像(Kernel Image)被映射到内核空间的一个固定区域。在 ARM64 Linux 中,内核镜像映射区域通常位于内核空间的起始部分,称为 KIMAGE_VADDR。该区域包含内核代码段、数据段、初始化数据等。
内核镜像映射的关键特性:
- 线性映射(Direct Mapping):内核镜像通常使用线性映射(也称为恒等映射或直接映射),即虚拟地址与物理地址之间存在固定的偏移量(
PAGE_OFFSET)。 - 模块区域:内核模块(动态加载的驱动)被映射到
MODULES_VADDR区域,紧邻内核镜像。 - vmalloc 区域:用于内核动态分配的非连续内存映射。
- fixmap 区域:固定映射区域,用于早期引导或特殊用途。
| 区域名称 | 虚拟地址范围(48位) | 用途 |
|---|---|---|
| KIMAGE_VADDR | 0xFFFF_8000_0000_0000 |
内核镜像映射(代码、数据) |
| MODULES_VADDR | 0xFFFF_8000_0000_0000 + 内核大小 |
内核模块映射 |
| VMALLOC_START | 0xFFFF_8000_0000_0000 + 模块区域大小 |
vmalloc 动态映射 |
| FIXADDR_START | 靠近内核空间顶部 | 固定映射(如早期 I/O) |
注意: 内核镜像映射区域的具体地址范围取决于内核配置(
CONFIG_ARM64_VA_BITS)和内核大小。上述地址为典型值,实际运行时可通过 /proc/kallsyms 或内核日志查看。
2.4 用户空间布局
用户空间布局由内核的 mmap 机制和 ELF 加载器决定。典型的用户空间地址布局包括:
- 代码段(.text):从低地址开始加载(通常为
0x400000或0x555555554000)。 - 数据段(.data, .bss):紧接代码段之后。
- 堆(Heap):从数据段上方开始,向高地址增长。
- 栈(Stack):从用户空间顶部(
0x7FFFFF_FFFF_FFFF附近)向低地址增长。 - 共享库(mmap 区域):位于堆和栈之间,用于加载动态链接库。
ASLR(地址空间布局随机化): Linux 内核默认启用 ASLR,随机化堆、栈、mmap 基址和代码段加载地址,以增加攻击难度。可通过
/proc/sys/kernel/randomize_va_space 控制。
2.5 地址空间切换:用户态与内核态
当 CPU 在用户空间执行时,MMU 使用用户空间的页表(TTBR0_EL1)。当发生系统调用、异常或中断进入内核时,CPU 切换到内核空间,MMU 切换为使用内核空间的页表(TTBR1_EL1)。
| 执行模式 | 使用的页表基址寄存器 | 虚拟地址范围 | 特权级别 |
|---|---|---|---|
| 用户态(EL0) | TTBR0_EL1 | 用户空间 (低地址) | 无特权 |
| 内核态(EL1) | TTBR1_EL1 | 内核空间 (高地址) | 完全特权 |
硬件加速: ARM64 硬件通过 TCR_EL1(Translation Control Register)配置地址空间大小和页表属性。TCR_EL1 中的 T0SZ 和 T1SZ 字段分别控制用户空间和内核空间的地址位宽。