Seemingly random behaviour after implementing GDT

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
thect36
Posts: 1
Joined: Mon Feb 21, 2022 5:10 am
Location: Taiwan

Seemingly random behaviour after implementing GDT

Post 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
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Seemingly random behaviour after implementing GDT

Post by Octocontrabass »

I see you're enabling interrupts with STI, but have you set up your IDT yet?
Post Reply