x /1hx $rsp显示限制为0x007f(存储在2个字节中,GDB称之为半字,Intel称之为字)。
x /1gx $rsp+2显示qword地址恰好是0xfffffe00000ed000,这是一个有效的内核地址(48位符号扩展,但离地址空间规范范围的上半部分的最顶端相当远。)根据docs/x86/x86-64/mm.txt,从fffffe0000000000开始的0.5TB保存cpu_entry_areaMap,因此在那里找到GDT并不奇怪,沿着其他内核内容,它们的地址暴露于用户空间(在没有UMIP的CPU上),并且必须一直Map,即使在有Meltdown的CPU上。
2条答案
按热度按时间smtd7mpg1#
sgdt
只能接受内存操作数,而不能接受寄存器,因此它必须是"=m"
。操作数大小为2+8字节(对于x86-64;限制然后按顺序寻址),所以需要一个结构体;使用long
将导致在对象外部存储。请阅读手册!https://www.felixcloutier.com/x86/sgdt
其他注意事项:
store_gdt(dtr)
,它使用将
asm volatile("sgdt %0":"=m" (*dtr));
与struct desc_ptr *dtr
进行比较。在我的Linux 5.18系统上,使用Skylake CPU(不支持UMIP),我将
sgdt [rsp]
(NASM语法)放入一个静态可执行文件中,这样我就可以使用GDB(starti
/stepi
)单步执行它。x /1hx $rsp
显示限制为0x007f
(存储在2个字节中,GDB称之为半字,Intel称之为字)。x /1gx $rsp+2
显示qword地址恰好是0xfffffe00000ed000
,这是一个有效的内核地址(48位符号扩展,但离地址空间规范范围的上半部分的最顶端相当远。)根据docs/x86/x86-64/mm.txt
,从fffffe0000000000
开始的0.5TB保存cpu_entry_area
Map,因此在那里找到GDT并不奇怪,沿着其他内核内容,它们的地址暴露于用户空间(在没有UMIP的CPU上),并且必须一直Map,即使在有Meltdown的CPU上。um6iljoc2#
顺便说一句,在Linux内核中,也可以通过已经定义的宏
store_gdt(dtr)
执行相同的操作。它内部包含相同的内联汇编代码。宏的头部是asm/desc.h