This commit is contained in:
2025-09-27 15:16:26 +02:00
parent 5af7c5276a
commit 3b1bb9d531
63 changed files with 1087 additions and 407 deletions

View File

@ -55,7 +55,6 @@ SRCFILES += $(call GRABSRC, \
proc \
proc/kproc \
proc/ps2kbproc \
proc/termproc \
proc/serialproc \
hal \
hal/$(ARCH) \
@ -67,6 +66,7 @@ SRCFILES += $(call GRABSRC, \
rbuf \
ipc/pipe \
drivers/ps2kb \
dev \
)
ifeq ($(ARCH),x86_64)

View File

@ -11,7 +11,7 @@ CFLAGS += -m64 \
-mno-red-zone \
-fno-stack-protector \
-fno-stack-check \
-O0 \
-Os \
LDFLAGS += -m elf_x86_64 \
-pie \

View File

@ -3,6 +3,7 @@
#include <stdbool.h>
#include "bitmap.h"
#include "util/util.h"
#include "kprintf.h"
void *bitmap_toptr(BitMap *bm, size_t block) {
uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE));
@ -104,13 +105,3 @@ void *bitmap_alloc(BitMap *bm, size_t blocks) {
void bitmap_free(BitMap *bm, void *base, size_t blocks) {
bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0);
}
size_t bitmap_allocpageframe(BitMap *bm) {
size_t pickedreg = bitmap_freeregion(bm, 1);
bitmap_markblocks(bm, pickedreg, 1, 1);
return (bm->mem_start + (pickedreg * BITMAP_BLOCK_SIZE));
}
void bitmap_freepageframe(BitMap *bm, void *addr) {
bitmap_markregion(bm, addr, BITMAP_BLOCK_SIZE * 1, 0);
}

View File

@ -31,7 +31,5 @@ void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used);
size_t bitmap_freeregion(BitMap *bm, size_t blocks);
void *bitmap_alloc(BitMap *bm, size_t blocks);
void bitmap_free(BitMap *bm, void *base, size_t blocks);
size_t bitmap_allocpageframe(BitMap *bm);
void bitmap_freepageframe(BitMap *bm, void *addr);
#endif // BITMAP_BITMAP_H_

14
kernel/dev/dev.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef DEV_DEV_H_
#define DEV_DEV_H_
#include <stdint.h>
#define DEV_FNS_MAX 32
typedef int32_t (*DevFn)(uint8_t *buffer, size_t len, void *extra);
typedef struct {
DevFn fns[DEV_FNS_MAX];
} Dev;
#endif // DEV_DEV_H_

19
kernel/dev/termdev.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdint.h>
#include <stddef.h>
#include "kprintf.h"
#include "hal/hal.h"
#include "termdev.h"
#include "dev.h"
#include "errors.h"
Dev TERMDEV;
int32_t termdev_putch(uint8_t *buffer, size_t len, void *extra) {
kprintf("%.*s", (int)len, (char *)buffer);
return E_OK;
}
void termdev_init(void) {
hal_memset(&TERMDEV, 0, sizeof(TERMDEV));
TERMDEV.fns[0] = &termdev_putch;
}

13
kernel/dev/termdev.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef DEV_TERMDEV_H_
#define DEV_TERMDEV_H_
#include <stdint.h>
#include <stddef.h>
#include "dev.h"
int32_t termdev_putch(uint8_t *buffer, size_t len, void *extra);
void termdev_init(void);
extern Dev TERMDEV;
#endif // DEV_TERMDEV_H_

View File

@ -49,7 +49,7 @@ int RELEASE_LOCK(SpinLock *sl) {
}
int INITIAL_LOCK(SpinLock *sl) {
spinlock_release(sl);
spinlock_init(sl);
return 0;
}

View File

