OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Mar 18, 2024 8:47 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Setting segment registers in long mode illegal?
PostPosted: Sun Oct 31, 2021 5:50 pm 
Offline
Member
Member

Joined: Sat Oct 23, 2021 5:36 am
Posts: 26
Is it illegal? When I try to do it, it triple faults immediately.

Do segment registers serve any purpose in long mode?


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Sun Oct 31, 2021 6:38 pm 
Online
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
angods wrote:
Is it illegal? When I try to do it, it triple faults immediately.

Most instructions to set segment registers work the same in 64-bit long mode as they do in protected mode, including the part where they load a segment descriptor into the hidden descriptor part of the segment register. A triple fault indicates an issue with your GDT, your LDT, your choice of selector, or your choice of instruction.

angods wrote:
Do segment registers serve any purpose in long mode?

In compatibility mode, segment registers behave the same way they do in protected mode.

In 64-bit mode, most functions of segmentation go away, but some of them still work. CS still determines the current privilege level. FS and GS still have base addresses. SS is given a new function as a flag to indicate privilege level changes.


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Sun Oct 31, 2021 6:59 pm 
Offline
Member
Member

Joined: Sat Oct 23, 2021 5:36 am
Posts: 26
Octocontrabass wrote:
angods wrote:
Is it illegal? When I try to do it, it triple faults immediately.

Most instructions to set segment registers work the same in 64-bit long mode as they do in protected mode, including the part where they load a segment descriptor into the hidden descriptor part of the segment register. A triple fault indicates an issue with your GDT, your LDT, your choice of selector, or your choice of instruction.

angods wrote:
Do segment registers serve any purpose in long mode?

In compatibility mode, segment registers behave the same way they do in protected mode.

In 64-bit mode, most functions of segmentation go away, but some of them still work. CS still determines the current privilege level. FS and GS still have base addresses. SS is given a new function as a flag to indicate privilege level changes.


My GDT is exactly the same as in https://wiki.osdev.org/Setting_Up_Long_Mode, so I'm sure it's valid.

But I just realised it only causes a triple fault when modifying ss.


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Sun Oct 31, 2021 9:35 pm 
Offline
Member
Member
User avatar

Joined: Wed Sep 28, 2005 11:00 pm
Posts: 85
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 4:49 am 
Offline
Member
Member

Joined: Sat Oct 23, 2021 5:36 am
Posts: 26
deadmutex wrote:
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.


It didn't change anything. I found a 'solution' though. Apparently, ss can be set to 0x0 (null segment). I'm not sure if it's ok to do that though.
Code:
xor ax, ax
mov ss, ax


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 5:18 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
deadmutex wrote:
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.

I don't think it makes any difference, does it? Isn't that bit just ignored for data segment descriptors?


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 5:23 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
angods wrote:
deadmutex wrote:
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.


It didn't change anything. I found a 'solution' though. Apparently, ss can be set to 0x0 (null segment). I'm not sure if it's ok to do that though.
Code:
xor ax, ax
mov ss, ax
I'm pretty sure that only the system should set SS to 0 (during interrupts). In any case, you are just masking the problem.

What value are you trying to use for SS, are you in kernel or user mode, and are you sure it refers to a valid data selector?


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 5:29 am 
Offline
Member
Member

Joined: Sat Oct 23, 2021 5:36 am
Posts: 26
angods wrote:
deadmutex wrote:
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.


It didn't change anything. I found a 'solution' though. Apparently, ss can be set to 0x0 (null segment). I'm not sure if it's ok to do that though.
Code:
xor ax, ax
mov ss, ax


It can't be '0' though, because IRETQ throws #GP when it's 0. I must find a different solution.


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 5:32 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
angods wrote:
It can't be '0' though, because IRETQ throws #GP when it's 0. I must find a different solution.
Yes it can be 0. It's the way that the processor marks nested interrupts in long mode.

I get the impression that you are just trying things at random that you have seen on the Internet (including this forum). Have you actually read the manufacturer's Programmer's Manual on the subject?


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 5:48 am 
Offline
Member
Member

Joined: Sat Oct 23, 2021 5:36 am
Posts: 26
iansjack wrote:
angods wrote:
deadmutex wrote:
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.


It didn't change anything. I found a 'solution' though. Apparently, ss can be set to 0x0 (null segment). I'm not sure if it's ok to do that though.
Code:
xor ax, ax
mov ss, ax
I'm pretty sure that only the system should set SS to 0 (during interrupts). In any case, you are just masking the problem.

What value are you trying to use for SS, are you in kernel or user mode, and are you sure it refers to a valid data selector?


Code:
PRESENT        equ 1 << 7
NOT_SYS        equ 1 << 4
EXEC           equ 1 << 3
DC             equ 1 << 2
RW             equ 1 << 1
ACCESSED       equ 1 << 0

GRAN_4K       equ 1 << 7
SZ_32         equ 1 << 6
LONG_MODE     equ 1 << 5

GlobalDescriptorTable64:
   dw GDTEnd64 - GDTStart64 - 1
   dq GDTStart64
