为什么 QEMU return 在填充 PML4 的高半部分时地址错误?
Why does QEMU return the wrong addresses when filling the higher half of the PML4?
我正在编写一个小型 x86-64 OS 我使用 UEFI 启动。我试图通过将内核的可执行文件移动到 0x800000000000 来使内核成为高半内核。这个地址应该在 PML4 的中间。基本上,我应该填写 PML4 的条目 256 来解决这个较高的一半。我尝试这样做,但我的代码出现三重故障。由于我在 QEMU 上测试内核并使用 GDB 进行调试,因此我在 GDB 中使用 monitor info mem
来查看虚拟地址到物理地址的映射。它返回以下内容:
(gdb) monitor info mem
0000000000000000-0000000000400000 0000000000400000 -rw
ffff800000000000-ffff800000c00000 0000000000c00000 -rw
它映射的不是 0x800000000000,而是 ffff800000000000。这可能就是为什么当我跳到上半部分时代码出现三重错误的原因。这是我的代码的一个小例子:
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef unsigned long UINT64;
struct GDT{
UINT64 nullDescriptor;
UINT16 codeLimit;
UINT16 codeBaseLow;
UINT8 codeBaseMid;
UINT8 codeFlags;
UINT8 codeLimitMid;
UINT8 codeBaseHigh;
UINT16 dataLimit;
UINT16 dataBaseLow;
UINT8 dataBaseMid;
UINT8 dataFlags;
UINT8 dataLimitMid;
UINT8 dataBaseHigh;
}__attribute__((packed));
struct GDTR{
UINT16 size;
GDT* address;
}__attribute__((packed));
void main(){
//Identity mapping for the first 4MB
UINT64* pml4Ptr = (UINT64*)0x200000;
*pml4Ptr = 0x20101b;
UINT64* pdpPtr = (UINT64*)0x201000;
*pdpPtr = 0x20201b;
UINT64* pdPtr = (UINT64*)0x202000;
*pdPtr = 0x20301b;
*(pdPtr + 1) = 0x20401b;
UINT64* ptPtr = (UINT64*)0x203000;
UINT64 physAddr = 0x1b;
for (UINT32 i = 0; i < 2 * 512; i++){
*(ptPtr + i) = physAddr;
physAddr += 0x1000;
}
//Kernel mapping for the higher half
*(pml4Ptr + 256) = 0x20601b; //When this is less then 256 I get the right addresses
pdpPtr = (UINT64*)0x206000;
*pdpPtr = 0x20701b;
pdPtr = (UINT64*)0x207000;
*pdPtr = 0x20801b;
*(pdPtr + 1) = 0x20901b;
*(pdPtr + 2) = 0x20a01b;
*(pdPtr + 3) = 0x20b01b;
*(pdPtr + 4) = 0x20c01b;
*(pdPtr + 5) = 0x20d01b;
ptPtr = (UINT64*)0x208000;
physAddr = 0x1b;
for (UINT32 i = 0; i < 6 * 512; i++){
*(ptPtr + i) = physAddr;
physAddr += 0x1000;
}
asm volatile(
"movq [=12=]x200018, %rax\n\t"
"mov %rax, %cr3\n\t"
"movq [=12=]x375000, %rsp\n\t"
);
GDT gdt = {
.nullDescriptor = 0,
.codeLimit = 0x0000,
.codeBaseLow = 0,
.codeBaseMid = 0,
.codeFlags = 0x9a,
.codeLimitMid = 0xaf,
.codeBaseHigh = 0,
.dataLimit = 0x0000,
.dataBaseLow = 0,
.dataBaseMid = 0,
.dataFlags = 0x92,
.dataLimitMid = 0x00,
.dataBaseHigh = 0
};
GDT* gdtAddr = &gdt;
GDTR gdtr = { 23, gdtAddr };
GDTR* gdtrAddr = &gdtr;
asm volatile("lgdt (%0)" : : "r"(gdtrAddr));
asm volatile(
"sub , %rsp\n\t"
"movq , 8(%rsp)\n\t"
"movabsq $fun, %rax\n\t"
"mov %rax, (%rsp)\n\t"
"lretq\n\t"
"fun:\n\t"
"movq [=12=]x10, %rax\n\t"
"mov %ax, %ss\n\t"
"mov %ax, %es\n\t"
"mov %ax, %ds\n\t"
"mov %ax, %gs\n\t"
"mov %ax, %fs\n\t"
"hlt"
);
}
我有一个指向 PML4 地址的指针,然后我 *(pml4Ptr + 256) = 0x20601b;
。这应该在没有缓存的情况下将 PML4 的条目 256 映射到 0x206000。内核映射部分下的其余小代码片段应该将 12MB 的数据映射到从物理地址 0 开始的虚拟地址的高半部分。相反,我得到上面的地址,这看起来很奇怪。
如果我用相同的代码 (*(pml4Ptr + 255) = 0x20601b;
) 设置 PML4 的条目 255,我得到以下结果:
(gdb) monitor info mem
0000000000000000-0000000000400000 0000000000400000 -rw
00007f8000000000-00007f8000c00000 0000000000c00000 -rw
我居然找到了正确的地址!?当您填充上半部分时,是否存在 QEMU 无法正确处理 PML4 的已知错误,或者我在代码中忽略了什么?
我还直接查看了页表(因为它们位于 RAM 中的静态位置)。我得到以下结果:
user@user-System-Product-Name:~$ hexdump -C result.bin
00000000 3b 10 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |;. .............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000800 1b 60 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |.` .............|
00000810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 3b 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |; .............|
00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000 1b 30 20 00 00 00 00 00 3b 40 20 00 00 00 00 00 |.0 .....;@ .....|
00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00003000 1b 00 00 00 00 00 00 00 1b 10 00 00 00 00 00 00 |................|
00003010 1b 20 00 00 00 00 00 00 1b 30 00 00 00 00 00 00 |. .......0......|
00003020 1b 40 00 00 00 00 00 00 1b 50 00 00 00 00 00 00 |.@.......P......|
00003030 1b 60 00 00 00 00 00 00 1b 70 00 00 00 00 00 00 |.`.......p......|
00003040 1b 80 00 00 00 00 00 00 1b 90 00 00 00 00 00 00 |................|
00003050 1b a0 00 00 00 00 00 00 1b b0 00 00 00 00 00 00 |................|
00003060 1b c0 00 00 00 00 00 00 1b d0 00 00 00 00 00 00 |................|
00003070 1b e0 00 00 00 00 00 00 1b f0 00 00 00 00 00 00 |................|
00003080 1b 00 01 00 00 00 00 00 1b 10 01 00 00 00 00 00 |................|
00003090 1b 20 01 00 00 00 00 00 1b 30 01 00 00 00 00 00 |. .......0......|
000030a0 1b 40 01 00 00 00 00 00 1b 50 01 00 00 00 00 00 |.@.......P......|
000030b0 1b 60 01 00 00 00 00 00 1b 70 01 00 00 00 00 00 |.`.......p......|
000030c0 1b 80 01 00 00 00 00 00 1b 90 01 00 00 00 00 00 |................|
000030d0 1b a0 01 00 00 00 00 00 1b b0 01 00 00 00 00 00 |................|
000030e0 1b c0 01 00 00 00 00 00 1b d0 01 00 00 00 00 00 |................|
000030f0 1b e0 01 00 00 00 00 00 1b f0 01 00 00 00 00 00 |................|
00003100 1b 00 02 00 00 00 00 00 1b 10 02 00 00 00 00 00 |................|
00003110 1b 20 02 00 00 00 00 00 1b 30 02 00 00 00 00 00 |. .......0......|
00003120 1b 40 02 00 00 00 00 00 1b 50 02 00 00 00 00 00 |.@.......P......|
00003130 1b 60 02 00 00 00 00 00 1b 70 02 00 00 00 00 00 |.`.......p......|
00003140 1b 80 02 00 00 00 00 00 1b 90 02 00 00 00 00 00 |................|
00003150 1b a0 02 00 00 00 00 00 1b b0 02 00 00 00 00 00 |................|
00003160 1b c0 02 00 00 00 00 00 1b d0 02 00 00 00 00 00 |................|
00003170 1b e0 02 00 00 00 00 00 1b f0 02 00 00 00 00 00 |................|
00003180 1b 00 03 00 00 00 00 00 1b 10 03 00 00 00 00 00 |................|
00003190 1b 20 03 00 00 00 00 00 1b 30 03 00 00 00 00 00 |. .......0......|
000031a0 1b 40 03 00 00 00 00 00 1b 50 03 00 00 00 00 00 |.@.......P......|
000031b0 1b 60 03 00 00 00 00 00 1b 70 03 00 00 00 00 00 |.`.......p......|
000031c0 1b 80 03 00 00 00 00 00 1b 90 03 00 00 00 00 00 |................|
000031d0 1b a0 03 00 00 00 00 00 1b b0 03 00 00 00 00 00 |................|
000031e0 1b c0 03 00 00 00 00 00 1b d0 03 00 00 00 00 00 |................|
000031f0 1b e0 03 00 00 00 00 00 1b f0 03 00 00 00 00 00 |................|
00003200 1b 00 04 00 00 00 00 00 1b 10 04 00 00 00 00 00 |................|
00003210 1b 20 04 00 00 00 00 00 1b 30 04 00 00 00 00 00 |. .......0......|
00003220 1b 40 04 00 00 00 00 00 1b 50 04 00 00 00 00 00 |.@.......P......|
00003230 1b 60 04 00 00 00 00 00 1b 70 04 00 00 00 00 00 |.`.......p......|
00003240 1b 80 04 00 00 00 00 00 1b 90 04 00 00 00 00 00 |................|
00003250 1b a0 04 00 00 00 00 00 1b b0 04 00 00 00 00 00 |................|
00003260 1b c0 04 00 00 00 00 00 1b d0 04 00 00 00 00 00 |................|
00003270 1b e0 04 00 00 00 00 00 1b f0 04 00 00 00 00 00 |................|
00003280 1b 00 05 00 00 00 00 00 1b 10 05 00 00 00 00 00 |................|
...
...
00004fa0 1b 40 3f 00 00 00 00 00 1b 50 3f 00 00 00 00 00 |.@?......P?.....|
00004fb0 1b 60 3f 00 00 00 00 00 1b 70 3f 00 00 00 00 00 |.`?......p?.....|
00004fc0 1b 80 3f 00 00 00 00 00 1b 90 3f 00 00 00 00 00 |..?.......?.....|
00004fd0 1b a0 3f 00 00 00 00 00 1b b0 3f 00 00 00 00 00 |..?.......?.....|
00004fe0 1b c0 3f 00 00 00 00 00 1b d0 3f 00 00 00 00 00 |..?.......?.....|
00004ff0 1b e0 3f 00 00 00 00 00 1b f0 3f 00 00 00 00 00 |..?.......?.....|
00005000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00006000 1b 70 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |.p .............|
00006010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00007000 1b 80 20 00 00 00 00 00 1b 90 20 00 00 00 00 00 |.. ....... .....|
00007010 1b a0 20 00 00 00 00 00 1b b0 20 00 00 00 00 00 |.. ....... .....|
00007020 1b c0 20 00 00 00 00 00 1b d0 20 00 00 00 00 00 |.. ....... .....|
00007030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00008000 1b 00 00 00 00 00 00 00 1b 10 00 00 00 00 00 00 |................|
00008010 1b 20 00 00 00 00 00 00 1b 30 00 00 00 00 00 00 |. .......0......|
00008020 1b 40 00 00 00 00 00 00 1b 50 00 00 00 00 00 00 |.@.......P......|
00008030 1b 60 00 00 00 00 00 00 1b 70 00 00 00 00 00 00 |.`.......p......|
00008040 1b 80 00 00 00 00 00 00 1b 90 00 00 00 00 00 00 |................|
00008050 1b a0 00 00 00 00 00 00 1b b0 00 00 00 00 00 00 |................|
00008060 1b c0 00 00 00 00 00 00 1b d0 00 00 00 00 00 00 |................|
00008070 1b e0 00 00 00 00 00 00 1b f0 00 00 00 00 00 00 |................|
00008080 1b 00 01 00 00 00 00 00 1b 10 01 00 00 00 00 00 |................|
00008090 1b 20 01 00 00 00 00 00 1b 30 01 00 00 00 00 00 |. .......0......|
000080a0 1b 40 01 00 00 00 00 00 1b 50 01 00 00 00 00 00 |.@.......P......|
000080b0 1b 60 01 00 00 00 00 00 1b 70 01 00 00 00 00 00 |.`.......p......|
000080c0 1b 80 01 00 00 00 00 00 1b 90 01 00 00 00 00 00 |................|
000080d0 1b a0 01 00 00 00 00 00 1b b0 01 00 00 00 00 00 |................|
000080e0 1b c0 01 00 00 00 00 00 1b d0 01 00 00 00 00 00 |................|
000080f0 1b e0 01 00 00 00 00 00 1b f0 01 00 00 00 00 00 |................|
00008100 1b 00 02 00 00 00 00 00 1b 10 02 00 00 00 00 00 |................|
00008110 1b 20 02 00 00 00 00 00 1b 30 02 00 00 00 00 00 |. .......0......|
00008120 1b 40 02 00 00 00 00 00 1b 50 02 00 00 00 00 00 |.@.......P......|
00008130 1b 60 02 00 00 00 00 00 1b 70 02 00 00 00 00 00 |.`.......p......|
00008140 1b 80 02 00 00 00 00 00 1b 90 02 00 00 00 00 00 |................|
00008150 1b a0 02 00 00 00 00 00 1b b0 02 00 00 00 00 00 |................|
00008160 1b c0 02 00 00 00 00 00 1b d0 02 00 00 00 00 00 |................|
00008170 1b e0 02 00 00 00 00 00 1b f0 02 00 00 00 00 00 |................|
00008180 1b 00 03 00 00 00 00 00 1b 10 03 00 00 00 00 00 |................|
00008190 1b 20 03 00 00 00 00 00 1b 30 03 00 00 00 00 00 |. .......0......|
000081a0 1b 40 03 00 00 00 00 00 1b 50 03 00 00 00 00 00 |.@.......P......|
000081b0 1b 60 03 00 00 00 00 00 1b 70 03 00 00 00 00 00 |.`.......p......|
000081c0 1b 80 03 00 00 00 00 00 1b 90 03 00 00 00 00 00 |................|
000081d0 1b a0 03 00 00 00 00 00 1b b0 03 00 00 00 00 00 |................|
000081e0 1b c0 03 00 00 00 00 00 1b d0 03 00 00 00 00 00 |................|
000081f0 1b e0 03 00 00 00 00 00 1b f0 03 00 00 00 00 00 |................|
00008200 1b 00 04 00 00 00 00 00 1b 10 04 00 00 00 00 00 |................|
00008210 1b 20 04 00 00 00 00 00 1b 30 04 00 00 00 00 00 |. .......0......|
00008220 1b 40 04 00 00 00 00 00 1b 50 04 00 00 00 00 00 |.@.......P......|
00008230 1b 60 04 00 00 00 00 00 1b 70 04 00 00 00 00 00 |.`.......p......|
00008240 1b 80 04 00 00 00 00 00 1b 90 04 00 00 00 00 00 |................|
00008250 1b a0 04 00 00 00 00 00 1b b0 04 00 00 00 00 00 |................|
00008260 1b c0 04 00 00 00 00 00 1b d0 04 00 00 00 00 00 |................|
00008270 1b e0 04 00 00 00 00 00 1b f0 04 00 00 00 00 00 |................|
00008280 1b 00 05 00 00 00 00 00 1b 10 05 00 00 00 00 00 |................|
00008290 1b 20 05 00 00 00 00 00 1b 30 05 00 00 00 00 00 |. .......0......|
000082a0 1b 40 05 00 00 00 00 00 1b 50 05 00 00 00 00 00 |.@.......P......|
000082b0 1b 60 05 00 00 00 00 00 1b 70 05 00 00 00 00 00 |.`.......p......|
000082c0 1b 80 05 00 00 00 00 00 1b 90 05 00 00 00 00 00 |................|
000082d0 1b a0 05 00 00 00 00 00 1b b0 05 00 00 00 00 00 |................|
000082e0 1b c0 05 00 00 00 00 00 1b d0 05 00 00 00 00 00 |................|
000082f0 1b e0 05 00 00 00 00 00 1b f0 05 00 00 00 00 00 |................|
00008300 1b 00 06 00 00 00 00 00 1b 10 06 00 00 00 00 00 |................|
00008310 1b 20 06 00 00 00 00 00 1b 30 06 00 00 00 00 00 |. .......0......|
00008320 1b 40 06 00 00 00 00 00 1b 50 06 00 00 00 00 00 |.@.......P......|
00008330 1b 60 06 00 00 00 00 00 1b 70 06 00 00 00 00 00 |.`.......p......|
00008340 1b 80 06 00 00 00 00 00 1b 90 06 00 00 00 00 00 |................|
00008350 1b a0 06 00 00 00 00 00 1b b0 06 00 00 00 00 00 |................|
00008360 1b c0 06 00 00 00 00 00 1b d0 06 00 00 00 00 00 |................|
00008370 1b e0 06 00 00 00 00 00 1b f0 06 00 00 00 00 00 |................|
00008380 1b 00 07 00 00 00 00 00 1b 10 07 00 00 00 00 00 |................|
00008390 1b 20 07 00 00 00 00 00 1b 30 07 00 00 00 00 00 |. .......0......|
000083a0 1b 40 07 00 00 00 00 00 1b 50 07 00 00 00 00 00 |.@.......P......|
000083b0 1b 60 07 00 00 00 00 00 1b 70 07 00 00 00 00 00 |.`.......p......|
000083c0 1b 80 07 00 00 00 00 00 1b 90 07 00 00 00 00 00 |................|
000083d0 1b a0 07 00 00 00 00 00 1b b0 07 00 00 00 00 00 |................|
000083e0 1b c0 07 00 00 00 00 00 1b d0 07 00 00 00 00 00 |................|
这个转储似乎是正确的。它从 0x200000 开始。这意味着转储中的地址 0 是 0x200000,地址 0x1000 是 0x201000 等
我用这个脚本编译代码:
g++ -fomit-frame-pointer --static -ffreestanding -nostdlib -mgeneral-regs-only -mno-red-zone -c -m64 Startup/Source/Main.cpp -oStartup/Object/Main.o
ld -entry main --oformat elf64-x86-64 --no-dynamic-linker -static -nostdlib -Ttext-segment=300000 Startup/Object/Main.o -ostartup.elf
谁能指出代码的任何问题或我忽略的任何问题?
0x800000000000
不是规范地址,因此页面目录布局中没有它的位置。 (并且尝试取消引用它会 #GP
出错,而不是触发 TLB 未命中 => 页面遍历。)
您有 PML4,因此前 16 个虚拟地址位必须是位 #47 的副本。即指针必须可以表示为 48 位值符号扩展到 64 位。
即 ((int64_t)addr << 16) >> 16 == addr
必须为真。
(右移使用sar
算术右移)。
(x86-64 canonical address?).
可用(规范)范围的上半部分实际上确实从ffff800000000000
开始,PML4E为它确实紧跟在下半部分的顶部 00007f8000000000
.
之后
包含虚拟地址 space.
中空洞的 ASCII 图
关于低半部分顶部的位置是正确的,但是您忘记将符号扩展 0x800000000000
到 64 位以到达高半部分的底部。指针名义上仍然是 64 位,而不仅仅是截断为 48 位。这就是为什么像 ffff800000000000
这样的地址可以存在的原因。
如果您启用了 PML5(例如 Ice Lake 硬件或该功能的软件仿真),额外级别的页面目录将使您获得最多 57 位的虚拟地址 space,从而可以地址 0x800000000000
.
另见
我正在编写一个小型 x86-64 OS 我使用 UEFI 启动。我试图通过将内核的可执行文件移动到 0x800000000000 来使内核成为高半内核。这个地址应该在 PML4 的中间。基本上,我应该填写 PML4 的条目 256 来解决这个较高的一半。我尝试这样做,但我的代码出现三重故障。由于我在 QEMU 上测试内核并使用 GDB 进行调试,因此我在 GDB 中使用 monitor info mem
来查看虚拟地址到物理地址的映射。它返回以下内容:
(gdb) monitor info mem
0000000000000000-0000000000400000 0000000000400000 -rw
ffff800000000000-ffff800000c00000 0000000000c00000 -rw
它映射的不是 0x800000000000,而是 ffff800000000000。这可能就是为什么当我跳到上半部分时代码出现三重错误的原因。这是我的代码的一个小例子:
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef unsigned long UINT64;
struct GDT{
UINT64 nullDescriptor;
UINT16 codeLimit;
UINT16 codeBaseLow;
UINT8 codeBaseMid;
UINT8 codeFlags;
UINT8 codeLimitMid;
UINT8 codeBaseHigh;
UINT16 dataLimit;
UINT16 dataBaseLow;
UINT8 dataBaseMid;
UINT8 dataFlags;
UINT8 dataLimitMid;
UINT8 dataBaseHigh;
}__attribute__((packed));
struct GDTR{
UINT16 size;
GDT* address;
}__attribute__((packed));
void main(){
//Identity mapping for the first 4MB
UINT64* pml4Ptr = (UINT64*)0x200000;
*pml4Ptr = 0x20101b;
UINT64* pdpPtr = (UINT64*)0x201000;
*pdpPtr = 0x20201b;
UINT64* pdPtr = (UINT64*)0x202000;
*pdPtr = 0x20301b;
*(pdPtr + 1) = 0x20401b;
UINT64* ptPtr = (UINT64*)0x203000;
UINT64 physAddr = 0x1b;
for (UINT32 i = 0; i < 2 * 512; i++){
*(ptPtr + i) = physAddr;
physAddr += 0x1000;
}
//Kernel mapping for the higher half
*(pml4Ptr + 256) = 0x20601b; //When this is less then 256 I get the right addresses
pdpPtr = (UINT64*)0x206000;
*pdpPtr = 0x20701b;
pdPtr = (UINT64*)0x207000;
*pdPtr = 0x20801b;
*(pdPtr + 1) = 0x20901b;
*(pdPtr + 2) = 0x20a01b;
*(pdPtr + 3) = 0x20b01b;
*(pdPtr + 4) = 0x20c01b;
*(pdPtr + 5) = 0x20d01b;
ptPtr = (UINT64*)0x208000;
physAddr = 0x1b;
for (UINT32 i = 0; i < 6 * 512; i++){
*(ptPtr + i) = physAddr;
physAddr += 0x1000;
}
asm volatile(
"movq [=12=]x200018, %rax\n\t"
"mov %rax, %cr3\n\t"
"movq [=12=]x375000, %rsp\n\t"
);
GDT gdt = {
.nullDescriptor = 0,
.codeLimit = 0x0000,
.codeBaseLow = 0,
.codeBaseMid = 0,
.codeFlags = 0x9a,
.codeLimitMid = 0xaf,
.codeBaseHigh = 0,
.dataLimit = 0x0000,
.dataBaseLow = 0,
.dataBaseMid = 0,
.dataFlags = 0x92,
.dataLimitMid = 0x00,
.dataBaseHigh = 0
};
GDT* gdtAddr = &gdt;
GDTR gdtr = { 23, gdtAddr };
GDTR* gdtrAddr = &gdtr;
asm volatile("lgdt (%0)" : : "r"(gdtrAddr));
asm volatile(
"sub , %rsp\n\t"
"movq , 8(%rsp)\n\t"
"movabsq $fun, %rax\n\t"
"mov %rax, (%rsp)\n\t"
"lretq\n\t"
"fun:\n\t"
"movq [=12=]x10, %rax\n\t"
"mov %ax, %ss\n\t"
"mov %ax, %es\n\t"
"mov %ax, %ds\n\t"
"mov %ax, %gs\n\t"
"mov %ax, %fs\n\t"
"hlt"
);
}
我有一个指向 PML4 地址的指针,然后我 *(pml4Ptr + 256) = 0x20601b;
。这应该在没有缓存的情况下将 PML4 的条目 256 映射到 0x206000。内核映射部分下的其余小代码片段应该将 12MB 的数据映射到从物理地址 0 开始的虚拟地址的高半部分。相反,我得到上面的地址,这看起来很奇怪。
如果我用相同的代码 (*(pml4Ptr + 255) = 0x20601b;
) 设置 PML4 的条目 255,我得到以下结果:
(gdb) monitor info mem
0000000000000000-0000000000400000 0000000000400000 -rw
00007f8000000000-00007f8000c00000 0000000000c00000 -rw
我居然找到了正确的地址!?当您填充上半部分时,是否存在 QEMU 无法正确处理 PML4 的已知错误,或者我在代码中忽略了什么?
我还直接查看了页表(因为它们位于 RAM 中的静态位置)。我得到以下结果:
user@user-System-Product-Name:~$ hexdump -C result.bin
00000000 3b 10 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |;. .............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000800 1b 60 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |.` .............|
00000810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 3b 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |; .............|
00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000 1b 30 20 00 00 00 00 00 3b 40 20 00 00 00 00 00 |.0 .....;@ .....|
00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00003000 1b 00 00 00 00 00 00 00 1b 10 00 00 00 00 00 00 |................|
00003010 1b 20 00 00 00 00 00 00 1b 30 00 00 00 00 00 00 |. .......0......|
00003020 1b 40 00 00 00 00 00 00 1b 50 00 00 00 00 00 00 |.@.......P......|
00003030 1b 60 00 00 00 00 00 00 1b 70 00 00 00 00 00 00 |.`.......p......|
00003040 1b 80 00 00 00 00 00 00 1b 90 00 00 00 00 00 00 |................|
00003050 1b a0 00 00 00 00 00 00 1b b0 00 00 00 00 00 00 |................|
00003060 1b c0 00 00 00 00 00 00 1b d0 00 00 00 00 00 00 |................|
00003070 1b e0 00 00 00 00 00 00 1b f0 00 00 00 00 00 00 |................|
00003080 1b 00 01 00 00 00 00 00 1b 10 01 00 00 00 00 00 |................|
00003090 1b 20 01 00 00 00 00 00 1b 30 01 00 00 00 00 00 |. .......0......|
000030a0 1b 40 01 00 00 00 00 00 1b 50 01 00 00 00 00 00 |.@.......P......|
000030b0 1b 60 01 00 00 00 00 00 1b 70 01 00 00 00 00 00 |.`.......p......|
000030c0 1b 80 01 00 00 00 00 00 1b 90 01 00 00 00 00 00 |................|
000030d0 1b a0 01 00 00 00 00 00 1b b0 01 00 00 00 00 00 |................|
000030e0 1b c0 01 00 00 00 00 00 1b d0 01 00 00 00 00 00 |................|
000030f0 1b e0 01 00 00 00 00 00 1b f0 01 00 00 00 00 00 |................|
00003100 1b 00 02 00 00 00 00 00 1b 10 02 00 00 00 00 00 |................|
00003110 1b 20 02 00 00 00 00 00 1b 30 02 00 00 00 00 00 |. .......0......|
00003120 1b 40 02 00 00 00 00 00 1b 50 02 00 00 00 00 00 |.@.......P......|
00003130 1b 60 02 00 00 00 00 00 1b 70 02 00 00 00 00 00 |.`.......p......|
00003140 1b 80 02 00 00 00 00 00 1b 90 02 00 00 00 00 00 |................|
00003150 1b a0 02 00 00 00 00 00 1b b0 02 00 00 00 00 00 |................|
00003160 1b c0 02 00 00 00 00 00 1b d0 02 00 00 00 00 00 |................|
00003170 1b e0 02 00 00 00 00 00 1b f0 02 00 00 00 00 00 |................|
00003180 1b 00 03 00 00 00 00 00 1b 10 03 00 00 00 00 00 |................|
00003190 1b 20 03 00 00 00 00 00 1b 30 03 00 00 00 00 00 |. .......0......|
000031a0 1b 40 03 00 00 00 00 00 1b 50 03 00 00 00 00 00 |.@.......P......|
000031b0 1b 60 03 00 00 00 00 00 1b 70 03 00 00 00 00 00 |.`.......p......|
000031c0 1b 80 03 00 00 00 00 00 1b 90 03 00 00 00 00 00 |................|
000031d0 1b a0 03 00 00 00 00 00 1b b0 03 00 00 00 00 00 |................|
000031e0 1b c0 03 00 00 00 00 00 1b d0 03 00 00 00 00 00 |................|
000031f0 1b e0 03 00 00 00 00 00 1b f0 03 00 00 00 00 00 |................|
00003200 1b 00 04 00 00 00 00 00 1b 10 04 00 00 00 00 00 |................|
00003210 1b 20 04 00 00 00 00 00 1b 30 04 00 00 00 00 00 |. .......0......|
00003220 1b 40 04 00 00 00 00 00 1b 50 04 00 00 00 00 00 |.@.......P......|
00003230 1b 60 04 00 00 00 00 00 1b 70 04 00 00 00 00 00 |.`.......p......|
00003240 1b 80 04 00 00 00 00 00 1b 90 04 00 00 00 00 00 |................|
00003250 1b a0 04 00 00 00 00 00 1b b0 04 00 00 00 00 00 |................|
00003260 1b c0 04 00 00 00 00 00 1b d0 04 00 00 00 00 00 |................|
00003270 1b e0 04 00 00 00 00 00 1b f0 04 00 00 00 00 00 |................|
00003280 1b 00 05 00 00 00 00 00 1b 10 05 00 00 00 00 00 |................|
...
...
00004fa0 1b 40 3f 00 00 00 00 00 1b 50 3f 00 00 00 00 00 |.@?......P?.....|
00004fb0 1b 60 3f 00 00 00 00 00 1b 70 3f 00 00 00 00 00 |.`?......p?.....|
00004fc0 1b 80 3f 00 00 00 00 00 1b 90 3f 00 00 00 00 00 |..?.......?.....|
00004fd0 1b a0 3f 00 00 00 00 00 1b b0 3f 00 00 00 00 00 |..?.......?.....|
00004fe0 1b c0 3f 00 00 00 00 00 1b d0 3f 00 00 00 00 00 |..?.......?.....|
00004ff0 1b e0 3f 00 00 00 00 00 1b f0 3f 00 00 00 00 00 |..?.......?.....|
00005000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00006000 1b 70 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |.p .............|
00006010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00007000 1b 80 20 00 00 00 00 00 1b 90 20 00 00 00 00 00 |.. ....... .....|
00007010 1b a0 20 00 00 00 00 00 1b b0 20 00 00 00 00 00 |.. ....... .....|
00007020 1b c0 20 00 00 00 00 00 1b d0 20 00 00 00 00 00 |.. ....... .....|
00007030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00008000 1b 00 00 00 00 00 00 00 1b 10 00 00 00 00 00 00 |................|
00008010 1b 20 00 00 00 00 00 00 1b 30 00 00 00 00 00 00 |. .......0......|
00008020 1b 40 00 00 00 00 00 00 1b 50 00 00 00 00 00 00 |.@.......P......|
00008030 1b 60 00 00 00 00 00 00 1b 70 00 00 00 00 00 00 |.`.......p......|
00008040 1b 80 00 00 00 00 00 00 1b 90 00 00 00 00 00 00 |................|
00008050 1b a0 00 00 00 00 00 00 1b b0 00 00 00 00 00 00 |................|
00008060 1b c0 00 00 00 00 00 00 1b d0 00 00 00 00 00 00 |................|
00008070 1b e0 00 00 00 00 00 00 1b f0 00 00 00 00 00 00 |................|
00008080 1b 00 01 00 00 00 00 00 1b 10 01 00 00 00 00 00 |................|
00008090 1b 20 01 00 00 00 00 00 1b 30 01 00 00 00 00 00 |. .......0......|
000080a0 1b 40 01 00 00 00 00 00 1b 50 01 00 00 00 00 00 |.@.......P......|
000080b0 1b 60 01 00 00 00 00 00 1b 70 01 00 00 00 00 00 |.`.......p......|
000080c0 1b 80 01 00 00 00 00 00 1b 90 01 00 00 00 00 00 |................|
000080d0 1b a0 01 00 00 00 00 00 1b b0 01 00 00 00 00 00 |................|
000080e0 1b c0 01 00 00 00 00 00 1b d0 01 00 00 00 00 00 |................|
000080f0 1b e0 01 00 00 00 00 00 1b f0 01 00 00 00 00 00 |................|
00008100 1b 00 02 00 00 00 00 00 1b 10 02 00 00 00 00 00 |................|
00008110 1b 20 02 00 00 00 00 00 1b 30 02 00 00 00 00 00 |. .......0......|
00008120 1b 40 02 00 00 00 00 00 1b 50 02 00 00 00 00 00 |.@.......P......|
00008130 1b 60 02 00 00 00 00 00 1b 70 02 00 00 00 00 00 |.`.......p......|
00008140 1b 80 02 00 00 00 00 00 1b 90 02 00 00 00 00 00 |................|
00008150 1b a0 02 00 00 00 00 00 1b b0 02 00 00 00 00 00 |................|
00008160 1b c0 02 00 00 00 00 00 1b d0 02 00 00 00 00 00 |................|
00008170 1b e0 02 00 00 00 00 00 1b f0 02 00 00 00 00 00 |................|
00008180 1b 00 03 00 00 00 00 00 1b 10 03 00 00 00 00 00 |................|
00008190 1b 20 03 00 00 00 00 00 1b 30 03 00 00 00 00 00 |. .......0......|
000081a0 1b 40 03 00 00 00 00 00 1b 50 03 00 00 00 00 00 |.@.......P......|
000081b0 1b 60 03 00 00 00 00 00 1b 70 03 00 00 00 00 00 |.`.......p......|
000081c0 1b 80 03 00 00 00 00 00 1b 90 03 00 00 00 00 00 |................|
000081d0 1b a0 03 00 00 00 00 00 1b b0 03 00 00 00 00 00 |................|
000081e0 1b c0 03 00 00 00 00 00 1b d0 03 00 00 00 00 00 |................|
000081f0 1b e0 03 00 00 00 00 00 1b f0 03 00 00 00 00 00 |................|
00008200 1b 00 04 00 00 00 00 00 1b 10 04 00 00 00 00 00 |................|
00008210 1b 20 04 00 00 00 00 00 1b 30 04 00 00 00 00 00 |. .......0......|
00008220 1b 40 04 00 00 00 00 00 1b 50 04 00 00 00 00 00 |.@.......P......|
00008230 1b 60 04 00 00 00 00 00 1b 70 04 00 00 00 00 00 |.`.......p......|
00008240 1b 80 04 00 00 00 00 00 1b 90 04 00 00 00 00 00 |................|
00008250 1b a0 04 00 00 00 00 00 1b b0 04 00 00 00 00 00 |................|
00008260 1b c0 04 00 00 00 00 00 1b d0 04 00 00 00 00 00 |................|
00008270 1b e0 04 00 00 00 00 00 1b f0 04 00 00 00 00 00 |................|
00008280 1b 00 05 00 00 00 00 00 1b 10 05 00 00 00 00 00 |................|
00008290 1b 20 05 00 00 00 00 00 1b 30 05 00 00 00 00 00 |. .......0......|
000082a0 1b 40 05 00 00 00 00 00 1b 50 05 00 00 00 00 00 |.@.......P......|
000082b0 1b 60 05 00 00 00 00 00 1b 70 05 00 00 00 00 00 |.`.......p......|
000082c0 1b 80 05 00 00 00 00 00 1b 90 05 00 00 00 00 00 |................|
000082d0 1b a0 05 00 00 00 00 00 1b b0 05 00 00 00 00 00 |................|
000082e0 1b c0 05 00 00 00 00 00 1b d0 05 00 00 00 00 00 |................|
000082f0 1b e0 05 00 00 00 00 00 1b f0 05 00 00 00 00 00 |................|
00008300 1b 00 06 00 00 00 00 00 1b 10 06 00 00 00 00 00 |................|
00008310 1b 20 06 00 00 00 00 00 1b 30 06 00 00 00 00 00 |. .......0......|
00008320 1b 40 06 00 00 00 00 00 1b 50 06 00 00 00 00 00 |.@.......P......|
00008330 1b 60 06 00 00 00 00 00 1b 70 06 00 00 00 00 00 |.`.......p......|
00008340 1b 80 06 00 00 00 00 00 1b 90 06 00 00 00 00 00 |................|
00008350 1b a0 06 00 00 00 00 00 1b b0 06 00 00 00 00 00 |................|
00008360 1b c0 06 00 00 00 00 00 1b d0 06 00 00 00 00 00 |................|
00008370 1b e0 06 00 00 00 00 00 1b f0 06 00 00 00 00 00 |................|
00008380 1b 00 07 00 00 00 00 00 1b 10 07 00 00 00 00 00 |................|
00008390 1b 20 07 00 00 00 00 00 1b 30 07 00 00 00 00 00 |. .......0......|
000083a0 1b 40 07 00 00 00 00 00 1b 50 07 00 00 00 00 00 |.@.......P......|
000083b0 1b 60 07 00 00 00 00 00 1b 70 07 00 00 00 00 00 |.`.......p......|
000083c0 1b 80 07 00 00 00 00 00 1b 90 07 00 00 00 00 00 |................|
000083d0 1b a0 07 00 00 00 00 00 1b b0 07 00 00 00 00 00 |................|
000083e0 1b c0 07 00 00 00 00 00 1b d0 07 00 00 00 00 00 |................|
这个转储似乎是正确的。它从 0x200000 开始。这意味着转储中的地址 0 是 0x200000,地址 0x1000 是 0x201000 等
我用这个脚本编译代码:
g++ -fomit-frame-pointer --static -ffreestanding -nostdlib -mgeneral-regs-only -mno-red-zone -c -m64 Startup/Source/Main.cpp -oStartup/Object/Main.o
ld -entry main --oformat elf64-x86-64 --no-dynamic-linker -static -nostdlib -Ttext-segment=300000 Startup/Object/Main.o -ostartup.elf
谁能指出代码的任何问题或我忽略的任何问题?
0x800000000000
不是规范地址,因此页面目录布局中没有它的位置。 (并且尝试取消引用它会 #GP
出错,而不是触发 TLB 未命中 => 页面遍历。)
您有 PML4,因此前 16 个虚拟地址位必须是位 #47 的副本。即指针必须可以表示为 48 位值符号扩展到 64 位。
即 ((int64_t)addr << 16) >> 16 == addr
必须为真。
(右移使用sar
算术右移)。
(x86-64 canonical address?).
可用(规范)范围的上半部分实际上确实从ffff800000000000
开始,PML4E为它确实紧跟在下半部分的顶部 00007f8000000000
.
关于低半部分顶部的位置是正确的,但是您忘记将符号扩展 0x800000000000
到 64 位以到达高半部分的底部。指针名义上仍然是 64 位,而不仅仅是截断为 48 位。这就是为什么像 ffff800000000000
这样的地址可以存在的原因。
如果您启用了 PML5(例如 Ice Lake 硬件或该功能的软件仿真),额外级别的页面目录将使您获得最多 57 位的虚拟地址 space,从而可以地址 0x800000000000
.
另见