kernel: some random modifications

This commit is contained in:
RaphProductions 2025-05-07 22:12:35 +02:00
parent e6a2c1e240
commit 175805604e
17 changed files with 141 additions and 237 deletions

View file

@ -177,7 +177,7 @@ kernel: kernel-deps
$(IMAGE_NAME).iso: limine/limine kernel $(IMAGE_NAME).iso: limine/limine kernel
rm -rf iso_root rm -rf iso_root
mkdir -p iso_root/boot mkdir -p iso_root/boot
cp -v kernel/bin-$(ARCH)/kernel iso_root/boot/ cp -v kernel/bin-$(ARCH)/soaplin iso_root/boot/
mkdir -p iso_root/boot/limine mkdir -p iso_root/boot/limine
cp -v limine.conf iso_root/boot/limine/ cp -v limine.conf iso_root/boot/limine/
mkdir -p iso_root/EFI/BOOT mkdir -p iso_root/EFI/BOOT

15
LICENSE
View file

@ -1,12 +1,7 @@
Copyright (C) 2023-2025 mintsuki and contributors. Copyright (C) 2025 Raphaël M.
Permission to use, copy, modify, and/or distribute this software for any Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View file

@ -1 +1,18 @@
# SILD (SILD isn't a Linux distro) # SILD (SILD isn't a Linux distro)
SILD is a Unix-like OS made with Limine.
## Features
* x86_64 support (kinda)
* Memory management (VMM/PMM)
* Simple pre-emptive scheduler
* Ring 3 (user mode) support
## To come
* RTC support
* ELF loader
* Virtual File System
* EXT2 driver
* FAT32 driver
* CPIO-based init ram disk
* Video driver for Bochs graphics adapter, and the VMware display adapter.
* FPU support

View file

@ -4,7 +4,7 @@ MAKEFLAGS += -rR
# This is the name that our final executable will have. # This is the name that our final executable will have.
# Change as needed. # Change as needed.
override OUTPUT := kernel override OUTPUT := soaplin
# Target architecture to build for. Default to x86_64. # Target architecture to build for. Default to x86_64.
ARCH := x86_64 ARCH := x86_64

66
kernel/src/fs/vfs.h Normal file
View file

@ -0,0 +1,66 @@
#pragma once
#include <stdint.h>
struct vfs {
struct vfs *vfs_next; /* next vfs in list */
struct vfsops *vfs_op; /* operations on vfs */
struct vnode *vfs_vnodecovered; /* vnode we cover */
int vfs_flag; /* flags */
int vfs_bsize; /* native block size */
uint64_t vfs_data; /* private data */
};
struct vfsops {
int (*vfs_mount)();
int (*vfs_unmount)();
int (*vfs_root)();
int (*vfs_statfs)();
int (*vfs_sync)();
int (*vfs_fid)();
int (*vfs_vget)();
};
enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VBAD };
struct vnode {
uint16_t v_flag; /* vnode flags */
uint16_t v_count; /* reference count */
uint16_t v_shlockc; /* # of shared locks */
uint16_t v_exlockc; /* # of exclusive locks */
struct vfs *v_vfsmountedhere; /* covering vfs */
struct vnodeops *v_op; /* vnode operations */
union {
struct socket *v_Socket; /* unix ipc */
struct stdata *v_Stream; /* stream */
};
struct vfs *v_vfsp; /* vfs we are in */
enum vtype v_type; /* vnode type */
uint64_t v_data; /* private data */
};
struct vnodeops {
int (*vn_open)();
int (*vn_close)();
int (*vn_rdwr)();
int (*vn_ioctl)();
int (*vn_select)();
int (*vn_getattr)();
int (*vn_setattr)();
int (*vn_access)();
int (*vn_lookup)();
int (*vn_create)();
int (*vn_remove)();
int (*vn_link)();
int (*vn_rename)();
int (*vn_mkdir)();
int (*vn_rmdir)();
int (*vn_readdir)();
int (*vn_symlink)();
int (*vn_readlink)();
int (*vn_fsync)();
int (*vn_inactive)();
int (*vn_bmap)();
int (*vn_strategy)();
int (*vn_bread)();
int (*vn_brelse)();
};

