Page 1 of 1

Seemingly random behaviour after implementing GDT

Posted: Mon Feb 21, 2022 6:24 am
by thect36
Hi, I'm trying to make my own kernel. I'm following tutorials from this site's wiki, "The little book about OS development", and some example OS I found on Github.

After implementing loading GDT, errors happens randomly on random points when executing GDT related codes. Sometimes everything works fine, serial console prints messages that executes after the GDT loading is finished. But sometimes the serial console shows everything works, but the video memory isn't updated anymore. Sometimes everything just doesn't work at all. I have very little knowledge in this area and couldn't figure out what might be the cause.

Code: Select all

gdt_object gdt_objects[5];
gdt_table table;

void gdt_entries_init() {

	serial_print(SERIAL_COM1_BASE, "GDT setup start.\n");

	table.size = (sizeof(gdt_object)*5)-1;
	table.base = (unsigned int)&gdt_objects;

	// NULL descriptor (Required)
	gdt_encode(&gdt_objects[0], 0, 0, 0, 0);
	gdt_encode(&gdt_objects[1], 0, 0xfffff, 0x9a, 0xcf);
	gdt_encode(&gdt_objects[2], 0, 0xfffff, 0x92, 0xcf);
	gdt_encode(&gdt_objects[3], 0, 0xfffff, 0xfa, 0xcf);
	serial_print(SERIAL_COM1_BASE, "Flag.\n");
	gdt_encode(&gdt_objects[4], 0, 0xfffff, 0xf2, 0xcf);

	gdt_flush((unsigned int)&table);
	serial_printf(SERIAL_COM1_BASE, "GDT flushed\n");
}

void gdt_encode(gdt_object *target, unsigned int base, unsigned int limit, unsigned char access, unsigned char flags) {
	cpu_cli();
	
	if (limit > 0xFFFFF) {
		serial_printf(SERIAL_COM1_BASE, "GDT source limit error.\nlimit: %X\nbase: %X\n", limit, base);
		return;
	}

	target->base_low    =  base         & 0xFFFF; // Lower  word of the base address.
	target->base_mid    = (base >> 16)  & 0xFF;   // Middle byte of the base address.
	target->base_high   = (base >> 24)  & 0xFF;   // Higher byte of the base address.

	target->limit_low   =  limit        & 0xFFFF; // Lower  word of the limit.
	target->flags_limit = (limit >> 16) & 0x0F;   // Higher byte of the limit.

	target->access = access;
 
	target->flags_limit |= (flags) & 0xF0;

	// serial_printf(
	// 	SERIAL_COM1_BASE,
	// 	"limit_low: %x\nbase_low: %x\nbase_mid: %x\naccess_byte: %x\nflags_limit: %x\nbase_high: %x\n\n",
	// 	target->limit_low,
	// 	target->base_low,
	// 	target->base_mid,
	// 	target->access,
	// 	target->flags_limit,
	// 	target->base_high
	// );

	cpu_sti();
}

Code: Select all

global cpu_sti
cpu_sti:
	sti
	ret

gdtr dw 0
	 dd 0

global gdt_flush:
gdt_flush:
	mov eax, [esp + 4]
	lgdt [eax]
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	jmp 0x08:.flush
.flush:
	ret

Re: Seemingly random behaviour after implementing GDT

Posted: Fri Feb 25, 2022 6:01 pm
by Octocontrabass
I see you're enabling interrupts with STI, but have you set up your IDT yet?