Triple fault on GDT install
Posted: Thu Apr 28, 2011 10:14 am
Hello,
My machine triple faults on my installation of the GDT, and, does it before the routines that should happen first happen (order:
parse command line
print messages
check boot loader info
install gdt
install idt
Instead it's doing it in this order:
install gdt
parse command line
print half the messages
crash
I had no problems before adding the gdt.
Anyway, I've read several posts about this, but nothing seems to fix my problem. And bochs won't compile for me So I'm limited on information about what happens when.
I know it's better to do the lgdt after the far jump, but I don't know if I would have to move 0x10 into ax and ax into the segments afterwards too (I assume so because I think I would have to load the new GDT ptr first). I wanna ask "please help?!?!?" but as that's not really gonna appease the computer demons............(shifty look)
Is there anything wrong with my code (I hope it's that)?
My machine triple faults on my installation of the GDT, and, does it before the routines that should happen first happen (order:
parse command line
print messages
check boot loader info
install gdt
install idt
Instead it's doing it in this order:
install gdt
parse command line
print half the messages
crash
I had no problems before adding the gdt.
Anyway, I've read several posts about this, but nothing seems to fix my problem. And bochs won't compile for me So I'm limited on information about what happens when.
Code: Select all
gdt.c
#include <gdt.h>
#include <link.h>
extern void gdt_flush(unsigned int);
void __install_gdt();
static void gdt_set_gate(int,unsigned int,unsigned int,unsigned char,unsigned char);
gdt_entry_t gdt_entries[5];
gdt_ptr_t gdt_ptr;
void __install_gdt()
{
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
gdt_ptr.base = (unsigned int)&gdt_entries;
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
gdt_flush((unsigned int)&gdt_ptr);
}
// Set the value of one GDT entry.
static void gdt_set_gate(int num, unsigned int base, unsigned int limit, unsigned char access, unsigned char gran)
{
gdt_entries[num].base_low = (base & 0xFFFF);
gdt_entries[num].base_middle = (base >> 16) & 0xFF;
gdt_entries[num].base_high = (base >> 24) & 0xFF;
gdt_entries[num].limit_low = (limit & 0xFFFF);
gdt_entries[num].granularity = (limit >> 16) & 0x0F;
gdt_entries[num].granularity |= gran & 0xF0;
gdt_entries[num].access = access;
}
Code: Select all
gdt.h
#ifndef __GDT_H
#define __GDT_H
struct gdt_entry_struct
{
unsigned short limit_low; // The lower 16 bits of the limit.
unsigned short base_low; // The lower 16 bits of the base.
unsigned char base_middle; // The next 8 bits of the base.
unsigned char access; // Access flags, determine what ring this segment can be used in.
unsigned char granularity;
unsigned char base_high; // The last 8 bits of the base.
} __attribute__((packed));
typedef struct gdt_entry_struct gdt_entry_t;
struct gdt_ptr_struct
{
unsigned short limit; // The upper 16 bits of all selector limits.
unsigned int base; // The address of the first gdt_entry_t struct.
}
__attribute__((packed));
typedef struct gdt_ptr_struct gdt_ptr_t;
#endif
Code: Select all
;gdt.asm
[GLOBAL gdt_flush] ; Allows the C code to call gdt_flush().
gdt_flush:
mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax] ; Load the new GDT pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:.flush ; 0x08 is the offset to our code segment: Far jump!
.flush:
ret
Is there anything wrong with my code (I hope it's that)?