@ -7,7 +7,7 @@
#define GDT_PRESENT 0x80
#define GDT_TSS 0x89
#define KSTACK 8192
#define KSTACK (1024*2*4096)
ALIGNED(16) static uint8_t kernelstack[KSTACK];
typedef struct {

View File

@ -178,8 +178,6 @@ void hal_syscalldispatch(IntrStackFrame *frame) {
frame->regs.rax = E_BADSYSCALL;
return;
}
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
int32_t ret = fn(frame, frame->regs.rdi, frame->regs.rsi, frame->regs.rdx,
frame->regs.r10, frame->regs.r8, frame->regs.r9);
@ -215,7 +213,7 @@ void intr_handleintr(IntrStackFrame *frame) {
break;
case INTR_IRQBASE+1:
int32_t c = ps2kb_intr();
if (c >= 0) {
if (c >= 0 && PS2KB_BUF.init) {
uint8_t b = c;
spinlock_acquire(&PS2KB_BUF.spinlock);
rbuf_push(&PS2KB_BUF.rbuf, b);

View File

@ -62,13 +62,13 @@
.endm
.macro _vecintr_bodygen
cli
_push_regs
cld
mov %rsp, %rdi
movq %rsp, %rdi
call intr_handleintr
_pop_regs
add $0x10, %rsp
iretq
.endm

View File

@ -2,15 +2,11 @@
.global hal_switchproc
hal_switchproc:
mov %cr3, %rcx
cmp %rsi, %rcx
je .done
mov %rsi, %cr3
.done:
testq %rsi, %rsi
je 1f
movq %rsi, %cr3
1:
mov %rdi, %rsp
_pop_regs
add $0x10, %rsp
iretq

View File

@ -29,12 +29,16 @@ PgIndex hal_vmm_pageindex(uint64_t vaddr) {
return ret;
}
uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent) {
uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent, bool alloc) {
uint64_t entry = table[ent];
uint64_t phys;
if (entry & HAL_PG_PRESENT) {
phys = entry & ~0xFFFULL;
} else {
if (!alloc) {
return NULL;
}
uint8_t *newphys = pmm_alloc(1);
phys = (uint64_t)newphys;
hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE);
@ -47,9 +51,9 @@ void hal_vmm_map_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr, ui
uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, true);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, true);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, true);
uint64_t *pte = &pml1[pi.pml1];
*pte = (physaddr & ~0xFFFULL) | ((uint64_t)flags & 0x7ULL);
@ -59,9 +63,9 @@ void hal_vmm_unmap_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr)
uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, false);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, false);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, false);
uint64_t *pte = &pml1[pi.pml1];
*pte &= ~HAL_PG_PRESENT;

View File

