This commit is contained in:
nub31
2025-09-03 14:55:45 +02:00
parent a1205703f0
commit 33239034a7
16 changed files with 310 additions and 303 deletions

View File

@@ -1,6 +1,5 @@
global _start
extern entry
extern handle_isr
%define FLAGS 0b10
%define MAGIC 0x1BADB002
@@ -139,39 +138,6 @@ section .text
hlt
jmp .hang
section .bss
align 4096
idt64:
resb 4096
section .data
align 8
idt64_descriptor:
dw 4095
dq idt64
section .data
align 8
isr_stub_table:
%assign i 0
%rep 256
dq isr_stub_%[i]
%assign i i+1
%endrep
%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
section .text
bits 64
long_mode:
@@ -183,108 +149,9 @@ section .text
mov gs, ax
mov ss, ax
; Fill in the idt table with the stub functions
mov rdi, idt64
mov rsi, isr_stub_table
mov rcx, 256
.loop:
mov rax, [rsi]
mov [rdi], ax
mov word [rdi + 2], 0x08
mov word [rdi + 4], 0x8E00
shr rax, 16
mov [rdi + 6], ax
shr rax, 16
mov [rdi + 8], eax
mov dword [rdi + 12], 0
add rdi, 16
add rsi, 8
loop .loop
lidt [idt64_descriptor]
; Finally, we call in to c
mov rdi, [multiboot_info]
call entry
.hang:
hlt
jmp .hang
isr_common:
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi, rsp
call handle_isr
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 16
iretq
; CPU exceptions 0-31. Some of these contain error codes, so we define them manually
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_ERR 30
ISR_NOERR 31
; Hardware interrupts and user-defined interrupts (32-255). These don't have error codes
%assign i 32
%rep 224
ISR_NOERR i
%assign i i+1
%endrep
jmp .hang

View File

@@ -1,139 +0,0 @@
#include "interrupts.h"
#include "../arch.h"
#include "util.h"
#include <stdio.h>
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
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 irq_handler_t irq_handlers[16] = {0};
bool cpu_has_apic()
{
uint32_t eax, edx;
cpuid(1, &eax, &edx);
return (edx & CPUID_FEAT_EDX_APIC) != 0;
}
void enable_apic()
{
uint64_t apic_base = rdmsr(0x1B);
apic_base |= (1 << 11);
wrmsr(0x1B, apic_base);
printf("APIC enabled\n");
}
void remap_pic()
{
outb(PIC1_COMMAND, 0x11);
outb(PIC2_COMMAND, 0x11);
outb(PIC1_DATA, 32);
outb(PIC2_DATA, 40);
outb(PIC1_DATA, 4);
outb(PIC2_DATA, 2);
outb(PIC1_DATA, 1);
outb(PIC2_DATA, 1);
outb(PIC1_DATA, 0);
outb(PIC2_DATA, 0);
printf("PIC remapped\n");
}
void disable_pic()
{
outb(PIC1_DATA, 0xFF);
outb(PIC2_DATA, 0xFF);
printf("PIC disabled\n");
}
static void handle_exception(const isr_frame_t* frame)
{
printf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code);
panic();
}
void register_irq_handler(uint8_t irq, irq_handler_t handler)
{
if (irq >= 16)
{
printf("Cannot register irq %d is out of bounds\n", irq);
}
else
{
irq_handlers[irq] = handler;
printf("Registered irq handler at vector %d\n", irq);
}
}
static void handle_irq(const isr_frame_t* frame)
{
uint8_t irq = frame->int_no - 32;
if (irq_handlers[irq])
{
irq_handlers[irq](frame);
}
if (irq >= 8)
{
outb(PIC2_COMMAND, 0x20);
}
outb(PIC1_COMMAND, 0x20);
}
void handle_isr(const isr_frame_t* frame)
{
if (frame->int_no < 32)
{
handle_exception(frame);
}
else if (frame->int_no < 48)
{
handle_irq(frame);
}
else
{
printf("interrupt[%d]: not implemented\n", frame->int_no);
}
}

View File

@@ -0,0 +1,43 @@
#include "exceptions.h"
#include "../../arch.h"
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",
};
void handle_exception(const isr_frame_t* frame)
{
printf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code);
panic();
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "isr.h"
typedef void (*exception_handler_t)(const isr_frame_t*);
void handle_exception(const isr_frame_t* frame);
void register_exception_handler(uint8_t irq, exception_handler_t handler);

View File

@@ -0,0 +1,136 @@
global idt_init
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
section .bss
align 4096
idt64:
resb 4096
section .data
align 8
isr_stub_table:
%assign i 0
%rep 256
dq isr_stub_%[i]
%assign i i+1
%endrep
idt64_descriptor:
dw 4095
dq idt64
section .text
bits 64
idt_init:
; Fill in the idt table with the stub functions
mov rdi, idt64
mov rsi, isr_stub_table
mov rcx, 256
.loop:
mov rax, [rsi]
mov [rdi], ax
mov word [rdi + 2], 0x08
mov word [rdi + 4], 0x8E00
shr rax, 16
mov [rdi + 6], ax
shr rax, 16
mov [rdi + 8], eax
mov dword [rdi + 12], 0
add rdi, 16
add rsi, 8
loop .loop
lidt [idt64_descriptor]
ret
isr_common:
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi, rsp
call handle_isr
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 16
iretq
; CPU exceptions 0-31. Some of these contain error codes, so we define them manually
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_ERR 30
ISR_NOERR 31
; Hardware interrupts and user-defined interrupts (32-255). These don't have error codes
%assign i 32
%rep 224
ISR_NOERR i
%assign i i+1
%endrep

