Linux 内核的文档描述了虚拟内存映射。
它说:
fffffe0000000000 - fffffe7fffffffff (=39 bits) cpu_entry_area mapping
这个“cpu入口区”是什么?是否可以通过某种方式访问运行的代码环3(即CPL3)?
我问这个问题是因为我正在试验 QEMU,并且似乎在 QEMU 来宾(Ubuntu 服务器 18.04)上运行的一些 CPL3 代码尝试(我不知道它是否成功)访问cpu_entry_area
.
起初,我以为我做错了什么,因为我认为所有高于0x00007fffffffffff
CPL3 的地址都无法访问,但后来我发现了vsyscall
(请参阅这里)。
我尝试从 QEMU 来宾中的 CPL3 代码访问vsyscall
内存(特别是*(int *)0xffffffffff600000
),并成功了,但是当我尝试访问cpu_entry_area
(特别是*(int *)0xfffffe0000000ee0
)时出现了段错误。
答案1
cpu_entry_area
包含允许 CPU 将控制权移交给内核所需的所有数据和代码。启用 KPTI 后,当用户空间运行时,仅映射内核的该部分。你可以看到它的定义arch/x86/include/asm/cpu_entry_area.h
: 它包含
- 全局数据表;
- 入口栈;
- 运输安全服务;
- 一套蹦床;
- 异常堆栈;
- 调试存储和缓冲区。
蹦床包含系统调用的入口点;参见例如arch/x86/entry/entry_64.S
它定义 64 位调用的入口点。
这些都无法从环 3 直接访问,但环 3 代码可以使用允许更改特权级别的 CPU 介导机制跳转到其中(例如CPUSYSCALL
指令)。
内核文档上页表隔离提供更多背景信息。