diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index ffd365b..ac07aff 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -5,7 +5,7 @@ jobs: runs-on: debian-12 steps: - name: Install dependencies - run: apt-get update && apt-get install -y clang gcc-multilib llvm mtools parted udev + run: apt-get update && apt-get install -y clang gcc-multilib llvm mtools parted python3 udev - name: Install Rustup run: curl https://sh.rustup.rs | sh -s -- -y - name: Checkout @@ -13,7 +13,7 @@ jobs: with: submodules: true - name: Build - run: . ~/.bashrc && ./build.sh + run: . ~/.bashrc && ./build.py - name: Install cargo-deny run: . ~/.bashrc && cargo install cargo-deny - name: Run cargo-deny diff --git a/build.py b/build.py new file mode 100755 index 0000000..39a59d3 --- /dev/null +++ b/build.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +import os +import shutil +import subprocess + + +def run_command(cmd, cwd=None): + subprocess.run(cmd, shell=True, check=True, cwd=cwd) + + +def main(): + target = os.environ.get("OS_TARGET", "release") + if os.path.exists("img"): + shutil.rmtree("img") + os.makedirs("img/boot/efi/boot") + + run_command("make -j4", cwd="lib/acpica-build") + + components = ["init", "kernel", "loader"] + for component in components: + cargo_cmd = f'cargo build {"--release" if target == "release" else ""}' + run_command(cargo_cmd, cwd=component) + + loader_path = f"target/x86_64-unknown-uefi/{target}/loader.efi" + shutil.copy(loader_path, "img/boot/efi/boot/bootx64.efi") + + os.chdir("img") + run_command("dd if=/dev/zero of=boot.img bs=1M count=16 status=none") + run_command("mformat -i boot.img") + run_command("mcopy -si boot.img boot/* ::") + + run_command("dd if=/dev/zero of=os.img bs=1M count=32 status=none") + run_command("parted -s os.img mklabel gpt") + run_command("parted -s os.img mkpart primary fat32 2048s 100%") + run_command("parted -s os.img set 1 esp on") + run_command("dd if=boot.img of=os.img bs=1M seek=1 conv=notrunc status=none") + + +if __name__ == "__main__": + main() diff --git a/build.sh b/build.sh deleted file mode 100755 index bbe5338..0000000 --- a/build.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -set -euo pipefail -target=${OS_TARGET:-release} -rm -rf img -mkdir -p img/boot/efi/boot -cd lib/acpica-build -make -j4 -cd ../../init -if [ "$target" = "release" ]; then - cargo build --release -else - cargo build -fi -cd ../kernel -if [ "$target" = "release" ]; then - cargo build --release -else - cargo build -fi -cd ../loader -if [ "$target" = "release" ]; then - cargo build --release -else - cargo build -fi -cd .. -cp target/x86_64-unknown-uefi/$target/loader.efi img/boot/efi/boot/bootx64.efi -cd img -dd if=/dev/zero of=boot.img bs=1M count=16 status=none -mformat -i boot.img -mcopy -si boot.img boot/* :: -dd if=/dev/zero of=os.img bs=1M count=32 status=none -parted -s os.img mklabel gpt -parted -s os.img mkpart primary fat32 2048s 100% -parted -s os.img set 1 esp on -dd if=boot.img of=os.img bs=1M seek=1 conv=notrunc status=none diff --git a/kernel/src/cpu/isr.rs b/kernel/src/cpu/isr.rs index a5443f3..dd96f0c 100644 --- a/kernel/src/cpu/isr.rs +++ b/kernel/src/cpu/isr.rs @@ -4,7 +4,7 @@ use core::{ }; use kernel_common::instructions::hlt; -use log::warn; +use log::{debug, warn}; use crate::{ sys::{ @@ -12,7 +12,7 @@ use crate::{ locks::Spinlock, scheduler::scheduler, sync::{IN_ISR_HANDLER, LOCKS_HELD}, - task::terminate_current_task, + task::{TaskState, CURRENT_TASKS}, }, BROADCASTED_PANIC, }; @@ -113,8 +113,8 @@ extern "C" fn isr_handler(state: &mut ISRState) { IN_ISR_HANDLER[lapic_id].store(true, Ordering::SeqCst); if state.isr < 32 { if state.cs == 0x23 && state.isr != 2 && state.isr != 8 && state.isr != 18 { - warn!("Exception in usermode: {}", EXCEPTIONS[state.isr as usize]); - terminate_current_task(); + debug!("Exception in usermode: {}", EXCEPTIONS[state.isr as usize]); + CURRENT_TASKS.lock()[get_current_lapic_id()].as_mut().unwrap().task_state = TaskState::Terminated; IN_ISR_HANDLER[lapic_id].store(false, Ordering::SeqCst); unsafe { asm!("int $254"); diff --git a/kernel/src/cpu/syscall.s b/kernel/src/cpu/syscall.s index 1cb8aa5..fec4199 100644 --- a/kernel/src/cpu/syscall.s +++ b/kernel/src/cpu/syscall.s @@ -8,26 +8,19 @@ syscall: swapgs sti push %r11 - push %r10 - push %r9 - push %r8 - push %rsi - push %rdi - push %rdx push %rcx - push %rax + mov %r10, %rcx call syscall_handler - pop %rax pop %rcx - pop %rdx - pop %rdi - pop %rsi - pop %r8 - pop %r9 - pop %r10 pop %r11 + xor %rdx, %rdx + xor %rdi, %rdi + xor %rsi, %rsi + xor %r8, %r8 + xor %r9, %r9 + xor %r10, %r10 cli swapgs mov %gs:8, %rsp diff --git a/kernel/src/sys/syscall.rs b/kernel/src/sys/syscall.rs index 4de76fe..45a6b4b 100644 --- a/kernel/src/sys/syscall.rs +++ b/kernel/src/sys/syscall.rs @@ -1,2 +1,34 @@ +use log::debug; + +use super::task::terminate_current_task; + +struct SyscallArgs { + _arg1: usize, + _arg2: usize, + _arg3: usize, + _arg4: usize, + _arg5: usize, +} + +const SYSCALL_TABLE: [fn(SyscallArgs) -> usize; 1] = [syscall_get_kernel_version]; + +fn syscall_get_kernel_version(_args: SyscallArgs) -> usize { + 0 +} + #[no_mangle] -extern "C" fn syscall_handler() {} +extern "C" fn syscall_handler(syscall: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 { + if syscall as usize >= SYSCALL_TABLE.len() { + debug!("Process requested invalid syscall"); + terminate_current_task(); + } + let args = SyscallArgs { + _arg1: arg1 as usize, + _arg2: arg2 as usize, + _arg3: arg3 as usize, + _arg4: arg4 as usize, + _arg5: arg5 as usize, + }; + let result = SYSCALL_TABLE[syscall as usize](args); + result as u64 +} diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index f18b56a..5b778cf 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -145,8 +145,10 @@ fn create_idle_task() { IDLE_TASKS.lock().push(idle_task); } } -pub fn terminate_current_task() { +pub fn terminate_current_task() -> ! { CURRENT_TASKS.lock()[get_current_lapic_id()].as_mut().unwrap().task_state = TaskState::Terminated; + yield_task(); + panic!("Failed to terminate task"); } extern "C" fn task_entry() -> ! { let func; @@ -156,8 +158,6 @@ extern "C" fn task_entry() -> ! { } func(); terminate_current_task(); - yield_task(); - panic!("Failed to terminate task"); } fn idle_main() { while !ALL_APS_STARTED.load(Ordering::SeqCst) { diff --git a/qemu.sh b/qemu.sh index 1bd9d83..71b5b1a 100755 --- a/qemu.sh +++ b/qemu.sh @@ -1,5 +1,5 @@ #!/bin/bash # shellcheck disable=SC2068 set -euo pipefail -./build.sh +./build.py qemu-system-x86_64 -M q35 -accel kvm -cpu qemu64,rdrand,smap,smep,umip -smp 4 -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@