From ed22a6995cddb7b61503fdca859267ef85b3bdd3 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Mon, 10 Nov 2008 14:32:54 -0500 Subject: [PATCH] add some fault handlers --- aseg-paging/Makefile | 1 + aseg-paging/pagingstub.c | 7 +++ aseg-paging/traps.c | 105 +++++++++++++++++++++++++++++++++++++++ aseg-paging/traps.h | 27 ++++++++++ 4 files changed, 140 insertions(+) create mode 100644 aseg-paging/traps.c create mode 100644 aseg-paging/traps.h diff --git a/aseg-paging/Makefile b/aseg-paging/Makefile index 0bbe048..a8d72cd 100644 --- a/aseg-paging/Makefile +++ b/aseg-paging/Makefile @@ -53,6 +53,7 @@ OBJS = ../ich2/smi.o \ smi.o \ vga-overlay.o \ main.o \ + traps.o \ firstrun.o diff --git a/aseg-paging/pagingstub.c b/aseg-paging/pagingstub.c index d839966..0115713 100644 --- a/aseg-paging/pagingstub.c +++ b/aseg-paging/pagingstub.c @@ -5,6 +5,7 @@ #include #include #include +#include "traps.h" #include "../net/net.h" #include "vga-overlay.h" @@ -114,6 +115,7 @@ void c_entry(void) set_cr0(get_cr0() | CR0_PG); outb(0x80, 0x43); + if (!entry_initialized) { /* If needed, copy in data. */ @@ -123,6 +125,11 @@ void c_entry(void) *bp = 0; serial_init(); dolog("Paging enabled."); + } + + traps_install(); + + if (!entry_initialized) { smi_init(); entry_initialized = 1; diff --git a/aseg-paging/traps.c b/aseg-paging/traps.c new file mode 100644 index 0000000..8184bdb --- /dev/null +++ b/aseg-paging/traps.c @@ -0,0 +1,105 @@ +#include +#include +#include + +#include "traps.h" + +#define CS_SEGSEL 0x10 + +#define FAULT_WRAPPER(func_name) asm ( \ + ".global " #func_name "_wrapper\n" \ + #func_name "_wrapper:\n" \ + "mov %cr2, %eax\n" \ + "push %eax\n" \ + "push %esp\n" \ + "call " #func_name "\n" \ +); void func_name##_wrapper(void); + +#define WRAPPER_INSTALL(idt, idt4_value, func_name, int_number) { \ + *(int *)((void *)idt + (8 * int_number)) = \ + ((int)func_name##_wrapper & 0xFFFF) | \ + (CS_SEGSEL << 16); \ + *(int *)((void *)idt + (8 * int_number) + 4) = \ + ((int)func_name##_wrapper & 0xFFFF0000) | idt4_value; \ +} + +/* The 16 bits at offset 4 from the start of an interrupt gate are a + * bitfield, according to the Intel spec: + * 15 P - Segment Present - set to 1 + * 14-13 DPL - Descriptor privilege level - set to 11 for trap/int, 00 for IPI + * 12-8 01111 for 32-bit trap gates, 01110 for 32-bit interrupt gates + * 7-0 Set to 0 + * Trap: binary 11101111 0000000, hex EF00. + * Interrupt: binary 11101110 0000000, hex EE00. + */ +#define TRAP 0xEF00 +#define INTERRUPT 0xEE00 + +typedef struct trap_t { + int cr2; + int error_code; + int eip; + int cs; + int eflags; + int esp; + int ss; +} trap_t; + +void die(struct trap_t * trap) { + outputf("Error %08x %%eip %08x", trap->error_code, trap->eip); + outputf("%%esp %08x %%eflags %08x", trap->esp, trap->eflags); + while(1) asm("hlt"); +} + +void fault_gp(struct trap_t * trap) { + outputf("GENERAL PROTECTION FAULT"); + die(trap); +} + +void fault_page(struct trap_t * trap) { + outputf("PAGE FAULT: %08x", trap->cr2); + die(trap); +} +void fault_divide(struct trap_t * trap) { + outputf("DIVISION FAULT"); + die(trap); +} +void double_fault(struct trap_t * trap) { + outputf("DOUBLE FAULT"); + die(trap); +} + +FAULT_WRAPPER(fault_gp); +FAULT_WRAPPER(fault_page); +FAULT_WRAPPER(fault_divide); +FAULT_WRAPPER(double_fault); + +/* pseudo_descriptor and x86_gate structs from 15-410 basis code. */ + +struct x86_gate { +unsigned int filler[2]; //64 bits; or 8 bytes. +}; + +static struct x86_gate idt[64]; + +struct pseudo_descriptor { + short pad; + unsigned short limit; + unsigned long linear_base; +}; + +void traps_install(void) { + + struct pseudo_descriptor pdesc; + pdesc.limit = sizeof(idt) - 1; + pdesc.linear_base = memory_v2p(&idt); + + WRAPPER_INSTALL(idt, TRAP, fault_divide, T_DIVIDE_ERROR); + WRAPPER_INSTALL(idt, TRAP, fault_gp, T_GENERAL_PROTECTION); + WRAPPER_INSTALL(idt, TRAP, fault_page, T_PAGE_FAULT); + WRAPPER_INSTALL(idt, TRAP, double_fault, T_DOUBLE_FAULT); + + outb(0x80, 0xCC); + asm volatile("lidt %0" : : "m" (pdesc.limit)); + outb(0x80, 0xCD); +} diff --git a/aseg-paging/traps.h b/aseg-paging/traps.h new file mode 100644 index 0000000..f57e036 --- /dev/null +++ b/aseg-paging/traps.h @@ -0,0 +1,27 @@ +#ifndef TRAPS_H +#define TRAPS_H + +/* Trap vectors from 15-410 basis code. */ + +#define T_DIVIDE_ERROR 0 +#define T_DEBUG 1 +#define T_NMI 2 +#define T_INT3 3 +#define T_OVERFLOW 4 +#define T_OUT_OF_BOUNDS 5 +#define T_INVALID_OPCODE 6 +#define T_NO_FPU 7 +#define T_DOUBLE_FAULT 8 +#define T_FPU_FAULT 9 +#define T_INVALID_TSS 10 +#define T_SEGMENT_NOT_PRESENT 11 +#define T_STACK_FAULT 12 +#define T_GENERAL_PROTECTION 13 +#define T_PAGE_FAULT 14 +#define T_FLOATING_POINT_ERROR 16 +#define T_ALIGNMENT_CHECK 17 +#define T_MACHINE_CHECK 18 + +void traps_install(void); + +#endif /* TRAPS_H */ -- 2.43.0