Espresso 0.0.0e

This commit is contained in:
2025-06-13 18:03:39 -05:00
parent 6d366537dd
commit 1e5b4a765b
40 changed files with 742 additions and 718 deletions

View File

@ -1,131 +1,141 @@
#include <string.h>
#include <stdio.h>
#include <port_io.h>
#include <idt.h>
#include <drivers/idt.h>
#define IDT_ENTRIES 256
struct idt_entry idt[IDT_ENTRIES];
struct idt_ptr idtp;
#define IDT_MAX_DESCRIPTORS 256
extern void idt_load(uint32_t);
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
void idt_install(void)
/*
Most of the code is this file (and idt.h) are taken from the osdev wiki: https://wiki.osdev.org/Interrupts_Tutorial, though not all of it.
*/
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 reserved; // Set to zero
uint8_t attributes; // Type and attributes; see the IDT page
uint16_t isr_high; // The higher 16 bits of the ISR's address
} __attribute__((packed)) idt_entry_t;
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__((packed)) idtr_t;
__attribute__((aligned(0x10)))
static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance
static idtr_t idtr;
static bool vectors[IDT_MAX_DESCRIPTORS];
extern void* isr_stub_table[];
__attribute__((noreturn))
void exception_dispatcher(uint32_t int_no, uint32_t err_code)
{
idtp.limit = sizeof(struct idt_entry) * IDT_ENTRIES - 1;
idtp.base = (uint32_t)&idt;
switch (int_no)
{
case 0:
printf("Divide by zero exception\n");
break;
case 13:
printf("General Protection Fault: err=0x%x\n", err_code);
break;
case 14:
{
uint32_t cr2;
__asm__ volatile ("mov %%cr2, %0" : "=r"(cr2));
printf("Page Fault at address: 0x%x, err=0x%x\n", cr2, err_code);
break;
}
default:
printf("Unhandled exception #%u, err=0x%x\n", int_no, err_code);
break;
}
memset(&idt, 0, sizeof(struct idt_entry) * IDT_ENTRIES);
uint16_t cs, ds, es, ss;
asm volatile ("mov %%cs, %0" : "=r"(cs));
asm volatile ("mov %%ds, %0" : "=r"(ds));
asm volatile ("mov %%es, %0" : "=r"(es));
asm volatile ("mov %%ss, %0" : "=r"(ss));
/* Set entries for IRQs/ISRs here using `idt_set_entry(...)` */
/* Example: idt_set_entry(0, (uint32_t)isr0, 0x08, 0x8E); */
printf("CS=0x%04x DS=0x%04x ES=0x%04x SS=0x%04x\n", cs, ds, es, ss);
idt_load((uint32_t)&idtp);
__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 = (uint32_t)isr & 0xFFFF;
descriptor->kernel_cs = 0x08;
descriptor->attributes = flags;
descriptor->isr_high = (uint32_t)isr >> 16;
descriptor->reserved = 0;
}
void pic_remap(void)
{
outb(0x20, 0x11); /* Start init for master PIC */
outb(0xA0, 0x11); /* Start init for slave PIC */
outb(0x21, 0x20); /* Master PIC vector offset */
outb(0xA1, 0x28); /* Slave PIC vector offset */
outb(0x21, 0x04); /* Tell Master PIC about Slave PIC at IRQ2 */
outb(0xA1, 0x02); /* Tell Slave PIC its cascade identity */
outb(0x21, 0x01); /* 8086/88 mode */
outb(0xA1, 0x01);
outb(0x21, 0x0); /* Unmask master */
outb(0xA1, 0x0); /* Unmask slave */
uint8_t a1, a2;
// Save masks
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
// Start initialization sequence (in cascade mode)
outb(PIC1_COMMAND, 0x11);
outb(PIC2_COMMAND, 0x11);
// Set vector offset
outb(PIC1_DATA, 0x20); // IRQs 0-7 mapped to IDT entries 0x20-0x27 (3239)
outb(PIC2_DATA, 0x28); // IRQs 8-15 mapped to IDT entries 0x28-0x2F (4047)
// Tell Master PIC about Slave PIC at IRQ2 (0000 0100)
outb(PIC1_DATA, 0x04);
// Tell Slave PIC its cascade identity (0000 0010)
outb(PIC2_DATA, 0x02);
// Set 8086/88 mode
outb(PIC1_DATA, 0x01);
outb(PIC2_DATA, 0x01);
// Restore saved masks
outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2);
}
void idt_set_entry(int num, uint32_t base, uint16_t sel, uint8_t flags)
void idt_init(void)
{
idt[num].base_low = base & 0xFFFF;
idt[num].base_high = (base >> 16) & 0xFFFF;
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1;
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
}
extern void IRQ0_handler(void);
extern void isr0(void);
extern void isr1(void);
extern void isr2(void);
extern void isr3(void);
extern void isr4(void);
extern void isr5(void);
extern void isr6(void);
extern void isr7(void);
extern void isr8(void);
extern void isr9(void);
extern void isr10(void);
extern void isr11(void);
extern void isr12(void);
extern void isr13(void);
extern void isr14(void);
extern void isr15(void);
extern void isr16(void);
extern void isr17(void);
extern void isr18(void);
extern void isr19(void);
extern void isr20(void);
extern void isr21(void);
extern void isr22(void);
extern void isr23(void);
extern void isr24(void);
extern void isr25(void);
extern void isr26(void);
extern void isr27(void);
extern void isr28(void);
extern void isr29(void);
extern void isr30(void);
extern void isr31(void);
extern void isr33(void);
extern void isr128(void);
void idt_install_isrs(void)
{
idt_set_entry(0, (uint32_t)isr0, 0x08, 0x8E);
idt_set_entry(1, (uint32_t)isr1, 0x08, 0x8E);
idt_set_entry(2, (uint32_t)isr2, 0x08, 0x8E);
idt_set_entry(3, (uint32_t)isr3, 0x08, 0x8E);
idt_set_entry(4, (uint32_t)isr4, 0x08, 0x8E);
idt_set_entry(5, (uint32_t)isr5, 0x08, 0x8E);
idt_set_entry(6, (uint32_t)isr6, 0x08, 0x8E);
idt_set_entry(7, (uint32_t)isr7, 0x08, 0x8E);
idt_set_entry(8, (uint32_t)isr8, 0x08, 0x8E);
idt_set_entry(9, (uint32_t)isr9, 0x08, 0x8E);
idt_set_entry(10, (uint32_t)isr10, 0x08, 0x8E);
idt_set_entry(11, (uint32_t)isr11, 0x08, 0x8E);
idt_set_entry(12, (uint32_t)isr12, 0x08, 0x8E);
idt_set_entry(13, (uint32_t)isr13, 0x08, 0x8E);
idt_set_entry(14, (uint32_t)isr14, 0x08, 0x8E);
idt_set_entry(15, (uint32_t)isr15, 0x08, 0x8E);
idt_set_entry(16, (uint32_t)isr16, 0x08, 0x8E);
idt_set_entry(17, (uint32_t)isr17, 0x08, 0x8E);
idt_set_entry(18, (uint32_t)isr18, 0x08, 0x8E);
idt_set_entry(19, (uint32_t)isr19, 0x08, 0x8E);
idt_set_entry(20, (uint32_t)isr20, 0x08, 0x8E);
idt_set_entry(21, (uint32_t)isr21, 0x08, 0x8E);
idt_set_entry(22, (uint32_t)isr22, 0x08, 0x8E);
idt_set_entry(23, (uint32_t)isr23, 0x08, 0x8E);
idt_set_entry(24, (uint32_t)isr24, 0x08, 0x8E);
idt_set_entry(25, (uint32_t)isr25, 0x08, 0x8E);
idt_set_entry(26, (uint32_t)isr26, 0x08, 0x8E);
idt_set_entry(27, (uint32_t)isr27, 0x08, 0x8E);
idt_set_entry(28, (uint32_t)isr28, 0x08, 0x8E);
idt_set_entry(29, (uint32_t)isr29, 0x08, 0x8E);
idt_set_entry(30, (uint32_t)isr30, 0x08, 0x8E);
idt_set_entry(31, (uint32_t)isr31, 0x08, 0x8E);
for (uint8_t vector = 0; vector < 32; vector++)
{
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = true;
}
idt_set_entry(33, (uint32_t)isr33, 0x08, 0x8E);
extern void* irq_stub_table[];
for (uint8_t i = 0; i < 16; i++)
{
idt_set_descriptor(32 + i, irq_stub_table[i], 0x8E);
}
__asm__ volatile ("lidt %0" : : "m"(idtr)); /* load the new IDT */
__asm__ volatile ("sti"); /* set the interrupt flag */
}
void idt_install_syscall(void)
{
idt_set_entry(128, (uint32_t)isr128, 0x08, 0xEE);
}