Quick and dirty IDT setup

This commit is contained in:
Thomas Lovén 2017-12-06 16:53:12 +01:00
parent 25ef5f4688
commit cbcc67fc31
6 changed files with 219 additions and 2 deletions

View File

@ -2,8 +2,8 @@ ifeq ($(MITTOS64),)
$(error Unsupported environment! See README) $(error Unsupported environment! See README)
endif endif
SRC := $(wildcard **/*.[cS]) SRC := $(wildcard **/*.[cS]*)
OBJ := $(patsubst %, %.o, $(basename $(SRC))) OBJ := $(patsubst %, %.o, $(basename $(basename $(SRC))))
CFLAGS ?= -Wall -Wextra -pedantic CFLAGS ?= -Wall -Wextra -pedantic
CFLAGS += -ffreestanding -mcmodel=large CFLAGS += -ffreestanding -mcmodel=large
@ -20,6 +20,9 @@ LDFLAGS := -n -nostdlib -lgcc -T Link.ld
kernel: $(OBJ) kernel: $(OBJ)
$(LINK.c) $^ -o $@ $(LINK.c) $^ -o $@
%.S: %.S.py
python $^ > $@
# Automatically generate dependency files # Automatically generate dependency files
# Those keep track of which header files are used by which source files # Those keep track of which header files are used by which source files
DEP := $(OBJ:.o=.d) DEP := $(OBJ:.o=.d)
@ -39,6 +42,7 @@ clean:
rm -rf $(OBJ) $(DEP) kernel rm -rf $(OBJ) $(DEP) kernel
.PHONY: install clean .PHONY: install clean
.INTERMEDIATE: $(basename $(filter %.py, $(SRC)))
# Include generated dependency files # Include generated dependency files
include $(DEP) include $(DEP)

View File

@ -4,6 +4,8 @@
#include <debug.h> #include <debug.h>
#include <multiboot.h> #include <multiboot.h>
void interrupt_init();
void kmain(uint64_t multiboot_magic, void *multiboot_data) void kmain(uint64_t multiboot_magic, void *multiboot_data)
{ {
serial_init(PORT_COM1); serial_init(PORT_COM1);
@ -14,6 +16,15 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
debug_info("Kernel was loaded with command line \"%s\", by <%s>\n", kernel_boot_data.commandline, kernel_boot_data.bootloader); debug_info("Kernel was loaded with command line \"%s\", by <%s>\n", kernel_boot_data.commandline, kernel_boot_data.bootloader);
interrupt_init();
// Force a divide by zero exception
// ISR 0
int a = 5, b = 0;
int c = a/b;
debug("a: %d b:%d c:%d\n", a,b,c);
debug_ok("Boot \"Complete\"\n"); debug_ok("Boot \"Complete\"\n");
PANIC("Reached end of kernel main function\n"); PANIC("Reached end of kernel main function\n");

View File

@ -0,0 +1,89 @@
#include <stdint.h>
#include <memory.h>
#include <debug.h>
struct int_gate_descriptor
{
uint16_t base_l;
uint16_t cs;
uint8_t ist;
uint8_t flags;
uint16_t base_m;
uint32_t base_h;
uint32_t ignored;
} __attribute__((packed));
struct idtr
{
uint16_t len;
struct int_gate_descriptor *addr;
} __attribute__((packed));
typedef struct
{
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t rbp;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t int_no;
uint64_t err_code;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} registers;
void load_idt(struct idtr *);
#define NUM_INTERRUPTS 256
struct int_gate_descriptor idt[NUM_INTERRUPTS];
struct idtr idtr;
extern uintptr_t isr_table[];
void idt_set_gate(uint32_t num, uintptr_t vector, uint16_t cs, uint8_t ist, uint8_t flags)
{
idt[num].base_l = vector & 0xFFFF;
idt[num].base_m = (vector >> 16) & 0xFFFF;
idt[num].base_h = (vector >> 32) & 0xFFFFFFFF;
idt[num].cs = cs;
idt[num].ist = ist;
idt[num].flags = flags;
}
void interrupt_init()
{
memset(idt, 0, sizeof(idt));
for(int i=0; i < NUM_INTERRUPTS; i++)
{
idt_set_gate(i, isr_table[i], 0x8, 0, 0x8E);
}
idtr.addr = idt;
idtr.len = sizeof(idt)-1;
load_idt(&idtr);
}
registers *int_handler(registers *r)
{
(void)r;
debug("Interrupt %d\n", r->int_no);
for(;;);
}

View File

@ -0,0 +1,31 @@
// vim: ft=c
#include <ttest.h>
#include <debug.h>
#undef debug
#define debug(...)
#include "idt.c"
uintptr_t isr_table[] ={};
void load_idt(struct idtr *_)
{
(void)_;
}
TEST(idt_set_gate_correctly_sets_address_L)
{
idt_set_gate(1, 0x1234567890ABCDEF, 0, 0, 0);
ASSERT_EQ_INT(idt[1].base_l, 0xCDEF);
}
TEST(idt_set_gate_correctly_sets_address_M)
{
idt_set_gate(1, 0x1234567890ABCDEF, 0, 0, 0);
ASSERT_EQ_INT(idt[1].base_m, 0x90AB);
}
TEST(idt_set_gate_correctly_sets_address_H)
{
idt_set_gate(1, 0x1234567890ABCDEF, 0, 0, 0);
ASSERT_EQ_INT(idt[1].base_h, 0x12345678);
}

View File

@ -0,0 +1,32 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
num_isr = 256
pushes_error = [8, 10, 11, 12, 13, 14, 17]
print '''
.intel_syntax noprefix
.extern isr_common
'''
print '// Interrupt Service Routines'
for i in range(num_isr):
print '''isr{0}:
cli
{1}
push {0}
jmp isr_common
'''.format(i,
'push 0' if i not in pushes_error else 'nop')
print ''
print '''
// Vector table
.section .data
.global isr_table
isr_table:'''
for i in range(num_isr):
print ' .quad isr{}'.format(i)

View File

@ -0,0 +1,50 @@
.intel_syntax noprefix
.global load_idt
load_idt:
lidt [rdi]
ret
.extern int_handler
.global isr_common
.global isr_return
isr_common:
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rbp
push rdi
push rsi
push rdx
push rcx
push rbx
push rax
mov rdi, rsp
call int_handler
mov rdi, rax
isr_return:
mov rsp, rdi
pop rax
pop rbx
pop rcx
pop rdx
pop rsi
pop rdi
pop rbp
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
add rsp, 0x10
iretq