Add an interrupt descriptor table.
Set up a very basic handler for divide by zero and general protection faults.
This commit is contained in:
parent
3e1a1f7485
commit
9fc1aa15ef
|
@ -2,6 +2,8 @@ add_executable(zion
|
|||
common/gdt.cpp
|
||||
common/load_gdt.s
|
||||
debug/debug.cpp
|
||||
interrupt/interrupt.cpp
|
||||
interrupt/interrupt_enter.s
|
||||
zion.cpp)
|
||||
|
||||
target_include_directories(zion
|
||||
|
|
|
@ -80,7 +80,7 @@ void InitGdt() {
|
|||
|
||||
GdtPointer gdtp{
|
||||
.size = sizeof(gGdtSegments) - 1,
|
||||
.base = reinterpret_cast<uint64_t>(&gGdtSegments),
|
||||
.base = reinterpret_cast<uint64_t>(gGdtSegments),
|
||||
};
|
||||
|
||||
asm volatile("lgdt %0" ::"m"(gdtp));
|
||||
|
|
|
@ -11,3 +11,11 @@ void dbgln(const char* str) {
|
|||
}
|
||||
outb(COM1, '\n');
|
||||
}
|
||||
|
||||
void panic(const char* str) {
|
||||
asm volatile("cli");
|
||||
dbgln(str);
|
||||
dbgln("PANIC");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void dbgln(const char *str);
|
||||
void dbgln(const char* str);
|
||||
void panic(const char* str);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#include "interrupt/interrupt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "debug/debug.h"
|
||||
|
||||
#define IDT_INTERRUPT_GATE 0x8E
|
||||
|
||||
#define KERNEL_CS 0x8
|
||||
|
||||
struct InterruptDescriptorTablePointer {
|
||||
uint16_t size;
|
||||
uint64_t base;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct InterruptDescriptor {
|
||||
uint16_t offset_low;
|
||||
uint16_t selector;
|
||||
uint8_t ist;
|
||||
uint8_t flags;
|
||||
uint16_t offset_medium;
|
||||
uint32_t offset_high;
|
||||
uint32_t zero;
|
||||
} __attribute__((packed));
|
||||
|
||||
static InterruptDescriptor gIdt[256];
|
||||
|
||||
InterruptDescriptor CreateDescriptor(void isr(void)) {
|
||||
uint64_t offset = reinterpret_cast<uint64_t>(isr);
|
||||
return InterruptDescriptor{
|
||||
.offset_low = static_cast<uint16_t>(offset),
|
||||
.selector = KERNEL_CS,
|
||||
.ist = 0,
|
||||
.flags = IDT_INTERRUPT_GATE,
|
||||
.offset_medium = static_cast<uint16_t>(offset >> 16),
|
||||
.offset_high = static_cast<uint32_t>(offset >> 32),
|
||||
.zero = 0x0,
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" void isr_divide_by_zero();
|
||||
extern "C" void interrupt_divide_by_zero(void* frame) { panic("DIV0"); }
|
||||
|
||||
extern "C" void isr_protection_fault();
|
||||
extern "C" void interrupt_protection_fault(void* frame) { panic("GP"); }
|
||||
|
||||
void InitIdt() {
|
||||
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
|
||||
gIdt[13] = CreateDescriptor(isr_protection_fault);
|
||||
InterruptDescriptorTablePointer idtp{
|
||||
.size = sizeof(gIdt),
|
||||
.base = reinterpret_cast<uint64_t>(gIdt),
|
||||
};
|
||||
asm volatile("lidt %0" ::"m"(idtp));
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void InitIdt();
|
|
@ -0,0 +1,56 @@
|
|||
.macro interrupt_enter
|
||||
push %rbp
|
||||
push %r15
|
||||
push %r14
|
||||
push %r13
|
||||
push %r12
|
||||
push %r11
|
||||
push %r10
|
||||
push %r9
|
||||
push %r8
|
||||
push %rdi
|
||||
push %rsi
|
||||
push %rdx
|
||||
push %rcx # (Return Address)
|
||||
push %rbx
|
||||
push %rax
|
||||
.endm
|
||||
|
||||
.macro interrupt_exit
|
||||
pop %rax
|
||||
pop %rbx
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
pop %r8
|
||||
pop %r9
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %rbp
|
||||
|
||||
add $8, %rsp # Remove error code.
|
||||
.endm
|
||||
|
||||
.macro isr_handler name error_code=0
|
||||
.global isr_\name
|
||||
isr_\name:
|
||||
.if \error_code
|
||||
.else
|
||||
push $0 # if we don't have an error code, equalize the stack.
|
||||
.endif
|
||||
interrupt_enter
|
||||
sti
|
||||
mov %rsp, %rdi
|
||||
call interrupt_\name
|
||||
cli
|
||||
interrupt_exit
|
||||
iretq
|
||||
.endm
|
||||
|
||||
isr_handler divide_by_zero
|
||||
isr_handler protection_fault,1
|
|
@ -2,11 +2,16 @@
|
|||
|
||||
#include "common/gdt.h"
|
||||
#include "debug/debug.h"
|
||||
#include "interrupt/interrupt.h"
|
||||
|
||||
extern "C" void zion() {
|
||||
dbgln("Hello World!");
|
||||
InitGdt();
|
||||
dbgln("New GDT Loaded!");
|
||||
InitIdt();
|
||||
dbgln("IDT Loaded!");
|
||||
uint64_t a = 11 / 0;
|
||||
dbgln("Recovered");
|
||||
|
||||
while (1)
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue