compiled newlib, need to hook up the system calls

This commit is contained in:
2026-06-28 17:58:58 -05:00
parent 43bc0df81a
commit 97357f3170
337 changed files with 47955 additions and 114 deletions

View File

@@ -37,6 +37,7 @@ higher:
push %eax
call kmain
loop:
hlt
jmp loop
.section .bss

10
kernel/common.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef KCOMMON_H
#define KCOMMON_H
#include <stdint.h>
void enable_interrupts();
void disable_interrupts();
uint32_t fetch_cr3();
#endif

View File

@@ -1,6 +1,6 @@
.code32
.global init_pit
init_pit: # tickrate: 1193182/1000 = 0x04A9 (1000hz) (1ms)
init_pit:
movb $0x36, %al
outb %al, $0x43

View File

@@ -129,6 +129,7 @@ void init_gdt() {
for (uint32_t i = 0; i < sizeof(tss_entry); i++) {
((char*)&tss)[i] = 0;
}
tss.ss0 = 0x10;
tss.iomap_base = sizeof(tss_entry);
@@ -136,6 +137,7 @@ void init_gdt() {
gdtr.limit = 6 * sizeof(uint64_t) - 1;
gdtr.base = (uint32_t)&gdt;
load_gdt();
tss_flush();
}

View File

@@ -14,7 +14,7 @@ isr\num:
jmp isr_common_stub
.endm
.extern common_interrupt_handler
.extern common_interrupt_handler # interrupts.c
isr_common_stub:
pushal
@@ -40,18 +40,20 @@ ISR_ERRCODE 14 # Page Fault (Has Error Code!)
// This is a special case so we need to handle it for task switching
.global isr32
.extern switch_context # scheduler.c
.extern send_eoi_master # drivers/pic/pic.c
isr32:
cli
pushal
pushl %esp
call schedule_next_task
call switch_context
movl %eax, %esp
call send_eoi_master
popal
sti
iret

View File

@@ -34,9 +34,8 @@ typedef struct __attribute__((packed)) {
uint32_t eip, cs, eflags, useresp, ss;
} registers;
// (interrupts.S)
extern void load_idt(void);
// isr stubs
extern void isr0();
extern void isr1();
extern void isr8();
@@ -127,10 +126,6 @@ void common_interrupt_handler(registers *args) {
while(1);
break;
}
case 32:
// wake the PIT timer driver
send_eoi_master();
break;
case 33: {
uint8_t data = ps2_read_data();
send_eoi_master();

View File

@@ -1,8 +1,8 @@
#include "multiboot.h"
#include "interrupts.h"
#include "elf.h"
#include "gdt.h"
#include "scheduler.h"
#include "common.h"
#include <lib/print.h>
#include <lib/stream.h>
@@ -20,21 +20,22 @@
#include <stddef.h>
#include <stdint.h>
extern void enable_interrupts();
extern void disable_interrupts();
extern uint32_t fetch_cr3();
extern char __kernel_start;
extern char __kernel_end;
void kernel_test_task() {
while (1) {
kprintf("task sleeping...\n");
sleep(10000000);
void first_task() {
kprintf("task started\n");
int i = 5;
while (i--) {
sleep(1000);
kprintf("task awake [%d]\n", i);
}
kprintf("exiting\n");
exit();
}
void kmain(uint32_t magic, multiboot_info* mbi) {
disable_interrupts();
if (!(mbi->flags & (1 << 6))) {
return;
}
@@ -54,9 +55,14 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
kprintf("basic initializations complete\n");
disable_interrupts();
disable_interrupts(); // just paranoid... do it again
init_scheduler();
enable_interrupts();
while(1) yield();
create_task((uint32_t)first_task, fetch_cr3());
while(1) {
sleep(5000);
kprintf("kernel awake\n");
}
}

View File

@@ -6,6 +6,7 @@
typedef enum {
STATE_READY,
STATE_SLEEPING,
STATE_BLOCKED,
STATE_DEAD
} process_state_t;
@@ -15,6 +16,7 @@ typedef struct {
uint32_t cr3;
process_state_t state;
uint32_t sleep;
void* next;
} __attribute__((packed)) process_t;
#endif

View File

@@ -1,12 +1,31 @@
.code32
.extern schedule_next_task
.code32
.global yield
yield:
cli
pushal
push %esp
call schedule_next_task
movl %eax, %esp
popal
sti
ret
.extern schedule_next_task
yield: # void yield()
cli
pushfl
pushl %cs
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 up.
# the stack now looks like a hardware interrupt just happened, even though we never called one.
pushal
pushl %esp
call switch_context
movl %eax, %esp
popal
sti
iret

View File

@@ -5,24 +5,30 @@
#include <stddef.h>
#include "common.h"
#include "process.h"
#include "scheduler.h"
static process_t* process_table;
static spinlock_t process_table_lock = {0};
static int current_process = 0;
static int total_processes = 0;
extern uint32_t fetch_cr3();
#define IDLE_TASK_PID 1
static void idle_task() {
while (1) asm volatile("hlt");
}
uint32_t schedule_next_task(uint32_t current_esp) {
spin_lock(&process_table_lock);
static void lock_scheduler() {
disable_interrupts();
}
static void unlock_scheduler() {
enable_interrupts();
}
// called from isr and yield, interrupts are already disabled and re enabled in the isr/yield func
uint32_t switch_context(uint32_t current_esp) {
process_table[current_process].esp = current_esp;
for (int i = 0; i < total_processes; i++) {
@@ -39,6 +45,7 @@ uint32_t schedule_next_task(uint32_t current_esp) {
int next_process = current_process;
int found_ready = 0;
while (1) {
next_process = (next_process + 1) % total_processes;
if (next_process != IDLE_TASK_PID && process_table[next_process].state == STATE_READY) {
@@ -66,10 +73,7 @@ uint32_t schedule_next_task(uint32_t current_esp) {
load_pd(process_table[current_process].cr3);
}
uint32_t rtn = process_table[current_process].esp;
spin_unlock(&process_table_lock);
return rtn;
return process_table[current_process].esp;
}
void init_scheduler() {
@@ -94,9 +98,19 @@ int create_task(uint32_t entry_point, uint32_t cr3) {
return 0;
}
spin_lock(&process_table_lock);
lock_scheduler();
// default to a new task, but if we find a dead one, re use it
process_t* process = &process_table[total_processes];
process->pid = 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;
}
}
process->pid = pid;
process->cr3 = cr3;
process->state = STATE_READY;
process->sleep = 0;
@@ -118,19 +132,24 @@ int create_task(uint32_t entry_point, uint32_t cr3) {
*(--esp) = 0; // EDI
process->esp = (uint32_t)esp;
spin_unlock(&process_table_lock);
total_processes++;
unlock_scheduler();
return 1;
}
void sleep(uint32_t ticks) {
if (ticks == 0) return;
spin_lock(&process_table_lock);
process_table[current_process].sleep = ticks;
void sleep(uint32_t ms) {
if (ms == 0) return;
lock_scheduler();
process_table[current_process].sleep = ms;
process_table[current_process].state = STATE_SLEEPING;
spin_unlock(&process_table_lock);
yield();
}
unlock_scheduler();
}
void exit() {
lock_scheduler();
process_table[current_process].state = STATE_DEAD;
yield(); // yield forever
unlock_scheduler();
}

View File

@@ -7,7 +7,8 @@ void init_scheduler();
int create_task(uint32_t entry_point, uint32_t cr3);
void sleep(uint32_t ticks);
void sleep(uint32_t ms);
void yield();
void exit();
#endif

View File

@@ -1,6 +1,6 @@
#include <stdint.h>
#include "lib/print.h"
#include "scheduler.h"
typedef struct registers {
uint32_t gs, fs, es, ds; // Pushed manually
@@ -9,19 +9,35 @@ typedef struct registers {
uint32_t eip, cs, eflags, useresp, ss; // Pushed automatically by CPU
} registers_t;
int32_t sys_vga_text_write(char* buf);
int32_t sys_exit();
int32_t sys_read();
int32_t sys_write();
int32_t sys_open();
int32_t sys_close();
int32_t sys_brk();
int32_t syscall(registers_t* regs) {
switch(regs->eax) {
case 1: {
return sys_vga_text_write((char*)regs->ebx);
}
case 1: return sys_exit();
case 3: return sys_read();
case 4: return sys_write();
case 5: return sys_open();
case 6: return sys_close();
case 12: return sys_brk();
default:
return -1;
}
}
int32_t sys_vga_text_write(char* buf) {
kprintf(buf);
int32_t sys_exit() {
exit();
return 0;
}
int32_t sys_read() {
return 0;
}
int32_t sys_write() {
return 0;
}