View File

@@ -0,0 +1,3 @@
#pragma once
extern void idt_init();

View File

@@ -0,0 +1,76 @@
#include "irq.h"
#include "../util.h"
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
static irq_handler_t irq_handlers[16] = {0};
bool cpu_has_apic()
{
uint32_t eax, edx;
cpuid(1, &eax, &edx);
return (edx & CPUID_FEAT_EDX_APIC) != 0;
}
void enable_apic()
{
uint64_t apic_base = rdmsr(0x1B);
apic_base |= (1 << 11);
wrmsr(0x1B, apic_base);
}
void remap_pic()
{
outb(PIC1_COMMAND, 0x11);
outb(PIC2_COMMAND, 0x11);
outb(PIC1_DATA, 32);
outb(PIC2_DATA, 40);
outb(PIC1_DATA, 4);
outb(PIC2_DATA, 2);
outb(PIC1_DATA, 1);
outb(PIC2_DATA, 1);
outb(PIC1_DATA, 0);
outb(PIC2_DATA, 0);
}
void disable_pic()
{
outb(PIC1_DATA, 0xFF);
outb(PIC2_DATA, 0xFF);
}
void register_irq_handler(uint8_t irq, irq_handler_t handler)
{
if (irq >= 16)
{
printf("Cannot register irq %d is out of bounds\n", irq);
}
else
{
irq_handlers[irq] = handler;
}
}
void handle_irq(const isr_frame_t* frame)
{
uint8_t irq = frame->int_no - 32;
if (irq_handlers[irq])
{
irq_handlers[irq](frame);
}
if (irq >= 8)
{
outb(PIC2_COMMAND, 0x20);
}
outb(PIC1_COMMAND, 0x20);
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "isr.h"
#include <stdbool.h>
typedef void (*irq_handler_t)(const isr_frame_t*);
void remap_pic();
void disable_pic();
bool cpu_has_apic();
void enable_apic();
void handle_irq(const isr_frame_t* frame);
void register_irq_handler(uint8_t irq, irq_handler_t handler);

View File

@@ -0,0 +1,20 @@
#include "isr.h"
#include "exceptions.h"
#include "irq.h"
#include <stdio.h>
void handle_isr(const isr_frame_t* frame)
{
if (frame->int_no < 32)
{
handle_exception(frame);
}
else if (frame->int_no < 48)
{
handle_irq(frame);
}
else
{
printf("interrupt[%d]: not implemented\n", frame->int_no);
}
}

View File

@@ -1,6 +1,5 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -13,24 +12,12 @@ typedef struct
uint64_t rip, cs, rflags, rsp, ss;
} __attribute__((packed)) isr_frame_t;
typedef void (*irq_handler_t)(const isr_frame_t*);
void remap_pic();
void disable_pic();
bool cpu_has_apic();
void enable_apic();
void register_irq_handler(uint8_t irq, irq_handler_t handler);
static inline void enable_interrupts()
{
__asm__ volatile("sti");
printf("Interrupts enabled\n");
}
static inline void disable_interrupts()
{
__asm__ volatile("cli");
printf("Interrupts disabled\n");
}

View File

@@ -101,7 +101,7 @@
// handler_index += 1;
// }
// void init_keyboard()
// void keyboard_init()
// {
// register_irq_handler(1, handle_keyboard);
// }

View File

@@ -14,6 +14,6 @@
// typedef void (*keyboard_handler_t)(const keyboard_event_t*);
// void init_keyboard();
// void keyboard_init();
// void register_keypress_handler(keyboard_handler_t handler);
// char scan_code_to_ascii(uint8_t scan_code);

View File

@@ -1,6 +1,7 @@
#include "../../kernel.h"
#include "../arch.h"
#include "interrupts.h"
#include "interrupts/idt.h"
#include "interrupts/irq.h"
#include "mmap.h"
#include "multiboot.h"
#include "util.h"
@@ -10,22 +11,16 @@
void entry(multiboot_info_t* mbd)
{
vga_clear();
map_memory(mbd);
idt_init();
remap_pic();
map_memory(mbd);
enable_interrupts();
main();
}
void arch_callback()
{
printf("Kernel panic!\n");
disable_interrupts();
halt();
}
void panic()
{
printf("Kernel panic!");
printf("Kernel panic!\n");
disable_interrupts();
halt();
}

View File

@@ -4,6 +4,6 @@
void main()
{
init_pmm();
pmm_init();
printf("Welcome to nub OS :)\n");
}

View File

@@ -11,7 +11,7 @@ static uint8_t page_bitmap[BITMAP_SIZE];
static uint64_t total_pages = 0;
static uint64_t free_pages = 0;
void init_pmm()
void pmm_init()
{
memset(page_bitmap, 0xFF, BITMAP_SIZE);
@@ -50,8 +50,6 @@ void init_pmm()
}
}
}
printf("PMM initialized\n");
}
uint64_t pmm_alloc_page()

View File

@@ -4,6 +4,6 @@
#define PAGE_SIZE 4096
void init_pmm();
void pmm_init();
uint64_t pmm_alloc_page();
void pmm_free_page(uint64_t addr);