关于linux x86 64中MSR_GS_BASE的详细信息

问题描述 投票:6回答:1

我试图弄清楚Linux内核中MACRO当前的细节。当前的最终汇编代码是:

movq %%gs:0xb000,%0

上面的代码可以工作!但是当我打印%% gs时,它的值为0,所以%% gs指向GDT NULL的第一项!!这个怎么运作?

mov %%gs, %0

相反,gs的基础在MSR_GS_BASE中,并且当前可以替换为:

/*0xb000 is the offset of per_cpu__current_task*/
cur_task = (unsigned long*)(x86_rdmsr64(MSR_GS_BASE) + 0xb000);
println("cur_task:%p",*cur_task);

我的问题是:

%gs指向GDT NULL的第一项!! ??如何从MSR_GS_BASE读取它是一个CPU功能?我需要一些关于此的参考。

assembly linux-kernel x86-64 memory-segmentation
1个回答
9
投票

来自AMD Architecture Programmer's Manual Volume 2: System Programming,第4.5.3节:

FS和GS寄存器采用64位模式。与CS,DS,ES和SS段不同,FS和GS段覆盖可以在64位模式下使用。当在64位模式下使用FS和GS段覆盖时,它们各自的基址将用于有效地址(EA)计算。然后完整的EA计算变为(FS或GS).base + base +(scale * index)+ displacement。 FS.base和GS.base值也扩展为完整的64位虚拟地址大小,如图4-5所示。允许生成的EA计算包含正负地址。

[...]

有两种方法可以更新FS.base和GS.base隐藏描述符字段的内容。第一个专用于特权软件(CPL = 0)。 FS.base和GS.base隐藏的描述符寄存器字段映射到MSR。特权软件可以使用单个WRMSR指令以规范形式将64位基址加载到FS.base或GS.base中。 FS.base MSR地址为C000_0100h,而GS.base MSR地址为C000_0101h。

更新FS和GS基本字段的第二种方法适用于以任何权限级别运行的软件(当实现支持并通过设置CR4 [FSGSBASE]启用)。 WRFSBASE和WRGSBASE指令分别将GPR的内容复制到FS.base和GS.base字段。当操作数大小为32位时,清除基数的高位双字。 WRFSBASE和WRGSBASE仅在64位模式下受支持。

© www.soinside.com 2019 - 2024. All rights reserved.