Page 1 of 1

loading GS base on x86_64

Posted: Tue Oct 16, 2012 2:32 am
by NickJohnson
I'm trying to use the MSR GS.base to set the base address for GS but it doesn't seem to be working properly. Here is what I'm doing: (all code is in 64-bit NASM)

Code: Select all

mov rax, (base address I want)
mov rdx, rax
shr rdx, 32
mov ecx, 0xC0000101
wrmsr
Then I check the base address of GS like this:

Code: Select all

lea rax, [gs:0x100]
I would expect rax to be set to the base of GS plus 0x100. However, rax is being set to just 0x100 here. Is there some additional operation I need to perform in order to get the new base for GS to load? Or am I loading the MSR incorrectly?

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 3:22 am
by gerryg400
You need to do a swapgs to move the msr value to the GS base.

In c I do ...

Code: Select all

    /* Set up the gs register */
    wr_msr(0xc0000102, (uintptr_t)&core_data[core]);
    __swapgs();

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 3:31 am
by NickJohnson
That doesn't seem to change anything for me.

On the other hand, it does look like performing loads relative to GS does work, e.g.:

Code: Select all

mov rax, [gs:0]
Is it just not possible to use LEA to get an address relative to the GS base? It seems odd that "lea rax, [gs:0]" is a valid instruction then.

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 4:38 am
by Kevin
This is just how lea works. The "effective address" is the offset, not the linear or physical address.

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 5:56 am
by qw
LEA ignores the segment override; it ignores the segment/selector all together. "lea rax, [0]" clears RAX no matter the base address. So does "lea rax, [gs:0]".

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 6:26 am
by iansjack
The Intel manual is pretty clear on this point. The lea instruction works on the offset, not the absolute address.

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 3:47 pm
by JamesM
The clue is in the name. "load effective address" loads the effective address, which is just the addressing mode computation. Segment offset is added to form the linear address later.

Re: loading GS base on x86_64

Posted: Tue Oct 16, 2012 10:50 pm
by xenos
It seems that the AMD manuals are confusingly unclear about this...
AMD manuals, Vol. 2, 4.5.3 wrote: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.
In contrast, the Intel manuals state:
Intel manuals, Vol. 3, 3.4.4 wrote:When FS and GS segment overrides are used in 64-bit mode, their respective base addresses are used in the linear address calculation: (FS or GS).base + index + displacement. FS.base and GS.base are then expanded to the full linear-address size supported by the implementation. The resulting effective address calculation can wrap across positive and negative addresses; the resulting linear address must be canonical.