Compare commits

..

2 commits

Author SHA1 Message Date
fbef354410 Small IDT work, gotta go hiking lol 2025-06-17 20:13:09 -04:00
8c51b7010e Interrupt Descriptors implemented
Now just need to populate the IDT, then debug the whole thing.
2025-06-16 22:40:02 -04:00
7 changed files with 104 additions and 15 deletions

View file

@ -17,6 +17,7 @@ typedef struct IDTR_s {
extern IDTR_t idtr;
extern InterruptDescriptor_t* idt_start;
extern char num_interrupts;
void setup_idt();
void write_descriptors();

View file

@ -0,0 +1,14 @@
#ifndef INTERRUPTHANDLERS_H
#define INTERRUPTHANDLERS_H
#include <stdint.h>
extern void* isr_ptrs;
typedef struct StateSnapshot_s {
uint32_t eax, ecx, edx, ebx, esp, esi, edi;
uint32_t interrupt_id, error_code;
uint32_t eip, cs, eflags;
} StateSnapshot_t;
void generic_isr_handler(StateSnapshot_t* cpu_state);
#endif

15
src/allocidt.s Normal file
View file

@ -0,0 +1,15 @@
%define NUM_INTERRUPTS 32
global idtr, idt_start, num_interrupts
section .idtr
num_interrupts:
db NUM_INTERRUPTS
idtr:
;Normally, the size would be the size of the whole table, but i'm only defining 32 interrupts for now.
;dw idt_end - idt_start
dw NUM_INTERRUPTS * 8
dd idt_start
section .idt nobits
idt_start:
resb NUM_INTERRUPTS * 8
idt_end:

18
src/idt.c Normal file
View file

@ -0,0 +1,18 @@
#include "idt.h"
void setup_idt() {
write_descriptors();
load_idt();
}
void write_descriptors() {
for(int i = 0; i < num_interrupts; i++) {
}
}
void load_idt() {
return;
}

View file

@ -1,11 +0,0 @@
global idtr, idt_start
section .idtr
idtr:
dw idt_end - idt_start
dd idt_start
section .idt nobits
idt_start:
resb 256 * 8 ;idt technically has 256 entries by the spec, so i'm reserving that much space... even if i dont implement that many.
idt_end:

13
src/interrupt_handlers.c Normal file
View file

@ -0,0 +1,13 @@
#include "interrupt_handlers.h"
#include "kio.h"
void generic_isr_handler(StateSnapshot_t* cpu_state) {
//We made it to C for our interrupt! For now, let's just print our interrupt to the screen.
vga_clear();
vga_printf("INTERRUPT TRIGGERED! Info below.\n");
vga_printf("Int_ID|ERR: %X|%X\n", cpu_state->interrupt_id, cpu_state->error_code);
vga_printf("EFLAGS|CS|EIP: %X|%X|%X\n", cpu_state->eflags, cpu_state->cs,cpu_state->eip);
vga_printf("GP Registers:\neax:%X\nebx:%X\necx:%X\nedx:%X\nesp:%X\nesi:%X\nedi:%X\n");
vga_printf("HALT!");
while(1);
}

View file

@ -2,11 +2,50 @@
;Let's make an interrupt pointer table so C can reference it and build the IDT.
global isr_ptrs
extern generic_isr_handler
;By the time we get here, we actually have a rather consistent stack:
; dword [Interrupt ID]
; dword [Error code (0 if int has no error code field)]
; dword [EIP]
; dword [CS]
; dword [EFLAGS]
; We can pass this to C. First, we might want to push all of our registers or something.
isr_common:
pusha
push esp ;Throwing a pointer to ESP in there for referencing the aforementioned stuff as a struct
call generic_isr_handler
add esp,4 ;Remove that esp ref from the stack
popad ;restore our gp registers
add esp,4 ;deallocate the error code from the stack before heading out
iret
%macro ISR_ENTRY 1
isr_%1:
cli
%if %1 = 8 || %1 = 10 || %1 = 11 || %1 = 12 || %1 = 13 || %1 = 14 || %1 = 17 || %1 = 21
%else
push dword 0
%endif
push dword %1 ; saving our interrupt so C knows
jmp isr_common
%endmacro
isr_table:
%assign j 0
%rep 32
isr_ %+ j:
ISR_ENTRY j
%assign j j+1
%endrep
; Generate a table of pointers that point to each of our ISRs. This will be accessed from C to setup our IDT.
isr_ptrs:
%assign i 0
%rep 21
isr_stub_ %+ i:
%rep 32
dd isr_ %+ i
%assign i i+1
%endrep
isr_ptrs_end: