[amd64] idt and exceptions

This commit is contained in:
Mark
2019-03-25 16:43:09 +02:00
parent 4d27fcac0b
commit 29ebc06bee
10 changed files with 327 additions and 4 deletions
+10 -4
View File
@@ -6,24 +6,30 @@ OBJS+=$(O)/arch/amd64/kernel.o \
$(O)/arch/amd64/mm/mm.o \
$(O)/arch/amd64/hw/rs232.o \
$(O)/arch/amd64/hw/gdt.o \
$(O)/arch/amd64/hw/gdt_s.o
$(O)/arch/amd64/hw/gdt_s.o \
$(O)/arch/amd64/hw/idt.o \
$(O)/arch/amd64/hw/ints.o \
$(O)/arch/amd64/hw/exc.o \
$(O)/arch/amd64/hw/regs.o
kernel_OBJS=$(O)/arch/amd64/entry.o \
$(OBJS)
kernel_LINKER=$(S)/arch/amd64/link.ld
kernel_LDFLAGS=-nostdlib -T$(kernel_LINKER)
kernel_CFLAGS=-ffreestanding -I$(S) $(DEFINES) $(CFLAGS)
kernel_CFLAGS=-ffreestanding -I$(S) $(DEFINES) $(CFLAGS) -mcmodel=large
DIRS+=$(O)/arch/amd64/mm \
$(O)/arch/amd64/hw
# add .inc includes for asm
HEADERS+=$(shell find $(S) -name "*.inc")
$(O)/kernel.elf: $(kernel_OBJS) $(kernel_LINKER)
@printf " LD\t%s\n" $@
@$(CROSSLD) $(kernel_LDFLAGS) -o $@ $(kernel_OBJS)
$(O)/%.o: $(S)/%.S
$(O)/%.o: $(S)/%.S $(HEADERS)
@printf " AS\t%s\n" $@
@$(CROSSCC) $(kernel_CFLAGS) -c -o $@ $<
$(O)/%.o: $(S)/%.c
$(O)/%.o: $(S)/%.c $(HEADERS)
@printf " CC\t%s\n" $@
@$(CROSSCC) $(kernel_CFLAGS) -c -o $@ $<
+1
View File
@@ -3,6 +3,7 @@ HEADERS=$(shell find $(S) -name "*.h")
CFLAGS+=-Wall \
-Wextra \
-Werror \
-Wpedantic \
-Wno-unused-parameter
DIRS+=$(O)/sys
+15
View File
@@ -0,0 +1,15 @@
#include "ints.h"
#include "sys/debug.h"
#include "regs.h"
int amd64_err_num;
void amd64_exc_handler(amd64_ctx_regs_t *regs) {
kfatal("Unhandled exception #%d\n", amd64_err_num);
amd64_ctx_dump(DEBUG_FATAL, regs);
while (1) {
asm volatile ("cli; hlt");
}
}
+123
View File
@@ -0,0 +1,123 @@
#include "ints.h"
#include "sys/mem.h"
#include <stdint.h>
#include <stddef.h>
#define ignore(x) if (0) {x = x;}
#define IDT_NENTR 256
#define IDT_FLG_TASK32 0x5
#define IDT_FLG_INT16 0x6
#define IDT_FLG_TRAP16 0x7
#define IDT_FLG_INT32 0xE
#define IDT_FLG_TRAP32 0xF
#define IDT_FLG_SS (1 << 4)
#define IDT_FLG_R0 (0 << 5)
#define IDT_FLG_R1 (1 << 5)
#define IDT_FLG_R2 (2 << 5)
#define IDT_FLG_R3 (3 << 5)
#define IDT_FLG_P (1 << 7)
extern void amd64_isr_0();
extern void amd64_isr_1();
extern void amd64_isr_2();
extern void amd64_isr_3();
extern void amd64_isr_4();
extern void amd64_isr_5();
extern void amd64_isr_6();
extern void amd64_isr_7();
extern void amd64_isr_8();
extern void amd64_isr_9();
extern void amd64_isr_10();
extern void amd64_isr_11();
extern void amd64_isr_12();
extern void amd64_isr_13();
extern void amd64_isr_14();
extern void amd64_isr_15();
extern void amd64_isr_16();
extern void amd64_isr_17();
extern void amd64_isr_18();
extern void amd64_isr_19();
extern void amd64_isr_20();
extern void amd64_isr_21();
extern void amd64_isr_22();
extern void amd64_isr_23();
extern void amd64_isr_24();
extern void amd64_isr_25();
extern void amd64_isr_26();
extern void amd64_isr_27();
extern void amd64_isr_28();
extern void amd64_isr_29();
extern void amd64_isr_30();
extern void amd64_isr_31();
typedef struct {
uint16_t base_lo;
uint16_t selector;
uint8_t zero;
uint8_t flags;
uint16_t base_hi;
uint32_t base_ex;
uint32_t zero1;
} amd64_idt_entry_t;
typedef struct {
uint16_t size;
uintptr_t offset;
} __attribute__((packed)) amd64_idt_ptr_t;
static amd64_idt_entry_t idt[IDT_NENTR];
static amd64_idt_ptr_t idtr;
void amd64_idt_set(int idx, uintptr_t base, uint16_t selector, uint8_t flags) {
idt[idx].base_lo = base & 0xFFFF;
idt[idx].base_hi = (base >> 16) & 0xFFFF;
idt[idx].base_ex = (base >> 32) & 0xFFFFFFFF;
idt[idx].selector = selector;
idt[idx].flags = flags;
idt[idx].zero = 0;
}
void amd64_idt_init(void) {
idtr.offset = (uintptr_t) idt;
idtr.size = sizeof(idt) - 1;
memset(idt, 0, sizeof(idt));
// Exceptions
amd64_idt_set(0 , (uintptr_t) amd64_isr_0 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(1 , (uintptr_t) amd64_isr_1 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(2 , (uintptr_t) amd64_isr_2 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(3 , (uintptr_t) amd64_isr_3 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(4 , (uintptr_t) amd64_isr_4 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(5 , (uintptr_t) amd64_isr_5 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(6 , (uintptr_t) amd64_isr_6 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(7 , (uintptr_t) amd64_isr_7 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(8 , (uintptr_t) amd64_isr_8 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(9 , (uintptr_t) amd64_isr_9 , 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(10, (uintptr_t) amd64_isr_10, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(11, (uintptr_t) amd64_isr_11, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(12, (uintptr_t) amd64_isr_12, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(13, (uintptr_t) amd64_isr_13, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(14, (uintptr_t) amd64_isr_14, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(15, (uintptr_t) amd64_isr_15, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(16, (uintptr_t) amd64_isr_16, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(17, (uintptr_t) amd64_isr_17, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(18, (uintptr_t) amd64_isr_18, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(19, (uintptr_t) amd64_isr_19, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(20, (uintptr_t) amd64_isr_20, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(21, (uintptr_t) amd64_isr_21, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(22, (uintptr_t) amd64_isr_22, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(23, (uintptr_t) amd64_isr_23, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(24, (uintptr_t) amd64_isr_24, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(25, (uintptr_t) amd64_isr_25, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(26, (uintptr_t) amd64_isr_26, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(27, (uintptr_t) amd64_isr_27, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(28, (uintptr_t) amd64_isr_28, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(29, (uintptr_t) amd64_isr_29, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(30, (uintptr_t) amd64_isr_30, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
amd64_idt_set(31, (uintptr_t) amd64_isr_31, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32);
asm volatile ("lea idtr(%%rip), %%rax; lidt (%%rax)":::"memory");
}
+37
View File
@@ -0,0 +1,37 @@
// vi:syntax=asm
.macro __int_push_ctx
// pushal for amd64 world
pushq %rax
pushq %rcx
pushq %rdx
pushq %rbx
pushq %rsp
pushq %rbp
pushq %rsi
pushq %rdi
// r8-r15
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r14
pushq %r15
// cr3
mov %cr3, %rax
pushq %rax
// segments
mov %gs, %rax
pushq %rax
mov %fs, %rax
pushq %rax
mov %es, %rax
pushq %rax
mov %ds, %rax
pushq %rax
.endm
+73
View File
@@ -0,0 +1,73 @@
#include "int_macros.inc"
.section .text
.extern amd64_err_num
__isr_generic:
cli
// TODO: preserve error codes
pushq %rax
mov 8(%rsp), %rax
mov %rax, amd64_err_num(%rip)
popq %rax
add $16, %rsp
__int_push_ctx
movq %rsp, %rdi
call amd64_exc_handler
// TODO: allow handling and returning from an exception ISR
1:
hlt
jmp 1b
// ISR with error code
.macro __isr_yerr n
.global amd64_isr_\n
amd64_isr_\n:
pushq $\n
jmp __isr_generic
.endm
// ISR with no error code
.macro __isr_nerr n
.global amd64_isr_\n
amd64_isr_\n:
pushq $0
pushq $\n
jmp __isr_generic
.endm
__isr_nerr 0
__isr_nerr 1
__isr_nerr 2
__isr_nerr 3
__isr_nerr 4
__isr_nerr 5
__isr_nerr 6
__isr_nerr 7
__isr_yerr 8
__isr_nerr 9
__isr_yerr 10
__isr_yerr 11
__isr_yerr 12
__isr_yerr 13
__isr_yerr 14
__isr_nerr 15
__isr_nerr 16
__isr_yerr 17
__isr_nerr 18
__isr_nerr 19
__isr_nerr 20
__isr_nerr 21
__isr_nerr 22
__isr_nerr 23
__isr_nerr 24
__isr_nerr 25
__isr_nerr 26
__isr_nerr 27
__isr_nerr 28
__isr_nerr 29
__isr_yerr 30
__isr_nerr 31
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void amd64_idt_init(void);
+32
View File
@@ -0,0 +1,32 @@
#include "regs.h"
#include "sys/debug.h"
void amd64_ctx_dump(int level, const amd64_ctx_regs_t *regs) {
kprint(level, "rax = %p (%ld)\n", regs->gp.rax, regs->gp.rax);
kprint(level, "rcx = %p (%ld)\n", regs->gp.rcx, regs->gp.rcx);
kprint(level, "rdx = %p (%ld)\n", regs->gp.rdx, regs->gp.rdx);
kprint(level, "rbx = %p (%ld)\n", regs->gp.rbx, regs->gp.rbx);
kprint(level, "r8 = %p (%ld)\n", regs->gp.r8, regs->gp.r8);
kprint(level, "r9 = %p (%ld)\n", regs->gp.r9, regs->gp.r9);
kprint(level, "r10 = %p (%ld)\n", regs->gp.r10, regs->gp.r10);
kprint(level, "r11 = %p (%ld)\n", regs->gp.r11, regs->gp.r11);
kprint(level, "r12 = %p (%ld)\n", regs->gp.r12, regs->gp.r12);
kprint(level, "r13 = %p (%ld)\n", regs->gp.r13, regs->gp.r13);
kprint(level, "r14 = %p (%ld)\n", regs->gp.r14, regs->gp.r14);
kprint(level, "r15 = %p (%ld)\n", regs->gp.r15, regs->gp.r15);
if (regs->iret.cs == 0x08) {
// Print stack pointer before the exception occurred
kprint(level, "rsp = %p\n", regs->gp.rsp + sizeof(amd64_ctx_regs_t));
}
kprint(level, "rbp = %p\n", regs->gp.rbp);
kprint(level, "rsi = %p\n", regs->gp.rsi);
kprint(level, "rdi = %p\n", regs->gp.rdi);
kprint(level, "pc: %02x:%p\n", regs->iret.cs, regs->iret.rip);
if (regs->iret.cs != 0x08) {
kprint(level, "stack: %02x:%p\n", regs->iret.ss, regs->iret.rsp);
}
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <stdint.h>
typedef struct {
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} amd64_iret_regs_t;
typedef struct {
uint64_t ds;
uint64_t es;
uint64_t fs;
uint64_t gs;
} amd64_seg_regs_t;
typedef struct {
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax;
} amd64_gp_regs_t;
typedef struct {
amd64_seg_regs_t segs;
uint64_t cr3;
amd64_gp_regs_t gp;
amd64_iret_regs_t iret;
} amd64_ctx_regs_t;
void amd64_ctx_dump(int level, const amd64_ctx_regs_t *regs);
+2
View File
@@ -1,6 +1,7 @@
#include "sys/mm.h"
#include "sys/debug.h"
#include "arch/amd64/hw/gdt.h"
#include "arch/amd64/hw/ints.h"
void kernel_main(void) {
kdebug("Booting\n");
@@ -8,4 +9,5 @@ void kernel_main(void) {
// Memory management
amd64_mm_init();
amd64_gdt_init();
amd64_idt_init();
}