Triple Fault after STI
Posted: Tue Sep 08, 2020 2:18 pm
I have problem with setting up an IDT, I read 3 different GDT and IDT tutorials and still I'm unable to set it up correctly, as far as I can investigate code with "HelpMe" function I can tell that CPU do not event jump into "HandleInterrupt" asm section. I'm fighting two days with this and this is probably my lack of knowledge. Here is code:
GDT.h:
GDT.c
GDTasm.s
interrupt.h
interrupt.c
interruptasm.s
I hope someone would help me.
GDT.h:
Code: Select all
#ifndef __GDT_H
#define __GDT_H
#include <stdint.h>
#include "kernelstdio.h"
struct gdt_entry
{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
}__attribute__((packed));
struct gdt_ptr
{
uint16_t limit;
uint32_t base;
}__attribute__((packed));
extern struct gdt_entry gdt[3];
extern struct gdt_ptr gp;
extern void gdt_flush();
extern void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran);
extern void gdt_install();
#endif
Code: Select all
#include "GDT.h"
struct gdt_entry gdt[3];
struct gdt_ptr gp;
void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran)
{
/* Setup the descriptor base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
/* Setup the descriptor limits */
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
/* Finally set up the granularity and access flags */
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
void gdt_install()
{
/* NULL descriptor*/
gdt_set_gate(0, 0, 0, 0, 0);
/* CODE segment 4GB */
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
/* DATA segment 4GB */
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
/*Flush old GDT and aplly new one*/
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
gp.base = gdt;
gdt_flush();
}
Code: Select all
.section .text
.global gdt_flush
.extern gp
gdt_flush:
lgdt gp
jmp $0x08, $flush2
flush2:
mov $0x10, %eax
mov %eax, %ds
mov %eax, %es
mov %eax, %fs
mov %eax, %gs
mov %eax, %ss
ret
Code: Select all
#ifndef __INTERRUPT_H
#define __INTERRUPT_H
#include <stdint.h>
#include "GDT.h"
#include "kernelstdio.h"
struct idt_entry
{
uint16_t handlerAddressLow;
uint16_t gdt_codeSegmentSelector;
uint8_t reserved;
uint8_t access;
uint16_t handlerAddressHigh;
}__attribute__((packed));
struct idt_ptr
{
uint16_t limit;
uint32_t base;
}__attribute__((packed));
extern struct idt_entry idt[256];
extern struct idt_ptr ip;
extern void InitInterupts();
extern void ActivateInterrupts();
extern void SetIDTentry(uint8_t INT_number, uint16_t CodeSegmentSelectorOffset, void(*handler)(), uint8_t DescriptorPrivilidgeLevel, uint8_t DescriptorType);
extern uint32_t HandleInterrupt(uint8_t INT_number, uint32_t ESP);
extern void HandleInterruptRequest0x00();
extern void HandleInterruptRequest0x01();
extern void IgnoreInterruptRequest();
extern void HelpMe();
extern void idt_install();
#endif
Code: Select all
#include "interrupt.h"
struct idt_entry idt[256];
struct idt_ptr ip;
void InitInterupts()
{
const uint8_t IDT_INT_GATE = 0xE;
uint16_t CodeSegment = &gdt[1];
for(uint16_t i=0; i<256; ++i)
{
SetIDTentry(i, CodeSegment, &IgnoreInterruptRequest, 0, IDT_INT_GATE);
}
SetIDTentry(0x20, CodeSegment, &HandleInterruptRequest0x00, 0, IDT_INT_GATE);
SetIDTentry(0x21, CodeSegment, &HandleInterruptRequest0x01, 0, IDT_INT_GATE);
ip.limit = (sizeof(struct idt_entry) * 256) - 1;
ip.base = idt;
idt_install();
}
void ActivateInterrupts()
{
asm volatile("sti");
}
void SetIDTentry(uint8_t INT_number, uint16_t CodeSegmentSelectorOffset, void(*handler)(), uint8_t DescriptorPrivilidgeLevel, uint8_t DescriptorType)
{
const uint8_t IDT_DESC_PRESENT = 0x80;
idt[INT_number].handlerAddressLow = ((uint32_t)handler) & 0xFFFF;
idt[INT_number].handlerAddressHigh = ((uint32_t)handler >> 16) & 0xFFFF;
idt[INT_number].gdt_codeSegmentSelector = CodeSegmentSelectorOffset;
idt[INT_number].access = IDT_DESC_PRESENT | DescriptorType | ((DescriptorPrivilidgeLevel & 3) << 5);
idt[INT_number].reserved = 0;
}
uint32_t HandleInterrupt(uint8_t INT_number, uint32_t ESP)
{
printf("INTERRUPT\n");
return ESP;
}
void HelpMe()
{
printf("Help\n");
}
Code: Select all
.set IRQ_BASE, 0x20
.section .text
.extern HandleInterrupt
.extern HelpMe
.extern ip
.global idt_install
.global IgnoreInterruptRequest
.macro MyHandleInterruptRequest num
.global HandleInterruptRequest\num\()
HandleInterruptRequest\num\():
movb $\num + IRQ_BASE, (interruptnumber)
jmp int_bottom
.endm
MyHandleInterruptRequest 0x00
MyHandleInterruptRequest 0x01
.macro MyHandleException num
.global HandleException\num\()
HandleException\num\():
movb $\num, (interruptnumber)
jmp int_bottom
.endm
idt_install:
lidt ip
ret
int_bottom:
pusha
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %esp
push (interruptnumber)
call HandleInterrupt
mov %eax, %esp
popl %gs
popl %fs
popl %es
popl %ds
popa
IgnoreInterruptRequest:
iret
.data
interruptnumber: .byte 0