Use ASM exception wrapper

This commit is contained in:
Mathieu Maret 2021-10-07 23:54:46 +02:00
parent 4e14b05f72
commit 5c7242e4dc
7 changed files with 136 additions and 161 deletions

View File

@ -17,7 +17,7 @@ CPPFLAGS += $(foreach dir, $(SUBDIRS), -I$(dir))
asmsrc=$(wildcard arch/$(ARCH)/boot/*.asm)
asmobj=$(asmsrc:%.asm=%.o)
csrc=$(shell find $(SUBDIRS) -type f -name "*.c")# $(wildcard *.c)
cobj=$(csrc:%.c=%.o) arch/$(ARCH)/cpu_context_switch.o arch/$(ARCH)/irq_pit.o arch/$(ARCH)/irq_wrappers.o
cobj=$(csrc:%.c=%.o) arch/$(ARCH)/cpu_context_switch.o arch/$(ARCH)/irq_pit.o arch/$(ARCH)/irq_wrappers.o arch/$(ARCH)/exception_wrappers.o
deps = $(csrc:%.c=%.d)
kernel kernel.sym &: $(asmobj) $(cobj) linker.ld
@ -34,10 +34,6 @@ fd.iso: kernel
disk.img:
qemu-img create -f qcow2 disk.img 32M
#https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes
arch/$(ARCH)/exception_handler.o:arch/$(ARCH)/exception_handler.c
$(CC) $(CFLAGS) $(CPPFLAGS) -mgeneral-regs-only -c $< -o $@
%.o:%.asm
$(AS) $(ASFLAGS) -o $@ $<

View File

@ -1,12 +1,29 @@
#include "exception.h"
#include "cpu_context.h"
#include "idt.h"
#include "interrupt.h"
#include "irq.h"
#include "klibc.h"
#include "kthread.h"
#include "vga.h"
exception_handler exception_handler_array[EXCEPTION_NUM] = {
NULL,
};
extern vaddr_t exception_handler_wrapper_array[EXCEPTION_NUM];
void exception_handler_wrap(int intr, struct cpu_state *frame)
{
if (0 > intr || EXCEPTION_NUM <= intr) {
pr_err("Trying to handle unknow exception %d\n", intr);
return;
}
if (exception_handler_array[intr] != NULL)
exception_handler_array[intr](frame, intr);
}
int exceptionSetRoutine(int exception, exception_handler handler)
{
uint32_t flags;
@ -17,54 +34,42 @@ int exceptionSetRoutine(int exception, exception_handler handler)
exception_handler_array[exception] = handler;
idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception, (unsigned int)handler, 0);
idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception,
(unsigned int)exception_handler_wrapper_array[exception], 0);
restore_IRQs(flags);
return 0;
}
void print_handler(struct cpu_state *frame, ulong intr)
{
int intNbInt = intr;
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d %d", intNbInt, intr);
printf("Exception %d (Err %d) at 0x%x\n", intr, intr,
cpu_context_get_PC(frame));
asm("hlt");
}
void pagefault_handler(struct cpu_state *frame, ulong intr)
{
// A page fault has occurred.
// The faulting address is stored in the CR2 register.
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
struct kthread *current = getCurrentThread();
printf("page fault while in thread %s at 0x%x 0x%x\n", current->name, faulting_address,
cpu_context_get_PC(frame));
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
(void)intr;
for (;;)
continue;
}
int exceptionSetup()
{
exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, ACCESS_INTERRUPT(EXCEPTION_DOUBLE_FAULT));
exceptionSetRoutine(EXCEPTION_DIVIDE_ZERO, ACCESS_INTERRUPT(EXCEPTION_DIVIDE_ZERO));
// Used by the DBG
// exceptionSetRoutine(EXCEPTION_DEBUG, ACCESS_INTERRUPT(EXCEPTION_DEBUG));
exceptionSetRoutine(EXCEPTION_NMI, ACCESS_INTERRUPT(EXCEPTION_NMI));
exceptionSetRoutine(EXCEPTION_BREAKPOINT, ACCESS_INTERRUPT(EXCEPTION_BREAKPOINT));
exceptionSetRoutine(EXCEPTION_OVERFLOW, ACCESS_INTERRUPT(EXCEPTION_OVERFLOW));
exceptionSetRoutine(EXCEPTION_BOUND_RANGE_EXCEEDED,
ACCESS_INTERRUPT(EXCEPTION_BOUND_RANGE_EXCEEDED));
exceptionSetRoutine(EXCEPTION_INVALID_OPCODE, ACCESS_INTERRUPT(EXCEPTION_INVALID_OPCODE));
exceptionSetRoutine(EXCEPTION_DEVICE_NOT_AVAILABLE,
ACCESS_INTERRUPT(EXCEPTION_DEVICE_NOT_AVAILABLE));
exceptionSetRoutine(EXCEPTION_COPRO_OVERRUN, ACCESS_INTERRUPT(EXCEPTION_COPRO_OVERRUN));
exceptionSetRoutine(EXCEPTION_INVALID_TSS, ACCESS_INTERRUPT(EXCEPTION_INVALID_TSS));
exceptionSetRoutine(EXCEPTION_SEGMENT_NOT_PRESENT,
ACCESS_INTERRUPT(EXCEPTION_SEGMENT_NOT_PRESENT));
exceptionSetRoutine(EXCEPTION_STACK_SEGMENT_FAULT,
ACCESS_INTERRUPT(EXCEPTION_STACK_SEGMENT_FAULT));
exceptionSetRoutine(EXCEPTION_GENERAL_PROTECTION_FAULT,
ACCESS_INTERRUPT(EXCEPTION_GENERAL_PROTECTION_FAULT));
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, ACCESS_INTERRUPT(EXCEPTION_PAGE_FAULT));
exceptionSetRoutine(EXCEPTION_RESERVED_1, ACCESS_INTERRUPT(EXCEPTION_RESERVED_1));
exceptionSetRoutine(EXCEPTION_X87_FP_EXCEPTION,
ACCESS_INTERRUPT(EXCEPTION_X87_FP_EXCEPTION));
exceptionSetRoutine(EXCEPTION_ALIGNMENT_CHECK,
ACCESS_INTERRUPT(EXCEPTION_ALIGNMENT_CHECK));
exceptionSetRoutine(EXCEPTION_MACHINE_CHECK, ACCESS_INTERRUPT(EXCEPTION_MACHINE_CHECK));
exceptionSetRoutine(EXCEPTION_SIMD_FP, ACCESS_INTERRUPT(EXCEPTION_SIMD_FP));
exceptionSetRoutine(EXCEPTION_VIRTUALIZATION, ACCESS_INTERRUPT(EXCEPTION_VIRTUALIZATION));
exceptionSetRoutine(EXCEPTION_RESERVED_2, ACCESS_INTERRUPT(EXCEPTION_RESERVED_2));
exceptionSetRoutine(EXCEPTION_RESERVED_3, ACCESS_INTERRUPT(EXCEPTION_RESERVED_3));
exceptionSetRoutine(EXCEPTION_RESERVED_4, ACCESS_INTERRUPT(EXCEPTION_RESERVED_4));
exceptionSetRoutine(EXCEPTION_RESERVED_5, ACCESS_INTERRUPT(EXCEPTION_RESERVED_5));
exceptionSetRoutine(EXCEPTION_RESERVED_6, ACCESS_INTERRUPT(EXCEPTION_RESERVED_6));
exceptionSetRoutine(EXCEPTION_RESERVED_7, ACCESS_INTERRUPT(EXCEPTION_RESERVED_7));
exceptionSetRoutine(EXCEPTION_RESERVED_8, ACCESS_INTERRUPT(EXCEPTION_RESERVED_8));
exceptionSetRoutine(EXCEPTION_RESERVED_9, ACCESS_INTERRUPT(EXCEPTION_RESERVED_9));
exceptionSetRoutine(EXCEPTION_RESERVED_10, ACCESS_INTERRUPT(EXCEPTION_RESERVED_10));
exceptionSetRoutine(EXCEPTION_SECURITY, ACCESS_INTERRUPT(EXCEPTION_SECURITY));
exceptionSetRoutine(EXCEPTION_RESERVED_11, ACCESS_INTERRUPT(EXCEPTION_RESERVED_11));
for (int i = 0; i < EXCEPTION_NUM; i++) {
exceptionSetRoutine(i, print_handler);
}
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
return 0;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "cpu_context.h"
#include "interrupt.h"
#include "stdarg.h"
@ -39,8 +40,8 @@
#define EXCEPTION_SECURITY 30
#define EXCEPTION_RESERVED_11 31
#define EXCEPTION_NUM 32
#define EXCEPTION_NUM 0x20
typedef void (*exception_handler)(struct interrupt_frame *frame, ulong error_code);
typedef void (*exception_handler)(struct cpu_state *frame, ulong intr_number);
int exceptionSetRoutine(int exception, exception_handler handler);
int exceptionSetup();

View File

@ -1,71 +0,0 @@
#include "exception.h"
#include "klibc.h"
#include "kthread.h"
#include "vga.h"
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
// Need GCC > 6
#define DEFINE_INTERRUPT(int_nb) \
__attribute__((interrupt)) void print_handler_##int_nb(struct interrupt_frame *frame, \
ulong error_code) \
{ \
int intNbInt = int_nb; \
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d %d", intNbInt, error_code); \
printf("Exception %d (Err %d) at 0x%x\n", int_nb, error_code, frame->eip); \
asm("hlt"); \
}
DEFINE_INTERRUPT(EXCEPTION_DOUBLE_FAULT)
DEFINE_INTERRUPT(EXCEPTION_DIVIDE_ZERO)
DEFINE_INTERRUPT(EXCEPTION_DEBUG)
DEFINE_INTERRUPT(EXCEPTION_NMI)
DEFINE_INTERRUPT(EXCEPTION_BREAKPOINT)
DEFINE_INTERRUPT(EXCEPTION_OVERFLOW)
DEFINE_INTERRUPT(EXCEPTION_BOUND_RANGE_EXCEEDED)
DEFINE_INTERRUPT(EXCEPTION_INVALID_OPCODE)
DEFINE_INTERRUPT(EXCEPTION_DEVICE_NOT_AVAILABLE)
DEFINE_INTERRUPT(EXCEPTION_COPRO_OVERRUN)
DEFINE_INTERRUPT(EXCEPTION_INVALID_TSS)
DEFINE_INTERRUPT(EXCEPTION_SEGMENT_NOT_PRESENT)
DEFINE_INTERRUPT(EXCEPTION_STACK_SEGMENT_FAULT)
DEFINE_INTERRUPT(EXCEPTION_GENERAL_PROTECTION_FAULT)
DEFINE_INTERRUPT(EXCEPTION_PAGE_FAULT)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_1)
DEFINE_INTERRUPT(EXCEPTION_X87_FP_EXCEPTION)
DEFINE_INTERRUPT(EXCEPTION_ALIGNMENT_CHECK)
DEFINE_INTERRUPT(EXCEPTION_MACHINE_CHECK)
DEFINE_INTERRUPT(EXCEPTION_SIMD_FP)
DEFINE_INTERRUPT(EXCEPTION_VIRTUALIZATION)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_2)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_3)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_4)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_5)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_6)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_7)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_8)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_9)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_10)
DEFINE_INTERRUPT(EXCEPTION_SECURITY)
DEFINE_INTERRUPT(EXCEPTION_RESERVED_11)
// c.f. https://wiki.osdev.org/Paging#Handling
// error_code bit0: Present ?
// bit1: Trying to write ?
// bit2: User page try to access?
__attribute__((interrupt)) void pagefault_handler(struct interrupt_frame *frame,
ulong error_code)
{
// A page fault has occurred.
// The faulting address is stored in the CR2 register.
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
struct kthread *current = getCurrentThread();
printf("page fault while in thread %s at 0x%x\n", current->name, faulting_address);
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", error_code);
(void)faulting_address;
(void)frame;
(void)error_code;
for(;;)
continue;
}

View File

@ -0,0 +1,84 @@
#define ASM_SOURCE 1
.file "irq_wrappers.S"
.text
.extern exception_handler_wrap
.globl exception_handler_wrapper_array
.altmacro
.macro exception_mac id
exception_wrapper_\id:
.type exception_wrapper_\id,@function
/* INTERRUPT FRAME START */
/* ALREADY PUSHED TO US BY THE PROCESSOR UPON ENTRY TO THIS INTERRUPT */
/* uint32_t ip */
/* uint32_t cs; */
/* uint32_t flags */
/* Pushes the other reg to save same and look like a struct cpu_state*/
/* Fake error code */
pushl $0
/* Backup the actual context */
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
subl $2,%esp
pushw %ss
pushw %ds
pushw %es
pushw %fs
pushw %gs
push %esp
pushl $\id
call exception_handler_wrap
addl $8, %esp
/* Restore the context */
popw %gs
popw %fs
popw %es
popw %ds
popw %ss
addl $2,%esp
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
/* Remove fake error code */
addl $4, %esp
iret
.endm
.set i, 0
.rept 0x20
exception_mac %i
.set i, i+1
.endr
.macro ref_exception_wrapper id
.long exception_wrapper_\id
.endm
.section ".rodata"
.p2align 5, 0x0
exception_handler_wrapper_array:
.set i, 0x0
.rept 0x20
ref_exception_wrapper %i
.set i, i+1
.endr

View File

@ -10,45 +10,5 @@ struct interrupt_frame {
uint32_t eflags;
} __attribute__((packed));
// Exception
#define DECLARE_INTERRUPT(int_nb) \
void print_handler_##int_nb(struct interrupt_frame *frame, ulong error_code);
#define ACCESS_INTERRUPT(int_nb) print_handler_##int_nb
void pagefault_handler(struct interrupt_frame *frame, ulong error_code);
DECLARE_INTERRUPT(EXCEPTION_DOUBLE_FAULT)
DECLARE_INTERRUPT(EXCEPTION_DIVIDE_ZERO)
DECLARE_INTERRUPT(EXCEPTION_DEBUG)
DECLARE_INTERRUPT(EXCEPTION_NMI)
DECLARE_INTERRUPT(EXCEPTION_BREAKPOINT)
DECLARE_INTERRUPT(EXCEPTION_OVERFLOW)
DECLARE_INTERRUPT(EXCEPTION_BOUND_RANGE_EXCEEDED)
DECLARE_INTERRUPT(EXCEPTION_INVALID_OPCODE)
DECLARE_INTERRUPT(EXCEPTION_DEVICE_NOT_AVAILABLE)
DECLARE_INTERRUPT(EXCEPTION_COPRO_OVERRUN)
DECLARE_INTERRUPT(EXCEPTION_INVALID_TSS)
DECLARE_INTERRUPT(EXCEPTION_SEGMENT_NOT_PRESENT)
DECLARE_INTERRUPT(EXCEPTION_STACK_SEGMENT_FAULT)
DECLARE_INTERRUPT(EXCEPTION_GENERAL_PROTECTION_FAULT)
DECLARE_INTERRUPT(EXCEPTION_PAGE_FAULT)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_1)
DECLARE_INTERRUPT(EXCEPTION_X87_FP_EXCEPTION)
DECLARE_INTERRUPT(EXCEPTION_ALIGNMENT_CHECK)
DECLARE_INTERRUPT(EXCEPTION_MACHINE_CHECK)
DECLARE_INTERRUPT(EXCEPTION_SIMD_FP)
DECLARE_INTERRUPT(EXCEPTION_VIRTUALIZATION)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_2)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_3)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_4)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_5)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_6)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_7)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_8)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_9)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_10)
DECLARE_INTERRUPT(EXCEPTION_SECURITY)
DECLARE_INTERRUPT(EXCEPTION_RESERVED_11)
// IRQ
void pit_handler(struct interrupt_frame *frame);

View File

@ -42,7 +42,7 @@ void initPic(void)
outb(PIC_SLAVE_DATA, 0xFF);
}
void EOIIrq(int irq)
inline void EOIIrq(int irq)
{
if (irq >= 8)
outb(PIC_SLAVE_CMD, PIC_EOI);