如何直接从32位切换到PAE分页?
How to switch from 32-bit to PAE paging directly?
我正在为我的个人研究开发一个微内核。我选择 运行 我的内核 0xf0000000
,为用户 space 程序留下 3.75 GiB。当我的内核启动时,它会设置 32 位分页(使用硬编码页面目录和页面 tables)。然后它检查主机是否支持 PAE 并设置页面目录指针 table (PDPT)。但是当我尝试将它加载到 %cr3
时,问题就来了。根据英特尔软件开发人员手册:
Software can transition between 32-bit paging and PAE paging by changing the value of CR4.PAE with MOV to CR4.
于是尝试使用以下代码切换到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 这么说),然后重置。我试着在 %cr4
之前写信给 %cr3
,但结果还是一样。
然后我尝试通过以下方式切换到 PAE 分页:取消设置 PG -> 设置 PAE -> 写入 %cr3
-> 设置 PG,我成功了。但是我想直接切换到 PAE 寻呼。这怎么可能?
Then I tried to switch to PAE paging by: unset PG -> set PAE -> write to %cr3 -> set PG and I succeeded. But I want switch to PAE paging directly. How is that possible?
不可能。
如果“plain paging”已经在use/enabled,那么你不能同时自动启用PAE和加载CR3,所以(不管你是先加载CR3再加载CR4,还是加载CR4首先然后尝试加载 CR3) 无论哪条指令先发生都会导致 CPU 在获取第二条指令之前崩溃。
唯一的办法就是暂时禁用分页。
终于找到了直接切换到PAE分页的方法,感谢@Brendan and his 。要直接从 32 位分页切换到 PAE 分页,我不得不欺骗 CPU。我的内核的虚拟基址在 0xf0000000
。因此,在我跳到更高的一半之后,前 960 个 PDE 未被使用。因此,我将新的 PDPT(页面目录指针 Table)复制到我的初始 32 位页面目录。然后我设置了 PAE 位,CPU 很高兴,因为它只读取了包含 PDPT 的初始页目录的前 32 个字节。
过程是这样的:
memcpy (initial_page_directory, new_pdpt, 32);
- 启用
%cr4
中的 PAE 位。 CPU 愉快地从您在步骤 1 中覆盖的初始页目录的前 32 个字节中读取 PDPT。
- 将新的 PDPT 加载到
%cr3
。
注意:如果您尝试在第 1 步和第 2 步之间访问前 32 MiB 的映射内存(如果已映射)(可能是未定义的行为或三重错误),则此过程将不起作用并重置)。
我正在为我的个人研究开发一个微内核。我选择 运行 我的内核 0xf0000000
,为用户 space 程序留下 3.75 GiB。当我的内核启动时,它会设置 32 位分页(使用硬编码页面目录和页面 tables)。然后它检查主机是否支持 PAE 并设置页面目录指针 table (PDPT)。但是当我尝试将它加载到 %cr3
时,问题就来了。根据英特尔软件开发人员手册:
Software can transition between 32-bit paging and PAE paging by changing the value of CR4.PAE with MOV to CR4.
于是尝试使用以下代码切换到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 这么说),然后重置。我试着在 %cr4
之前写信给 %cr3
,但结果还是一样。
然后我尝试通过以下方式切换到 PAE 分页:取消设置 PG -> 设置 PAE -> 写入 %cr3
-> 设置 PG,我成功了。但是我想直接切换到 PAE 寻呼。这怎么可能?
Then I tried to switch to PAE paging by: unset PG -> set PAE -> write to %cr3 -> set PG and I succeeded. But I want switch to PAE paging directly. How is that possible?
不可能。
如果“plain paging”已经在use/enabled,那么你不能同时自动启用PAE和加载CR3,所以(不管你是先加载CR3再加载CR4,还是加载CR4首先然后尝试加载 CR3) 无论哪条指令先发生都会导致 CPU 在获取第二条指令之前崩溃。
唯一的办法就是暂时禁用分页。
终于找到了直接切换到PAE分页的方法,感谢@Brendan and his 0xf0000000
。因此,在我跳到更高的一半之后,前 960 个 PDE 未被使用。因此,我将新的 PDPT(页面目录指针 Table)复制到我的初始 32 位页面目录。然后我设置了 PAE 位,CPU 很高兴,因为它只读取了包含 PDPT 的初始页目录的前 32 个字节。
过程是这样的:
memcpy (initial_page_directory, new_pdpt, 32);
- 启用
%cr4
中的 PAE 位。 CPU 愉快地从您在步骤 1 中覆盖的初始页目录的前 32 个字节中读取 PDPT。 - 将新的 PDPT 加载到
%cr3
。
注意:如果您尝试在第 1 步和第 2 步之间访问前 32 MiB 的映射内存(如果已映射)(可能是未定义的行为或三重错误),则此过程将不起作用并重置)。