GDT Not installing properly?

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
Gogeta70
Member
Member
Posts: 28
Joined: Thu Jun 06, 2013 11:15 am

GDT Not installing properly?

Post by Gogeta70 »

I've been following bran's kernel development tutorial for setting up my GDT.

I first tried doing it his way, in C, with the ASM stub that loads the gdt. That didn't work, so i tried loading the whole GDT in assembly. However, i'm getting the same result with both of my methods.

In my code, i have it output "Installing GDT...\n", call gdt_install(), and then output "GDT Successfully Installed!\n"
However, it only prints "Installing GDT...\n", and (i assume) never returns from the gdt_install() function.

Could someone give me a poke in the right direction here? I'm new to OS development, so it may be an amateurish mistake. The relevant source code is posted below.

Note:
Compiled with a gcc cross compiler on Debian linux
Run in VirtualBox on windows 7, x64

kernel.c - entry point function

Code: Select all


#include "./kernel/gdt.h"

void kernel_main()
{
	k_clearscreen(TEXT_ATTRIB);
	
	char *tst = "Kernel is loaded.\n\n";
	k_putstring(tst, TEXT_ATTRIB);
	
	k_putstring("Installing GDT...\n", TEXT_ATTRIB);
	
	//init_gdt_entries();
	gdt_install();
	
	k_putstring("GDT installed successfully!\n\n", TEXT_ATTRIB);
	
}
gdt.h

Code: Select all

#if !defined(__cplusplus)
#include <stdbool.h> /* C doesn't have booleans by default. */
#endif
#include <stddef.h>
#include <stdint.h>

#define GDT_ENTRY_COUNT 3

struct GDT_ENTRY {
	
	unsigned short limit_low;
	unsigned short base_low;
	unsigned char base_mid;
	unsigned char access;
	unsigned char granularity;
	unsigned char base_high;
	
} __attribute__((packed));

struct GDT_PTR {
	
	unsigned short limit;
	unsigned long base;
	
} __attribute__((packed));

struct GDT_ENTRY gdt_entries[GDT_ENTRY_COUNT];
struct GDT_PTR gdt_ptr;

void init_gdt_entries();
extern void gdt_install();
gdt.c

Code: Select all

#include "gdt.h"

void init_gdt_entries()
{
	// null descriptor
	gdt_entries[0].limit_low = 0;
	gdt_entries[0].base_low = 0;
	gdt_entries[0].base_mid = 0;
	gdt_entries[0].base_high = 0;
	gdt_entries[0].access = 0;
	gdt_entries[0].granularity = 0;
	
	// code descriptor
	gdt_entries[0].limit_low = 0xFFFF;
	gdt_entries[0].base_low = 0x0000;
	gdt_entries[0].base_mid = 0x00;
	gdt_entries[0].base_high = 0x00;
	gdt_entries[0].access = 0x9A;
	gdt_entries[0].granularity = 0xCF;
	
	// data descriptor
	gdt_entries[0].limit_low = 0xFFFF;
	gdt_entries[0].base_low = 0x0000;
	gdt_entries[0].base_mid = 0x00;
	gdt_entries[0].base_high = 0x00;
	gdt_entries[0].access = 0x92;
	gdt_entries[0].granularity = 0xCF;
	
	gdt_ptr.base = (unsigned long) &gdt_entries;
	gdt_ptr.limit = (sizeof(struct GDT_ENTRY) * GDT_ENTRY_COUNT) - 1;
	
}
install_gdt.asm

Code: Select all


;extern gdt_ptr
global gdt_install

gdt_install:
	lgdt [m_gdt]
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	jmp 0x08:gdt_return
	
gdt_return:
	ret


gdt_start:
	
	; null descriptor
	
	dd 0
	dd 0
	
	;code descriptor
	
	dw 0xFFFF ; limit low
	dw 0x0000 ; base low
	db 0x00	  ; base middle
	db 0x9A	  ; access
	db 0xCF	  ; granularity
	db 0x00   ; base high
	
	;data descriptor
	
	dw 0xFFFF ; limit low
	dw 0x0000 ; base low
	db 0x00	  ; base middle
	db 0x92	  ; access
	db 0xCF	  ; granularity
	db 0x00   ; base high
	
gdt_end:

m_gdt:
	dw gdt_end - gdt_start - 1;
	dd gdt_start

Last edited by Gogeta70 on Thu Jun 06, 2013 12:52 pm, edited 1 time in total.
tharkun
Member
Member
Posts: 51
Joined: Sat Mar 21, 2009 1:29 pm
Location: Ireland

Re: GDT Not installing properly?

Post by tharkun »

GDT base should be 0.
Gogeta70
Member
Member
Posts: 28
Joined: Thu Jun 06, 2013 11:15 am

Re: GDT Not installing properly?

Post by Gogeta70 »

