interrupts

This commit is contained in:
nub31
2025-08-24 18:52:51 +02:00
parent 1402a227f1
commit 57ef424e00
8 changed files with 162 additions and 3 deletions

View File

@@ -1,3 +1,7 @@
menuentry "nub-os" { menuentry "nub-os" {
multiboot2 /boot/kernel multiboot2 /boot/kernel
boot
} }
set default="nub-os"
set timeout=0

View File

@@ -1,7 +1,7 @@
CC = x86_64-elf-gcc CC = x86_64-elf-gcc
LD = x86_64-elf-ld LD = x86_64-elf-ld
CFLAGS = -m64 -ffreestanding -fno-builtin -Wall -Wextra -Werror -Wshadow -std=c23 CFLAGS = -m64 -ffreestanding -fno-builtin -Wall -Wextra -Wshadow -std=c23
LDFLAGS = LDFLAGS =
all: .build/nub-os.iso all: .build/nub-os.iso
@@ -18,8 +18,8 @@ build-dir:
cp .build/kernel .build/iso/boot/ cp .build/kernel .build/iso/boot/
grub-mkrescue -o .build/nub-os.iso .build/iso/ grub-mkrescue -o .build/nub-os.iso .build/iso/
.build/kernel: build-dir .build/boot.o .build/kernel.o .build/vga.o .build/kernel: build-dir .build/boot.o .build/kernel.o .build/vga.o .build/idt.o .build/idt2.o
$(LD) $(LDFLAGS) -T src/boot.ld -o .build/kernel .build/boot.o .build/kernel.o .build/vga.o $(LD) $(LDFLAGS) -T src/boot.ld -o .build/kernel .build/boot.o .build/kernel.o .build/vga.o .build/idt.o .build/idt2.o
.build/kernel.o: build-dir src/kernel.c .build/kernel.o: build-dir src/kernel.c
$(CC) $(CFLAGS) -c -o .build/kernel.o src/kernel.c $(CC) $(CFLAGS) -c -o .build/kernel.o src/kernel.c
@@ -27,5 +27,11 @@ build-dir:
.build/vga.o: build-dir src/vga.c .build/vga.o: build-dir src/vga.c
$(CC) $(CFLAGS) -c -o .build/vga.o src/vga.c $(CC) $(CFLAGS) -c -o .build/vga.o src/vga.c
.build/idt.o: build-dir src/idt.c
$(CC) $(CFLAGS) -c -o .build/idt.o src/idt.c
.build/idt2.o: build-dir src/idt.asm
nasm -f elf64 -o .build/idt2.o src/idt.asm
.build/boot.o: build-dir src/boot.asm .build/boot.o: build-dir src/boot.asm
nasm -f elf64 -o .build/boot.o src/boot.asm nasm -f elf64 -o .build/boot.o src/boot.asm

53
src/idt.asm Normal file
View File

@@ -0,0 +1,53 @@
%macro isr_err_stub 1
isr_stub_%+%1:
call exception_handler
iretq
%endmacro
%macro isr_no_err_stub 1
isr_stub_%+%1:
call exception_handler
iretq
%endmacro
extern exception_handler
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub 8
isr_no_err_stub 9
isr_err_stub 10
isr_err_stub 11
isr_err_stub 12
isr_err_stub 13
isr_err_stub 14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
dq isr_stub_%+i
%assign i i+1
%endrep

65
src/idt.c Normal file
View File

@@ -0,0 +1,65 @@
#include "vga.h"
#include <stdbool.h>
#include <stdint.h>
#define IDT_MAX_DESCRIPTORS 255
typedef struct
{
uint16_t isr_low; // The lower 16 bits of the ISR's address
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
uint8_t attributes; // Type and attributes; see the IDT page
uint16_t isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
uint32_t isr_high; // The higher 32 bits of the ISR's address
uint32_t reserved; // Set to zero
} __attribute__((packed)) idt_entry_t;
typedef struct
{
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idtr_t;
static idt_entry_t idt[256];
static idtr_t idtr;
void exception_handler(void)
{
vga_print_error("An unhandled exception occurred");
__asm__ volatile("cli; hlt");
}
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags)
{
idt_entry_t* descriptor = &idt[vector];
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
descriptor->kernel_cs = 0x08;
descriptor->ist = 0;
descriptor->attributes = flags;
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
descriptor->reserved = 0;
}
static bool vectors[IDT_MAX_DESCRIPTORS];
extern void* isr_stub_table[];
void idt_init(void)
{
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1;
for (uint8_t vector = 0; vector < 32; vector++)
{
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = true;
}
__asm__ volatile("lidt %0" : : "m"(idtr));
__asm__ volatile("sti");
vga_print_success("IDT intialzied");
}

5
src/idt.h Normal file
View File

@@ -0,0 +1,5 @@
#include <stdint.h>
void idt_init(void);
void exception_handler(void);
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags);

View File

@@ -1,7 +1,13 @@
#include "idt.h"
#include "vga.h" #include "vga.h"
void kernel_main(void) void kernel_main(void)
{ {
vga_clear(); vga_clear();
idt_init();
vga_print("Welcome to nub OS\n"); vga_print("Welcome to nub OS\n");
int x = 1 / 0;
} }

View File

@@ -108,4 +108,22 @@ void vga_print_colored(const char* string, vga_color_t color)
void vga_print(const char* string) void vga_print(const char* string)
{ {
vga_print_colored(string, vga_default_color()); vga_print_colored(string, vga_default_color());
}
void vga_print_success(const char* message)
{
vga_print("[ ");
vga_print_colored("success", VGA_GREEN);
vga_print(" ] ");
vga_print(message);
vga_print("\n");
}
void vga_print_error(const char* message)
{
vga_print("[ ");
vga_print_colored("error", VGA_RED);
vga_print(" ] ");
vga_print(message);
vga_print("\n");
} }

View File

@@ -26,6 +26,8 @@ void vga_set_cursor_position(uint8_t row, uint8_t col);
void vga_print_colored(const char* string, vga_color_t color); void vga_print_colored(const char* string, vga_color_t color);
void vga_print(const char* string); void vga_print(const char* string);
void vga_print_success(const char* message);
void vga_print_error(const char* message);
static inline vga_color_t vga_color(vga_color_t fg_color, vga_color_t bg_color) static inline vga_color_t vga_color(vga_color_t fg_color, vga_color_t bg_color)
{ {