GDTStart64:
   GDTEntry64_0: dd 0, 0 ;NULL
   GDTEntry64_1:
      dd 0xFFFF                           
      db 0                                 
      db PRESENT | NOT_SYS | EXEC | RW | 0xF
      db GRAN_4K | LONG_MODE   
      db 0                       
   GDTEntry64_2:
            dd 0xFFFF                                 
                 db 0                                       
                 db PRESENT | NOT_SYS | RW | 0xF
                 db GRAN_4K
                 db 0                                       
GDTEnd64:


I can never be 100% sure, but this is the code.

Code:
       lgdt [GlobalDescriptorTable64]
        jmp 0x8:LongModeMain ;Where 0x8 is code segment


Code:
LongModeMain:
   mov ax, 0x10
   mov ds, ax
   mov es, ax
   mov fs, ax
   xor ax, ax ;If I don't xor it, it crashes
   mov ss, ax


I'm in kernel mode. I mean.. I don't even know. I didn't do anything with permission level yet..


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 6:08 am 
Offline
Member
Member

Joined: Sat Oct 23, 2021 5:36 am
Posts: 26
iansjack wrote:
angods wrote:
It can't be '0' though, because IRETQ throws #GP when it's 0. I must find a different solution.
Yes it can be 0. It's the way that the processor marks nested interrupts in long mode.

I get the impression that you are just trying things at random that you have seen on the Internet (including this forum). Have you actually read the manufacturer's Programmer's Manual on the subject?


I try to reference intel's manual(s) whenever I can, but finding some information is hard.

And the Intel ISA manual mentions that 'If the stack segment selector is NULL going back to compatibility mode,' #GP is thrown.

https://www.felixcloutier.com/x86/iret:iretd


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 8:44 am 
Offline

Joined: Sat Oct 10, 2020 4:05 pm
Posts: 14
You are currently using
Code:
.Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)

The '| 0xF' on the Access byte of that data segment descriptor may be setting a bit that should be zero - the AMD manual suggests that bit 11 in the upper dword should be 0 and bit 12 should be 1, and my code triple faults when I have bit 11 set. Bit 12 is set correctly by NOT_SYS.
You may also want to remove the '| 0xF' from your code segment descriptor to make the code cleaner, although it will probably have no effect on the outcome.
'0x0000920000000000' works for me as the full data segment entry, and you seem to be using '0x00A09F000000FFFF', while removing the '| 0xF' should give you '0x00A092000000FFFF', which should at least work. Please correct me if I've mis-counted the bytes somewhere there.
You can view the full AMD manual here, and the relevant section is Volume 2 Chapter 4 sections 7 (legacy) and 8 (long mode). I'd recommend bookmarking that link, and I've found the AMD manuals to be easier to navigate than Intel's, although that is probably just personal preference.

If this works for you, the wiki page should probably be updated.


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 9:26 am 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1071
One thing I want to add is that I used to ask questions about basic x86 stuff here. I soon realized that the only way to truly understand x86 is to look at the manuals. I have to thank @iansjack for pointing me to the manuals instead of just giving me the answer here. Trust, me it works!

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 9:32 am 
Offline
Member
Member
User avatar

Joined: Wed Sep 28, 2005 11:00 pm
Posts: 85
iansjack wrote:
deadmutex wrote:
The 'LONG_MODE' flag should not be set for data segment descriptors. It's only used to indicate a 64-bit code segment:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                                   ; Limit & Base (low)
        db 0                                        ; Base (mid)
        db PRESENT | NOT_SYS | RW | 0xF             ; Access
        db GRAN_4K | LONG_MODE                      ; Flags
        db 0                                        ; Base (high)


Try removing it and see if it changes anything.

I don't think it makes any difference, does it? Isn't that bit just ignored for data segment descriptors?


For the L bit, the manual specifically says:

Quote:
When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to 0.


Also, the access and flag bits for the data segment are wrong. It should be:

Code:
    .Data: equ $ - GDT
        dd 0xFFFF                       ; Limit & Base (low)
        db 0                            ; Base (mid)
        db PRESENT | NOT_SYS | RW | DC  ; Access
        db GRAN_4K | SZ_32              ; Flags
        db 0                            ; Base (high)


EDIT: Fixed formatting


Top
 Profile  
 
 Post subject: Re: Setting segment registers in long mode illegal?
PostPosted: Mon Nov 01, 2021 11:12 am 
Online
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
Doctor5555 wrote:
The '| 0xF' on the Access byte of that data segment descriptor may be setting a bit that should be zero - the AMD manual suggests that bit 11 in the upper dword should be 0 and bit 12 should be 1, and my code triple faults when I have bit 11 set. [...] If this works for you, the wiki page should probably be updated.

The wiki page needs to be updated either way. The 0xF is supposed to be the upper 4 bits of the limit, which is part of the flags byte, not the access byte.

The AMD manual gives the impression that only the present bit matters for data segments, but I can't say the same for Intel. However, both manuals do say that system calls require particular descriptors for SS, so you should match your descriptor for SS with the descriptor used by SYSCALL/SYSENTER.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group