I don't understand what you mean.

I thought LGDT expected a base address for the GDT and a size of the GDT?

Edit: I totally derped... i have set the base_high, base_middle, and base_low values for the code and data descriptors to 0 now. However, i'm still having the same issue. I'll update the source code above to reflect my changes.
rdos
Member
Member
Posts: 3306
Joined: Wed Oct 01, 2008 1:55 pm

Re: GDT Not installing properly?

Post by rdos »

My guess is that you mix-up 16-bit and 32-bit code. In the boot part, your code segment has 16-bit default operand size, but after loading the CS from the GDT you end up with 32-bit default operand size, which leads to faults.
Gogeta70
Member
Member
Posts: 28
Joined: Thu Jun 06, 2013 11:15 am

Re: GDT Not installing properly?

Post by Gogeta70 »

I'm doing from the assembly stub that is loaded by grub. I followed the tutorial on here for a barebones c kernel. Putting the code in there worked, for some reason. :/

Before i moved the code there, it was in a separate assembly file that was linked in, and then the function was called from my k_main function.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: GDT Not installing properly?

Post by BMW »

Gogeta70 wrote:
gdt.c

Code: Select all

#include "gdt.h"

void init_gdt_entries()
{
	// null descriptor
	gdt_entries[0].limit_low = 0;
	gdt_entries[0].base_low = 0;
	gdt_entries[0].base_mid = 0;
	gdt_entries[0].base_high = 0;
	gdt_entries[0].access = 0;
	gdt_entries[0].granularity = 0;
	
	// code descriptor
	gdt_entries[0].limit_low = 0xFFFF;
	gdt_entries[0].base_low = 0x0000;
	gdt_entries[0].base_mid = 0x00;
	gdt_entries[0].base_high = 0x00;
	gdt_entries[0].access = 0x9A;
	gdt_entries[0].granularity = 0xCF;
	
	// data descriptor
	gdt_entries[0].limit_low = 0xFFFF;
	gdt_entries[0].base_low = 0x0000;
	gdt_entries[0].base_mid = 0x00;
	gdt_entries[0].base_high = 0x00;
	gdt_entries[0].access = 0x92;
	gdt_entries[0].granularity = 0xCF;
	
	gdt_ptr.base = (unsigned long) &gdt_entries;
	gdt_ptr.limit = (sizeof(struct GDT_ENTRY) * GDT_ENTRY_COUNT) - 1;
	
}
Did you mean to put all of your GDT entries at offset 0? :wink:
Gogeta70 wrote: install_gdt.asm

Code: Select all


;extern gdt_ptr
global gdt_install

gdt_install:
	lgdt [m_gdt]
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	jmp 0x08:gdt_return
	
gdt_return:
	ret


gdt_start:
	
	; null descriptor
	
	dd 0
	dd 0
	
	;code descriptor
	
	dw 0xFFFF ; limit low
	dw 0x0000 ; base low
	db 0x00	  ; base middle
	db 0x9A	  ; access
	db 0xCF	  ; granularity
	db 0x00   ; base high
	
	;data descriptor
	
	dw 0xFFFF ; limit low
	dw 0x0000 ; base low
	db 0x00	  ; base middle
	db 0x92	  ; access
	db 0xCF	  ; granularity
	db 0x00   ; base high
	
gdt_end:

m_gdt:
	dw gdt_end - gdt_start - 1;
	dd gdt_start

Try this...

Code: Select all

gdt_install:
	lgdt [m_gdt]
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	cli
	mov eax,cr0
	or al,00000001b
	mov cr0,eax ;enable protected mode
	jmp 0x08:gdt_return

bits 32
	
gdt_return:
	ret
You have to enable protected mode before trying to use GDT selectors e.g. jmp 0x08:gdt_return, otherwise it would just interpret the 0x08:gdt_return as a segment:offset address. I guess that was why it wasn't returning from the gdt_install function. And since we are in protected mode when we do the far jump, we must set the assembly to 32 bits.

More info on segmentation/real mode/protected mode here: http://wiki.osdev.org/Segmentation

I'm not sure why Bran left it out of his tutorial...
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: GDT Not installing properly?

Post by AJ »

BMW wrote: You have to enable protected mode before trying to use GDT selectors
...
I'm not sure why Bran left it out of his tutorial...
Because the kernel is booted by GRUB which does the switch to PMode already. The only reason for reloading the GDT is that the multiboot documentation states that you cannot rely on the temporary GDT put in place by a multiboot compliant loader.

Cheers,
Adam
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: GDT Not installing properly?

Post by BMW »

AJ wrote: Because the kernel is booted by GRUB which does the switch to PMode already. The only reason for reloading the GDT is that the multiboot documentation states that you cannot rely on the temporary GDT put in place by a multiboot compliant loader.
Ahh, my bad.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
Post Reply