Loading GDT causes triple-fault
Posted: Thu Jul 26, 2007 9:07 am
Okay, I know that everyone has answered droves of questions related to newbie attempts at using Bran's tutorial. I've personally used the tutorial successfully on numerous occasions (cut and paste tinkering) for the sake of playing around. It's a nice piece of work. Now that I've sat down to actually work on a research kernel, I've managed to code a GDT that triple-faults.
I apologize for such a lenghty post but I sincerely appreciate anyone's help which might clear up this issue. I've worked on this for over a week and have made no progress.![Mad :x](./images/smilies/icon_mad.gif)
I've attached the tarball of my code. It is heavily borrowed from Bran's tutorial to act as a skeleton while I rework his code and start on my additions. If you've fiddled with his tutorial any, the code will look familiar.
When I run the code from Bochs (or VMware), I get a triple-fault at the far jump.
I've tried using the original code to look like:
but that triple-faults at the mov ds, ax operation.
My link.ld looks like:
The output from Bochs using the far jump:
The output from Bochs when I use the original gdt_flush looks similar, but hoses at the mov ds, ax.
The first lines look suspicious, but I can also see that DS, SS, ES, DS, and GS all look to have 0x10 mov'd to them (which likely happened earlier in the run).
FWIW: I'm using GRUB and I know that GRUB sends us to protected mode and sets up a GDT (of sorts) and that a triple-fault will occur if you step on that one. Could it be that this is what's occuring in my code?
1000 thanks!
I apologize for such a lenghty post but I sincerely appreciate anyone's help which might clear up this issue. I've worked on this for over a week and have made no progress.
![Mad :x](./images/smilies/icon_mad.gif)
I've attached the tarball of my code. It is heavily borrowed from Bran's tutorial to act as a skeleton while I rework his code and start on my additions. If you've fiddled with his tutorial any, the code will look familiar.
Code: Select all
/* gdt.c */
#include <gdt.h>
/* setup descriptor in gdt */
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity)
{
/* set up descriptor base addr */
gdt[num].base_lo = (base & 0xFFFF);
gdt[num].base_mid = (base >> 16) & 0xFF;
gdt[num].base_hi = (base >> 24) & 0xFF;
/* set up descriptor limits */
gdt[num].limit_lo = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
/* set up granularity and access flags */
gdt[num].granularity |= (granularity & 0xF0);
gdt[num].access = access;
}
/* called by main to set up gdt, first 3 entries in gdt, and call gdt_flush */
void gdt_install()
{
/* setup gdt pointer and limit */
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
gp.base = (unsigned int)(&gdt);
/* null descriptor */
gdt_set_gate(0, 0, 0, 0, 0);
/* cs - base addr is 0, limit is 4gb w/ 4kb gran, 32-bit opcodes */
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
/* ds - same as code, but descriptor type is ds */
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
/* flush old gdt and install new */
gdt_flush();
}
Code: Select all
/* include/gdt.h */
#ifndef __GDT_H
#define __GDT_H
/* define gdt entry - packed prevents compiler from dorking it up */
struct gdt_entry
{
unsigned short limit_lo;
unsigned short base_lo;
unsigned char base_mid;
unsigned char access;
unsigned char granularity;
unsigned char base_hi;
} __attribute__ ((__packed__));
/* special pointer - max bytes taken by gdt - 1 */
struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__ ((__packed__));
/* a simple 3-entry gdt and pointer */
struct gdt_entry gdt[3];
struct gdt_ptr gp;
/* the extern function in loader.asm */
extern void gdt_flush();
void gdt_set_gate(int, unsigned long, unsigned long, unsigned char, unsigned char);
void gdt_install();
#endif
Code: Select all
; snippet from loader.asm
;; the gdt (global descriptor table)
[global gdt_flush] ; allow c code to link this
[extern gp] ; gp is in gdt.c
gdt_flush:
lgdt [gp]
jmp 0x08:gdt_flush2 ; 0x08 is offset to code seg - far jmp
gdt_flush2:
mov ax, 0x10 ; 0x10 is offset in gdt to ds
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret ; return back to c code
Code: Select all
;; the gdt (global descriptor table)
[global gdt_flush] ; allow c code to link this
[extern gp] ; gp is in gdt.c
gdt_flush:
lgdt [gp]
mov ax, 0x10 ; 0x10 is offset in gdt to ds
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
gdt_flush2:
ret ; return back to c code
My link.ld looks like:
Code: Select all
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys)
{
code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
*(.COMMON*)
. = ALIGN(4096);
}
end = .;
}
Code: Select all
00079523319e[CPU ] fetch_raw_descriptor: GDT: index (f)1 > limit (0)
00079523319e[CPU ] interrupt(): gate descriptor is not valid sys seg
00079523319e[CPU ] interrupt(): gate descriptor is not valid sys seg
00079523319i[CPU ] protected mode
00079523319i[CPU ] CS.d_b = 32 bit
00079523319i[CPU ] SS.d_b = 32 bit
00079523319i[CPU ] | EAX=2badb002 EBX=0002cc80 ECX=00103000 EDX=00000001
00079523319i[CPU ] | ESP=00102fcc EBP=00067ebc ESI=000538f4 EDI=000538f5
00079523319i[CPU ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00079523319i[CPU ] | SEG selector base limit G D
00079523319i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00079523319i[CPU ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00079523319i[CPU ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00079523319i[CPU ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00079523319i[CPU ] | ES:0010( 0002| 0| 0) 00000000 000fffff 1 1
00079523319i[CPU ] | FS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00079523319i[CPU ] | GS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00079523319i[CPU ] | EIP=00100032 (00100032)
00079523319i[CPU ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00079523319i[CPU ] | CR3=0x00000000 CR4=0x00000000
00079523319i[CPU ] >> jmp far 0008:00100039 : EA390010000800
00079523319p[CPU ] >>PANIC<< exception(): 3rd (13) exception with no resolution
Code: Select all
00074203321e[CPU ] fetch_raw_descriptor: GDT: index (17)2 > limit (0)
00074203321e[CPU ] interrupt(): gate descriptor is not valid sys seg
00074203321e[CPU ] interrupt(): gate descriptor is not valid sys seg
00074203321i[CPU ] protected mode
00074203321i[CPU ] CS.d_b = 32 bit
00074203321i[CPU ] SS.d_b = 32 bit
00074203321i[CPU ] | EAX=2bad0010 EBX=0002cc80 ECX=00103000 EDX=00000001
00074203321i[CPU ] | ESP=00102fcc EBP=00067ebc ESI=000538f4 EDI=000538f5
00074203321i[CPU ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00074203321i[CPU ] | SEG selector base limit G D
00074203321i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00074203321i[CPU ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00074203321i[CPU ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00074203321i[CPU ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00074203321i[CPU ] | ES:0010( 0002| 0| 0) 00000000 000fffff 1 1
00074203321i[CPU ] | FS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00074203321i[CPU ] | GS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00074203321i[CPU ] | EIP=00100036 (00100036)
00074203321i[CPU ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00074203321i[CPU ] | CR3=0x00000000 CR4=0x00000000
00074203321i[CPU ] >> mov ds, ax : 8ED8
00074203321p[CPU ] >>PANIC<< exception(): 3rd (13) exception with no resolution
![Crying or Very sad :cry:](./images/smilies/icon_cry.gif)
1000 thanks!