I tried to figure out the details of MACRO current in Linux kernel. The final assembly code of current is:
movq %%gs:0xb000,%0
The code above can work! But when I print the %%gs, its value is 0, so the %%gs points to the first item of GDT NULL!!?? How it works?
mov %%gs, %0
Instead, the base of gs is in MSR_GS_BASE, and the current can be replaced like:
/*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);
My questions is:
%gs points to the first item of GDT NULL!!?? How it works as read from MSR_GS_BASE, is it a CPU feature? I need some references about this.
From the AMD Architecture Programmer's Manual Volume 2: System Programming, section 4.5.3:
FS and GS Registers in 64-Bit Mode. Unlike the CS,DS,ES, and SS segments, the FS and GS segment overrides can be used in 64-bit mode. When FS and GS segment overrides are used in 64-bit mode, their respective base addresses are used in the effective-address (EA) calculation. The complete EA calculation then becomes (FS or GS).base + base + (scale * index) + displacement. The FS.base and GS.base values are also expanded to the full 64-bit virtual-address size, as shown in Figure 4-5. The resulting EA calculation is allowed to wrap across positive and negative addresses.
[...]
There are two methods to update the contents of the FS.base and GS.base hidden descriptor fields. The first is available exclusively to privileged software (CPL = 0). The FS.base and GS.base hidden descriptor-register fields are mapped to MSRs. Privileged software can load a 64-bit base address in canonical form into FS.base or GS.base using a single WRMSR instruction. The FS.base MSR address is C000_0100h while the GS.base MSR address is C000_0101h.
The second method of updating the FS and GS base fields is available to software running at any privilege level (when supported by the implementation and enabled by setting CR4[FSGSBASE]). The WRFSBASE and WRGSBASE instructions copy the contents of a GPR to the FS.base and GS.base fields respectively. When the operand size is 32 bits, the upper doubleword of the base is cleared. WRFSBASE and WRGSBASE are only supported in 64-bit mode.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With