From 63b19831bd7dd06e3c6fd8b9fe34e62f6697741e Mon Sep 17 00:00:00 2001
From: =?utf8?q?Duje=20Mihanovi=C4=87?= <duje.mihanovic@skole.hr>
Date: Tue, 14 Jun 2022 11:23:08 +0200
Subject: [PATCH] Use interrupt frame and new double fault handler

---
 include/arch/x86/irq/idt.h       |  1 +
 include/arch/x86/irq/interrupt.h | 18 ++++++++-
 kernel/arch/x86/irq/interrupt.c  |  9 +++--
 kernel/arch/x86/irq/stub.s       | 67 ++++++++++++++++++++++++++++----
 kernel/kernel.c                  | 42 ++++++++++++++++++++
 5 files changed, 125 insertions(+), 12 deletions(-)

diff --git a/include/arch/x86/irq/idt.h b/include/arch/x86/irq/idt.h
index 501e5cd..f16cf96 100644
--- a/include/arch/x86/irq/idt.h
+++ b/include/arch/x86/irq/idt.h
@@ -2,6 +2,7 @@
 #define X86_IDT_H
 
 #include <stdint.h>
+#include <irq/interrupt.h>
 
 #define IDT_VECTOR_COUNT 256 /* our IDT will have 256 vectors */
 #define IDT_DESCRIPTOR_SIZE 8 /* each IDT descriptor is 8 bytes long */
diff --git a/include/arch/x86/irq/interrupt.h b/include/arch/x86/irq/interrupt.h
index fbecdd8..f43b28c 100644
--- a/include/arch/x86/irq/interrupt.h
+++ b/include/arch/x86/irq/interrupt.h
@@ -1,6 +1,22 @@
 #ifndef X86_INTERRUPT_H
 #define X86_INTERRUPT_H
 
-extern int register_interrupt(int irq, int (*handler)(void));
+struct interrupt_frame {
+	int interrupt;
+	int edi;
+	int esi;
+	int ebp;
+	int esp; /* before pushad */
+	int ebx;
+	int edx;
+	int ecx;
+	int eax;
+	int err_code;
+	int eip;
+	int cs;
+	int eflags;
+};
+
+extern int register_interrupt(int irq, int (*handler)(struct interrupt_frame *));
 
 #endif
diff --git a/kernel/arch/x86/irq/interrupt.c b/kernel/arch/x86/irq/interrupt.c
index b2abef9..f7cbcdc 100644
--- a/kernel/arch/x86/irq/interrupt.c
+++ b/kernel/arch/x86/irq/interrupt.c
@@ -5,16 +5,17 @@
 #include <irq/i8259a.h>
 
 /* This table will hold pointers to our interrupt handlers. */
-static int (*int_handler_table[256])(void);
+static int (*int_handler_table[256])(struct interrupt_frame *);
 
-void int_handler(int interrupt)
+void int_handler(struct interrupt_frame *frame)
 {
+	int interrupt = frame->interrupt;
 	if (int_handler_table[interrupt] == NULL) {
 		kprint("WARNING: Unhandled interrupt ", 0);
 		kprintb(interrupt);
 		kprint(" occurred!\n", 0);
 	} else {
-		int ret = (*int_handler_table[interrupt])();
+		int ret = (*int_handler_table[interrupt])(frame);
 		if (ret) {
 			kprint("WARNING: Error while handling interrupt ", 0);
 			kprintb(interrupt);
@@ -26,7 +27,7 @@ void int_handler(int interrupt)
 	}
 }
 
-int register_interrupt(int irq, int (*handler)(void))
+int register_interrupt(int irq, int (*handler)(struct interrupt_frame *))
 {
 	int_handler_table[irq] = handler;
 	if (irq >= 32 && irq < 48) {
diff --git a/kernel/arch/x86/irq/stub.s b/kernel/arch/x86/irq/stub.s
index c15969a..e5e43e5 100644
--- a/kernel/arch/x86/irq/stub.s
+++ b/kernel/arch/x86/irq/stub.s
@@ -7,24 +7,77 @@ extern int_handler
 
 int_common:
 	cld
+	push esp
 	call int_handler
-	add esp, 4
+	add esp, 12
 	popad
 	iretd
 
 %macro INTERRUPT 1
-global int%1
+global int_%1
 int_%1:
+	push dword 0
 	pushad
 	push dword %1
 	jmp int_common
 %endmacro
 
-%assign i 0
-%rep 48
-INTERRUPT i
-%assign i i+1
-%endrep
+%macro INTERRUPT_ERR 1
+global int_%1
+int_%1:
+	pushad
+	push dword %1
+	jmp int_common
+%endmacro
+
+INTERRUPT 0
+INTERRUPT 1
+INTERRUPT 2
+INTERRUPT 3
+INTERRUPT 4
+INTERRUPT 5
+INTERRUPT 6
+INTERRUPT 7
+INTERRUPT_ERR 8
+INTERRUPT 9
+INTERRUPT_ERR 10
+INTERRUPT_ERR 11
+INTERRUPT_ERR 12
+INTERRUPT_ERR 13
+INTERRUPT_ERR 14
+INTERRUPT 15
+INTERRUPT 16
+INTERRUPT_ERR 17
+INTERRUPT 18
+INTERRUPT 19
+INTERRUPT 20
+INTERRUPT_ERR 21
+INTERRUPT 22
+INTERRUPT 23
+INTERRUPT 24
+INTERRUPT 25
+INTERRUPT 26
+INTERRUPT 27
+INTERRUPT 28
+INTERRUPT_ERR 29
+INTERRUPT_ERR 30
+INTERRUPT 31
+INTERRUPT 32
+INTERRUPT 33
+INTERRUPT 34
+INTERRUPT 35
+INTERRUPT 36
+INTERRUPT 37
+INTERRUPT 38
+INTERRUPT 39
+INTERRUPT 40
+INTERRUPT 41
+INTERRUPT 42
+INTERRUPT 43
+INTERRUPT 44
+INTERRUPT 45
+INTERRUPT 46
+INTERRUPT 47
 
 ; Define flat table containing addresses of handlers
 section .rodata
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 2af3372..c82bd4d 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -10,6 +10,47 @@ struct idt_descriptor idt[256] __attribute__((aligned(0x10)));
 struct idtr idtr __attribute__((aligned(0x10)));
 extern void (*_int_handler_table[48])(void);
 
+/* Small handler for double faults. Will be put elsewhere eventually. */
+int double_fault_handler(struct interrupt_frame *frame)
+{
+	kprint("PANIC: Double fault occurred!\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EAX: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->eax);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EBX: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->ebx);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("ECX: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->ecx);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EDX: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->edx);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EBP: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->ebp);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("ESP: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->esp);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("ESI: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->esi);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EDI: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->edi);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EIP: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->eip);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+	kprint("EFLAGS: ", VGA_COLOR_BRIGHT_RED);
+	kprintd(frame->eflags);
+	kprint("\n", VGA_COLOR_BRIGHT_RED);
+
+	/* IF has already been cleared for us */
+halt:
+	asm("hlt");
+	goto halt;
+}
+
 void kmain(void)
 {
 	int ps2_success;
@@ -25,6 +66,7 @@ void kmain(void)
 	populate_idtr(&idtr, idt);
 	load_idt(idtr);
 	kprint("Setting up interrupts...\n", 0);
+	register_interrupt(8, &double_fault_handler);
 	pic_init(0x20, 0x28);
 	pic_mask_all();
 	ps2_success = ps2_initialize();
-- 
2.39.5