I have a problem (and probably I did misunderstood something):
I loaded the kernel, kernel loaded GDT and IDT, if after this I execute asm("sti"); I go double fault! Is that normal behavior?
kernel:
Code: Select all
static void k_set_descriptors();
//Main kernel function
extern int k_start(){
start_textmode();
print_to_screen("Text mode initialized: 80x25 console screen\n");
print_to_screen("Initializing Global and Interrupt Descriptor Tables...");
k_set_descriptors();
print_to_screen("Done!\n");
asm("sti");
/* exceptions test
{
int a, b;
a = 23;
b = 0;
a = a / b;
}*/
asm("hlt");
return 0;
}
//Set descriptors
static void k_set_descriptors(){
gdt_init();
idt_init();
}
Code: Select all
//Selectors
static gdt_descriptor_t selectors[MAX_SELECTORS];
/**
* Internal function.
* Set specific gdt selector.
* @param sel_num Number of selector.
* @param limit Low limit of selector.
* @param base_low Low base of selector.
* @param base_middle Middle base of selector.
* @param access Selector acces and info.
* @param granularity Selector info.
* @param base_high High base of selector.
*/
static void gdt_set_selector(u8int sel_id,
u16int limit, u16int base_low, u8int base_middle, u8int access,
u8int granularity, u8int base_high);
/**
* Load GDT to CPU.
* @param ptr GDT Pointer structure.
*/
static void gdt_load(gdt_pointer_t ptr);
//Init gdt
void gdt_init(){
gdt_pointer_t ptr;
//Null selector
gdt_set_selector(NULL_SEL_ID, 0, 0, 0, 0, 0, 0);
//Kernel code selector
gdt_set_selector(KERNEL_CODE_SEL_ID, 0xFFFF, 0, 0, 0x9A, 0xCF, 0);
//Kernel data selector
gdt_set_selector(KERNEL_DATA_SEL_ID, 0xFFFF, 0, 0, 0x92, 0xCF, 0);
ptr.limit = (sizeof(gdt_descriptor_t) * MAX_SELECTORS) - 1;
ptr.base = (unsigned long)&selectors;
//Load selectors
gdt_load(ptr);
}
//Set selector
static void gdt_set_selector(u8int sel_id,
u16int limit, u16int base_low, u8int base_middle, u8int access,
u8int granularity, u8int base_high){
if((sel_id < 0) || (sel_id >= MAX_SELECTORS)){
//Error here
///@todo
}else{
selectors[sel_id].limit = limit;
selectors[sel_id].base_low = base_low;
selectors[sel_id].base_middle = base_middle;
selectors[sel_id].access = access;
selectors[sel_id].granularity = granularity;
selectors[sel_id].base_high = base_high;
}
}
//Load gdt register
static void gdt_load(gdt_pointer_t ptr){
asm volatile("lgdt %0" : "=m" (ptr));
}
Code: Select all
//IDT entries
static idt_descriptor_t entries[MAX_IDT];
/**
* Set IDT gate.
* @param idt_num Number of IDT.
* @param base Address of interrupt handler.
* @param selector Selector type.
* @param info IDT info.
*/
static void idt_set_gate(u8int idt_num,
u32int base, u16int selector, u8int info);
/**
* Load IDT to IDTR.
* @param ptr Pointer to valid IDT structure.
*/
static void idt_load(idt_pointer_t ptr);
//Initialize IDT
void idt_init(){
idt_pointer_t ptr;
//Must defined ISRs, all run 32bit and ring0
idt_set_gate( 0, (u32int) isr0, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 1, (u32int) isr1, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 2, (u32int) isr2, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 3, (u32int) isr3, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 4, (u32int) isr4, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 5, (u32int) isr5, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 6, (u32int) isr6, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 7, (u32int) isr7, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 8, (u32int) isr8, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate( 9, (u32int) isr9, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(10, (u32int)isr10, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(11, (u32int)isr11, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(12, (u32int)isr12, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(13, (u32int)isr13, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(14, (u32int)isr14, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(15, (u32int)isr15, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(16, (u32int)isr16, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(17, (u32int)isr17, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(18, (u32int)isr18, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(19, (u32int)isr19, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(20, (u32int)isr20, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(21, (u32int)isr21, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(22, (u32int)isr22, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(23, (u32int)isr23, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(24, (u32int)isr24, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(25, (u32int)isr25, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(26, (u32int)isr26, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(27, (u32int)isr27, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(28, (u32int)isr28, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(29, (u32int)isr29, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(30, (u32int)isr30, KERNEL_CODE_SELECTOR, 0x8E);
idt_set_gate(31, (u32int)isr31, KERNEL_CODE_SELECTOR, 0x8E);
//Rest interrupts are zero for now
{
int i;
for(i = 32; i < MAX_IDT; ++i)
idt_set_gate(i, 0, 0, 0);
}
ptr.limit = (sizeof(idt_descriptor_t) * MAX_IDT) - 1;
ptr.base = (unsigned long)&entries;
//load idt
idt_load(ptr);
}
//Set IDT gate
static void idt_set_gate(u8int idt_num,
u32int base, u16int selector, u8int info){
if((idt_num < 0) || (idt_num >= MAX_IDT)){
//error
///@todo
}else{
entries[idt_num].base_low = base & 0xFFFF;
entries[idt_num].base_high = (base >> 16) & 0xFFFF;
entries[idt_num].selector = selector;
entries[idt_num].zero = 0;
entries[idt_num].info = info;
}
}
//Load idt
static void idt_load(idt_pointer_t ptr){
asm volatile("lidt %0" : "=m" (ptr));
}
Am I doing something wrong?