...
This commit is contained in:
163
src/idt.c
163
src/idt.c
@@ -4,6 +4,13 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define IDT_SIZE 256
|
||||||
|
|
||||||
|
#define PIC1_COMMAND 0x20
|
||||||
|
#define PIC1_DATA 0x21
|
||||||
|
#define PIC2_COMMAND 0xA0
|
||||||
|
#define PIC2_DATA 0xA1
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint16_t address_low;
|
uint16_t address_low;
|
||||||
@@ -21,22 +28,95 @@ typedef struct
|
|||||||
uint64_t base;
|
uint64_t base;
|
||||||
} __attribute__((packed)) idtr_t;
|
} __attribute__((packed)) idtr_t;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
|
||||||
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
|
|
||||||
uint64_t int_no;
|
|
||||||
uint64_t err_code;
|
|
||||||
uint64_t rip, cs, rflags, rsp, ss;
|
|
||||||
} __attribute__((packed)) isr_frame_t;
|
|
||||||
|
|
||||||
#define IDT_SIZE 256
|
|
||||||
|
|
||||||
extern void* isr_stub_table[];
|
extern void* isr_stub_table[];
|
||||||
|
static irq_handler_t irq_handlers[16] = { 0 };
|
||||||
|
|
||||||
|
static const char* exception_messages[32] = { "divide by zero",
|
||||||
|
"debug",
|
||||||
|
"non maskable interrupt",
|
||||||
|
"breakpoint",
|
||||||
|
"overflow",
|
||||||
|
"bound range exceeded",
|
||||||
|
"invalid opcode",
|
||||||
|
"device not available",
|
||||||
|
"double fault",
|
||||||
|
"coprocessor segment overrun",
|
||||||
|
"invalid tss",
|
||||||
|
"segment not present",
|
||||||
|
"stack-segment fault",
|
||||||
|
"general protection fault",
|
||||||
|
"page fault",
|
||||||
|
"reserved",
|
||||||
|
"x87 floating point exception",
|
||||||
|
"alignment check",
|
||||||
|
"machine check",
|
||||||
|
"simd floating point exception",
|
||||||
|
"virtualization exception",
|
||||||
|
"control protection exception",
|
||||||
|
"reserved",
|
||||||
|
"reserved",
|
||||||
|
"reserved",
|
||||||
|
"reserved",
|
||||||
|
"reserved",
|
||||||
|
"reserved",
|
||||||
|
"hypervisor injection exception",
|
||||||
|
"vmm communication exception",
|
||||||
|
"security exception",
|
||||||
|
"reserved" };
|
||||||
|
|
||||||
static interrupt_descriptor idt[IDT_SIZE];
|
static interrupt_descriptor idt[IDT_SIZE];
|
||||||
|
|
||||||
void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl)
|
static inline void outb(uint16_t port, uint8_t val)
|
||||||
|
{
|
||||||
|
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t inb(uint16_t port)
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pic_remap(int offset1, int offset2)
|
||||||
|
{
|
||||||
|
uint8_t a1, a2;
|
||||||
|
|
||||||
|
a1 = inb(PIC1_DATA);
|
||||||
|
a2 = inb(PIC2_DATA);
|
||||||
|
|
||||||
|
outb(PIC1_COMMAND, 0x11);
|
||||||
|
outb(PIC2_COMMAND, 0x11);
|
||||||
|
|
||||||
|
outb(PIC1_DATA, offset1);
|
||||||
|
outb(PIC2_DATA, offset2);
|
||||||
|
|
||||||
|
outb(PIC1_DATA, 4);
|
||||||
|
outb(PIC2_DATA, 2);
|
||||||
|
|
||||||
|
outb(PIC1_DATA, 0x01);
|
||||||
|
outb(PIC2_DATA, 0x01);
|
||||||
|
|
||||||
|
outb(PIC1_DATA, a1);
|
||||||
|
outb(PIC2_DATA, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pic_send_eoi(uint8_t irq)
|
||||||
|
{
|
||||||
|
if (irq >= 8)
|
||||||
|
{
|
||||||
|
outb(PIC2_COMMAND, 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
outb(PIC1_COMMAND, 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_irq_handler(uint8_t irq, irq_handler_t handler)
|
||||||
|
{
|
||||||
|
irq_handlers[irq] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl)
|
||||||
{
|
{
|
||||||
interrupt_descriptor* entry = &idt[vector];
|
interrupt_descriptor* entry = &idt[vector];
|
||||||
|
|
||||||
@@ -49,21 +129,11 @@ void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl)
|
|||||||
entry->reserved = 0;
|
entry->reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exception_handler(isr_frame_t* frame)
|
|
||||||
{
|
|
||||||
vga_print("Interrupt\n");
|
|
||||||
vga_print(" int_no: ");
|
|
||||||
vga_print_uint(frame->int_no);
|
|
||||||
vga_print("\n");
|
|
||||||
vga_print(" err_code: ");
|
|
||||||
vga_print_uint(frame->err_code);
|
|
||||||
vga_print("\n");
|
|
||||||
__asm__ volatile("cli; hlt");
|
|
||||||
}
|
|
||||||
|
|
||||||
void idt_init(void)
|
void idt_init(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; i++)
|
pic_remap(0x20, 0x28);
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
idt_set_descriptor(i, isr_stub_table[i], 0);
|
idt_set_descriptor(i, isr_stub_table[i], 0);
|
||||||
}
|
}
|
||||||
@@ -71,4 +141,47 @@ void idt_init(void)
|
|||||||
idtr_t idtr = { .base = (uintptr_t)&idt[0], .limit = (uint16_t)sizeof(interrupt_descriptor) * IDT_SIZE - 1 };
|
idtr_t idtr = { .base = (uintptr_t)&idt[0], .limit = (uint16_t)sizeof(interrupt_descriptor) * IDT_SIZE - 1 };
|
||||||
|
|
||||||
__asm__ volatile("lidt %0" : : "m"(idtr));
|
__asm__ volatile("lidt %0" : : "m"(idtr));
|
||||||
|
__asm__ volatile("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_enable(void)
|
||||||
|
{
|
||||||
|
__asm__ volatile("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_isr(isr_frame_t* frame)
|
||||||
|
{
|
||||||
|
if (frame->int_no < 32)
|
||||||
|
{
|
||||||
|
vga_print_error();
|
||||||
|
vga_print(" exception[");
|
||||||
|
vga_print_uint(frame->int_no);
|
||||||
|
vga_print("]: ");
|
||||||
|
vga_print(exception_messages[frame->int_no]);
|
||||||
|
|
||||||
|
vga_print(", error code: ");
|
||||||
|
vga_print_uint(frame->err_code);
|
||||||
|
vga_print("\n");
|
||||||
|
|
||||||
|
__asm__ volatile("cli; hlt");
|
||||||
|
}
|
||||||
|
else if (frame->int_no < 48)
|
||||||
|
{
|
||||||
|
uint8_t irq = frame->int_no - 32;
|
||||||
|
|
||||||
|
if (irq_handlers[irq])
|
||||||
|
{
|
||||||
|
irq_handlers[irq](frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
pic_send_eoi(irq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vga_print_error();
|
||||||
|
vga_print(" interrupt[");
|
||||||
|
vga_print_uint(frame->int_no);
|
||||||
|
vga_print("]: ");
|
||||||
|
vga_print("not implemented\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
14
src/idt.h
14
src/idt.h
@@ -2,5 +2,17 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
||||||
|
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
|
||||||
|
uint64_t int_no;
|
||||||
|
uint64_t err_code;
|
||||||
|
uint64_t rip, cs, rflags, rsp, ss;
|
||||||
|
} __attribute__((packed)) isr_frame_t;
|
||||||
|
|
||||||
|
typedef void (*irq_handler_t)(isr_frame_t*);
|
||||||
|
|
||||||
void idt_init(void);
|
void idt_init(void);
|
||||||
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags);
|
void idt_enable(void);
|
||||||
|
void register_irq_handler(uint8_t irq, irq_handler_t handler);
|
||||||
@@ -1,17 +1,4 @@
|
|||||||
extern exception_handler
|
extern handle_isr
|
||||||
|
|
||||||
%macro ISR_NOERR 1
|
|
||||||
isr_stub_%1:
|
|
||||||
push qword 0
|
|
||||||
push qword %1
|
|
||||||
jmp isr_common
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
%macro ISR_ERR 1
|
|
||||||
isr_stub_%1:
|
|
||||||
push qword %1
|
|
||||||
jmp isr_common
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
isr_common:
|
isr_common:
|
||||||
push rax
|
push rax
|
||||||
@@ -31,7 +18,7 @@ isr_common:
|
|||||||
push r15
|
push r15
|
||||||
|
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
call exception_handler
|
call handle_isr
|
||||||
|
|
||||||
pop r15
|
pop r15
|
||||||
pop r14
|
pop r14
|
||||||
@@ -52,6 +39,20 @@ isr_common:
|
|||||||
add rsp, 16
|
add rsp, 16
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
|
%macro ISR_NOERR 1
|
||||||
|
isr_stub_%1:
|
||||||
|
push qword 0
|
||||||
|
push qword %1
|
||||||
|
jmp isr_common
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro ISR_ERR 1
|
||||||
|
isr_stub_%1:
|
||||||
|
push qword %1
|
||||||
|
jmp isr_common
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; CPU exceptions 0-31
|
||||||
ISR_NOERR 0
|
ISR_NOERR 0
|
||||||
ISR_NOERR 1
|
ISR_NOERR 1
|
||||||
ISR_NOERR 2
|
ISR_NOERR 2
|
||||||
@@ -85,37 +86,24 @@ ISR_NOERR 29
|
|||||||
ISR_ERR 30
|
ISR_ERR 30
|
||||||
ISR_NOERR 31
|
ISR_NOERR 31
|
||||||
|
|
||||||
|
%macro GENERATE_ISRS 2
|
||||||
|
%assign i %1
|
||||||
|
%rep (%2 - %1 + 1)
|
||||||
|
ISR_NOERR i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
GENERATE_ISRS 32, 255
|
||||||
|
|
||||||
|
%macro GENERATE_ISR_TABLE 2
|
||||||
|
%assign i %1
|
||||||
|
%rep (%2 - %1 + 1)
|
||||||
|
dq isr_stub_%[i]
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
global isr_stub_table
|
global isr_stub_table
|
||||||
isr_stub_table:
|
isr_stub_table:
|
||||||
dq isr_stub_0
|
GENERATE_ISR_TABLE 0, 255
|
||||||
dq isr_stub_1
|
|
||||||
dq isr_stub_2
|
|
||||||
dq isr_stub_3
|
|
||||||
dq isr_stub_4
|
|
||||||
dq isr_stub_5
|
|
||||||
dq isr_stub_6
|
|
||||||
dq isr_stub_7
|
|
||||||
dq isr_stub_8
|
|
||||||
dq isr_stub_9
|
|
||||||
dq isr_stub_10
|
|
||||||
dq isr_stub_11
|
|
||||||
dq isr_stub_12
|
|
||||||
dq isr_stub_13
|
|
||||||
dq isr_stub_14
|
|
||||||
dq isr_stub_15
|
|
||||||
dq isr_stub_16
|
|
||||||
dq isr_stub_17
|
|
||||||
dq isr_stub_18
|
|
||||||
dq isr_stub_19
|
|
||||||
dq isr_stub_20
|
|
||||||
dq isr_stub_21
|
|
||||||
dq isr_stub_22
|
|
||||||
dq isr_stub_23
|
|
||||||
dq isr_stub_24
|
|
||||||
dq isr_stub_25
|
|
||||||
dq isr_stub_26
|
|
||||||
dq isr_stub_27
|
|
||||||
dq isr_stub_28
|
|
||||||
dq isr_stub_29
|
|
||||||
dq isr_stub_30
|
|
||||||
dq isr_stub_31
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
void kernel_main(void)
|
void kernel_main(void)
|
||||||
{
|
{
|
||||||
@@ -8,11 +9,13 @@ void kernel_main(void)
|
|||||||
vga_print(" VGA intialzied\n");
|
vga_print(" VGA intialzied\n");
|
||||||
|
|
||||||
idt_init();
|
idt_init();
|
||||||
|
idt_enable();
|
||||||
vga_print_success();
|
vga_print_success();
|
||||||
vga_print(" IDT intialzied\n");
|
vga_print(" IDT intialzied\n");
|
||||||
|
|
||||||
vga_print("\nWelcome to nub OS\n");
|
vga_print("\nWelcome to nub OS\n");
|
||||||
vga_print(">");
|
|
||||||
|
|
||||||
int x = 1 / 0;
|
while (true)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user