Page 1 of 1

IDT problem [SOLVED]

Posted: Fri Apr 27, 2007 10:17 am
by bsunisol
hi all,
i am currently working on my osloader in c.
but when i call a HLT or JMP insturction after
setting up the idt and enabling interrupts it throws
a general protection fault (13). and bochs restarts.
it says the system segments are not valid.
but why?

the jumps from c-code to asm-code and back
are correct.
and all typdefs are defined with #pragma pack( 1 )

thanks
Uni_Sol

---

now the code:

Code: Select all

void osloader() {
	/* ************************************************************************* */

	TableRegister gdt, idt;
	char* con = (char*)0xB8000;
	int n=0, i=0;
	char* version = VER_STRING;

	/* ************************************************************************* */

	pDescriptor	GDT_BASE_POINTER = (pDescriptor)	0x00100000;
	pGate		IDT_BASE_POINTER = (pGate)			0x00110000;

	gdt.size = (unsigned short) 0xFFFF;
	gdt.base = (unsigned long ) GDT_BASE_POINTER;
	
	idt.size = (unsigned short) 0xFFFF;
	idt.base = (unsigned long ) IDT_BASE_POINTER;

	/* ************************************************************************* */

	FlushGDT();
	GDTCreateDesc( 0, 0x00, 0x00, 0, 0, 0, 0, 0 );
	GDTCreateDesc( 1, 0x00, 0xFFFFFFFF, TYPE_CODE_EXEC_AND_READ,  LEVEL_RING_0, SYSTEM_SEGMENT, PRESENT, SIZE_4KBYTE );
	GDTCreateDesc( 2, 0x00, 0xFFFFFFFF, TYPE_DATA_READ_AND_WRITE, LEVEL_RING_0, SYSTEM_SEGMENT, PRESENT, SIZE_4KBYTE );

	/* ************************************************************************* */

	FlushIDT();
	isr_install();
	irq_install();

	/* ************************************************************************* */

	LoadIDT( idt );
	LoadGDT( gdt );

	/* ************************************************************************* */

	enable();
	halt();
}
error:

Code: Select all

