From b6ee4fc3de326f1f6be2e9baab4bca141a9bfa88 Mon Sep 17 00:00:00 2001 From: slinky55 Date: Wed, 1 Jul 2026 20:00:22 -0500 Subject: [PATCH] more userspace stuff --- deploy_programs.sh | 21 +++++++++++++++ kernel/common.S | 23 +++++++++-------- kernel/common.h | 2 ++ kernel/drivers/pic/pic.S | 4 +-- kernel/gdt.h | 1 + kernel/interrupts.c | 8 +++++- kernel/kmain.c | 43 +++++++++++++++++++++---------- kernel/lib/memory.c | 4 +++ kernel/lib/memory.h | 2 +- kernel/memory/mm.c | 3 +++ kernel/process.h | 10 ++++++-- kernel/scheduler.S | 4 +-- kernel/scheduler.c | 28 ++++++++++++++------ kernel/scheduler.h | 2 +- kernel/syscall.S | 48 +++++++++++++++++------------------ kernel/syscall.c | 4 ++- programs/crt0.S | 25 ++++++++---------- programs/crt0.s | 28 -------------------- programs/main.c | 6 ++--- programs/makefile | 4 +-- rocklibc/src/rockos/syscall.c | 12 ++++----- 21 files changed, 161 insertions(+), 121 deletions(-) create mode 100755 deploy_programs.sh delete mode 100644 programs/crt0.s diff --git a/deploy_programs.sh b/deploy_programs.sh new file mode 100755 index 0000000..f970e8e --- /dev/null +++ b/deploy_programs.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +cd rocklibc +make clean +make +cd .. + +cd programs +make clean +make +cd .. + +make clean +make + +cd initrd +./make_img.sh +cd .. + +make -B + diff --git a/kernel/common.S b/kernel/common.S index 2b1b563..31f5c73 100644 --- a/kernel/common.S +++ b/kernel/common.S @@ -20,8 +20,8 @@ io_wait: liftoff: cli - mov 4(%esp), %ecx - mov 8(%esp), %ebx + mov 4(%esp), %ecx + mov 8(%esp), %ebx mov $0x23, %ax mov %ax, %ds @@ -29,15 +29,20 @@ liftoff: mov %ax, %fs mov %ax, %gs - push $0x23 - push %ebx - push $0x202 - push $0x1B - push %ecx + pushl $0x23 # User Data Segment (SS) + pushl %ebx # User Stack Pointer (ESP) + pushl $0x202 # EFLAGS (Interrupts enabled, bit 1 standard) + pushl $0x1B # User Code Segment (CS) + pushl %ecx # User Entry Point (EIP) xor %eax, %eax + xor %ebx, %ebx + xor %ecx, %ecx xor %edx, %edx - + xor %esi, %esi + xor %edi, %edi + xor %ebp, %ebp + iret .global outb @@ -121,5 +126,3 @@ outsw: fetch_cr3: mov %cr3, %eax ret - -.global set_cr3 diff --git a/kernel/common.h b/kernel/common.h index b7c189a..0cd97ab 100644 --- a/kernel/common.h +++ b/kernel/common.h @@ -7,4 +7,6 @@ void enable_interrupts(); void disable_interrupts(); uint32_t fetch_cr3(); +void liftoff(uint32_t entry_point, uint32_t user_stack) __attribute__((noreturn)); + #endif \ No newline at end of file diff --git a/kernel/drivers/pic/pic.S b/kernel/drivers/pic/pic.S index 0719097..da5fff6 100644 --- a/kernel/drivers/pic/pic.S +++ b/kernel/drivers/pic/pic.S @@ -33,9 +33,9 @@ init_pic: outb %al, $PIC2_DATA # mask - mov $0xF8, %al + mov $0xFF, %al outb %al, $PIC1_DATA - mov $0x3F, %al + mov $0xFF, %al outb %al, $PIC2_DATA ret diff --git a/kernel/gdt.h b/kernel/gdt.h index 43104cf..f4338bb 100644 --- a/kernel/gdt.h +++ b/kernel/gdt.h @@ -34,6 +34,7 @@ typedef struct __attribute__((packed)) { } tss_entry_t; void init_gdt(); +void tss_flush(); extern tss_entry_t tss; diff --git a/kernel/interrupts.c b/kernel/interrupts.c index f9838c1..d53e868 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -110,7 +110,7 @@ void common_interrupt_handler(registers *args) { case 13: case 15: case 16: - kprintf("CPU Error: %s", err_messages[args->int_no]); + kprintf("CPU Error: %s, %d\n", err_messages[args->int_no], args->error_code); break; case 14:{ uint32_t faulting_address; @@ -119,6 +119,9 @@ void common_interrupt_handler(registers *args) { kprintf("Faulted Virtual Address: 0x%x\n", faulting_address); kprintf("Error Code: 0x%x\n", args->error_code); kprintf("Instruction Pointer: 0x%x\n", args->eip); + kprintf("Stack Pointer: 0x%x\n", args->useresp); + kprintf("EAX: 0x%x\n", args->eax); + kprintf("EFLAGS: 0x%x\n", args->eflags); kprintf("Caused by: %s, %s, running in %s mode\n", (args->error_code & 0x01) ? "Protection Violation" : "Page Not Present", (args->error_code & 0x02) ? "Write" : "Read", @@ -127,15 +130,18 @@ void common_interrupt_handler(registers *args) { break; } case 33: { + kprintf("ps2 keyboard interrupt\n"); uint8_t data = ps2_read_data(); send_eoi_master(); break; } case 46: { // IDE PRIMARY + kprintf("IDE PRIMARY interrupt\n"); send_eoi_slave(); break; } case 47: { // IDE SLAVE + kprintf("IDE SLAVE interrupt\n"); send_eoi_slave(); break; } diff --git a/kernel/kmain.c b/kernel/kmain.c index 1b714f7..e58f9ee 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -1,10 +1,11 @@ #include "multiboot.h" #include "interrupts.h" #include "gdt.h" -#include "scheduler.h" #include "common.h" +#include "scheduler.h" #include "vfs.h" #include "elf.h" +#include "gdt.h" #include #include @@ -26,6 +27,9 @@ extern char __kernel_start; extern char __kernel_end; +extern uint32_t page_directory[1024]; +void* kernel_cr3 = page_directory; + void parse_multiboot_modules(uint32_t mbi_vaddr) { // find where grub put the boot module containing initrd multiboot_info* mbi = (multiboot_info*)mbi_vaddr; @@ -52,7 +56,8 @@ vfs_node_t* load_initrd() { return cpio_read_fs(initrd_module->mod_start); } -void load_program(const char* path) { +void load_root_program(const char* path) { + uint32_t kernel_cr3 = fetch_cr3(); void* cr3 = create_task_pd(); load_pd(cr3); flush_tlb(); @@ -93,12 +98,12 @@ void load_program(const char* path) { for (uint32_t v = page_start; v < page_end; v += PAGE_SIZE) { void* phys_frame = p_alloc_frame(); - map_page(v, (uint32_t)phys_frame, 0x07); + map_page(v, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); } uint32_t data_ptr = ph->p_offset; fseek(fd, data_ptr); - read(fd, (void*)vstart, ph->p_memsz); + read(fd, (void*)vstart, ph->p_filesz); // 0 out bss if (ph->p_memsz > ph->p_filesz) { @@ -110,15 +115,24 @@ void load_program(const char* path) { ph_table_ptr += sizeof(elf_program_header_t); } - uint32_t esp = 0xBFFF0000; - void* pesp = p_alloc_frame(); - map_page(esp - PAGE_SIZE, (uint32_t)pesp, 0x07); + uint32_t stack_sz = PAGE_SIZE * 16; + uint32_t stack_top = 0xBFFF0000; + uint32_t stack_bottom = stack_top - stack_sz; + for (uint32_t vaddr = stack_bottom; vaddr < stack_top; vaddr += PAGE_SIZE) { + void* phys_frame = p_alloc_frame(); + map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); + } - create_task(e_hdr->e_entry, fetch_cr3(), 1); -} + uint32_t* u_esp = (uint32_t*)stack_top; + *(--u_esp) = 0; // envp = NULL + *(--u_esp) = 0; // argv = NULL + *(--u_esp) = 0; // argc = 0 -void start_origin() { - load_program("/origin.elf"); + create_task(e_hdr->e_entry, (uint32_t)cr3, 1, (uint32_t)u_esp); + load_pd((void*)kernel_cr3); + flush_tlb(); + + kprintf("task created for origin program %s\n", path); } void kmain(uint32_t magic, multiboot_info* mbi) { @@ -150,13 +164,14 @@ void kmain(uint32_t magic, multiboot_info* mbi) { if (!initrd_root) { kprintf("failed to load initrd\n"); } + mount(vfs_root, initrd_root); kprintf("initrd read, mounted @ /\n"); - disable_interrupts(); init_scheduler(); enable_interrupts(); - kprintf("loading user program\n"); - start_origin(); + kprintf("loading origin program\n"); + load_root_program("/origin.elf"); + yield(); } diff --git a/kernel/lib/memory.c b/kernel/lib/memory.c index 6fa9533..698e0eb 100644 --- a/kernel/lib/memory.c +++ b/kernel/lib/memory.c @@ -134,4 +134,8 @@ void* kalloc(size_t sz) { } return kalloc(sz); +} + +void kfree(void* ptr) { + } \ No newline at end of file diff --git a/kernel/lib/memory.h b/kernel/lib/memory.h index a8470fc..3e98ae8 100644 --- a/kernel/lib/memory.h +++ b/kernel/lib/memory.h @@ -14,6 +14,6 @@ char* strcpy(char* dest, const char* src); void kgrow(size_t pages); void* kalloc(size_t sz); - +void kfree(void* ptr); #endif \ No newline at end of file diff --git a/kernel/memory/mm.c b/kernel/memory/mm.c index 2d3c175..1b10b30 100644 --- a/kernel/memory/mm.c +++ b/kernel/memory/mm.c @@ -18,6 +18,9 @@ extern uint32_t page_directory[1024]; #define TEMP_MAPPING_VADDR 0xDFFF0000 +#define USR_PAGE 0x07 +#define SUP_PAGE 0x03 + static uint32_t max_address = 0; static uint32_t total_available_memory = 0; static uint8_t memory_bitmap[BITMAP_SIZE]; diff --git a/kernel/process.h b/kernel/process.h index 689f691..3dd028e 100644 --- a/kernel/process.h +++ b/kernel/process.h @@ -10,15 +10,21 @@ typedef enum { STATE_DEAD } process_state_t; +typedef enum { + PROCESS_FLAG_NONE = 0, + PROCESS_FLAG_KERNEL = 1 << 0, + PROCESS_FLAG_USER = 1 << 1 +} process_flags_t; + typedef struct { uint32_t pid; uint32_t esp; - uint32_t esp0; + uint32_t kstack_top; uint32_t cr3; process_state_t state; uint32_t sleep; - void* next; uint32_t heap_end; + uint32_t flags; } __attribute__((packed)) process_t; #endif \ No newline at end of file diff --git a/kernel/scheduler.S b/kernel/scheduler.S index fa526e0..83181d5 100644 --- a/kernel/scheduler.S +++ b/kernel/scheduler.S @@ -17,9 +17,7 @@ yield: # void yield() movl 0(%esp), %ebx # Get Return EIP movl %ebx, 4(%esp) # Move Return EIP over CS addl $4, %esp # Adjust stack pointer up. - - # the stack now looks like a hardware interrupt just happened, even though we never called one. - + pushal pushl %esp diff --git a/kernel/scheduler.c b/kernel/scheduler.c index ef70e01..021e58a 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -69,7 +70,9 @@ uint32_t switch_context(uint32_t current_esp) { current_process = next_process; - tss.esp0 = process_table[current_process].esp0; + if (process_table[current_process].flags & PROCESS_FLAG_USER ) { + tss.esp0 = process_table[current_process].kstack_top; + } if (fetch_cr3() != process_table[current_process].cr3) { load_pd((void*)process_table[current_process].cr3); @@ -88,14 +91,15 @@ void init_scheduler() { process->cr3 = fetch_cr3(); process->state = STATE_READY; process->sleep = 0; + process->flags = PROCESS_FLAG_KERNEL; total_processes++; - create_task((uint32_t)idle_task, fetch_cr3(), 0); + create_task((uint32_t)idle_task, fetch_cr3(), 0, 0); current_process = 0; } -int create_task(uint32_t entry_point, uint32_t cr3, int user) { +int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp) { if (total_processes >= 16) { return 0; } @@ -103,12 +107,14 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user) { lock_scheduler(); // default to a new task, but if we find a dead one, re use it + int reuse = 0; process_t* process = &process_table[total_processes]; uint32_t pid = total_processes; for (uint32_t i = 0; i < total_processes; i++) { if (process_table[i].state == STATE_DEAD) { process = &process_table[i]; pid = i; + reuse = 1; } } @@ -116,22 +122,26 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user) { process->cr3 = cr3; process->state = STATE_READY; process->sleep = 0; + process->flags = user ? PROCESS_FLAG_USER : PROCESS_FLAG_KERNEL; - void* stack_bottom = kalloc(4096); - uint32_t* esp = (uint32_t*)((uint32_t)stack_bottom + 4096); - process->esp0 = (uint32_t)esp; + void* kstack_bottom = kalloc(PAGE_SIZE); + uint32_t kstack_top = (uint32_t)kstack_bottom + PAGE_SIZE; + process->kstack_top = kstack_top; + uint32_t* esp = (uint32_t*)kstack_top; if (user) { *(--esp) = 0x23; // User Data Segment (SS) with RPL 3 (0x20 | 3) - *(--esp) = 0xBFFFF000; // User Stack Pointer (ESP) - location mapped in user space + *(--esp) = u_esp; // User Stack Pointer (ESP) - location mapped in user space *(--esp) = 0x0202; // EFLAGS (Interrupts enabled) *(--esp) = 0x1B; // User Code Segment (CS) with RPL 3 (0x18 | 3) *(--esp) = entry_point; // EIP + *(--esp) = 0x23; } else { // IRET values for Ring 0 *(--esp) = 0x0202; // EFLAGS *(--esp) = 0x08; // Kernel Code Segment (CS) *(--esp) = entry_point; // EIP + *(--esp) = 0x10; } *(--esp) = 0; // EAX @@ -144,7 +154,9 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user) { *(--esp) = 0; // EDI process->esp = (uint32_t)esp; - total_processes++; + if (!reuse) { + total_processes++; + } unlock_scheduler(); return 1; } diff --git a/kernel/scheduler.h b/kernel/scheduler.h index 20616d0..63755fe 100644 --- a/kernel/scheduler.h +++ b/kernel/scheduler.h @@ -6,7 +6,7 @@ void init_scheduler(); -int create_task(uint32_t entry_point, uint32_t cr3, int user); +int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp); process_t* current_task(); void sleep(uint32_t ms); diff --git a/kernel/syscall.S b/kernel/syscall.S index 931e612..bd7e539 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -4,33 +4,33 @@ syscall_handler: cli - push $0 - push $0x80 + pushfl + pushl %cs - pusha + movl 8(%esp), %eax + pushl %eax + movl 4(%esp), %ebx # Get CS + movl %ebx, 8(%esp) # Move CS over Old EIP + movl 0(%esp), %ebx # Get Return EIP + movl %ebx, 4(%esp) # Move Return EIP over CS + addl $4, %esp # Adjust stack pointer - push %ds - push %es - push %fs - push %gs + movw %ds, %ax + pushl %eax - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs + pushal + + pushl %esp + call switch_context + movl %eax, %esp + + popal - push %esp - call syscall - add $4, %esp - - mov 28(%esp), %eax + popl %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs - pop %gs - pop %fs - pop %es - pop %ds - - popa - add $8, %esp + sti iret \ No newline at end of file diff --git a/kernel/syscall.c b/kernel/syscall.c index 84c5571..c3fb359 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -7,6 +7,8 @@ #include +#include + typedef struct registers { uint32_t gs, fs, es, ds; // Pushed manually uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha @@ -16,7 +18,7 @@ typedef struct registers { static int32_t sys_exit(int status) { - exit(); + asm volatile("hlt"); return 0; } diff --git a/programs/crt0.S b/programs/crt0.S index 5521689..655f862 100644 --- a/programs/crt0.S +++ b/programs/crt0.S @@ -1,24 +1,21 @@ .global _start -.intel_syntax noprefix .section .text _start: - xor ebp, ebp - push ebp - mov ebp, esp + xor %ebp, %ebp + push %ebp + mov %esp, %ebp - mov eax, [esp + 4] - lea ebx, [esp + 8] - lea ecx, [esp + 12] + mov (%esp), %eax + lea 4(%esp), %ebx + lea 8(%esp, %eax, 4), %ecx - push ecx - push ebx - push eax + push %ecx + push %ebx + push %eax call main - push eax + push %eax call exit - -1: hlt - jmp 1b \ No newline at end of file +1: jmp 1b diff --git a/programs/crt0.s b/programs/crt0.s deleted file mode 100644 index 8c72caa..0000000 --- a/programs/crt0.s +++ /dev/null @@ -1,28 +0,0 @@ -# 0 "crt0.S" -# 0 "" -# 0 "" -# 1 "crt0.S" -.global _start -.intel_syntax noprefix - -.section .text -_start: - xor ebp, ebp - push ebp - mov ebp, esp - - mov eax, [esp + 4] - lea ebx, [esp + 8] - lea ecx, [esp + 12] - - push ecx - push ebx - push eax - - call main - - push eax - call exit - -1: hlt - jmp 1b diff --git a/programs/main.c b/programs/main.c index 69d8084..a3d10c6 100644 --- a/programs/main.c +++ b/programs/main.c @@ -1,8 +1,6 @@ #include -#include -int main(int argc, char** argv) { - printf("Hello, World from RockOS!\n"); - +int main() { + printf("RockOS booting...\n"); return 0; } \ No newline at end of file diff --git a/programs/makefile b/programs/makefile index 9d074de..8bf6c96 100644 --- a/programs/makefile +++ b/programs/makefile @@ -8,8 +8,8 @@ TARGET = origin.elf all: $(TARGET) -crt0.o: crt0.s - $(CC) $(CFLAGS) -c crt0.s -o crt0.o +crt0.o: crt0.S + $(CC) $(CFLAGS) -c crt0.S -o crt0.o main.o: main.c $(CC) $(CFLAGS) -c main.c -o main.o diff --git a/rocklibc/src/rockos/syscall.c b/rocklibc/src/rockos/syscall.c index fa1b822..f318af0 100644 --- a/rocklibc/src/rockos/syscall.c +++ b/rocklibc/src/rockos/syscall.c @@ -1,5 +1,6 @@ #include #include +#include typedef int _PDCLIB_fd_t; @@ -14,13 +15,8 @@ static inline int32_t inline_syscall(uint32_t num, uint32_t arg1, uint32_t arg2, return ret; } -void _exit(int status) { - inline_syscall(1, (uint32_t)status, 0, 0); - while(1) { asm volatile("hlt"); } -} - void _PDCLIB_exit(int status) { - _exit(status); + inline_syscall(1, (uint32_t)status, 0, 0);; } int _PDCLIB_read(_PDCLIB_fd_t fd, void *buf, size_t count) { @@ -111,4 +107,8 @@ void * sbrk(intptr_t increment) { } return (void *)-1; +} + +void exit(int status) { + _PDCLIB_exit(status); } \ No newline at end of file