Page 2 of 2

Re: Change GDT and update CS while in long mode

Posted: Mon Dec 14, 2015 10:53 am
by lodo1995
Ok guys. Thank you for your time.
I'm feeling very stupid in this moment, because I just found out that all of those problems are caused by a stupid error.
The line

Code: Select all

pushq fun
should in fact be

Code: Select all

pushq $fun
This change solved the issues. Now that retfq does his job, changing the CS to 0x08.

Thank you again, and sorry if I wasted your time.

Re: Change GDT and update CS while in long mode

Posted: Mon Dec 14, 2015 12:23 pm
by Brendan
Hi,
lodo1995 wrote:I suppose I should use a far jump, but this code does not work (AT&T syntax):

Code: Select all

mov %rax, %cr3   # load paging structures (it works)
lgdt 6(%rcx)     # load gdt (it works)
mov $100, %rsp   # update stack pointer (it works)

# now what I tried unsuccessfully:
pushw $8         # new code segment selector
pushq fun        # function to execute next
retfq            # far return (pops address and code segment)
I'd assume that "pushw $8" stores 2 bytes on the stack, the "pushq fun" stores 8 more bytes (for a total of 10 bytes so far); and then the "retfq" takes 16 bytes from the stack leaving you with a corrupted mess.

A far jump would be more fun.. ;)


Cheers,

Brendan

Re: Change GDT and update CS while in long mode

Posted: Wed Dec 16, 2015 7:50 am
by lodo1995
The final code is this:

Code: Select all

    mov %rax, %cr3
    lgdt 6(%rcx)
    mov $128, %rsp
    pushq $8
    pushq $update_segments
    retfq
    
update_segments:
    mov $16, %ax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    mov %ax, %ss
Thank you again to everybody.

Re: Change GDT and update CS while in long mode

Posted: Wed Dec 16, 2015 3:47 pm
by intx13
I thought that only FS and GS could be adjusted in long mode, and the others were forced to a base address of 0000?

http://www.andrea-allievi.com/blog/x64- ... game-over/

Re: Change GDT and update CS while in long mode

Posted: Sat Dec 19, 2015 8:36 am
by lodo1995
intx13 wrote:I thought that only FS and GS could be adjusted in long mode, and the others were forced to a base address of 0000?

http://www.andrea-allievi.com/blog/x64- ... game-over/
That's true, when in long mode, the GDT is only used to check permissions of segments. But you still have to load into the registers the offsets to the GDT entries (so that CPU knows which segments to check permissions for). The base and limit values into the GDT are ignored for every segment register. For FS and GS, special MSR are provided with their bases (if needed).