assembly - 如何直接从 32 位切换到 PAE 分页?
问题描述
我正在为我的个人研究开发一个微内核。我选择在 运行我的内核0xf0000000
,为用户空间程序留下 3.75 GiB。当我的内核启动时,它会设置 32 位分页(带有硬编码的页目录和页表)。然后它检查主机是否支持 PAE 并设置页面目录指针表 (PDPT)。但是当我尝试将其加载到%cr3
. 根据英特尔软件开发人员手册:
软件可以通过将带有 MOV 的 CR4.PAE 的值更改为 CR4 来在 32 位分页和 PAE 分页之间转换。
于是尝试使用如下代码切换到PAE分页:
movl %cr4, %eax
orl $(1 << 5), %eax
movl %eax, %cr4
movl %ebx, %cr3 // %ebx holds physical address to PDPT
或者,在 Intel 语法(或 NASM)中:
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
mov cr3, ebx // ebx holds physical address to PDPT
但它失败了(在 QEMU 上)。它写入%cr4
,设置%eip
到下一条指令,执行它(至少 GDB 这么说),然后重置。%cr3
我之前尝试写信%cr4
,但结果仍然相同。
然后我尝试通过以下方式切换到 PAE 分页:unset PG -> set PAE -> write to %cr3
-> set PG,我成功了。但我想直接切换到 PAE 分页。这怎么可能?
解决方案
最后,感谢@Brendan和他的宝贵评论,我找到了直接切换到 PAE 分页的方法。要直接从 32 位分页切换到 PAE 分页,我不得不欺骗 CPU。我的内核的虚拟基础位于0xf0000000
. 所以在我跳到更高的一半之后,前 960 个 PDE 没有被使用。因此,我将新的 PDPT(页面目录指针表)复制到了我最初的 32 位页面目录。然后我设置了 PAE 位,CPU 很高兴,因为它只读取了保存 PDPT 的初始页面目录的前 32 个字节。
过程是这样的:
memcpy (initial_page_directory, new_pdpt, 32);
- 启用 PAE 位
%cr4
。CPU 愉快地从您在步骤 1 中覆盖的初始页面目录的前 32 个字节读取 PDPT。 - 将您的新 PDPT 加载到
%cr3
.
注意:如果您尝试在第 1 步和第 2 步之间访问前 32 MiB 的映射内存(如果您已映射它)(可能是未定义的行为或可能是三重故障和重置),则此过程将不起作用。
推荐阅读
- websocket - MediaSource 缓冲区仅适用于一个客户端
- ios - UIScrollView contentInset 在设置后正在改变
- python - 如何将此特定的 json 文件转换为数据框?
- c# - 无法编译映射文件 nhibernate
- angular - Angular 5 路由有效,但在更改浏览器 url 时无效
- ios - 使用 Uri Savely 加载托管对象
- java - Firebase 嵌套结构搜索
- c++ - 我将如何搜索这个包含数组的文件以查找任何剩余的船只?
- java - 整数不是参考吗?为什么公司不更新哈希图值?
- ios - 将录制的音频上传到 Firebase