[amd64] idt and exceptions
This commit is contained in:
+10
-4
@@ -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 $@ $<
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ HEADERS=$(shell find $(S) -name "*.h")
|
||||
CFLAGS+=-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Wpedantic \
|
||||
-Wno-unused-parameter
|
||||
|
||||
DIRS+=$(O)/sys
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void amd64_idt_init(void);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user