From b77c53ae99a888371230429f174ce739db7b0366 Mon Sep 17 00:00:00 2001 From: xamidev Date: Wed, 18 Mar 2026 13:07:26 +0100 Subject: [PATCH 1/5] Keyboard buffer + getline --- docs/MANUAL.md | 27 +++++++++++++-- include/config.h | 3 ++ include/io/kbd/ps2.h | 5 +++ src/idt/idt.c | 2 +- src/io/kbd/ps2.c | 80 +++++++++++++++++++++++++++++++++++++++++++ src/kmain.c | 12 +++++-- src/sched/scheduler.c | 4 +-- 7 files changed, 125 insertions(+), 8 deletions(-) diff --git a/docs/MANUAL.md b/docs/MANUAL.md index 34195e4..35ac2c5 100644 --- a/docs/MANUAL.md +++ b/docs/MANUAL.md @@ -2,9 +2,30 @@ # Table of Contents -- nothing (yet). +- [Overview](#i-overview) + - [Supported Hardware](#a-supported-hardware) + - [Features](#b-features) +- [Kernel architecture](#ii-kernel-architecture) + - [Boot process](#a-boot-process) + - [Memory management](#b-memory-management) + - [Scheduling](#c-scheduling) + - [Input/output](#d-inputoutput) +- [Syscall table](#iii-syscall-table) -## I. Kernel architecture +## I. Overview + +## a. Supported Hardware + +The recommended hardware to run PepperOS is the following: + +- UEFI/BIOS +- Any x86 processor, 64-bits only +- PS/2 Keyboard +- Minimum 128MB of memory + +## b. Features + +## II. Kernel architecture ### a. Boot process @@ -14,6 +35,6 @@ ### d. Input/Output -## II. Syscall table +## III. Syscall table Not yet implemented. \ No newline at end of file diff --git a/include/config.h b/include/config.h index 8cab072..5c3dbc5 100644 --- a/include/config.h +++ b/include/config.h @@ -39,6 +39,9 @@ /* term */ #define TERM_HISTORY_MAX_LINES 256 +/* kbd */ +#define KBD_BUFFER_MAX 256 + /* time */ #define TIMER_FREQUENCY 1000 diff --git a/include/io/kbd/ps2.h b/include/io/kbd/ps2.h index c9aed30..55c12b5 100644 --- a/include/io/kbd/ps2.h +++ b/include/io/kbd/ps2.h @@ -7,7 +7,12 @@ #ifndef PS2_H #define PS2_H +#include + void keyboard_handler(void); +char keyboard_getchar(); +int keyboard_putchar(char c); +int keyboard_getline(char* output, size_t size); #define SHIFT_PRESSED_BIT 0b00000001 #define ALT_PRESSED_BIT 0b00000010 diff --git a/src/idt/idt.c b/src/idt/idt.c index 51b0eca..c101d05 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -258,7 +258,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) case 33: // Keyboard Interrupt keyboard_handler(); - process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG + //process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG outb(0x20, 0x20); break; diff --git a/src/io/kbd/ps2.c b/src/io/kbd/ps2.c index e47d8a8..d36403a 100644 --- a/src/io/kbd/ps2.c +++ b/src/io/kbd/ps2.c @@ -4,6 +4,7 @@ * @license GPL-3.0-only */ +#include "config.h" #include #include #include @@ -18,6 +19,11 @@ uint8_t key_status = 0b00000000; unsigned char* keymap; unsigned char* keymap_shifted; +// Keyboard buffer +char keyboard_buffer[KBD_BUFFER_MAX] = {0}; +int write_index = 0; +int read_index = 0; + extern struct init_status init; unsigned char kbdus[128] = @@ -214,6 +220,7 @@ void keyboard_handler() } // Should probably have a keyboard buffer here... instead of this _putchar(c); + keyboard_putchar(c); } } } @@ -221,6 +228,79 @@ void keyboard_handler() } } +/* + * keyboard_getchar - Get a character from keyboard + * + * This function reads one character from the keyboard buffer. + * If the keyboard buffer is empty, it will block until a key + * is pressed. + * + * Return: + * - character from keyboard buffer + */ +char keyboard_getchar() +{ + while (read_index == write_index); // Empty buffer + + char c = keyboard_buffer[read_index]; + read_index = (read_index+1) % KBD_BUFFER_MAX; + return c; +} + +/* + * keyboard_putchar - Puts a character in the keyboard buffer + * @c: character to add + * + * This function is used in the keyboard handler to add new + * characters to the keyboard buffer. + * + * Return: + * %-1 - keyboard buffer is full + * %0 - operation completed successfully + */ +int keyboard_putchar(char c) +{ + if ((write_index+1) % KBD_BUFFER_MAX == read_index) { + // Full buffer + return -1; + } + + keyboard_buffer[write_index] = c; + write_index = (write_index+1) % KBD_BUFFER_MAX; + return 0; +} + +/* + * keyboard_getline - Gets a line of input from keyboard + * @output: Output string + * @size: Size of output string + * + * Read a line of characters from the keyboard, until the + * buffer fills or a newline character is read. + * The output string is NULL-terminated. + * + * Return: + * - the number of characters read + */ +int keyboard_getline(char* output, size_t size) +{ + char c; + size_t index = 0; + + // Read until Enter is pressed + while ((c = keyboard_getchar()) != 0x0A) { + if (index == size-1) { + output[index] = c; + output[index+1] = '\0'; + return index; + } + output[index] = c; + index++; + } + output[index+1] = '\0'; + return index; +} + /* * keyboard_init - Keyboard initialization * @layout: Desired layout diff --git a/src/kmain.c b/src/kmain.c index 37daa7f..139a515 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -68,7 +68,7 @@ struct process_t* idle_proc; // Never gets executed although pedicel is scheduled? void pedicel_main(void* arg) { - printf("\n\nWelcome to PepperOS! Pedicel speaking.\r\nNothing left to do, let's go idle!"); + printf("\n\nWelcome to PepperOS! Pedicel speaking.\r\nNothing left to do, let's go idle!\r\n"); } void idle_main(void* arg) @@ -78,6 +78,14 @@ void idle_main(void* arg) } } +void thing_main(void* arg) +{ + printf("What's your name, pal? "); + char name[10]; + keyboard_getline(name, 10); + printf("\r\n{%s} is such a nice name!\r\n", name); +} + extern uintptr_t kheap_start; /* @@ -118,7 +126,7 @@ void kmain() process_init(); idle_proc = process_create("idle", (void*)idle_main, 0); struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0); - + process_create("thing", thing_main, NULL); process_display_list(processes_list); scheduler_init(); diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index 932bcf2..3e98632 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -69,10 +69,10 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) } } - DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); + //DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table)); - DEBUG("Loaded process PML4 into CR3"); + //DEBUG("Loaded process PML4 into CR3"); return current_process->context; } \ No newline at end of file -- 2.49.1 From 6a82d581fb03c2788c7d960245c778a62268d05d Mon Sep 17 00:00:00 2001 From: xamidev Date: Thu, 19 Mar 2026 16:54:23 +0100 Subject: [PATCH 2/5] Fix PMM for real HW + serial lock --- include/config.h | 2 +- src/debug/panic.c | 21 --------------------- src/idt/idt.c | 2 +- src/io/serial/serial.c | 16 +++++++++++++--- src/io/term/term.c | 2 +- src/kmain.c | 5 +++-- src/mem/paging.c | 4 ++-- src/mem/pmm.c | 41 ++++++++++++++++++++++++++++------------- src/sched/scheduler.c | 4 +++- 9 files changed, 52 insertions(+), 45 deletions(-) diff --git a/include/config.h b/include/config.h index 5c3dbc5..0231bf0 100644 --- a/include/config.h +++ b/include/config.h @@ -31,7 +31,7 @@ #define KERNEL_IDT_ENTRIES 33 /* paging */ -#define PAGING_MAX_PHYS 0x100000000 +#define PAGING_MAX_PHYS 0x200000000 /* heap */ #define KHEAP_SIZE (32*1024*1024) diff --git a/src/debug/panic.c b/src/debug/panic.c index 5fc2069..0e91c35 100644 --- a/src/debug/panic.c +++ b/src/debug/panic.c @@ -36,27 +36,6 @@ void read_rflags(uint64_t rflags) CHECK_BIT(rflags, 19) ? "VIF " : "", /*virtual interrupt flag*/ CHECK_BIT(rflags, 20) ? "VIP " : "", /*virtual interrupt pending*/ CHECK_BIT(rflags, 21) ? "ID " : ""); /*id flag*/ - - if (init.terminal) { - printf("\x1b[38;5;226m%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1b[38;5;231m\r\n", - CHECK_BIT(rflags, 0) ? "CF " : "", - CHECK_BIT(rflags, 2) ? "PF " : "", - CHECK_BIT(rflags, 4) ? "AF " : "", - CHECK_BIT(rflags, 6) ? "ZF " : "", - CHECK_BIT(rflags, 7) ? "SF " : "", - CHECK_BIT(rflags, 8) ? "TF " : "", - CHECK_BIT(rflags, 9) ? "IF " : "", - CHECK_BIT(rflags, 10) ? "DF " : "", - CHECK_BIT(rflags, 11) ? "OF " : "", - (CHECK_BIT(rflags, 12) && CHECK_BIT(rflags, 13)) ? "IOPL3 " : "IOPL0 ", - CHECK_BIT(rflags, 14) ? "NT " : "", - CHECK_BIT(rflags, 16) ? "RF " : "", - CHECK_BIT(rflags, 17) ? "VM " : "", - CHECK_BIT(rflags, 18) ? "AC " : "", - CHECK_BIT(rflags, 19) ? "VIF " : "", - CHECK_BIT(rflags, 20) ? "VIP " : "", - CHECK_BIT(rflags, 21) ? "ID " : ""); - } } /* diff --git a/src/idt/idt.c b/src/idt/idt.c index c101d05..51b0eca 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -258,7 +258,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) case 33: // Keyboard Interrupt keyboard_handler(); - //process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG + process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG outb(0x20, 0x20); break; diff --git a/src/io/serial/serial.c b/src/io/serial/serial.c index 95ea78f..f36a450 100644 --- a/src/io/serial/serial.c +++ b/src/io/serial/serial.c @@ -6,9 +6,13 @@ #include #include +#include extern struct init_status init; +extern int panic_count; +struct spinlock_t serial_lock = {0}; + /* * outb - Writes a byte to a CPU port * @port: CPU port to write to @@ -85,9 +89,15 @@ static int is_transmit_empty() */ void skputc(char c) { - // TODO: Spinlock here (serial access) - while (!is_transmit_empty()); // wait for free spot - outb(PORT, c); + if (panic_count == 0) { + spinlock_acquire(&serial_lock); + while (!is_transmit_empty()); // wait for free spot + outb(PORT, c); + spinlock_release(&serial_lock); + } else { + while (!is_transmit_empty()); + outb(PORT, c); + } } /* diff --git a/src/io/term/term.c b/src/io/term/term.c index 785151d..31f7b18 100644 --- a/src/io/term/term.c +++ b/src/io/term/term.c @@ -113,7 +113,7 @@ extern struct flanterm_context* ft_ctx; extern struct boot_context boot_ctx; /* - * flanterm_free_wrapper - free() wrapper for Flanterm + * flanterm_free_wrapper - free() wrapper for Flanterm (DEPRECATED) * @ptr: pointer to free * @size: amount of bytes to free * diff --git a/src/kmain.c b/src/kmain.c index 139a515..2926773 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -80,10 +80,11 @@ void idle_main(void* arg) void thing_main(void* arg) { - printf("What's your name, pal? "); +/* printf("What's your name, pal? "); char name[10]; keyboard_getline(name, 10); - printf("\r\n{%s} is such a nice name!\r\n", name); + printf("\r\n{%s} is such a nice name!\r\n", name); */ + while (ticks < 500); } extern uintptr_t kheap_start; diff --git a/src/mem/paging.c b/src/mem/paging.c index b1de8a5..ae75bb4 100644 --- a/src/mem/paging.c +++ b/src/mem/paging.c @@ -173,9 +173,9 @@ void paging_init(struct boot_context boot_ctx) } } - // 4GB + // 8GB if (max_phys > PAGING_MAX_PHYS) { - DEBUG("WARNING: max_phys capped to 4GB (%x) (from max_phys=%p)", PAGING_MAX_PHYS, max_phys); + DEBUG("WARNING: max_phys capped to PAGING_MAX_PHYS (from max_phys=%p)", max_phys); max_phys = PAGING_MAX_PHYS; } diff --git a/src/mem/pmm.c b/src/mem/pmm.c index 81f7cfd..564837c 100644 --- a/src/mem/pmm.c +++ b/src/mem/pmm.c @@ -11,6 +11,7 @@ it will probably need to get some info from Limine, to see which pages are used by kernel/bootloader/mmio/fb etc. */ +#include "config.h" #include #include #include @@ -24,10 +25,11 @@ First we'll have to discover the physical memory layout, and for that we can use a Limine request. */ +// DEPRECATED struct limine_memmap_entry* biggest_entry; /* - * pmm_find_biggest_usable_region - Finding the biggest free memory region + * pmm_find_biggest_usable_region - Finding the biggest free memory region (DEPRECATED) * @memmap: Limine memory map * @hhdm: Limine HHDM offset * @@ -99,19 +101,32 @@ void pmm_free(uintptr_t addr) * This function marks the biggest memory region as * free, so we can use it in pmm_alloc. */ -static void pmm_init_freelist() +static void pmm_init_freelist(struct limine_memmap_response* memmap) { - // We simply call pmm_free() on each page that is marked USABLE - // in our big memory region. - uint64_t base = ALIGN_UP(biggest_entry->base, PAGE_SIZE); - uint64_t end = ALIGN_DOWN(biggest_entry->base + biggest_entry->length, PAGE_SIZE); + uint64_t total_pages = 0; - uint64_t page_count=0; - for (uint64_t addr = base; addr < end; addr += PAGE_SIZE) { - pmm_free(addr); - page_count++; + for (size_t i=0; ientry_count; i++) { + struct limine_memmap_entry* entry = memmap->entries[i]; + + if (entry->type == LIMINE_MEMMAP_USABLE) { + uint64_t base = ALIGN_UP(entry->base, PAGE_SIZE); + uint64_t end = ALIGN_DOWN(entry->base + entry->length, PAGE_SIZE); + + if (end > PAGING_MAX_PHYS) { + end = PAGING_MAX_PHYS; + } + + // Region above PAGING_MAX_PHYS + if (base >= end) continue; + + for (uint64_t addr = base; addr < end; addr += PAGE_SIZE) { + pmm_free(addr); + total_pages++; + } + } } - DEBUG("%u frames in freelist, available for use (%u bytes)", page_count, page_count*PAGE_SIZE); + + DEBUG("%u frames in freelist, %u bytes available (%u MB)", total_pages, total_pages*PAGE_SIZE, total_pages*PAGE_SIZE/1000000); } /* @@ -124,9 +139,9 @@ static void pmm_init_freelist() void pmm_init(struct boot_context boot_ctx) { hhdm_off = boot_ctx.hhdm->offset; - pmm_find_biggest_usable_region(boot_ctx.mmap, boot_ctx.hhdm); + //pmm_find_biggest_usable_region(boot_ctx.mmap, boot_ctx.hhdm); // Now we have biggest USABLE region, // so to populate the free list we just iterate through it - pmm_init_freelist(); + pmm_init_freelist(boot_ctx.mmap); } diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index 3e98632..a03e314 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -49,7 +49,6 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) } current_process->context = context; - //current_process->status = READY; for (;;) { struct process_t* prev_process = current_process; @@ -65,6 +64,9 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) return idle_proc->context; } else { current_process->status = RUNNING; + if (prev_process != current_process) { + DEBUG("Changed from {pid=%u, name=%s} to {pid=%u, name=%s}", prev_process->pid, prev_process->name, current_process->pid, current_process->name); + } break; } } -- 2.49.1 From 424b4c46323f5aa637ddc495715f8fdca7fecf6b Mon Sep 17 00:00:00 2001 From: xamidev Date: Thu, 19 Mar 2026 19:34:31 +0100 Subject: [PATCH 3/5] Use MSR to map framebuffer as WC (write-combining) = huge speed diff on real HW --- include/arch/x86.h | 13 +++++++++ src/arch/x86/cpuid.c | 20 ++++++++++++++ src/arch/x86/init.c | 28 +++++++++++++++++++ src/arch/x86/msr.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ src/kmain.c | 4 +++ src/mem/paging.c | 4 +-- 6 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 include/arch/x86.h create mode 100644 src/arch/x86/cpuid.c create mode 100644 src/arch/x86/init.c create mode 100644 src/arch/x86/msr.c diff --git a/include/arch/x86.h b/include/arch/x86.h new file mode 100644 index 0000000..9521859 --- /dev/null +++ b/include/arch/x86.h @@ -0,0 +1,13 @@ +#ifndef X86_H +#define X86_H + +#include +#include + +uint64_t rdmsr(uint32_t msr); +void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); +void wrmsr(uint32_t msr, uint64_t value); +bool x86_has_msr(); +void x86_arch_init(); + +#endif \ No newline at end of file diff --git a/src/arch/x86/cpuid.c b/src/arch/x86/cpuid.c new file mode 100644 index 0000000..2d96368 --- /dev/null +++ b/src/arch/x86/cpuid.c @@ -0,0 +1,20 @@ +/* + * @author xamidev + * @brief x86 CPU identification + * @license GPL-3.0-only + */ + +#include + +/* + * cpuid - Wrapper for CPUID instruction + * @leaf: Requested leaf + * @eax: EAX register value + * @ebx: EBX register value + * @ecx: ECX register value + * @edx: EDX register value +*/ +void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) +{ + __asm__ volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf)); +} \ No newline at end of file diff --git a/src/arch/x86/init.c b/src/arch/x86/init.c new file mode 100644 index 0000000..0a97bff --- /dev/null +++ b/src/arch/x86/init.c @@ -0,0 +1,28 @@ +/* + * @author xamidev + * @brief x86 architecture-dependant initialization + * @license GPL-3.0-only + */ + +#include +#include +#include + +/* + * x86_arch_init - Initialize x86 CPU structures + * + * This function is responsible for overriding a PAT entry + * (to put the framebuffer area in WC mode) only. + * + * Later, all architecture-dependant init (GDT, IDT, TSS, ...) + * should be initialized here, and separate function pointers + * should be set up for each arch. + */ +void x86_arch_init() +{ + uint64_t pat = rdmsr(0x277); + pat &= ~(0xFFULL << 8); // Clear PAT1 + pat |= (0x01ULL << 8); // PAT1 = 0x01 (WC) + wrmsr(0x277, pat); + DEBUG("Overrode PAT1 entry to set up Write-Combining"); +} \ No newline at end of file diff --git a/src/arch/x86/msr.c b/src/arch/x86/msr.c new file mode 100644 index 0000000..276239c --- /dev/null +++ b/src/arch/x86/msr.c @@ -0,0 +1,66 @@ +/* + * @author xamidev + * @brief x86 MSR C wrappers + * @description + * Wrapper functions to access Model Specific Registers + * + * @license GPL-3.0-only + */ + +#include +#include +#include + +/* + * rdmsr - Read from MSR + * @msr: model specific register number + * + * Read a 64-bit word from a Model Specific Register. + * Wrapper for the "rdmsr" instruction. It originally + * outputs to two 32-bit registers (EDX:EAX), so the + * function does the job of uniting them as a 64-bit + * value for us. + * + * Return: + * - value read from MSR + */ +uint64_t rdmsr(uint32_t msr) +{ + uint32_t low; + uint32_t high; + + __asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr)); + + return ((uint64_t)high << 32) | low; +} + +/* + * wrmsr - Write to MSR + * @msr: model specific register number + * + * Write a 64-bit value to a Model Specific Register. + */ +void wrmsr(uint32_t msr, uint64_t value) +{ + uint32_t low = (uint32_t)(value & 0xFFFFFFFF); + uint32_t high = (uint32_t)(value >> 32); + + __asm__ volatile("wrmsr" : : "c"(msr), "a"(low), "d"(high) : "memory"); +} + +/* + * x86_has_msr - Test for MSR support + * + * Checks if CPU supports Model Specific Registers + * using CPUID.01h:EDX[bit 5]. + * + * Return: + * true - MSR are supported + * false - MSR are not supported + */ +bool x86_has_msr() +{ + uint32_t eax, ebx, ecx, edx; + cpuid(1, &eax, &ebx, &ecx, &edx); + return (edx & (1 << 5)) != 0; +} \ No newline at end of file diff --git a/src/kmain.c b/src/kmain.c index 2926773..d4d3ea0 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -4,6 +4,7 @@ * @license GPL-3.0-only */ +#include "arch/x86.h" #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include // Limine version used __attribute__((used, section(".limine_requests"))) @@ -112,6 +114,8 @@ void kmain() serial_init(); timer_init(); + x86_arch_init(); + boot_mem_display(); pmm_init(boot_ctx); diff --git a/src/mem/paging.c b/src/mem/paging.c index ae75bb4..44290ea 100644 --- a/src/mem/paging.c +++ b/src/mem/paging.c @@ -202,9 +202,9 @@ void paging_init(struct boot_context boot_ctx) uint64_t fb_size = fb->pitch * fb->height; uint64_t fb_pages = (fb_size + PAGE_SIZE-1)/PAGE_SIZE; - // Map the framebuffer (with cache-disable & write-through) + // Map the framebuffer (PWT set, and no PCD means PAT1 [Write-Combining] for this region) for (uint64_t i=0; i Date: Fri, 20 Mar 2026 09:01:57 +0100 Subject: [PATCH 4/5] printf spinlock + remove DEPRECATED stuff + begin separating x86 stuff --- Makefile | 4 +-- include/arch/x86.h | 49 ++++++++++++++++++++++++++++++ include/idt/idt.h | 59 ------------------------------------- include/io/term/term.h | 2 +- include/kernel.h | 2 +- src/{idt => arch/x86}/idt.S | 0 src/{idt => arch/x86}/idt.c | 2 +- src/debug/panic.c | 2 +- src/io/kbd/ps2.c | 6 ++-- src/io/term/term.c | 51 ++++++++++++-------------------- src/kmain.c | 1 - src/mem/pmm.c | 37 ----------------------- 12 files changed, 77 insertions(+), 138 deletions(-) delete mode 100644 include/idt/idt.h rename src/{idt => arch/x86}/idt.S (100%) rename src/{idt => arch/x86}/idt.c (99%) diff --git a/Makefile b/Makefile index c6d91ed..b2499c8 100644 --- a/Makefile +++ b/Makefile @@ -12,13 +12,13 @@ CC_PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable LD := x86_64-elf-ld $(ELFFILE): $(BUILDDIR) $(OBJFILES) - nasm -f elf64 src/idt/idt.S -o $(BUILDDIR)/idt_stub.o + nasm -f elf64 src/arch/x86/idt.S -o $(BUILDDIR)/idt_stub.o $(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o # Get the symbols for debugging nm -n $(ELFFILE) | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map python3 symbols.py nasm -f elf64 symbols.S -o $(BUILDDIR)/symbols.o - $(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o + $(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o $(BUILDDIR)/symbols.o $(BUILDDIR): @mkdir -p $(BUILDDIR) diff --git a/include/arch/x86.h b/include/arch/x86.h index 9521859..1c677d8 100644 --- a/include/arch/x86.h +++ b/include/arch/x86.h @@ -10,4 +10,53 @@ void wrmsr(uint32_t msr, uint64_t value); bool x86_has_msr(); void x86_arch_init(); +/* Interrupt Descriptor Table */ + +void idt_init(void); + +struct interrupt_descriptor { + uint16_t address_low; + uint16_t selector; + uint8_t ist; + uint8_t flags; + uint16_t address_mid; + uint32_t address_high; + uint32_t reserved; +} __attribute__((packed)); + +struct idtr { + uint16_t limit; + uint64_t base; +} __attribute__((packed)); + +// All general-purpose registers (except rsp) as stored on the stack, +// plus the values we pushed (vector number, error code) and the iret frame +// In reverse order because the stack grows downwards. +struct cpu_status_t { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rbp; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; + + uint64_t vector_number; + uint64_t error_code; + + uint64_t iret_rip; + uint64_t iret_cs; + uint64_t iret_flags; + uint64_t iret_rsp; + uint64_t iret_ss; +}; + #endif \ No newline at end of file diff --git a/include/idt/idt.h b/include/idt/idt.h deleted file mode 100644 index b74fb56..0000000 --- a/include/idt/idt.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * @author xamidev - * @brief Interrupt Descriptor Table setup and dispatching - * @license GPL-3.0-only - */ - -#ifndef IDT_H -#define IDT_H - -#include - -void idt_init(void); - -struct interrupt_descriptor { - uint16_t address_low; - uint16_t selector; - uint8_t ist; - uint8_t flags; - uint16_t address_mid; - uint32_t address_high; - uint32_t reserved; -} __attribute__((packed)); - -struct idtr { - uint16_t limit; - uint64_t base; -} __attribute__((packed)); - -// All general-purpose registers (except rsp) as stored on the stack, -// plus the values we pushed (vector number, error code) and the iret frame -// In reverse order because the stack grows downwards. -struct cpu_status_t { - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rbp; - uint64_t rdi; - uint64_t rsi; - uint64_t rdx; - uint64_t rcx; - uint64_t rbx; - uint64_t rax; - - uint64_t vector_number; - uint64_t error_code; - - uint64_t iret_rip; - uint64_t iret_cs; - uint64_t iret_flags; - uint64_t iret_rsp; - uint64_t iret_ss; -}; - -#endif \ No newline at end of file diff --git a/include/io/term/term.h b/include/io/term/term.h index 3ce0722..4ce1a32 100644 --- a/include/io/term/term.h +++ b/include/io/term/term.h @@ -8,8 +8,8 @@ #define TERM_H void kputs(const char* str); -void _putchar(char character); void term_init(void); int printf(const char* fmt, ...); +void internal_putc(int c, void *_); #endif diff --git a/include/kernel.h b/include/kernel.h index 58784aa..98b43ac 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -17,7 +17,7 @@ enum ErrorCodes { #include #include -#include +#include #include extern volatile uint64_t ticks; diff --git a/src/idt/idt.S b/src/arch/x86/idt.S similarity index 100% rename from src/idt/idt.S rename to src/arch/x86/idt.S diff --git a/src/idt/idt.c b/src/arch/x86/idt.c similarity index 99% rename from src/idt/idt.c rename to src/arch/x86/idt.c index 51b0eca..822033c 100644 --- a/src/idt/idt.c +++ b/src/arch/x86/idt.c @@ -4,7 +4,7 @@ * @license GPL-3.0-only */ -#include +#include #include #include #include diff --git a/src/debug/panic.c b/src/debug/panic.c index 0e91c35..22ff590 100644 --- a/src/debug/panic.c +++ b/src/debug/panic.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include diff --git a/src/io/kbd/ps2.c b/src/io/kbd/ps2.c index d36403a..aea8c13 100644 --- a/src/io/kbd/ps2.c +++ b/src/io/kbd/ps2.c @@ -216,10 +216,10 @@ void keyboard_handler() if (c) { if (c == '\n') { - _putchar('\r'); + internal_putc('\r', NULL); } - // Should probably have a keyboard buffer here... instead of this - _putchar(c); + + internal_putc(c, NULL); keyboard_putchar(c); } } diff --git a/src/io/term/term.c b/src/io/term/term.c index 31f7b18..65b11a1 100644 --- a/src/io/term/term.c +++ b/src/io/term/term.c @@ -30,19 +30,10 @@ extern struct flanterm_context* ft_ctx; extern struct init_status init; struct spinlock_t term_lock = {0}; +struct spinlock_t printf_lock = {0}; extern int panic_count; -/* - * _putchar - Writes a character to terminal (DEPRECATED) - * @character: character to write - */ -void _putchar(char character) -{ - // TODO: Spinlock here (terminal access) - flanterm_write(ft_ctx, &character, 1); -} - /* * internal_putc - Internal putchar function * @c: char to print @@ -83,14 +74,26 @@ void internal_putc(int c, void *_) * * Return: * - number of characters sent to the callback + * %-1 - error */ int printf(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - int ret = npf_vpprintf(internal_putc, NULL, fmt, args); - va_end(args); - return ret; + if (panic_count == 0) { + spinlock_acquire(&printf_lock); + va_list args; + va_start(args, fmt); + int ret = npf_vpprintf(internal_putc, NULL, fmt, args); + va_end(args); + spinlock_release(&printf_lock); + return ret; + } else { + va_list args; + va_start(args, fmt); + int ret = npf_vpprintf(internal_putc, NULL, fmt, args); + va_end(args); + return ret; + } + return -1; } /* @@ -103,30 +106,14 @@ void kputs(const char* str) { size_t i=0; while (str[i] != 0) { - _putchar(str[i]); + internal_putc(str[i], NULL); i++; } - _putchar('\r'); } extern struct flanterm_context* ft_ctx; extern struct boot_context boot_ctx; -/* - * flanterm_free_wrapper - free() wrapper for Flanterm (DEPRECATED) - * @ptr: pointer to free - * @size: amount of bytes to free - * - * This function exists solely because the Flanterm initialization - * function only accepts a free() function with a size parameter, - * and the default one doesn't have it. - */ -void flanterm_free_wrapper(void* ptr, size_t size) -{ - (void)size; - kfree(ptr); -} - /* * term_init - Video output/terminal initialization * diff --git a/src/kmain.c b/src/kmain.c index d4d3ea0..56aca6f 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include