IA32 GS.base用法

时间:2014-08-14 18:48:18

标签: assembly kernel x86-64

我正在尝试编写一个自定义内核,它使用%gs作为分段基础来加载和存储x86_64下的CPU本地信息。 (我正在使用QEMU 2.1.0运行我的内核,如果这很重要。)I previously asked about this issue,但从那时起我发现了更多的信息,而且这些更改并不完全适合我之前的问题。

我使用IA32_GS_BASE MSR加载CPU本地数据结构的地址。但是,无论我做什么,似乎MSR中的地址都没有被尊重。 %gs仍然评估为零,因此我得到的地址是:(a)使用时崩溃,(b)不指向我之前加载的数据结构。

我有两个假设。一个是我需要在确认MSR值之前执行某种缓存清除操作。另一个是我没有正确设置MSR。但是,IA32_GS_BASE 非常记录不清,我找不到任何证据来支持这两种理论。

任何指针? (没有双关语。)

2 个答案:

答案 0 :(得分:1)

根据我的测试,您的问题不会立即与GS基础相关。 在qemu中运行时会出现双重故障,并未提供有关GS问题的任何指示。使用bochs运行时,我无法从代码中获得任何合理的调试输出,但我可以使用内置调试器来证明至少GS base的设置和读取操作有效。

(0) [0x000000000030d346] 0008:ffffff800030d346 (unk. ctxt): wrmsr                     ; 0f30
<bochs:20> r
rax: 0x00000000_00828c00 rcx: 0x00000000_c0000101
rdx: 0x00000000_ffffff80 rbx: 0xffffff80_00833480
rsp: 0xffffff80_0010bfb0 rbp: 0xffffff80_0010bfb0
rsi: 0xffffff80_0010bf48 rdi: 0xffffff80_00828c00
r8 : 0xffffff80_007dbe03 r9 : 0x00000000_0000007f
r10: 0x00000021_00000000 r11: 0xffffff80_00cf9000
r12: 0x80000000_00c74003 r13: 0x00000000_00000084
r14: 0x00000000_00a33000 r15: 0xffffff80_00c75000
rip: 0xffffff80_0030d346
eflags 0x00000002: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af pf cf

我相信这个断点应该在你的_cpu_data_realloc函数中。查看寄存器,我们可以看到MSR 0xc0000101将使用0xffffff8000828c00的值编写,这将正确设置GS base。事实上,在一次触发事故发生后,bochs很友好地证实了这一点:

10725675946i[CPU0 ] |  MSR_GS_BASE:ffffff8000828c00

我在后续使用GS时放置了另一个断点,不确定源代码中的位置:

(0) [0x00000000003232b2] 0008:ffffff80003232b2 (unk. ctxt): mov r14d, dword ptr gs:0x000000000000001c ; 65448b34251c000000

好的,所以它显示为gs:0x1c。测试表明这是零。为了证明确实从正确的内存位置读取了值,让我们将它设置为有趣的东西:

<bochs:21> page 0xffffff8000828c1c
PML4: 0x0000000000c72023 ps         A pcd pwt S W P
PDPE: 0x0000000000c6e023 ps         A pcd pwt S W P
 PDE: 0x0000000000a7e023 ps         A pcd pwt S W P
 PTE: 0x0000000000828063    g pat D A pcd pwt S W P
linear page 0xffffff8000828000 maps to physical page 0x0000000000828000
<bochs:22> setpmem 0x828c1c 4 0x42424242

然后加载执行没有问题,并且确实加载了该值:

<bochs:23> s
Next at t=91228625505
(0) [0x00000000003232bb] 0008:ffffff80003232bb (unk. ctxt): lea rdi, qword ptr ds:[rip+5863966] ; 488d3d1e7a5900
<bochs:24> r
rax: 0x00000000_00000000 rcx: 0xffffff80_0087ae80
rdx: 0xffffff80_008bad10 rbx: 0xffffff80_0075b564
rsp: 0xffffff80_0010bde0 rbp: 0xffffff80_0010be10
rsi: 0x00000000_00000072 rdi: 0xffffff80_0075b564
r8 : 0x00000000_00000010 r9 : 0x00000000_00000000
r10: 0x00000000_00000000 r11: 0x00000000_00000000
r12: 0xffffff80_0010bec4 r13: 0x00000000_00000084
r14: 0x00000000_42424242 r15: 0xffffff80_008f2b38
rip: 0xffffff80_003232bb
eflags 0x00000082: id vip vif ac vm rf nt IOPL=0 of df if tf SF zf af pf cf

无论你遇到什么问题,都可能在其他地方。

答案 1 :(得分:0)

一些快速搜索表明,更好的选择是使用WRGSBASE指令。这可以避免任何混乱的MSR。

如果这不起作用,另一种方法是设置IA32_KERNEL_GS_BASE(索引0xC0000102;注意中间的KERNEL),然后是SWAPGS指令。