Page 1 of 1

Crash after attempting to load GDT

Posted: Sun Jul 17, 2022 4:27 am
by Rzed781
When I tried to load my GDT, my OS immediately crashes and reboots. I have tried debugging and all that I have found is that it occurs on the line attempting to reload CS.
This is my code:
gdtc.c:

Code: Select all

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

struct GDT {
        uint32_t base;
        uint32_t limit;
        uint8_t type;
        uint8_t flags;
};

extern void setGdt(uint8_t* limit, uint32_t base);
extern void reloadSegments(void);

void encodeGdtEntry(uint8_t *target, struct GDT source) {
        if (source.limit > 0xFFFFF) {k_print("GDT cannot encode limits larger than 0xFFFFF");}
        target[0] = source.limit & 0xFF;
        target[1] = (source.limit >> 8) & 0xFF;
        target[6] = (source.limit >> 16) & 0x0F;
        target[2] = source.base & 0xFF;
        target[3] = (source.base >> 8) & 0xFF;
        target[4] = (source.base >> 16) & 0xFF;
        target[7] = (source.base >> 24) & 0xFF;
        target[5] = source.type;
        target[6] |= (source.flags << 4);
}

void gdt_init(uint8_t* buffer) {
        struct GDT GdtEntries[5] = {
                {0, 0, 0, 0},           // Selector 0x00 cannot be used
                {0, 0xfffff, 0x9A, 0xC},// Selector 0x08 will be our code
                {0, 0xfffff, 0x92, 0xC},// Selector 0x10 will be our data
                {0, 0xfffff, 0xFA, 0xC},// Selector 0x18 will be user code
                {0, 0xfffff, 0xF2, 0xC} // Selector 0x20 will be user data

        };
        for (int i = 0; i < 5; i++) encodeGdtEntry(buffer+i*8, GdtEntries[i]);
        setGdt(buffer, 255);
        reloadSegments();
}

gdt.asm:

Code: Select all

global setGdt
global reloadSegments

section .data:
        gdtr DW 0 ; For limit storage
             DD 0 ; For base storage

section .text
        setGdt:
                MOV AX, [esp + 4]
                MOV [gdtr], AX
                MOV EAX, [ESP + 8]
                MOV [gdtr + 2], EAX
                LGDT [gdtr]
                RET
        reloadSegments:
                ; Reload CS register containing code selector:
                JMP   0x08:.reload_CS ; reboot occurs here
        .reload_CS:
                ; Reload data segment registers:
                MOV   AX, 0x10 ; 0x10 is a stand-in for your data segment
                MOV   DS, AX
                MOV   ES, AX
                MOV   FS, AX
                MOV   GS, AX
                MOV   SS, AX
                RET
gdt_init is called like this:

Code: Select all

void gdt_init(uint8_t* buffer);
uint8_t gdt_buffer[256];

void kernel_main(void) {
	for (int i = 0; i<256; i++) gdt_buffer[i] = 0;
	gdt_init(gdt_buffer);
	// rest of code
}

Re: Crash after attempting to load GDT

Posted: Wed Jul 20, 2022 7:52 pm
by Octocontrabass
Rzed781 wrote:I have tried debugging
How did you try debugging? A virtual machine that can show you the contents of registers (such as the GDTR) will quickly reveal the problem. I like using QEMU with the "-d int" option, but there are several ways to do this.
Rzed781 wrote:

Code: Select all

        setGdt(buffer, 255);

Code: Select all

                MOV AX, [esp + 4]
                MOV [gdtr], AX
                MOV EAX, [ESP + 8]
                MOV [gdtr + 2], EAX
The order of the parameters doesn't match. (Parameter passing is defined in the i386 psABI.)

Re: Crash after attempting to load GDT

Posted: Fri Jul 22, 2022 2:54 am
by Rzed781
Don't worry, I fixed it before it got approved. I debugged it using qemu -s and gdb and found the values in gdtr to be incorrect.