关于MSR_GS_BASE详细信息在Linux的x86 64(Detail about MSR_GS

2019-06-26 07:23发布

我试图找出MACRO电流的细节在Linux内核中。 电流的最终装配的代码是:

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功能吗?我需要一些有关此引用。

Answer 1:

从AMD架构程序员手册第2卷:系统编程 ,第4.5.3节:

FS和GS寄存器在64位模式。 不同于CS,DS,ES,SS和段,FS和GS段重写可以在64位模式下使用。 当FS和GS段覆盖在64位模式下的使用,它们各自的基地址在有效地址(EA)计算中使用。 然后将完整的EA计算变得(FS或GS).base +碱+(规模*指数)+位移。 的FS.base和GS.base值也被扩展到了完整的64位虚拟地址的尺寸,如图4-5所示。 将所得EA计算允许跨正极和负极地址来包装。

[...]

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

(当实现支持,并通过设置CR4 [FSGSBASE]启用)更新FS和GS碱字段的第二种方法是提供给在任何特权级别上运行的软件。 该WRFSBASE和WRGSBASE指令的GPR的内容分别复制到FS.base和GS.base领域。 当操作数大小是32位,所述基座的上部双字被清除。 WRFSBASE和WRGSBASE在64位模式只支持。



文章来源: Detail about MSR_GS_BASE in linux x86 64