View file

@ -80,9 +80,9 @@ char kstack[8192];
// linker script accordingly. // linker script accordingly.
void kmain(void) { void kmain(void) {
// Ensure the bootloader actually understands our base revision (see spec). // Ensure the bootloader actually understands our base revision (see spec).
if (LIMINE_BASE_REVISION_SUPPORTED == false) { /*if (LIMINE_BASE_REVISION_SUPPORTED == false) {
hcf(); hcf();
} }*/
// Ensure we got a framebuffer. // Ensure we got a framebuffer.
if (framebuffer_request.response == NULL if (framebuffer_request.response == NULL
@ -118,11 +118,13 @@ void kmain(void) {
uint8_t *mem = pmm_request_page(); uint8_t *mem = pmm_request_page();
mem[0] = 0xCD; mem[0] = 0xCD;
mem[1] = 0x80; mem[1] = 0x80;
mem[2] = 0xF4; //mem[2] = 0xF4;
//mem[3] = 0xFE; //mem[3] = 0xFE;
pagemap_t* pm = vmm_alloc_pm(); pagemap_t* pm = vmm_alloc_pm();
vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER); vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
sched_process *proc = sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS); sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS);
log("kernel - Soaplin initialized sucessfully.\n"); log("kernel - Soaplin initialized sucessfully.\n");
while (1) while (1)

View file

@ -53,7 +53,7 @@ void rt_print(char *str) {
for (int i = 0; i < _rt_strlen(str); i++) { for (int i = 0; i < _rt_strlen(str); i++) {
if (str[i] == '\n' && _curctx.use_crlf_ending) if (str[i] == '\n' && _curctx.use_crlf_ending)
if (_curctx.y * 16 >= _curctx.framebuffer_height) { if (_curctx.y * 16 >= (int)_curctx.framebuffer_height) {
_curctx.y = 0; _curctx.y = 0;
memset( memset(
_curctx.framebuffer, _curctx.bg_color, _curctx.framebuffer, _curctx.bg_color,
@ -63,7 +63,7 @@ void rt_print(char *str) {
} }
else if (str[i] == '\n') else if (str[i] == '\n')
{ {
if (_curctx.y * 16 >= _curctx.framebuffer_height) { if (_curctx.y * 16 >= (int)_curctx.framebuffer_height) {
_curctx.y = 0; _curctx.y = 0;
memset( memset(
_curctx.framebuffer, _curctx.bg_color, _curctx.framebuffer, _curctx.bg_color,

View file

@ -56,10 +56,12 @@ sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t* pm, uin
if (flags == SCHED_KERNEL_PROCESS) { if (flags == SCHED_KERNEL_PROCESS) {
proc->stack_base = stack_phys; proc->stack_base = stack_phys;
proc->stack_base_physical = stack_phys;
proc->stack_end = proc_list->stack_base + PMM_PAGE_SIZE; proc->stack_end = proc_list->stack_base + PMM_PAGE_SIZE;
} else if (flags == SCHED_USER_PROCESS) { } else if (flags == SCHED_USER_PROCESS) {
vmm_map(proc->pm, (uint64_t)stack_virt, (uint64_t)stack_phys, VMM_PRESENT | VMM_WRITABLE | VMM_USER); vmm_map(proc->pm, (uint64_t)stack_virt, (uint64_t)stack_phys, VMM_PRESENT | VMM_WRITABLE | VMM_USER);
proc->stack_base = stack_virt; proc->stack_base = stack_virt;
proc->stack_base_physical = stack_phys;
proc->stack_end = proc_list->stack_base + PMM_PAGE_SIZE; proc->stack_end = proc_list->stack_base + PMM_PAGE_SIZE;
} }
proc->regs.rip = (uint64_t)entry_point; proc->regs.rip = (uint64_t)entry_point;
@ -91,6 +93,12 @@ sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t* pm, uin
return proc; return proc;
} }
void sched_exit(int exit_code) {
log("sched - Process %d exited with code %d!", curr_proc->pid, exit_code);
curr_proc->type = SCHED_DIED;
schedule(&curr_proc->regs);
}
void schedule(registers_t *regs) void schedule(registers_t *regs)
{ {
if (standby) { if (standby) {
@ -98,6 +106,22 @@ void schedule(registers_t *regs)
return; return;
} }
if (curr_proc->type == SCHED_DIED) {
sched_process *prev_proc = proc_list;
while (prev_proc->next != curr_proc) {
prev_proc = prev_proc->next;
}
prev_proc->next = curr_proc->next;
// Now, it is safe to free the process's memory.
vmm_release_pm(curr_proc->pm);
pmm_free_page(curr_proc->stack_base_physical);
// R.I.P. process
pmm_free_page(curr_proc);
}
memcpy(&curr_proc->regs, regs, sizeof(registers_t)); memcpy(&curr_proc->regs, regs, sizeof(registers_t));
curr_proc = curr_proc->next; curr_proc = curr_proc->next;

View file

@ -8,7 +8,7 @@
typedef enum { typedef enum {
SCHED_RUNNING, SCHED_RUNNING,
SCHED_EXITED, SCHED_DIED,
SCHED_EMPTY SCHED_EMPTY
} sched_proc_type; } sched_proc_type;
@ -23,6 +23,7 @@ typedef struct _sched_process {
uint64_t *stack_end; uint64_t *stack_end;
uint64_t *stack_base; uint64_t *stack_base;
uint64_t *stack_base_physical;
struct _sched_process *next; struct _sched_process *next;
} sched_process; } sched_process;
@ -36,5 +37,5 @@ extern sched_process *proc_list;
void sched_init(); void sched_init();
sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm, uint32_t flags); sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm, uint32_t flags);
void sched_exit(sched_process *proc); void sched_exit(int exit_code);
void schedule(registers_t *regs); void schedule(registers_t *regs);

View file

@ -73,7 +73,8 @@ void exception_handler(registers_t *regs) {
{ {
log("syscall - Hello World! Current process: %s\n", curr_proc->name); log("syscall - Hello World! Current process: %s\n", curr_proc->name);
if (curr_proc->flags == SCHED_USER_PROCESS) if (curr_proc->flags == SCHED_USER_PROCESS)
log("syscall - Btw we made it to userspace, baby!\n", curr_proc->name); log("syscall - Btw we made it to userspace, baby!\n", curr_proc->name);
} }
//logln(info, "arch/ints", "Received interrupt %d\n", regs->int_no); //logln(info, "arch/ints", "Received interrupt %d\n", regs->int_no);
pic_ack(regs->int_no - 32); pic_ack(regs->int_no - 32);

View file

@ -21,5 +21,6 @@ void rtc_init() {
} }
void rtc_handle_interrupt(registers_t *regs) { void rtc_handle_interrupt(registers_t *regs) {
(void)regs;
printf("RTC!\n"); printf("RTC!\n");
} }

View file

@ -0,0 +1,6 @@
#include "sys/arch/x86_64/smp.h"
#include "limine.h"
void smp_init() {
}

View file

@ -0,0 +1,3 @@
#pragma once
void smp_init();

View file

@ -16,14 +16,14 @@ void log(char *format, ...) {
rt_print(buf); rt_print(buf);
char *date = "1970-01-01 00:00:00 | "; char *date = "1970-01-01 00:00:00 | ";
for (int i;;i++) { for (int i=0;;i++) {
if (date[i] == '\0') if (date[i] == '\0')
break; break;
outb(0xE9, date[i]); outb(0xE9, date[i]);
} }
for (int i;;i++) { for (int i=0;;i++) {
if (buf[i] == '\0') if (buf[i] == '\0')
break; break;

View file

@ -1,208 +0,0 @@
diff --git a/kernel/src/main.c b/kernel/src/main.c
index b5b6fa0..2d326ef 100755
--- a/kernel/src/main.c
+++ b/kernel/src/main.c
@@ -63,6 +63,8 @@ static void hcf(void) {
}
}
+
+
int init() {
asm("int $0x80");
while (1)
@@ -71,6 +73,8 @@ int init() {
struct limine_framebuffer *fb;
+char kstack[8192];
+
// The following will be our kernel's entry point.
// If renaming kmain() to something else, make sure to change the
// linker script accordingly.
@@ -99,7 +103,7 @@ void kmain(void) {
printf("\n Soaplin 1.0-sild is booting up your computer...\n\n");
//printf("Physical kernel EP: %p", entrypoint_request.entry);
- gdt_init();
+ gdt_init(&kstack[8192]);
idt_init();
sse_init();
@@ -115,8 +119,9 @@ void kmain(void) {
mem[1] = 0x80;
mem[2] = 0xFE;
mem[3] = 0xEB;
- sched_process *proc = sched_create("Init", 0x1000, SCHED_USER_PROCESS);
- vmm_map(proc->pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
+ pagemap_t* pm = vmm_alloc_pm();
+ vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
+ sched_process *proc = sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS);
log("kernel - Soaplin initialized sucessfully.\n");
while (1)
diff --git a/kernel/src/mm/vmm.c b/kernel/src/mm/vmm.c
index 6d905e2..f7df03e 100755
--- a/kernel/src/mm/vmm.c
+++ b/kernel/src/mm/vmm.c
@@ -3,6 +3,7 @@
#include "mm/pmm.h"
#include "mm/memop.h"
#include "sys/log.h"
+#include "vmm.h"
#include <stddef.h>
@@ -148,12 +149,26 @@ void vmm_load_pagemap(pagemap_t *pm) {
}
static uint64_t *__vmm_get_next_lvl(uint64_t *level, uint64_t entry, uint64_t flags) {
- if (level[entry] & 1)
- return HIGHER_HALF(PTE_GET_ADDR(level[entry]));
- uint64_t *pml = HIGHER_HALF(pmm_request_page());
- memset(pml, 0, PMM_PAGE_SIZE);
- level[entry] = (uint64_t)PHYSICAL(pml) | (flags & 0xFFF); // N'ajoute que les flags pertinents
- return pml;
+ if (!(level[entry] & 1)){
+ uint64_t *pml = HIGHER_HALF(pmm_request_page());
+ memset(pml, 0, PMM_PAGE_SIZE);
+ level[entry] = (uint64_t)PHYSICAL(pml);
+ }
+ level[entry] |= (flags & 0xFFF); // N'ajoute que les flags pertinents
+ return HIGHER_HALF(PTE_GET_ADDR(level[entry]));
+}
+
+uint64_t vmm_get_flags(pagemap_t* pm, uint64_t vaddr) {
+ uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
+ uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
+ uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
+ uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
+
+ uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry, 0);
+ uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, 0);
+ uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, 0);
+
+ return pml1[pml1_entry] & 0x7000000000000FFF;
}
void vmm_map(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
diff --git a/kernel/src/mm/vmm.h b/kernel/src/mm/vmm.h
index 97239b4..4e4c8aa 100755
--- a/kernel/src/mm/vmm.h
+++ b/kernel/src/mm/vmm.h
@@ -37,5 +37,6 @@ pagemap_t *vmm_alloc_pm();
void vmm_init();
void vmm_release_pm(pagemap_t *pm);
void vmm_load_pagemap(pagemap_t *pm);
+uint64_t vmm_get_flags(pagemap_t* pm, uint64_t vaddr);
void vmm_map(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t flags);
void vmm_unmap(pagemap_t *pm, uint64_t vaddr) ;
\ No newline at end of file
diff --git a/kernel/src/sched/sched.c b/kernel/src/sched/sched.c
index b39c2fc..f09da0d 100755
--- a/kernel/src/sched/sched.c
+++ b/kernel/src/sched/sched.c
@@ -29,7 +29,7 @@ void sched_init() {
"mode.\n");
}
-sched_process *sched_create(char *name, uint64_t entry_point, uint32_t flags)
+sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t* pm, uint32_t flags)
{
// TODO: implement a separate strlen function
// as there's like 4 strlen impls in the kernel.
@@ -48,7 +48,7 @@ sched_process *sched_create(char *name, uint64_t entry_point, uint32_t flags)
// If it's broken, it's a boom in the ass of your computer
// (and a CPU exception)
- proc->pm = vmm_alloc_pm();
+ proc->pm = pm;
uint64_t *stack_phys = pmm_request_page();
uint64_t *stack_virt = (uint64_t*)0x40000000;
@@ -107,5 +107,5 @@ void schedule(registers_t *regs)
memcpy(regs, &curr_proc->regs, sizeof(registers_t));
// Finally, load our pagemap
- //vmm_load_pagemap(curr_proc->pm);
+ vmm_load_pagemap(curr_proc->pm);
}
\ No newline at end of file
diff --git a/kernel/src/sched/sched.h b/kernel/src/sched/sched.h
index f5d2b04..5dcf23d 100755
--- a/kernel/src/sched/sched.h
+++ b/kernel/src/sched/sched.h
@@ -34,6 +34,6 @@ extern sched_process *proc_list;
//extern sched_process *idle_process;
void sched_init();
-sched_process *sched_create(char *name, uint64_t entry_point, uint32_t flags);
+sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm, uint32_t flags);
void sched_exit(sched_process *proc);
void schedule(registers_t *regs);
\ No newline at end of file
diff --git a/kernel/src/sys/arch/x86_64/gdt.c b/kernel/src/sys/arch/x86_64/gdt.c
index 0559625..d6d712a 100755
--- a/kernel/src/sys/arch/x86_64/gdt.c
+++ b/kernel/src/sys/arch/x86_64/gdt.c
@@ -2,6 +2,7 @@
#include <stdint.h>
#include <sys/arch/x86_64/gdt.h>
#include <sys/log.h>
+#include <mm/memop.h>
gdt_table def_table = {
{
@@ -25,10 +26,10 @@ gdt_table def_table = {
tssr tss_list[256]; // One tssr per CPU
-void gdt_init() {
+void gdt_init( char* kstack ) {
// TODO: adapt for multiprocessor kernel
- tss_list[0].iopb = sizeof(tssr);
+ tss_list[0].rsp[0] = (uint64_t)kstack;
uintptr_t tss = (uintptr_t)&tss_list[0];
def_table.tss_entry.length = sizeof(tss_entry);
diff --git a/kernel/src/sys/arch/x86_64/gdt.h b/kernel/src/sys/arch/x86_64/gdt.h
index 8e51e53..6004d06 100755
--- a/kernel/src/sys/arch/x86_64/gdt.h
+++ b/kernel/src/sys/arch/x86_64/gdt.h
@@ -26,7 +26,7 @@ typedef struct {
typedef struct {
uint32_t resv;
- uint64_t rsp[3];
+ uint64_t rsp[4];
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
@@ -34,4 +34,4 @@ typedef struct {
uint16_t iopb;
} __attribute__((packed)) tssr; // Per CPU
-void gdt_init();
\ No newline at end of file
+void gdt_init(char* kstack);
\ No newline at end of file
diff --git a/kernel/src/sys/arch/x86_64/interrupts.c b/kernel/src/sys/arch/x86_64/interrupts.c
index d243629..6bab678 100755
--- a/kernel/src/sys/arch/x86_64/interrupts.c
+++ b/kernel/src/sys/arch/x86_64/interrupts.c
@@ -39,6 +39,14 @@ void exception_handler(registers_t *regs) {
if (regs->int_no < 32) {
//panic(kmode_cpu_exception, regs);
log("ints - %d (RIP: %p, ERR: %d)\n", regs->int_no, regs->rip, regs->err_code);
+
+ if(regs->int_no == 0xe) {
+ uint64_t cr2;
+ asm ("mov %%cr2, %0" : "=r"(cr2));
+ log("faulting locations: %p\n", cr2);
+ log("faulting page flags: %p\n", vmm_get_flags(vmm_current_pm, cr2));
+ }
+
dump_backtrace(regs);
asm ("cli");
while (1)

View file

@ -1,12 +1,8 @@
# Timeout in seconds that Limine will use before automatically booting.
timeout: 3 timeout: 3
serial: yes serial: yes
verbose: yes verbose: yes
# The entry name that will be displayed in the boot menu.
/SILD - Soaplin 1.0 /SILD - Soaplin 1.0
# We use the Limine boot protocol.
protocol: limine protocol: limine
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. path: boot():/boot/soaplin
path: boot():/boot/kernel