@ -11,6 +11,7 @@
#include "storedev/storedev.h"
#include "util/util.h"
#include "proc/proc.h"
#include "dev/termdev.h"
const char *human_size(uint64_t bytes, char *buf, size_t bufsize) {
static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" };
@ -64,6 +65,7 @@ void kmain(void) {
storedev_init();
baseimg_init();
vfs_init();
termdev_init();
proc_init();
for(;;);

View File

@ -40,6 +40,9 @@ void pmm_init(void) {
hal_memset(bm->map, 0xff, bm->nbytes);
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
if (entry == memmap_ent) {
continue;
}
// mark usable as 0 and unusable as 1
bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE);
}

View File

@ -15,7 +15,6 @@
#include "ipc/pipe/pipe.h"
#include "kproc/kproc.h"
#include "ps2kbproc/ps2kbproc.h"
#include "termproc/termproc.h"
#include "serialproc/serialproc.h"
#include "sysdefs/processctl.h"
@ -181,6 +180,7 @@ Proc *proc_spawnuser(char *mountpoint, char *path) {
proc->mman_map_base = PROC_MMAN_MAP_BASE;
spinlock_init(&proc->bcast_pipes.spinlock);
spinlock_init(&proc->pipes_spinlock);
spinlock_init(&proc->devs_spinlock);
proc->pipes[0] = dlmalloc(sizeof(IpcPipe));
ipc_pipeinit(proc->pipes[0], proc->pid);
@ -308,26 +308,20 @@ void proc_init(void) {
spinlock_init(&PROCS.spinlock);
PROCS.procs = NULL;
kproc_init(proc_spawnkern(&kproc_fn, "kproc"));
proc_register(KPROC);
PROCS.current = KPROC;
KPROC->state = PROC_READY;
/* kproc_init(proc_spawnkern(&kproc_fn, "kproc")); */
/* proc_register(KPROC); */
/* PROCS.current = KPROC; */
/* KPROC->state = PROC_READY; */
ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc"));
proc_register(PS2KBPROC);
PS2KBPROC->state = PROC_READY;
termproc_init(proc_spawnkern(&termproc_fn, "termproc"));
proc_register(TERMPROC);
TERMPROC->state = PROC_READY;
/* ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); */
/* proc_register(PS2KBPROC); */
/* PS2KBPROC->state = PROC_READY; */
/* serialproc_init(proc_spawnkern(&serialproc_fn, "serialproc")); */
/* proc_register(SERIALPROC); */
Proc *init = proc_spawnuser("base", "/bin/init");
ipc_pipefree(init->pipes[0]);
dlfree(init->pipes[0]);
init->pipes[0] = TERMPROC->pipes[1];
PROCS.current = init;
proc_register(init);
init->state = PROC_READY;

View File

@ -8,6 +8,7 @@
#include "vfs/vfs.h"
#include "ipc/pipe/pipe.h"
#include "sysdefs/processctl.h"
#include "dev/dev.h"
#define PROC_NAME_MAX 0x100
@ -18,9 +19,10 @@
#define PROC_VFSHANDLES_MAX 0x80
#define PROC_PIPEHANDLES_MAX 0x20
#define PROC_DEVHANDLES_MAX 0x20
#define PROC_MMAN_MAP_BASE 0x0000100000000000ULL
#define PROC_USER_STACK_TOP 0x0000800000000000ULL
#define PROC_USER_STACK_TOP 0x00007FFFFFFFF000ULL
typedef struct {
IntrStackFrame trapframe;
@ -56,12 +58,18 @@ typedef struct Proc {
VfsObj *vobjs[PROC_VFSHANDLES_MAX];
uint64_t vobjcnt;
IpcPipe *pipes[PROC_PIPEHANDLES_MAX];
SpinLock pipes_spinlock;
struct {
IpcPipe *list;
SpinLock spinlock;
} bcast_pipes;
Dev *devs[PROC_DEVHANDLES_MAX];
SpinLock devs_spinlock;
struct {
ProcArg *list;
size_t len;

View File

@ -7,7 +7,7 @@
#include "ps2kbproc.h"
Proc *PS2KBPROC = NULL;
Ps2KbFastBuf PS2KB_BUF;
Ps2KbFastBuf PS2KB_BUF = {0};
void ps2kbproc_init(Proc *proc) {
PS2KBPROC = proc;
@ -17,22 +17,23 @@ void ps2kbproc_init(Proc *proc) {
uint8_t *buf = dlmalloc(IPC_PIPE_MAX);
rbuf_init(&PS2KB_BUF.rbuf, buf, IPC_PIPE_MAX);
spinlock_init(&PS2KB_BUF.spinlock);
PS2KB_BUF.init = true;
}
void ps2kbproc_fn(void) {
for (;;) {
uint8_t b = 0;
spinlock_acquire(&PS2KB_BUF.spinlock);
if (rbuf_pop(&PS2KB_BUF.rbuf, &b) == 0) {
spinlock_acquire(&PS2KBPROC->bcast_pipes.spinlock);
IpcPipe *head = PS2KBPROC->bcast_pipes.list;
while (head != NULL) {
ipc_pipewrite(head, &b, 1);
head = head->next;
}
spinlock_release(&PS2KBPROC->bcast_pipes.spinlock);
}
spinlock_release(&PS2KB_BUF.spinlock);
/* uint8_t b = 0; */
/* spinlock_acquire(&PS2KB_BUF.spinlock); */
/* if (rbuf_pop(&PS2KB_BUF.rbuf, &b) == 0) { */
/* spinlock_acquire(&PS2KBPROC->bcast_pipes.spinlock); */
/* IpcPipe *head = PS2KBPROC->bcast_pipes.list; */
/* while (head != NULL) { */
/* ipc_pipewrite(head, &b, 1); */
/* head = head->next; */
/* } */
/* spinlock_release(&PS2KBPROC->bcast_pipes.spinlock); */
/* } */
/* spinlock_release(&PS2KB_BUF.spinlock); */
}
}

View File

@ -9,6 +9,7 @@
typedef struct {
RBuf rbuf;
SpinLock spinlock;
bool init;
} Ps2KbFastBuf;
extern Proc *PS2KBPROC;

View File

@ -1,25 +0,0 @@
#include <stdint.h>
#include "proc/proc.h"
#include "ipc/pipe/pipe.h"
#include "kprintf.h"
#include "hal/hal.h"
#include "dlmalloc/malloc.h"
#include "spinlock/spinlock.h"
Proc *TERMPROC;
void termproc_init(Proc *proc) {
TERMPROC = proc;
TERMPROC->pipes[1] = dlmalloc(sizeof(IpcPipe));
ipc_pipeinit(TERMPROC->pipes[1], TERMPROC->pid);
}
void termproc_fn(void) {
for (;;) {
char c = 0;
int32_t read = ipc_piperead(TERMPROC->pipes[1], (uint8_t *)&c, 1);
if (read > 0) {
kprintf("%c", c);
}
}
}

View File

@ -1,11 +0,0 @@
#ifndef PROC_TERMPROC_TERMPROC_H_
#define PROC_TERMPROC_TERMPROC_H_
#include "proc/proc.h"
extern Proc *TERMPROC;
void termproc_init(Proc *proc);
void termproc_fn(void);
#endif // PROC_TERMPROC_TERMPROC_H_

View File

@ -5,25 +5,62 @@
#include "hal/hal.h"
#include "kprintf.h"
#define SPINLOCK_IRQ_DBG 1
#define SPINLOCK_HINT() asm volatile("pause")
struct {
atomic_uint64_t irq_flags;
atomic_int irq_nest;
} IRQ_CTX;
void spinlock_init(SpinLock *sl) {
atomic_store(&sl->lock, false);
sl->flags = 0;
}
uint64_t spinlock_irqsave(void) {
uint64_t irqsave(void) {
uint64_t flags;
asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory");
asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory", "cc");
return flags;
}
void spinlock_irqrestore(uint64_t flags) {
void irqrestore(uint64_t flags) {
if (flags & (1<<9)) {
asm volatile("sti" ::: "memory");
asm volatile("sti" ::: "memory", "cc");
}
}
void irqsave_nested(void) {
if (atomic_load(&IRQ_CTX.irq_nest) == 0) {
atomic_store(&IRQ_CTX.irq_flags, irqsave());
}
atomic_inc(&IRQ_CTX.irq_nest);
#if SPINLOCK_IRQ_DBG
if (atomic_load(&IRQ_CTX.irq_nest) < 0) {
kprintf("IRQ_CTX.irq_nest underflow\n");
hal_hang();
}
#endif
}
void irqrestore_nested(void) {
#if SPINLOCK_IRQ_DBG
int irq_nest = atomic_load(&IRQ_CTX.irq_nest);
if (irq_nest <= 0) {
kprintf("spinlock: irqs restored too many times: %d\n", irq_nest);
hal_hang();
}
#endif
atomic_dec(&IRQ_CTX.irq_nest);
if (atomic_load(&IRQ_CTX.irq_nest) == 0) {
irqrestore(atomic_load(&IRQ_CTX.irq_flags));
}
}
void spinlock_acquire(SpinLock *sl) {
sl->flags = spinlock_irqsave();
irqsave_nested();
while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) {
SPINLOCK_HINT();
@ -33,6 +70,6 @@ void spinlock_acquire(SpinLock *sl) {
void spinlock_release(SpinLock *sl) {
atomic_clear_flag_explicit(&sl->lock, memory_order_release);
spinlock_irqrestore(sl->flags);
irqrestore_nested();
}

View File

@ -6,11 +6,8 @@
typedef struct {
atomic_bool lock;
uint64_t flags;
} SpinLock;
#define SPINLOCK_HINT() asm volatile("pause")
void spinlock_init(SpinLock *sl);
void spinlock_acquire(SpinLock *sl);
void spinlock_release(SpinLock *sl);

65
kernel/syscall/devctl.c Normal file
View File

@ -0,0 +1,65 @@
#include <stdint.h>
#include <stddef.h>
#include "kprintf.h"
#include "syscall.h"
#include "errors.h"
#include "spinlock/spinlock.h"
#include "proc/proc.h"
#include "sysdefs/devctl.h"
#include "dev/termdev.h"
#include "util/util.h"
Dev *DEVS[] = {
[0x10] = &TERMDEV,
};
int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1) {
uint64_t *devh = (uint64_t *)devh1;
uint64_t cmd = cmd1;
int32_t ret = E_OK;
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
switch (cmd) {
case DEVCTL_GET_HANDLE: {
uint64_t devid = buffer1;
if (devid >= LEN(DEVS)) {
ret = E_INVALIDARGUMENT;
goto done;
}
bool found = false;
for (size_t i = 0; i < PROC_DEVHANDLES_MAX; i++) {
if (proc->devs[i] == NULL) {
found = true;
proc->devs[i] = DEVS[devid];
break;
}
}
if (!found) {
ret = E_NOENTRY;
goto done;
}
} break;
default: {
if (devh == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
if (cmd >= DEV_FNS_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
Dev *dev = proc->devs[*devh];
ret = dev->fns[cmd]((uint8_t *)buffer1, (size_t)len1, (void *)extra1);
} break;
}
done:
return ret;
}

9
kernel/syscall/devctl.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef SYSCALL_DEVCTL_H_
#define SYSCALL_DEVCTL_H_
#include <stdint.h>
#include "syscall.h"
int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1);
#endif // SYSCALL_DEVCTL_H_

View File

@ -10,6 +10,7 @@
#include "sysdefs/mman.h"
#include "bootinfo/bootinfo.h"
#include "dlmalloc/malloc.h"
#include "kprintf.h"
int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) {
uint8_t *addr = (uint8_t *)addr1;
@ -27,9 +28,6 @@ int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) {
size_t pages = _DIV_ROUNDUP(size, HAL_PAGE_SIZE);
uint8_t *phys = (uint8_t *)pmm_alloc(pages);
if (phys == NULL) {
return E_NOMEMORY;
}
hal_memset(VIRT(phys), 0, pages * HAL_PAGE_SIZE);
spinlock_acquire(&PROCS.spinlock);

View File

@ -63,8 +63,10 @@ int32_t SYSCALL5(sys_processctl, pid1, cmd1, arg1, arg2, arg3) {
size_t argslen = arg3;
char *(*args)[] = (char *(*)[])arg2;
for (size_t i = 0; i < argslen; i++) {
PROC_ARG(newproc, (*args)[i]);
if (args != NULL && argslen > 0) {
for (size_t i = 0; i < argslen; i++) {
PROC_ARG(newproc, (*args)[i]);
}
}
for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) {

View File

@ -11,7 +11,7 @@ int32_t SYSCALL0(sys_schedrelease) {
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
proc_sched((void *)frame);
/* proc_sched((void *)frame); */
return E_OK;
}

View File

@ -8,6 +8,7 @@
#include "ipcpipe.h"
#include "mman.h"
#include "sched.h"
#include "devctl.h"
int32_t SYSCALL1(sys_debugprint, string) {
char *p = (char *)string;
@ -23,4 +24,5 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = {
[SYS_MMAN_MAP] = &sys_mman_map,
[SYS_MMAN_UNMAP] = &sys_mman_unmap,
[SYS_SCHEDRELEASE] = &sys_schedrelease,
[SYS_DEVCTL] = &sys_devctl,
};

View File

@ -58,14 +58,14 @@
} while(0)
#define LL_FOREACH_SAFE(head, var, tmp) \
for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \
for (var = (head), tmp = (var ? var->next : NULL); \
var != NULL; \
var = tmp, tmp = (var ? var->next : NULL) \
)
#define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \
for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \
var != NULL && ((idx) = 0, 1); \
for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
var != NULL; \
var = tmp, tmp = (var ? var->next : NULL), (idx)++)
#define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \