diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 00000000..6b1341cb --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,13 @@ +name: Xernel Lint +on: [push, pull_request] +jobs: + xernel-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: sudo apt update && sudo apt install -y mtools + - run: rustup update && rustup toolchain install nightly + - run: rustup component add rust-src rustfmt clippy + - run: cargo kernel build + - run: cargo kernel fmt --check + - run: cargo kernel clippy diff --git a/README.md b/README.md index 321f3ae9..fbe5e785 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ # xernel -A kernel that tries to support multiple architectures/platforms using a hybrid kernel architecture. -It's using the limine protocol. +A kernel for x86-64 (and maybe ARM/RISC-V later on) using the limine boot protocol. Mostly made for learning purposes, no real-world application. ![xernel](status_quo.png) ## Building -For building, you simply need a working Rust installation with the nightly toolchain installed and the `mtools` package which we use for the generation of the disk image. +For building, you simply need a working Rust installation with the nightly toolchain installed. We use xtask as our workflow for building and running the kernel. Therefore, the command `cargo kernel` is used. @@ -16,6 +15,9 @@ You can simply use `cargo kernel build` or `cargo kernel run`, it is going to us ## Contact Feel free to reach out to `lockna` or `mp1310` on Discord +or join our **Offical Discord Server:** https://discord.gg/e3gsmHX4w4 + +Here you can talk to us in the `xernel-development` category. ## TODO Things that are still to do: diff --git a/build/xtask/Cargo.toml b/build/xtask/Cargo.toml index 2ce032b9..37482e8d 100644 --- a/build/xtask/Cargo.toml +++ b/build/xtask/Cargo.toml @@ -11,3 +11,4 @@ pico-args = "0.5.0" anyhow = "1" wsl = "0.1.0" dotenv = "0.15.0" +fatfs = "0.3.6" diff --git a/build/xtask/src/main.rs b/build/xtask/src/main.rs index d4286381..a644f576 100644 --- a/build/xtask/src/main.rs +++ b/build/xtask/src/main.rs @@ -1,8 +1,10 @@ use anyhow::{bail, Result}; use dotenv::dotenv; +use fatfs::{format_volume, FormatVolumeOptions}; use pico_args::Arguments; -use std::env; +use std::io::{Cursor, Read, Seek, Write}; use std::path::{Path, PathBuf}; +use std::{env, fs, vec}; use xshell::{cmd, Shell}; const HELP: &str = "\ @@ -85,14 +87,7 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> { .opt_value_from_str::<_, String>("--target")? .unwrap_or_else(|| "x86_64".to_string()); - if !Path::new( - sh.current_dir() - .as_path() - .join("xernel/kernel/limine") - .as_path(), - ) - .exists() - { + if !Path::new(sh.current_dir().as_path().join("xernel/kernel/limine").as_path()).exists() { sh.change_dir(sh.current_dir().as_path().join("xernel/kernel")); cmd!( sh, @@ -121,34 +116,30 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> { let build_dir = if rl { "release" } else { "debug" }; let diskname = "xernel.hdd"; - let disksize = 64.to_string(); + let disksize = 64 * 1024 * 1024; // 64 MB - cmd!( - sh, - "dd if=/dev/zero of={diskname} bs=1M count=0 seek={disksize}" - ) - .run()?; + let data_vec = vec![0_u8; disksize]; + let mut disk = Cursor::new(data_vec); - cmd!(sh, "mformat -i {diskname} -F").run()?; - cmd!( - sh, - "mcopy -i {diskname} ./target/{target}/{build_dir}/xernel ::/xernel" - ) - .run()?; - cmd!( - sh, - "mcopy -i {diskname} xernel/kernel/limine.cfg ::/limine.cfg" - ) - .run()?; + format_volume(&mut disk, FormatVolumeOptions::new().fat_type(fatfs::FatType::Fat32))?; - cmd!(sh, "mcopy -i {diskname} ./logo.bmp ::/logo.bmp").run()?; - cmd!(sh, "mmd -i {diskname} ::/EFI").run()?; - cmd!(sh, "mmd -i {diskname} ::/EFI/BOOT").run()?; - cmd!( - sh, - "mcopy -i {diskname} xernel/kernel/limine/BOOTX64.EFI ::/EFI/BOOT" - ) - .run()?; + let fs = fatfs::FileSystem::new(&mut disk, fatfs::FsOptions::new())?; + { + let root_dir = fs.root_dir(); + + copy_to_image(&root_dir, &format!("./target/{target}/{build_dir}/xernel"), "xernel")?; + + copy_to_image(&root_dir, "./logo.bmp", "logo.bmp")?; + + let dir = root_dir.create_dir("EFI")?; + let dir = dir.create_dir("BOOT")?; + + copy_to_image(&dir, "./xernel/kernel/limine/BOOTX64.EFI", "BOOTX64.EFI")?; + copy_to_image(&dir, "./xernel/kernel/limine.cfg", "limine.cfg")?; + } + fs.unmount()?; + + fs::write(diskname, disk.into_inner())?; Ok(()) } @@ -159,10 +150,7 @@ fn run(sh: &Shell, gdb: bool, mut args: Arguments) -> Result<()> { let ram = args .opt_value_from_str::<_, String>("--ram")? .unwrap_or_else(|| "128M".to_string()); - let cpus = args - .opt_value_from_str::<_, u32>("--cpus")? - .unwrap_or(2) - .to_string(); + let cpus = args.opt_value_from_str::<_, u32>("--cpus")?.unwrap_or(2).to_string(); let kvm = if args.contains("--kvm") { &["-enable-kvm"] @@ -174,10 +162,7 @@ fn run(sh: &Shell, gdb: bool, mut args: Arguments) -> Result<()> { let qemu_in_wsl_arg = args.contains("--wsl-qemu"); - let qemu_in_wsl_env = env::var("qemu_in_wsl") - .unwrap_or("false".to_string()) - .parse() - .unwrap(); + let qemu_in_wsl_env = env::var("qemu_in_wsl").unwrap_or("false".to_string()).parse().unwrap(); let qemu_in_wsl = qemu_in_wsl_arg || qemu_in_wsl_env; @@ -242,3 +227,11 @@ fn root() -> PathBuf { path.pop(); path } + +fn copy_to_image(dir: &fatfs::Dir, src_path: &str, dst_path: &str) -> Result<()> { + let data = fs::read(src_path)?; + + dir.create_file(dst_path)?.write_all(&data)?; + + Ok(()) +} diff --git a/crates/libxernel/Cargo.toml b/crates/libxernel/Cargo.toml index dcf1e763..dff82372 100644 --- a/crates/libxernel/Cargo.toml +++ b/crates/libxernel/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bitflags = "2.4.1" [features] kernel = [] diff --git a/crates/libxernel/src/sync/spin.rs b/crates/libxernel/src/sync/spin.rs index e188b8b2..cae5eee6 100644 --- a/crates/libxernel/src/sync/spin.rs +++ b/crates/libxernel/src/sync/spin.rs @@ -66,6 +66,14 @@ impl Spinlock { None } + pub fn with_lock(&self, function: F) -> U + where + F: FnOnce(&mut T) -> U, + { + let mut lock = self.lock(); + function(&mut *lock) + } + /// Unlocking a spinlock /// /// With the drop approach the lock only gets released when the [`MutexGuard`] value goes out of scope. diff --git a/crates/libxernel/src/syscall.rs b/crates/libxernel/src/syscall.rs index 11d1f9fd..3b1f8e1a 100644 --- a/crates/libxernel/src/syscall.rs +++ b/crates/libxernel/src/syscall.rs @@ -1,9 +1,12 @@ // constants for syscall numbers +use bitflags::bitflags; + pub const SYS_READ: usize = 0; pub const SYS_WRITE: usize = 1; pub const SYS_OPEN: usize = 2; pub const SYS_CLOSE: usize = 3; +pub const SYS_MMAP: usize = 4; #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[repr(isize)] @@ -18,4 +21,23 @@ pub enum SyscallError { MountPointNotFound = -8, FileSystemNotFound = -9, MalformedPath = -10, + InvalidArgument = -11, +} + +bitflags! { + #[derive(Clone, Copy)] + pub struct ProtectionFlags: u8 { + const READ = 1 << 0; + const WRITE = 1 << 1; + const EXECUTE = 1 << 2; + } +} + +bitflags! { + #[derive(PartialEq, Eq)] + pub struct MapFlags: u8 { + const SHARED = 1 << 0; + const PRIVATE = 1 << 1; + const ANONYMOUS = 1 << 3; + } } diff --git a/xernel/kernel/Cargo.toml b/xernel/kernel/Cargo.toml index 9d65d678..68797ff9 100644 --- a/xernel/kernel/Cargo.toml +++ b/xernel/kernel/Cargo.toml @@ -13,6 +13,5 @@ x86_64 = { git = "https://github.com/rust-osdev/x86_64" } acpi_parsing = { package = "acpi", version = "4.1.1" } libxernel = { path = "../../crates/libxernel", features = ["kernel"] } linked_list_allocator = { version = "0.10.3", features = [] } -bitflags = "1.3.2" paste = "1.0.14" seq-macro = "0.3.5" diff --git a/xernel/kernel/src/arch/amd64/gdt.rs b/xernel/kernel/src/arch/amd64/gdt.rs index 8ec102f7..8d1ac098 100644 --- a/xernel/kernel/src/arch/amd64/gdt.rs +++ b/xernel/kernel/src/arch/amd64/gdt.rs @@ -1,6 +1,7 @@ use alloc::alloc::alloc_zeroed; use alloc::boxed::Box; use alloc::vec::Vec; +use core::ptr::addr_of; use libxernel::sync::{Once, TicketMutex}; use x86_64::instructions::segmentation::{Segment, CS, DS, ES, SS}; use x86_64::instructions::tables::load_tss; @@ -39,7 +40,7 @@ pub struct Selectors { pub fn init() { let mut tss = TaskStateSegment::new(); tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = { - let stack_start = VirtAddr::from_ptr(unsafe { &BSP_IST_STACK }); + let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(BSP_IST_STACK) }); stack_start + IST_STACK_SIZE }; diff --git a/xernel/kernel/src/arch/amd64/idt.rs b/xernel/kernel/src/arch/amd64/idt.rs index da685b89..08085c1a 100644 --- a/xernel/kernel/src/arch/amd64/idt.rs +++ b/xernel/kernel/src/arch/amd64/idt.rs @@ -1,8 +1,10 @@ -use crate::arch::amd64::ports::outb; use crate::sched::context::CpuContext; +use crate::{arch::amd64::ports::outb, mem::mmap::handle_page_fault}; use core::arch::asm; use core::mem::size_of; +use core::ptr::addr_of; use libxernel::sync::{Spinlock, SpinlockIRQ}; +use x86_64::structures::idt::PageFaultErrorCode; use crate::arch::amd64::read_cr2; use paste::paste; @@ -165,7 +167,7 @@ pub fn init() { let idtr = Idtr::new( ((IDT.len() * size_of::()) - 1) as u16, - (&IDT as *const _) as u64, + (addr_of!(IDT) as *const _) as u64, ); idtr.load(); @@ -238,17 +240,26 @@ fn double_fault_handler(frame: CpuContext) { } fn page_fault_handler(frame: CpuContext) { - dbg!("EXCEPTION: PAGE FAULT"); - dbg!("Accessed Address: {:?}", read_cr2()); - dbg!("Error Code: {:?}", frame.error_code); - dbg!("{:#?}", frame); - println!("EXCEPTION: PAGE FAULT"); - println!("Accessed Address: {:?}", read_cr2()); - println!("Error Code: {:?}", frame.error_code); - println!("{:#?}", frame); - loop { - unsafe { - asm!("hlt"); + let addr = read_cr2(); + let error_code = PageFaultErrorCode::from_bits_truncate(frame.error_code); + + let handled_successfully = handle_page_fault(addr, error_code); + + if !handled_successfully { + dbg!("EXCEPTION: PAGE FAULT"); + dbg!("Accessed Address: {:?}", read_cr2()); + dbg!("Error Code: {:?}", frame.error_code); + dbg!("{:#?}", frame); + + error!("EXCEPTION: PAGE FAULT"); + error!("Accessed Address: {:?}", read_cr2()); + error!("Error Code: {:?}", error_code); + error!("{:#?}", frame); + + loop { + unsafe { + asm!("hlt"); + } } } } diff --git a/xernel/kernel/src/fs/file.rs b/xernel/kernel/src/fs/file.rs index 7dda3a3e..47d4e95b 100644 --- a/xernel/kernel/src/fs/file.rs +++ b/xernel/kernel/src/fs/file.rs @@ -5,11 +5,12 @@ use super::vnode::VNode; pub struct File { node: Arc>, + offset: usize, } impl File { pub fn new(node: Arc>) -> Self { - Self { node } + Self { node, offset: 0 } } pub fn get_node(&self) -> Arc> { diff --git a/xernel/kernel/src/fs/vfs.rs b/xernel/kernel/src/fs/vfs.rs index 277f4716..7f9e8c19 100644 --- a/xernel/kernel/src/fs/vfs.rs +++ b/xernel/kernel/src/fs/vfs.rs @@ -3,6 +3,7 @@ use alloc::{ sync::Arc, vec::Vec, }; +use libxernel::boot::InitAtBoot; use libxernel::sync::Spinlock; use libxernel::boot::InitAtBoot; diff --git a/xernel/kernel/src/main.rs b/xernel/kernel/src/main.rs index d88f0126..7aacd695 100644 --- a/xernel/kernel/src/main.rs +++ b/xernel/kernel/src/main.rs @@ -1,8 +1,6 @@ #![no_std] #![no_main] #![feature(abi_x86_interrupt)] -#![feature(core_intrinsics)] -#![feature(pointer_byte_offsets)] #![feature(naked_functions)] #![feature(exclusive_range_pattern)] #![feature(let_chains)] @@ -155,13 +153,13 @@ extern "C" fn kernel_main() -> ! { } } - KERNEL_PROCESS.set_once(Arc::new(Spinlock::new(Process::new(None, true)))); + KERNEL_PROCESS.set_once(Arc::new(Spinlock::new(Process::new(None)))); wait_until_cpus_registered(); scheduler::init(); - let process = Arc::new(Spinlock::new(Process::new(Some(KERNEL_PROCESS.clone()), false))); + let process = Arc::new(Spinlock::new(Process::new(Some(KERNEL_PROCESS.clone())))); let _user_task = Thread::new_user_thread(process.clone(), VirtAddr::new(0x200000)); diff --git a/xernel/kernel/src/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs new file mode 100644 index 00000000..02540c6c --- /dev/null +++ b/xernel/kernel/src/mem/mmap.rs @@ -0,0 +1,72 @@ +use libxernel::syscall::{MapFlags, ProtectionFlags, SyscallError}; +use x86_64::{ + structures::{ + idt::PageFaultErrorCode, + paging::{Page, PageSize, Size4KiB}, + }, + VirtAddr, +}; + +use crate::{allocator::align_up, sched::scheduler::Scheduler}; + +use super::{frame::FRAME_ALLOCATOR, vm::ptflags_from_protflags}; + +#[allow(unused_variables)] +pub fn mmap( + addr: usize, + len: usize, + prot: usize, + flags: usize, + fd: usize, + offset: usize, +) -> Result { + let addr = VirtAddr::new(addr as u64); + let prot = ProtectionFlags::from_bits(prot as u8).ok_or(SyscallError::InvalidArgument)?; + let flags = MapFlags::from_bits(flags as u8).ok_or(SyscallError::InvalidArgument)?; + let len = align_up(len, Size4KiB::SIZE as usize); + + let process = Scheduler::current_process(); + let mut process = process.lock(); + + match flags { + MapFlags::ANONYMOUS => { + let start_address = process.vm().find_next_start_address(); + process.vm().add_entry(start_address, len, prot, flags); + + Ok(start_address.as_u64() as isize) + } + _ => todo!("mmap: implement MAP_SHARED and MAP_PRIVATE"), + } +} + +/// Handles a page fault and returns whether the fault was handled successfully +pub fn handle_page_fault(addr: VirtAddr, error_code: PageFaultErrorCode) -> bool { + let process = Scheduler::current_process(); + let mut process = process.lock(); + + let vm_entry = process.vm().get_entry_from_address(addr); + + if let Some(vm_entry) = vm_entry { + if vm_entry.flags != MapFlags::ANONYMOUS { + todo!("handle_page_fault: implement non-anonymous mappings"); + } + + // If the page is present we don't need to map it + // FIXME: this doesn't work when COW is implemented + if error_code.contains(PageFaultErrorCode::PROTECTION_VIOLATION) { + return false; + } + + let base_addr = addr.align_down(Size4KiB::SIZE); + let frame = FRAME_ALLOCATOR.lock().allocate_frame::().unwrap(); + + let pt_flags = ptflags_from_protflags(vm_entry.prot); + let mut pt = process.get_page_table().unwrap(); + + pt.map::(frame, Page::from_start_address(base_addr).unwrap(), pt_flags, true); + + true + } else { + false + } +} diff --git a/xernel/kernel/src/mem/mod.rs b/xernel/kernel/src/mem/mod.rs index 954cf769..d8dc4ec2 100644 --- a/xernel/kernel/src/mem/mod.rs +++ b/xernel/kernel/src/mem/mod.rs @@ -1,5 +1,6 @@ pub mod frame; pub mod heap; +pub mod mmap; pub mod paging; pub mod vm; @@ -12,6 +13,9 @@ pub static HIGHER_HALF_OFFSET: Once = Once::new(); pub const KERNEL_OFFSET: u64 = 0xffff_ffff_8000_0000; pub const HEAP_START_ADDR: usize = 0xffff_9000_0000_0000; +// NOTE: there are 16 TB available for mmap until it overflows into the non-canonical address space +pub const MMAP_START_ADDR: usize = 0x0000_7000_0000_0000; + // NOTE: stack grows down pub const KERNEL_THREAD_STACK_TOP: u64 = 0xffff_a000_0000_0000; pub const USER_THREAD_STACK_TOP: u64 = 0x0000_ffff_ffff_f000; diff --git a/xernel/kernel/src/mem/paging.rs b/xernel/kernel/src/mem/paging.rs index dce77ac3..d1c11266 100644 --- a/xernel/kernel/src/mem/paging.rs +++ b/xernel/kernel/src/mem/paging.rs @@ -295,6 +295,12 @@ impl Pagemap { } } +impl Drop for Pagemap { + fn drop(&mut self) { + todo!("drop pagemap") + } +} + pub fn init() { unsafe { // create new pagetable and map the kernel + all memory maps in higher half diff --git a/xernel/kernel/src/mem/vm.rs b/xernel/kernel/src/mem/vm.rs index c15d5de0..f4691c9e 100644 --- a/xernel/kernel/src/mem/vm.rs +++ b/xernel/kernel/src/mem/vm.rs @@ -1,21 +1,27 @@ use alloc::vec::Vec; -use bitflags::bitflags; -use x86_64::VirtAddr; +use libxernel::syscall::{MapFlags, ProtectionFlags}; +use x86_64::align_up; +use x86_64::structures::paging::PageTableFlags; +use x86_64::{ + structures::paging::{PageSize, Size4KiB}, + VirtAddr, +}; -bitflags! { - pub struct ProtFlags: u8 { - const READ = 1 << 0; - const WRITE = 1 << 1; - const EXECUTE = 1 << 2; - } -} +use super::MMAP_START_ADDR; pub struct VmEntry { start: VirtAddr, - // TODO: should we remove one of these as it is reduntant? - end: VirtAddr, length: usize, - prot: ProtFlags, + pub prot: ProtectionFlags, + pub flags: MapFlags, + // TODO: add something to represent to which file this entry belongs to + file: Option<()>, +} + +impl VmEntry { + pub fn end(&self) -> VirtAddr { + self.start + self.length + } } pub struct Vm { @@ -27,18 +33,53 @@ impl Vm { Self { entries: Vec::new() } } - pub fn add_entry(&mut self, start: VirtAddr, length: usize, prot: ProtFlags) { - let end = start + length; + pub fn add_entry(&mut self, start: VirtAddr, length: usize, prot: ProtectionFlags, flags: MapFlags) { self.entries.push(VmEntry { start, - end, length, prot, + flags, + file: None, }); } + pub fn find_next_start_address(&self) -> VirtAddr { + let last_entry = self.entries.last(); + + if let Some(last_entry) = last_entry { + VirtAddr::new(align_up(last_entry.end().as_u64(), Size4KiB::SIZE)) + } else { + VirtAddr::new(MMAP_START_ADDR as u64) + } + } + + pub fn get_entry_from_address(&self, addr: VirtAddr) -> Option<&VmEntry> { + self.entries + .iter() + .find(|entry| entry.start <= addr && entry.end() > addr) + } + pub fn clean_up(&mut self) { todo!("clean up all mappings and free memory") // NOTE: don't forget to remove the entries from the vector } } + +pub fn ptflags_from_protflags(flags: ProtectionFlags) -> PageTableFlags { + let mut new_flags = PageTableFlags::PRESENT; + + if flags.contains(ProtectionFlags::READ) { + // TODO: how to handle this?? + todo!("PageTableFlags::READ") + } + + if flags.contains(ProtectionFlags::WRITE) { + new_flags |= PageTableFlags::WRITABLE; + } + + if !flags.contains(ProtectionFlags::EXECUTE) { + new_flags |= PageTableFlags::NO_EXECUTE; + } + + new_flags +} diff --git a/xernel/kernel/src/sched/process.rs b/xernel/kernel/src/sched/process.rs index 211be9b3..f2fcc620 100644 --- a/xernel/kernel/src/sched/process.rs +++ b/xernel/kernel/src/sched/process.rs @@ -7,8 +7,9 @@ use crate::fs::file::File; use crate::fs::vnode::VNode; use crate::VFS; use crate::mem::frame::FRAME_ALLOCATOR; -use crate::mem::vm::{ProtFlags, Vm}; +use crate::mem::vm::Vm; use crate::mem::{KERNEL_THREAD_STACK_TOP, STACK_SIZE, USER_THREAD_STACK_TOP}; +use crate::VFS; use alloc::collections::BTreeMap; use alloc::sync::Arc; use alloc::vec::Vec; @@ -18,6 +19,8 @@ use libxernel::sync::{Once, Spinlock}; use crate::mem::paging::{Pagemap, KERNEL_PAGE_MAPPER}; use crate::sched::thread::Thread; +use libxernel::syscall::{MapFlags, ProtectionFlags}; + /// Ongoing counter for the ProcessID static PROCESS_ID_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -40,7 +43,7 @@ pub struct Process { } impl Process { - pub fn new(parent_process: Option>>, is_kernel_process: bool) -> Self { + pub fn new(parent_process: Option>>) -> Self { let mut page_map = Pagemap::new(None); page_map.fill_with_kernel_entries(); @@ -56,7 +59,6 @@ impl Process { children: Vec::new(), threads: Vec::new(), fds: BTreeMap::new(), - is_kernel_process, kernel_thread_stack_top: KERNEL_THREAD_STACK_TOP as usize, user_thread_stack_top: USER_THREAD_STACK_TOP as usize, thread_id_counter: 0, @@ -88,7 +90,8 @@ impl Process { self.vm.add_entry( VirtAddr::new(stack_bottom as u64), STACK_SIZE as usize, - ProtFlags::READ | ProtFlags::WRITE, + ProtectionFlags::READ | ProtectionFlags::WRITE, + MapFlags::ANONYMOUS, ); stack_top @@ -120,7 +123,8 @@ impl Process { self.vm.add_entry( VirtAddr::new(stack_bottom as u64), STACK_SIZE as usize, - ProtFlags::READ | ProtFlags::WRITE, + ProtectionFlags::READ | ProtectionFlags::WRITE, + MapFlags::ANONYMOUS, ); stack_top @@ -157,6 +161,10 @@ impl Process { pub fn get_page_table(&self) -> Option { self.page_table.clone() } + + pub fn vm(&mut self) -> &mut Vm { + &mut self.vm + } } impl Drop for Process { diff --git a/xernel/kernel/src/sched/scheduler.rs b/xernel/kernel/src/sched/scheduler.rs index 89146638..e49e66ad 100644 --- a/xernel/kernel/src/sched/scheduler.rs +++ b/xernel/kernel/src/sched/scheduler.rs @@ -200,7 +200,7 @@ pub extern "C" fn scheduler_irq_handler(_stack_frame: InterruptStackFrame) { #[no_mangle] pub fn schedule_handle(ctx: CpuContext) { let mut sched = SCHEDULER.get().lock(); - if let Some(task) = sched.threads.get(0) + if let Some(task) = sched.threads.front() && task.lock().status == ThreadStatus::Running { sched.save_ctx(ctx); diff --git a/xernel/kernel/src/syscall/mod.rs b/xernel/kernel/src/syscall/mod.rs index 02b3b5ca..948b1d47 100644 --- a/xernel/kernel/src/syscall/mod.rs +++ b/xernel/kernel/src/syscall/mod.rs @@ -3,7 +3,7 @@ use alloc::{ string::{String, ToString}, }; use core::{arch::asm, ffi::c_char}; -use libxernel::syscall::{SyscallError, SYS_CLOSE, SYS_OPEN, SYS_READ, SYS_WRITE}; +use libxernel::syscall::{SyscallError, SYS_CLOSE, SYS_MMAP, SYS_OPEN, SYS_READ, SYS_WRITE}; use x86_64::{ registers::{ model_specific::{Efer, EferFlags, LStar, Star}, @@ -15,6 +15,7 @@ use x86_64::{ use crate::{ arch::amd64::gdt::GDT_BSP, fs::{self, vfs_syscalls}, + mem::mmap::mmap, }; impl From for SyscallError { @@ -173,6 +174,7 @@ extern "sysv64" fn general_syscall_handler(data: SyscallData) -> i64 { } } SYS_CLOSE => vfs_syscalls::sys_close(data.arg0), + SYS_MMAP => mmap(data.arg0, data.arg1, data.arg2, data.arg3, data.arg4, data.arg5), _ => { unimplemented!("unknown syscall: {:x?}", data); }