Page 1 of 1

Ring 3 in long mode

Posted: Tue Aug 12, 2014 11:04 pm
by iefbr14
I know that I simply have done some stupid error (or didn't read the manual careful enough), but I'm standing still without any idea. When attempting to execute the following code:

Code: Select all

  mov rax,rsp
  push qword 24 ;SS
  push qword rax ;RSP
  push qword 0 ;RFLAGS
  push qword 16 ;CS
  push qword TEST ;RIP
  iretq
TEST:
  jmp $
#GP comes at 'ireq' with error code 10 (the selector of my ring-3 code segment). My GDT is:

Code: Select all

    align 8
GDT:
  dq 0 ; Null descriptor.
  db 0,0,0,0,0,10011000b,00100000b,0 ; Ring-0 descriptor.
  db 0,0,0,0,0,11111000b,00100000b,0 ; Ring-3 descriptor.
  db 0,0,0,0,0,10010000b,00000000b,0 ; Ring-3 stack.
GDTP:
  dw $-GDT-1
  dq GDT
I have got no TSS, but the ireq doesn't require one, does it? Ring0-to-ring0 interrupts and ireqs works fine, U/S paging flag is on, but that is not relevant anyway, as the fault occurs before the user code starts execution. Can anybody help me? Thanks in advance.

Re: Ring 3 in long mode

Posted: Tue Aug 12, 2014 11:17 pm
by Gigasoft
The return CS is wrong. It should be 19. And you'll need a TSS when going back to ring 0 afterwards.

Re: Ring 3 in long mode

Posted: Tue Aug 12, 2014 11:22 pm
by bluemoon
RFLAG must not be zero, bit #1 should be set.

Also, the GDT looks not quite right, and where's the ring0 data?

Re: Ring 3 in long mode

Posted: Tue Aug 12, 2014 11:41 pm
by iefbr14
bluemoon wrote:RFLAG must not be zero, bit #1 should be set.
Thanks. But still doesn't work, even if I use pushfq.
bluemoon wrote:where's the ring0 data?
I use zero selector, that seems to work both on qemu and on real hardware. That should, as it is normally used as interrupt stack segment.
The return CS is wrong. It should be 19.
Still no effect. RE: at least now the stack segment (0x18) is reported as error code, and not the code segment.
you'll need a TSS when going back to ring 0 afterwards.
I know, but I just didn't came so far yet.

Re: Ring 3 in long mode

Posted: Wed Aug 13, 2014 12:57 am
by iefbr14
Thanks everybody. My problem was RPL, just as Gigasoft told. But it seems like QEMU checks for write access on stack. Is it correct behaviour? I didn't figured it out from the AMD manual.

Re: Ring 3 in long mode

Posted: Wed Aug 13, 2014 2:38 am
by bluemoon
iefbr14 wrote:
bluemoon wrote:where's the ring0 data?
I use zero selector, that seems to work both on qemu and on real hardware. That should, as it is normally used as interrupt stack segment.
This may work, but there are two reason not to do so:
1. According to intel manual:
9.8.1 Protected-Mode System Data Structures
To implement a flat memory model without paging, software initialization code must at a minimum load a GDT with one code and one data-segment descriptor. A null descriptor in the first GDT entry is also required.
Although it says "flat memory model without paging", I read it as a minimal example and also apply to more complex memory models (ie. standard flat paging).

Also note that, while base and limit is not checked in 64-bit mode, other fields are still significant.

2. syscall/sysret requires specific GDT layout which "data selector" is "code selector+8", so you need an entry for data anyway.


As a side note, if TR is insane (e.g. point to bogus memory, or mapped to 16bit TSS), 64-bit consistency check may fail when attempt to switch to long mode, and generate #GP.