Loading GDT in x86_64 always faults

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
AlectronikLabs
Posts: 3
Joined: Sun Jan 08, 2023 3:44 pm

Loading GDT in x86_64 always faults

Post by AlectronikLabs »

I try to implement a simple OS kernel but just can't get around a nasty bug which mostly triple faults or causes other non-wanted behaviour. In 32 bit w/GRUB it was no problems, the first attempt worked. But on x86_64 (Limine) I can't get it to work. I even simplified the code to the max by copying & pasteing code out of a functioning project but still an error. What I do have now is the following:

Code: Select all

.section .rodata
.align 16
GDT64:                           # Global Descriptor Table (64-bit).
#.equ Null, $ - $GDT64         # The null descriptor.
    .short 0                         # Limit (low).
    .short 0                         # Base (low).
    .byte 0                         # Base (middle)
    .byte 0                         # Access.
    .byte 0                         # Granularity.
    .byte 0                         # Base (high).
#.equ Code, $ - $GDT64         # The code descriptor.
    .short 0xFFFF                       # Limit (low).
    .short 0                         # Base (low).
    .byte 0                         # Base (middle)
    .byte 0b10011010                 # Access (exec/read).
    .byte 0b10101111                 # Granularity.
    .byte 0                         # Base (high).
#.equ Data, $ - $GDT64         # The data descriptor.
    .short 0                         # Limit (low).
    .short 0                         # Base (low).
    .byte 0                         # Base (middle)
    .byte 0b10010010                 # Access (read/write).
    .byte 0b00000000                 # Granularity.
    .byte 0                         # Base (high).
GDTPointer:                    # The GDT-pointer.
    .short (GDTPointer - GDT64 - 1)             # Limit.
    .quad GDT64                     # Base.


.section .text
.code64

.global loadGDT
loadGDT:
    lgdt GDTPointer
    push $0x0008
    push $.afterLoad
    
    retfq
.afterLoad:
    mov $0x0010, %ax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    mov %ax, %ss

    ret
The call to loadGDT() doesn't triple fault as it did before but it stops the other code from working, notably not running any calls from after loadGDT(). What did I do wrong? I am near to discard long mode and to go with 32 bit for now but it sucks, I want the solution to this bug! I don't use any optimization in the compilation. Other code in my project is flawless as it's just the limine barebone.

I tried to run the code in QEmu with -d int but this doesn't seem to work on limine, it just hangs in an endless loop of output.

Many thanks in advance.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: Loading GDT in x86_64 always faults

Post by Octocontrabass »

AlectronikLabs wrote:The call to loadGDT() doesn't triple fault as it did before but it stops the other code from working, notably not running any calls from after loadGDT().
What calls are you trying to make after calling loadGDT()?
AlectronikLabs wrote:I tried to run the code in QEmu with -d int but this doesn't seem to work on limine, it just hangs in an endless loop of output.
Redirect the output to a file and it'll go faster. Displaying text in the terminal can be pretty slow, especially on Windows.
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Loading GDT in x86_64 always faults

Post by MichaelPetch »

I have seen you post a similar question on Reddit I think over the past month with no solution. What may be useful is if you put a version of your project that has problems, including all source code, a Makefile (or commands to build everything) onto Github (or similar service) so that people could investigate the problem directly. I think that until you can get someone else's eyeballs to look at everything together it will be hard for you to get resolution.

Other concerns I have seen of your code that has been shown on Reddit are incorrect usage of inline assembly and clobbering registers without telling the compiler. GCC's inline assembly looks easy, but is very nuanced and can be easy to break code in weird and unexpected ways if you don't have an excellent understanding of inline assembly.

Stackoverflow is rife with questions about weird things happening that comes down to bad inline assembly in GCC that looks right.

There is also a lot of misinformation and bad tutorials all over the internet about using GCC's inline assembly.

My view is that the problem exists with something in the code/data you aren't showing us. F9or example you suggest the loading of the GDT isn't a problem now but other code after it breaks. Maybe the other code running after it has the problems/bugs.
Post Reply