From 394202c032c4adeb0456f56437d27be5e0d2cfb5 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Thu, 5 Feb 2026 16:41:37 -0300 Subject: [PATCH] x86: add int 0x80 syscall gate and minimal sys_write --- include/syscall.h | 12 ++++++++++++ src/arch/x86/idt.c | 7 ++++++- src/arch/x86/interrupts.S | 3 +++ src/kernel/main.c | 4 ++++ src/kernel/syscall.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 include/syscall.h create mode 100644 src/kernel/syscall.c diff --git a/include/syscall.h b/include/syscall.h new file mode 100644 index 0000000..863f179 --- /dev/null +++ b/include/syscall.h @@ -0,0 +1,12 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#include + +void syscall_init(void); + +enum { + SYSCALL_WRITE = 1, +}; + +#endif diff --git a/src/arch/x86/idt.c b/src/arch/x86/idt.c index 8bef4bc..6b80a80 100644 --- a/src/arch/x86/idt.c +++ b/src/arch/x86/idt.c @@ -26,6 +26,8 @@ extern void irq4(); extern void irq5(); extern void irq6(); extern void irq7(); extern void irq8(); extern void irq9(); extern void irq10(); extern void irq11(); extern void irq12(); extern void irq13(); extern void irq14(); extern void irq15(); +extern void isr128(); + void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { idt[num].base_lo = base & 0xFFFF; idt[num].base_hi = (base >> 16) & 0xFFFF; @@ -129,6 +131,9 @@ void idt_init(void) { idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E); idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E); + // Syscall gate (int 0x80) must be callable from user mode (DPL=3) + idt_set_gate(128, (uint32_t)isr128, 0x08, 0xEE); + // Load IDT __asm__ volatile("lidt %0" : : "m"(idtp)); @@ -198,7 +203,7 @@ void isr_handler(struct registers* regs) { } // Send EOI (End of Interrupt) to PICs for IRQs (32-47) - if (regs->int_no >= 32) { + if (regs->int_no >= 32 && regs->int_no <= 47) { if (regs->int_no >= 40) { outb(0xA0, 0x20); // Slave EOI } diff --git a/src/arch/x86/interrupts.S b/src/arch/x86/interrupts.S index 7f99981..235e31c 100644 --- a/src/arch/x86/interrupts.S +++ b/src/arch/x86/interrupts.S @@ -130,3 +130,6 @@ IRQ 12, 44 IRQ 13, 45 IRQ 14, 46 IRQ 15, 47 + +/* Syscall vector (int 0x80 -> 128) */ +ISR_NOERRCODE 128 diff --git a/src/kernel/main.c b/src/kernel/main.c index 4d9dd9e..d418bac 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -14,6 +14,8 @@ #include "initrd.h" #include "fs.h" +#include "syscall.h" + /* Check if the compiler thinks we are targeting the wrong operating system. */ #if defined(__linux__) #error "You are not using a cross-compiler, you will run into trouble" @@ -58,6 +60,8 @@ void kernel_main(unsigned long magic, unsigned long addr) { // 5. Initialize Interrupts (x86) uart_print("[AdrOS] Initializing IDT...\n"); idt_init(); + + syscall_init(); // 6. Initialize Drivers keyboard_init(); diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c new file mode 100644 index 0000000..e42d4a3 --- /dev/null +++ b/src/kernel/syscall.c @@ -0,0 +1,34 @@ +#include "syscall.h" +#include "idt.h" +#include "uart_console.h" + +static void syscall_handler(struct registers* regs) { + uint32_t syscall_no = regs->eax; + + if (syscall_no == SYSCALL_WRITE) { + uint32_t fd = regs->ebx; + const char* buf = (const char*)regs->ecx; + uint32_t len = regs->edx; + + if (fd != 1 && fd != 2) { + regs->eax = (uint32_t)-1; + return; + } + + for (uint32_t i = 0; i < len; i++) { + char c = buf[i]; + uart_put_char(c); + } + + regs->eax = len; + return; + } + + regs->eax = (uint32_t)-1; +} + +void syscall_init(void) { +#if defined(__i386__) + register_interrupt_handler(128, syscall_handler); +#endif +} -- 2.43.0