protected mode: loading the idt



Hi!
I have a lot of problems with loading the idt. Perhaps I'm a little bit
confused - but that's why I write this message.
I'm currently writing on a small kernel for IA-32 processors. I've already
set up my gdt and jumped successfully into the protected mode. Now I'd like
to enable interrupts. My plan is the following:

- Creating a 2-byte-aligned block in RAM with 256*8 bytes for the idt's
descriptors.
- These descriptors are all filled with the selector of my current
code-segment (which starts at 0x0 and has 4 GiB) and an interrupt-handler
written in assembly language.
- loading the idt via lidt. The base is where the idt-block starts and the
limit is set to 256*8 bytes.

Well, I did that and everything worked fine. But when I tried to enable
interrupts with the sti-instruction the computer stops and reboots.

Is there enything that I've forgotten?

My sourcecode is the following. I have a file called main.c with the
function _setup_idt(). Further I've got some header-files with preprocessor
definitions written in C. Last but not least there is a file written in
assembly language that is linked to the c-file. The asm-file contains the
interrupt-handler:

-------------- main.c: --------------------------

#include <utils.h>
#include <pmode.h>

void _setup_idt();
int main()
{
_setup_idt();

hang:
goto hang;

return 0;
}

#define NUM_IDT_ENTRIES 256

extern void interrupt0();
void _setup_idt()
{
static volatile _idt_pointer idt;
static volatile _idt_entry entries[NUM_IDT_ENTRIES];

idt.base = (_u32)&entries[0];
idt.limit = 8*NUM_IDT_ENTRIES;


for(int i = 0; i < NUM_IDT_ENTRIES; i++)
fill_idt_entry(&entries[i], (_u32)interrupt0, 8, ACS_INT,
0);

asm volatile("lidt (%%eax)\n" ::"a"(&idt));
asm volatile("sti"::);
}

--------------------- pmode.h: --------------------
#ifndef __UUID_KERNEL_PMODE_H
#define __UUID_KERNEL_PMODE_H

#include <types.h>

#define IDTENTRY_DPL_0 0x0
#define IDTENTRY_DPL_1 0x20
#define IDTENTRY_DPL_2 0x40
#define IDTENTRY_DPL_3 0x60

#define IDTENTRY_PRESENT 0x80

typedef struct {
_u16 offs1;
_u16 selector;
_u8 reserved;
_u8 flags;
_u16 offs2;
} _idt_entry __attribute__((packed)) __attribute__((aligned(2)));

typedef struct {
_u16 limit;
_u32 base;
} _idt_pointer __attribute__((packed)) __attribute__((aligned(2)));


/* Access byte's flags */
#define ACS_PRESENT 0x80 /* present segment */
#define ACS_CSEG 0x18 /* code segment */
#define ACS_DSEG 0x10 /* data segment */
#define ACS_CONFORM 0x04 /* conforming segment */
#define ACS_READ 0x02 /* readable segment */
#define ACS_WRITE 0x02 /* writable segment */
#define ACS_IDT ACS_DSEG /* segment type is the same type */
#define ACS_INT_GATE 0x06 /* int gate for 286 */
#define ACS_INT (ACS_PRESENT | ACS_INT_GATE) /* present int gate */

/* Ready-made values */
#define ACS_CODE (ACS_PRESENT | ACS_CSEG | ACS_READ)
#define ACS_DATA (ACS_PRESENT | ACS_DSEG | ACS_WRITE)
#define ACS_STACK (ACS_PRESENT | ACS_DSEG | ACS_WRITE)

#endif //__UUID_KERNEL_PMODE_H


------------------------- types.h: -------------------------------
#ifndef __UUID_KERNEL_TYPES_H
#define __UUID_KERNEL_TYPES_H

#define _u8 unsigned char
#define _s8 char
#define _u16 unsigned short
#define _s16 short
#define _u32 unsigned long
#define _s32 long

#endif //__UUID_KERNEL_TYPES_H

----------------------- irq.s -----------------------------------
..section .data

..section .text
..globl interrupt0


..align 2
interrupt0:
pusha
push %gs
push %fs
push %es
push %ds

movb $0x43, %al
movb %al, 0xB8000

pop %ds
pop %es
pop %fs
pop %gs
popa
iret

.



Relevant Pages