00015000306-e-@00000708-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00015000306-e-@00000708-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00015000306-e-@00000708-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00015000306-i-@00000708-[CPU0 ] protected mode
00015000306-i-@00000708-[CPU0 ] CS.d_b = 32 bit
00015000306-i-@00000708-[CPU0 ] SS.d_b = 32 bit
00015000306-i-@00000708-[CPU0 ] | EAX=00000010  EBX=00008003  ECX=00000021  EDX=0000008e
00015000306-i-@00000708-[CPU0 ] | ESP=0001050b  EBP=00000000  ESI=0000803c  EDI=00000010
00015000306-i-@00000708-[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf zf af pf cf
00015000306-i-@00000708-[CPU0 ] | SEG selector     base    limit G D
00015000306-i-@00000708-[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00015000306-i-@00000708-[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00015000306-i-@00000708-[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00015000306-i-@00000708-[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00015000306-i-@00000708-[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00015000306-i-@00000708-[CPU0 ] |  FS:0000( 0000| 0|  0) 000ffff0 0000ffff 0 0
00015000306-i-@00000708-[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00015000306-i-@00000708-[CPU0 ] | EIP=00000708 (00000708)
00015000306-i-@00000708-[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00015000306-i-@00000708-[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00015000306-i-@00000708-[CPU0 ] >> ret  : C3
00015000306-e-@00000708-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
tydefs:

Code: Select all

typedef struct _Gate {							/* Gate in der IDT				 */
	unsigned int	offset_low	:16;			/* 1. Word der Funk.-Adresse	 */
	unsigned int	selector	:16;			/* Selektor aus der GDT			 */
	unsigned int	reserved	:8;				/* Reserviert					 */
	unsigned int	type		:8;				/* Zugriffs- und Statusbyte		 */
	unsigned int	offset_high	:16;			/* 2. Word der Funk.-Adresse	 */
} Gate, *pGate;
functions:

Code: Select all

void GDTCreateDesc( unsigned int	num,
				    unsigned long	base,
					unsigned long	size,
					unsigned int	type,			// 3
					unsigned int	level,			// 2
					unsigned int	system,			// 1
					unsigned int	present,		// 1
					unsigned int	seg_size ) {	// 1
    /* Setup the descriptor base address */
    GDT_BASE_POINTER[num].base_low		= (base & 0xFFFF);
    GDT_BASE_POINTER[num].base_mid		= (base >> 16) & 0xFF;
    GDT_BASE_POINTER[num].base_high		= (base >> 24) & 0xFF;

    /* Setup the descriptor size */
    GDT_BASE_POINTER[num].size_low		= (size & 0xFFFF);
    GDT_BASE_POINTER[num].size_high		= ((size >> 16) & 0xF);

	GDT_BASE_POINTER[num].type			= type;
	GDT_BASE_POINTER[num].level			= level;
	GDT_BASE_POINTER[num].system		= system;
	GDT_BASE_POINTER[num].present		= present;
	GDT_BASE_POINTER[num].seg_size		= seg_size;
}

/* ***************************************************************************** */

void IDTCreateGate( unsigned int num,
				    unsigned long offset,
					unsigned short selector,
				    unsigned char type ) {
	/* Setup the gate base address */
    IDT_BASE_POINTER[num].offset_low	= (offset & 0xFFFF);
    IDT_BASE_POINTER[num].offset_high	= (offset >> 16);

    /* Setup the gate selector */
    IDT_BASE_POINTER[num].selector		= selector;

    /* Finally, set up the type and reserved */
    IDT_BASE_POINTER[num].type			= type;
    IDT_BASE_POINTER[num].reserved		= 0;
}

/* ***************************************************************************** */

void LoadGDT( TableRegister gdt ) {
	asm( "lgdt %0" : "=m" (gdt) );
}

/* ***************************************************************************** */

void LoadIDT( TableRegister idt ) {
	asm( "lidt %0" : "=m" (idt) );
}

/* ***************************************************************************** */

void FlushIDT() {
	int i=0;
	for( i; i <= 0xFFFF; i++ ) {
		IDTCreateGate( 0, 0, 0, 0 );
	}
}

/* ***************************************************************************** */

void FlushGDT() {
	int i=0;
	for( i; i <= 0xFFFF; i++ ) {
		GDTCreateDesc( 0, 0, 0, 0, 0, 0, 0, 0 );
	}
}

/* ***************************************************************************** */
asm:

Code: Select all

CODE_SECTION32:
	call	_osloader

	; künstlicher fehler
	;xor	eax, eax
	;mov	ebx, eax
	;div	ebx

; ***********************************************

hang:	jmp	hang

; ***********************************************
; void halt()
_halt:	hlt
	ret

; ***********************************************
; void disable()
_disable:
	cli
	ret

; ***********************************************
; void enable()
_enable:	sti
	ret

Posted: Fri Apr 27, 2007 11:34 am
by INF1n1t
I don't know, man. I never saw, where you call IDTCreateGate with valid parameters.

Posted: Fri Apr 27, 2007 11:59 am
by bsunisol
I never saw, where you call IDTCreateGate with valid parameters
ahhhh sry forgot to post it.

:arrow:

Code: Select all

void isr_install() {
	IDTCreateGate(  0, (unsigned)  isr0, CODE_SELECTOR, 0x8E ); 
	IDTCreateGate(  1, (unsigned)  isr1, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  2, (unsigned)  isr2, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  3, (unsigned)  isr3, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  4, (unsigned)  isr4, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  5, (unsigned)  isr5, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  6, (unsigned)  isr6, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  7, (unsigned)  isr7, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  8, (unsigned)  isr8, CODE_SELECTOR, 0x8E );
	IDTCreateGate(  9, (unsigned)  isr9, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 10, (unsigned) isr10, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 11, (unsigned) isr11, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 12, (unsigned) isr12, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 13, (unsigned) isr13, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 14, (unsigned) isr14, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 15, (unsigned) isr15, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 16, (unsigned) isr16, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 17, (unsigned) isr17, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 18, (unsigned) isr18, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 19, (unsigned) isr19, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 20, (unsigned) isr20, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 21, (unsigned) isr21, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 22, (unsigned) isr22, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 23, (unsigned) isr23, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 24, (unsigned) isr24, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 25, (unsigned) isr25, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 26, (unsigned) isr26, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 27, (unsigned) isr27, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 28, (unsigned) isr28, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 29, (unsigned) isr29, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 30, (unsigned) isr30, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 31, (unsigned) isr31, CODE_SELECTOR, 0x8E );
}

Code: Select all

void irq_install() {

	irq_routines[ 0] = 0;
	irq_routines[ 1] = 0;
	irq_routines[ 2] = 0;
	irq_routines[ 3] = 0;
	irq_routines[ 4] = 0;
	irq_routines[ 5] = 0;
	irq_routines[ 6] = 0;
	irq_routines[ 7] = 0;
	irq_routines[ 8] = 0;
	irq_routines[ 9] = 0;
	irq_routines[10] = 0;
	irq_routines[11] = 0;
	irq_routines[12] = 0;
	irq_routines[13] = 0;
	irq_routines[14] = 0;
	irq_routines[15] = 0;

    out( 0x20, 0x11 );
    out( 0xA0, 0x11 );
    out( 0x21, 0x20 );
    out( 0xA1, 0x28 );
    out( 0x21, 0x04 );
    out( 0xA1, 0x02 );
    out( 0x21, 0x01 );
    out( 0xA1, 0x01 );
    out( 0x21,  0x0 );
    out( 0xA1,  0x0 );

	IDTCreateGate( 32, (unsigned)  irq0, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 33, (unsigned)  irq1, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 34, (unsigned)  irq2, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 35, (unsigned)  irq3, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 36, (unsigned)  irq4, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 37, (unsigned)  irq5, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 38, (unsigned)  irq6, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 39, (unsigned)  irq7, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 40, (unsigned)  irq8, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 41, (unsigned)  irq9, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 42, (unsigned) irq10, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 43, (unsigned) irq11, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 44, (unsigned) irq12, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 45, (unsigned) irq13, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 46, (unsigned) irq14, CODE_SELECTOR, 0x8E );
	IDTCreateGate( 47, (unsigned) irq15, CODE_SELECTOR, 0x8E );
}

Posted: Fri Apr 27, 2007 3:07 pm
by INF1n1t
OK, one thing I can't undestand: correct me if I'm wrong please.

So, you create three global descriptors (null, code and data). But you try to make them system segments. Ok, either it is code/data or it is system. I think you can't create code system segments. And that appears to be the purpose of this code.

Define your DPL=0 code segment wich is not a system segment. Then define new segment, which is a system segment and has the type of E - Interrupt Gate.

Edit: Note that when S flag is clear, the segment descriptor is SYSTEM.

Posted: Fri Apr 27, 2007 3:23 pm
by bsunisol
hmm i think i dont get it....

:?:

pmode.h:

Code: Select all

#ifndef __PMODE_H
#define __PMODE_H

/* ***************************************************************************** */

#pragma pack( 1 )

/* ***************************************************************************** */

typedef struct _TableRegister {					/* IDT/GDT register				 */
	unsigned short	size;						/* Größe der Tabelle			 */
	unsigned long	base;						/* Basisadresse der Tabelle		 */
} TableRegister, *pTableRegister;

/* ***************************************************************************** */

typedef struct _Gate {							/* Gate in der IDT				 */
	unsigned int	offset_low	:16;			/* 1. Word der Funk.-Adresse	 */
	unsigned int	selector	:16;			/* Selektor aus der GDT			 */
	unsigned int	reserved	: 8;			/* Reserviert					 */
	unsigned int	type		: 8;			/* Zugriffs- und Statusbyte		 */
	unsigned int	offset_high	:16;			/* 2. Word der Funk.-Adresse	 */
} Gate, *pGate;

/* ***************************************************************************** */

typedef struct _Descriptor {					/* Descriptor in der GDT		 */
	unsigned int	size_low	:16;			/* 1. Word der Größe			 */
	unsigned int	base_low	:16;			/* 1. Word der Basisadresse		 */
	unsigned int	base_mid	: 8;			/* 3. Byte der Basisadresse		 */
	unsigned int	access		: 1;			/* zugriff & segmenttyp			 */
	unsigned int	type		: 3;			/* zugriff & segmenttyp			 */
	unsigned int	system		: 1;			/* zugriff & segmenttyp			 */
	unsigned int	level		: 2;			/* zugriff & segmenttyp			 */
	unsigned int	present		: 1;			/* zugriff & segmenttyp			 */
	unsigned int	size_high	: 4;			/* Letztes Nibble der Größe		 */
	unsigned int	avl			: 1;			/* zusatz						 */
	unsigned int	null		: 1;			/* zusatz						 */
	unsigned int	_386		: 1;			/* zusatz						 */
	unsigned int	seg_size	: 1;			/* zusatz						 */
	unsigned int	base_high	: 8;			/* Letztes Byte der Basisadresse */
} Descriptor, *pDescriptor;

/* ***************************************************************************** */

pDescriptor	GDT_BASE_POINTER;
pGate		IDT_BASE_POINTER;

/* ***************************************************************************** */

#define TYPE_DATA_NO_WRITE				0x0
#define TYPE_DATA_READ_AND_WRITE		0x1
#define TYPE_RESERVED					0x2
#define TYPE_DATA_EXPAND_DOWN			0x3
#define TYPE_CODE_EXEC_NO_READ			0x4
#define TYPE_CODE_EXEC_AND_READ			0x5
#define TYPE_CONFIRM_CODE_EXEC_NO_READ	0x6
#define TYPE_CONFRIM_CODE_EXEC_AND_READ	0x7

/* ***************************************************************************** */

#define LEVEL_RING_0					0x0
#define LEVEL_RING_1					0x1
#define LEVEL_RING_2					0x2
#define LEVEL_RING_3					0x3

/* ***************************************************************************** */

#define SYSTEM_SEGMENT					0x0
#define NON_SYSTEM_SEGMENT				0x1

/* ***************************************************************************** */

#define PRESENT							0x1
#define NOT_PRESENT						0x0

/* ***************************************************************************** */

#define SIZE_1BYTE						0x0
#define SIZE_4KBYTE						0x1

/* ***************************************************************************** */

#define CODE_SELECTOR					0x08
#define DATA_SELECTOR					0x10

/* ***************************************************************************** */

void GDTCreateDesc( unsigned int num, unsigned long base, unsigned long size,
					unsigned int type, unsigned int level, unsigned int system,
					unsigned int present, unsigned int seg_size );
void IDTCreateGate( unsigned int num, unsigned long base, unsigned short selector,
				    unsigned char flags );
void LoadGDT( TableRegister gdt );
void LoadIDT( TableRegister idt );
void FlushIDT();
void FlushGDT();

/* ***************************************************************************** */

#endif
pmode.c:

Code: Select all

#include "pmode.h"

/* ***************************************************************************** */

void GDTCreateDesc( unsigned int	num,
				    unsigned long	base,
					unsigned long	size,
					unsigned int	type,			// 3
					unsigned int	level,			// 2
					unsigned int	system,			// 1
					unsigned int	present,		// 1
					unsigned int	seg_size ) {	// 1
    /* Setup the descriptor base address */
    GDT_BASE_POINTER[num].base_low		= (base & 0xFFFF);
    GDT_BASE_POINTER[num].base_mid		= (base >> 16) & 0xFF;
    GDT_BASE_POINTER[num].base_high		= (base >> 24) & 0xFF;

    /* Setup the descriptor size */
    GDT_BASE_POINTER[num].size_low		= (size & 0xFFFF);
    GDT_BASE_POINTER[num].size_high		= ((size >> 16) & 0xF);

	GDT_BASE_POINTER[num].type			= type;
	GDT_BASE_POINTER[num].level			= level;
	GDT_BASE_POINTER[num].system		= system;
	GDT_BASE_POINTER[num].present		= present;
	GDT_BASE_POINTER[num].seg_size		= seg_size;
}

/* ***************************************************************************** */

void IDTCreateGate( unsigned int num,
				    unsigned long offset,
					unsigned short selector,
				    unsigned char type ) {
	/* Setup the gate base address */
    IDT_BASE_POINTER[num].offset_low	= (offset & 0xFFFF);
    IDT_BASE_POINTER[num].offset_high	= (offset >> 16);

    /* Setup the gate selector */
    IDT_BASE_POINTER[num].selector		= selector;

    /* Finally, set up the type and reserved */
    IDT_BASE_POINTER[num].type			= type;
    IDT_BASE_POINTER[num].reserved		= 0;
}

/* ***************************************************************************** */

void LoadGDT( TableRegister gdt ) {
	asm( "lgdt %0" : "=m" (gdt) );
}

/* ***************************************************************************** */

void LoadIDT( TableRegister idt ) {
	asm( "lidt %0" : "=m" (idt) );
}

/* ***************************************************************************** */

void FlushIDT() {
	int i=0;
	for( i; i <= 0xFFFF; i++ ) {
		IDTCreateGate( 0, 0, 0, 0 );
	}
}

/* ***************************************************************************** */

void FlushGDT() {
	int i=0;
	for( i; i <= 0xFFFF; i++ ) {
		GDTCreateDesc( 0, 0, 0, 0, 0, 0, 0, 0 );
	}
}

/* ***************************************************************************** */

Posted: Fri Apr 27, 2007 4:04 pm
by INF1n1t
And now I've been able to read your complete code and I saw that your defines are not wrong. :lol: I was confused by the three bits type field. However,

Code: Select all

 GDTCreateDesc( 1, 0x00, 0xFFFFFFFF, TYPE_CODE_EXEC_AND_READ,  LEVEL_RING_0, SYSTEM_SEGMENT, PRESENT, SIZE_4KBYTE );
   GDTCreateDesc( 2, 0x00, 0xFFFFFFFF, TYPE_DATA_READ_AND_WRITE, LEVEL_RING_0, SYSTEM_SEGMENT, PRESENT, SIZE_4KBYTE ); 
I think it should be

Code: Select all

 GDTCreateDesc( 1, 0x00, 0xFFFFFFFF, TYPE_CODE_EXEC_AND_READ,  LEVEL_RING_0, NON_SYSTEM_SEGMENT, PRESENT, SIZE_4KBYTE );
   GDTCreateDesc( 2, 0x00, 0xFFFFFFFF, TYPE_DATA_READ_AND_WRITE, LEVEL_RING_0, NON_SYSTEM_SEGMENT, PRESENT, SIZE_4KBYTE ); 

Posted: Sat Apr 28, 2007 5:23 am
by bsunisol
ahh thanks.
dont thought about it. systemsegments are tss-segs but my kernel code is not :lol: 8)

Posted: Sat Apr 28, 2007 11:54 am
by INF1n1t
Did it work?

Posted: Sat Apr 28, 2007 12:18 pm
by bsunisol
yes. thanks.

now im working on paging.