Creating the GDT causes crash
Posted: Tue Oct 22, 2024 12:29 am
Hi, I have been putting together a very simple 64 bit UEFI kernel to learn about OS dev. I have tried to set up the GDT but it crashes at the lgdt instruction (commenting it out is enough to prevent it from crashing). Can anyone with more experience see anything wrong that I'm missing?
C:
assembly:
C:
Code: Select all
#include <stdio.h>
#include <stdint.h>
struct gdt_entry_t {
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
} __attribute__((packed, aligned(8)));
struct gdt_ptr_t {
uint16_t limit;
uint64_t base;
}__attribute__((packed));
extern void load_gdt();
struct gdt_entry_t gdt_entries[5];
struct gdt_ptr_t gdt_ptr;
struct gdt_ptr_t* gp;
static void gdt_set_gate(int32_t entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
gdt_entries[entry].base_low = (base & 0xFFFF);
gdt_entries[entry].base_middle = (base >> 16) & 0xFF;
gdt_entries[entry].base_high = (base >> 24) & 0xFF;
gdt_entries[entry].limit_low = (limit & 0xFFFF);
gdt_entries[entry].granularity = (limit >> 16) & 0x0F;
gdt_entries[entry].granularity |= gran & 0xF0;
gdt_entries[entry].access = access;
}
void gdt_init() {
gdt_ptr.limit = (sizeof(struct gdt_entry_t)*5) - 1;
gdt_ptr.base = (uint64_t)&gdt_entries;
gp = &gdt_ptr;
gdt_set_gate(0, 0, 0, 0, 0); // Null segment
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); //Code segment
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //Data segment
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User mode code segment
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User mode data segment
load_gdt();
}
Code: Select all
bits 64
global load_gdt
extern gp
load_gdt:
CLI
LGDT [rel gp]
PUSH 0x08 ; Push code segment to stack, 0x08 is a stand-in for your code segment
LEA RAX, [rel .reload_CS] ; Load address of .reload_CS into RAX
PUSH RAX ; Push this value to the stack
RETFQ ; Perform a far return, RETFQ or LRETQ depending on syntax
.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