为什么QEMU在填写PML4的上半部分时返回错误的地址? [英] Why does QEMU return the wrong addresses when filling the higher half of the PML4?
问题描述
我正在编写一个使用UEFI引导的小型x86-64操作系统。我试图通过将内核的可执行文件移到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 $0x200018, %rax
"
"mov %rax, %cr3
"
"movq $0x375000, %rsp
"
);
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 $16, %rsp
"
"movq $8, 8(%rsp)
"
"movabsq $fun, %rax
"
"mov %rax, (%rsp)
"
"lretq
"
"fun:
"
"movq $0x10, %rax
"
"mov %ax, %ss
"
"mov %ax, %es
"
"mov %ax, %ds
"
"mov %ax, %gs
"
"mov %ax, %fs
"
"hlt"
);
}
我有指向PML4地址的指针,然后我就有了。这应该在不缓存的情况下将PML4的条目256映射到0x206000。内核映射部分下的其余小代码片段应该映射从物理地址0开始的虚拟地址的上半部分中的12MB数据。相反,我得到了上面的地址,这似乎很奇怪。
如果我用相同的代码(*(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未命中=&>页面遍历。)
即
((int64_t)addr << 16) >> 16 == addr
必须为真。(使用
sar
算术右移进行右移)。(x86-64 canonical address?)。
可用(规范)范围的上半部分实际上从ffff800000000000
开始,其PML4E紧跟在下半部分上半部分的PML4E之后,00007f8000000000
。
Address canonical form and pointer arithmetic包括虚拟地址空间中漏洞的ASCII图。
关于下半部分的顶部在哪里,您是正确的,但是您忘记了将0x800000000000
符号扩展到64位以达到上半部分的底部。指针名义上仍然是64位的,而不仅仅是被截断为48位。这就是为什么像ffff800000000000
这样的地址可以存在。
如果您启用了PML5(例如,Ice Lake硬件或该功能的软件模拟),则额外的页目录级别将为您提供高达57位的虚拟地址空间,从而可以寻址0x800000000000
。
另见x86-64: canonical addresses and actual available range
这篇关于为什么QEMU在填写PML4的上半部分时返回错误的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!