From e170d7be3ed6cf7eef403d19d42a58764079b30d Mon Sep 17 00:00:00 2001 From: "Raphael O." Date: Mon, 30 Oct 2023 19:46:35 +0100 Subject: [PATCH 01/23] chore: Rename FileHandle to File --- xernel/kernel/src/fs/file.rs | 5 ++--- xernel/kernel/src/fs/vfs_syscalls.rs | 4 ++-- xernel/kernel/src/sched/process.rs | 12 +++++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/xernel/kernel/src/fs/file.rs b/xernel/kernel/src/fs/file.rs index 28ae1df1..7dda3a3e 100644 --- a/xernel/kernel/src/fs/file.rs +++ b/xernel/kernel/src/fs/file.rs @@ -3,12 +3,11 @@ use libxernel::sync::Spinlock; use super::vnode::VNode; -// FileDescriptor -pub struct FileHandle { +pub struct File { node: Arc>, } -impl FileHandle { +impl File { pub fn new(node: Arc>) -> Self { Self { node } } diff --git a/xernel/kernel/src/fs/vfs_syscalls.rs b/xernel/kernel/src/fs/vfs_syscalls.rs index ca5858b1..7a13326b 100644 --- a/xernel/kernel/src/fs/vfs_syscalls.rs +++ b/xernel/kernel/src/fs/vfs_syscalls.rs @@ -2,14 +2,14 @@ use alloc::string::String; use crate::{sched::scheduler::Scheduler, syscall::Result}; -use super::{file::FileHandle, vfs::VFS}; +use super::{file::File, vfs::VFS}; pub fn sys_open(path: String, mode: u64) -> Result { let vfs = VFS.lock(); let node = vfs.vn_open(path, mode)?; - let file_handle = FileHandle::new(node); + let file_handle = File::new(node); let process = Scheduler::current_process(); let mut process = process.lock(); diff --git a/xernel/kernel/src/sched/process.rs b/xernel/kernel/src/sched/process.rs index 092d5caa..b0686dc7 100644 --- a/xernel/kernel/src/sched/process.rs +++ b/xernel/kernel/src/sched/process.rs @@ -3,7 +3,9 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use x86_64::structures::paging::{Page, PageSize, PageTableFlags, Size4KiB}; use x86_64::VirtAddr; -use crate::fs::file::FileHandle; +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::{KERNEL_THREAD_STACK_TOP, STACK_SIZE, USER_THREAD_STACK_TOP}; @@ -28,13 +30,13 @@ pub struct Process { pub parent: Weak>, pub children: Vec>>, pub threads: Vec>>, - pub fds: BTreeMap, + pub fds: BTreeMap, pub is_kernel_process: bool, pub kernel_thread_stack_top: usize, pub user_thread_stack_top: usize, pub thread_id_counter: usize, pub vm: Vm, - // TODO: add cwd here + pub cwd: Arc>, } impl Process { @@ -130,7 +132,7 @@ impl Process { tid } - pub fn append_fd(&mut self, file_handle: FileHandle) -> u32 { + pub fn append_fd(&mut self, file_handle: File) -> u32 { let mut counter = 0; let fd = loop { @@ -145,7 +147,7 @@ impl Process { fd as u32 } - pub fn get_filehandle_from_fd(&self, fd: usize) -> &FileHandle { + pub fn get_filehandle_from_fd(&self, fd: usize) -> &File { let handle = self.fds.get(&fd).expect("Failed to get FileHandle for fd"); handle From 999c300225918a723f4dc70f1e1a62fcb1b8feff Mon Sep 17 00:00:00 2001 From: "Raphael O." Date: Mon, 30 Oct 2023 19:47:05 +0100 Subject: [PATCH 02/23] feat: Have reference to root node in vfs object --- xernel/kernel/src/fs/vfs.rs | 11 ++++++++++- xernel/kernel/src/sched/process.rs | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/xernel/kernel/src/fs/vfs.rs b/xernel/kernel/src/fs/vfs.rs index 9b65a2eb..54ac28c3 100644 --- a/xernel/kernel/src/fs/vfs.rs +++ b/xernel/kernel/src/fs/vfs.rs @@ -4,6 +4,7 @@ use alloc::{ vec::Vec, }; use libxernel::sync::Spinlock; +use libxernel::boot::InitAtBoot; use super::{ mount::{Mount, VfsOps}, @@ -19,6 +20,7 @@ pub struct Vfs { mount_point_list: Vec<(PathBuf, Arc>)>, drivers: Vec<(String, Arc>)>, free_vnodes: Vec>, + root: InitAtBoot>>, } impl Vfs { @@ -29,9 +31,14 @@ impl Vfs { mount_point_list: Vec::new(), drivers: Vec::new(), free_vnodes: Vec::new(), + root: InitAtBoot::Uninitialized, } } + pub fn root_node(&self) -> Arc> { + self.root.clone() + } + pub fn get_mount(&self, mounted_on: &PathBuf) -> Result>> { self.mount_point_list .iter() @@ -142,7 +149,9 @@ pub fn init() { tmpfs.lock().vfs_init(); - vfs.register_filesystem(String::from("tmpfs"), tmpfs); + vfs.register_filesystem(String::from("tmpfs"), tmpfs.clone()); + + vfs.root = InitAtBoot::Initialized(tmpfs.lock().vfs_root().unwrap()); vfs.vn_mount("tmpfs", "/").expect("Mounting tmpfs on / failed"); } diff --git a/xernel/kernel/src/sched/process.rs b/xernel/kernel/src/sched/process.rs index b0686dc7..211be9b3 100644 --- a/xernel/kernel/src/sched/process.rs +++ b/xernel/kernel/src/sched/process.rs @@ -61,6 +61,7 @@ impl Process { user_thread_stack_top: USER_THREAD_STACK_TOP as usize, thread_id_counter: 0, vm: Vm::new(), + cwd: VFS.lock().root_node(), } } From 8921537ee4de47dfed249b4b2f9ad7c02e2f2439 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Wed, 1 Nov 2023 13:21:53 +0100 Subject: [PATCH 03/23] remove unnecessary feature --- xernel/kernel/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/xernel/kernel/src/main.rs b/xernel/kernel/src/main.rs index d88f0126..520d3f2a 100644 --- a/xernel/kernel/src/main.rs +++ b/xernel/kernel/src/main.rs @@ -2,7 +2,6 @@ #![no_main] #![feature(abi_x86_interrupt)] #![feature(core_intrinsics)] -#![feature(pointer_byte_offsets)] #![feature(naked_functions)] #![feature(exclusive_range_pattern)] #![feature(let_chains)] From 22e76de235a257e44919022c4ea46003181f0875 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Wed, 1 Nov 2023 15:28:26 +0100 Subject: [PATCH 04/23] remove ``is_kernel_process`` member in process --- xernel/kernel/src/main.rs | 4 ++-- xernel/kernel/src/sched/process.rs | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/xernel/kernel/src/main.rs b/xernel/kernel/src/main.rs index 520d3f2a..33fe82bf 100644 --- a/xernel/kernel/src/main.rs +++ b/xernel/kernel/src/main.rs @@ -154,13 +154,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/sched/process.rs b/xernel/kernel/src/sched/process.rs index 211be9b3..ca51f525 100644 --- a/xernel/kernel/src/sched/process.rs +++ b/xernel/kernel/src/sched/process.rs @@ -31,7 +31,6 @@ pub struct Process { pub children: Vec>>, pub threads: Vec>>, pub fds: BTreeMap, - pub is_kernel_process: bool, pub kernel_thread_stack_top: usize, pub user_thread_stack_top: usize, pub thread_id_counter: usize, @@ -40,7 +39,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 +55,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, From fc24ed8b45bbd951c694d59eeecfdea46ad2eee5 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Wed, 1 Nov 2023 20:17:11 +0100 Subject: [PATCH 05/23] add mmap syscall --- crates/libxernel/Cargo.toml | 1 + crates/libxernel/src/syscall.rs | 19 +++++++++++++++++++ xernel/kernel/Cargo.toml | 1 - xernel/kernel/src/mem/mmap.rs | 18 ++++++++++++++++++ xernel/kernel/src/mem/mod.rs | 1 + xernel/kernel/src/mem/vm.rs | 19 ++++++++----------- xernel/kernel/src/sched/process.rs | 12 ++++++++---- xernel/kernel/src/syscall/mod.rs | 11 ++++++++++- 8 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 xernel/kernel/src/mem/mmap.rs 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/syscall.rs b/crates/libxernel/src/syscall.rs index 11d1f9fd..a3f00c31 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)] @@ -19,3 +22,19 @@ pub enum SyscallError { FileSystemNotFound = -9, MalformedPath = -10, } + +bitflags! { + pub struct ProtectionFlags: u8 { + const READ = 1 << 0; + const WRITE = 1 << 1; + const EXECUTE = 1 << 2; + } +} + +bitflags! { + 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/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs new file mode 100644 index 00000000..5e72b380 --- /dev/null +++ b/xernel/kernel/src/mem/mmap.rs @@ -0,0 +1,18 @@ +use libxernel::syscall::{MapFlags, ProtectionFlags, SyscallError}; +use x86_64::VirtAddr; + +use crate::sched::scheduler::Scheduler; + +#[allow(unused_variables)] +pub fn mmap( + addr: VirtAddr, + len: usize, + prot: ProtectionFlags, + flags: MapFlags, + fd: usize, + offset: usize, +) -> Result { + let process = Scheduler::current_process(); + + todo!("mmap") +} diff --git a/xernel/kernel/src/mem/mod.rs b/xernel/kernel/src/mem/mod.rs index 954cf769..7385fd26 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; diff --git a/xernel/kernel/src/mem/vm.rs b/xernel/kernel/src/mem/vm.rs index c15d5de0..efe4c718 100644 --- a/xernel/kernel/src/mem/vm.rs +++ b/xernel/kernel/src/mem/vm.rs @@ -1,21 +1,16 @@ use alloc::vec::Vec; -use bitflags::bitflags; +use libxernel::syscall::{MapFlags, ProtectionFlags}; use x86_64::VirtAddr; -bitflags! { - pub struct ProtFlags: u8 { - const READ = 1 << 0; - const WRITE = 1 << 1; - const EXECUTE = 1 << 2; - } -} - pub struct VmEntry { start: VirtAddr, // TODO: should we remove one of these as it is reduntant? end: VirtAddr, length: usize, - prot: ProtFlags, + prot: ProtectionFlags, + flags: MapFlags, + // TODO: add something to represent to which file this entry belongs to + file: Option<()>, } pub struct Vm { @@ -27,13 +22,15 @@ impl Vm { Self { entries: Vec::new() } } - pub fn add_entry(&mut self, start: VirtAddr, length: usize, prot: ProtFlags) { + pub fn add_entry(&mut self, start: VirtAddr, length: usize, prot: ProtectionFlags, flags: MapFlags) { let end = start + length; self.entries.push(VmEntry { start, end, length, prot, + flags, + file: None, }); } diff --git a/xernel/kernel/src/sched/process.rs b/xernel/kernel/src/sched/process.rs index ca51f525..f2c02c76 100644 --- a/xernel/kernel/src/sched/process.rs +++ b/xernel/kernel/src/sched/process.rs @@ -5,10 +5,10 @@ use x86_64::VirtAddr; 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 +18,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); @@ -86,7 +88,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 @@ -118,7 +121,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 diff --git a/xernel/kernel/src/syscall/mod.rs b/xernel/kernel/src/syscall/mod.rs index 02b3b5ca..347335eb 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::{MapFlags, ProtectionFlags, 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,14 @@ extern "sysv64" fn general_syscall_handler(data: SyscallData) -> i64 { } } SYS_CLOSE => vfs_syscalls::sys_close(data.arg0), + SYS_MMAP => mmap( + VirtAddr::new(data.arg0 as u64), + data.arg1, + ProtectionFlags::from_bits_truncate(data.arg2 as u8), + MapFlags::from_bits_truncate(data.arg3 as u8), + data.arg4, + data.arg5, + ), _ => { unimplemented!("unknown syscall: {:x?}", data); } From dd96121e37870fb92fd130f2c3ff53273f578a95 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Wed, 1 Nov 2023 20:26:06 +0100 Subject: [PATCH 06/23] mmap: improve error handling --- crates/libxernel/src/syscall.rs | 1 + xernel/kernel/src/mem/mmap.rs | 10 +++++++--- xernel/kernel/src/syscall/mod.rs | 11 ++--------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/crates/libxernel/src/syscall.rs b/crates/libxernel/src/syscall.rs index a3f00c31..dd5843e0 100644 --- a/crates/libxernel/src/syscall.rs +++ b/crates/libxernel/src/syscall.rs @@ -21,6 +21,7 @@ pub enum SyscallError { MountPointNotFound = -8, FileSystemNotFound = -9, MalformedPath = -10, + InvalidArgument = -11, } bitflags! { diff --git a/xernel/kernel/src/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs index 5e72b380..c0462d53 100644 --- a/xernel/kernel/src/mem/mmap.rs +++ b/xernel/kernel/src/mem/mmap.rs @@ -5,13 +5,17 @@ use crate::sched::scheduler::Scheduler; #[allow(unused_variables)] pub fn mmap( - addr: VirtAddr, + addr: usize, len: usize, - prot: ProtectionFlags, - flags: MapFlags, + 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 process = Scheduler::current_process(); todo!("mmap") diff --git a/xernel/kernel/src/syscall/mod.rs b/xernel/kernel/src/syscall/mod.rs index 347335eb..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::{MapFlags, ProtectionFlags, SyscallError, SYS_CLOSE, SYS_MMAP, 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}, @@ -174,14 +174,7 @@ extern "sysv64" fn general_syscall_handler(data: SyscallData) -> i64 { } } SYS_CLOSE => vfs_syscalls::sys_close(data.arg0), - SYS_MMAP => mmap( - VirtAddr::new(data.arg0 as u64), - data.arg1, - ProtectionFlags::from_bits_truncate(data.arg2 as u8), - MapFlags::from_bits_truncate(data.arg3 as u8), - data.arg4, - data.arg5, - ), + SYS_MMAP => mmap(data.arg0, data.arg1, data.arg2, data.arg3, data.arg4, data.arg5), _ => { unimplemented!("unknown syscall: {:x?}", data); } From db6d476a1b5bdba587bfc09332e95403bab69121 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Thu, 2 Nov 2023 22:06:13 +0100 Subject: [PATCH 07/23] implement anonymous mappings --- crates/libxernel/src/syscall.rs | 1 + xernel/kernel/src/mem/mmap.rs | 18 +++++++++++++++--- xernel/kernel/src/mem/mod.rs | 1 + xernel/kernel/src/mem/vm.rs | 18 +++++++++++++++++- xernel/kernel/src/sched/process.rs | 4 ++++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/crates/libxernel/src/syscall.rs b/crates/libxernel/src/syscall.rs index dd5843e0..2bb52567 100644 --- a/crates/libxernel/src/syscall.rs +++ b/crates/libxernel/src/syscall.rs @@ -33,6 +33,7 @@ bitflags! { } bitflags! { + #[derive(PartialEq, Eq)] pub struct MapFlags: u8 { const SHARED = 1 << 0; const PRIVATE = 1 << 1; diff --git a/xernel/kernel/src/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs index c0462d53..68fb6f3c 100644 --- a/xernel/kernel/src/mem/mmap.rs +++ b/xernel/kernel/src/mem/mmap.rs @@ -1,7 +1,10 @@ use libxernel::syscall::{MapFlags, ProtectionFlags, SyscallError}; -use x86_64::VirtAddr; +use x86_64::{ + structures::paging::{PageSize, Size4KiB}, + VirtAddr, +}; -use crate::sched::scheduler::Scheduler; +use crate::{allocator::align_up, sched::scheduler::Scheduler}; #[allow(unused_variables)] pub fn mmap( @@ -15,8 +18,17 @@ pub fn mmap( 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(); - todo!("mmap") + if 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) + } else { + todo!("mmap: implement MAP_SHARED and MAP_PRIVATE"); + } } diff --git a/xernel/kernel/src/mem/mod.rs b/xernel/kernel/src/mem/mod.rs index 7385fd26..f6c7134a 100644 --- a/xernel/kernel/src/mem/mod.rs +++ b/xernel/kernel/src/mem/mod.rs @@ -13,6 +13,7 @@ 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; +pub const MMAP_START_ADDR: usize = 0xffff_a000_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/vm.rs b/xernel/kernel/src/mem/vm.rs index efe4c718..d381a8c2 100644 --- a/xernel/kernel/src/mem/vm.rs +++ b/xernel/kernel/src/mem/vm.rs @@ -1,6 +1,12 @@ use alloc::vec::Vec; use libxernel::syscall::{MapFlags, ProtectionFlags}; -use x86_64::VirtAddr; +use x86_64::align_up; +use x86_64::{ + structures::paging::{PageSize, Size4KiB}, + VirtAddr, +}; + +use super::MMAP_START_ADDR; pub struct VmEntry { start: VirtAddr, @@ -34,6 +40,16 @@ impl Vm { }); } + 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 clean_up(&mut self) { todo!("clean up all mappings and free memory") // NOTE: don't forget to remove the entries from the vector diff --git a/xernel/kernel/src/sched/process.rs b/xernel/kernel/src/sched/process.rs index f2c02c76..5e16880d 100644 --- a/xernel/kernel/src/sched/process.rs +++ b/xernel/kernel/src/sched/process.rs @@ -159,6 +159,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 { From 358d831202705300361cf3fb20bf756f3333141f Mon Sep 17 00:00:00 2001 From: Raphael O Date: Fri, 3 Nov 2023 08:32:10 +0100 Subject: [PATCH 08/23] feat: Add offset attribute to filehandle struct --- xernel/kernel/src/fs/file.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xernel/kernel/src/fs/file.rs b/xernel/kernel/src/fs/file.rs index 7dda3a3e..e35c3560 100644 --- a/xernel/kernel/src/fs/file.rs +++ b/xernel/kernel/src/fs/file.rs @@ -5,11 +5,15 @@ use super::vnode::VNode; pub struct File { node: Arc>, + offset: usize } impl File { pub fn new(node: Arc>) -> Self { - Self { node } + Self { + node: node, + offset: 0 + } } pub fn get_node(&self) -> Arc> { From 900b0d71ad90f22c359f8a77f34818334ce035bb Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Sat, 4 Nov 2023 21:50:14 +0100 Subject: [PATCH 09/23] improve mmap --- xernel/kernel/src/mem/mmap.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/xernel/kernel/src/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs index 68fb6f3c..a484123a 100644 --- a/xernel/kernel/src/mem/mmap.rs +++ b/xernel/kernel/src/mem/mmap.rs @@ -23,12 +23,13 @@ pub fn mmap( let process = Scheduler::current_process(); let mut process = process.lock(); - if flags == MapFlags::ANONYMOUS { - let start_address = process.vm().find_next_start_address(); - process.vm().add_entry(start_address, len, prot, flags); + 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) - } else { - todo!("mmap: implement MAP_SHARED and MAP_PRIVATE"); + Ok(start_address.as_u64() as isize) + } + _ => todo!("mmap: implement MAP_SHARED and MAP_PRIVATE"), } } From 85ca32c54e8ecd3ca7fbeca66aaab5c4efdb11e1 Mon Sep 17 00:00:00 2001 From: Raphael O Date: Mon, 13 Nov 2023 16:30:12 +0100 Subject: [PATCH 10/23] Add discord server to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 321f3ae9..dc8c178c 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,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: From 7d234f2b3bcd5040d500760ac2a9849d1140abb8 Mon Sep 17 00:00:00 2001 From: Raphael O Date: Wed, 15 Nov 2023 15:47:31 +0100 Subject: [PATCH 11/23] Update spin.rs --- crates/libxernel/src/sync/spin.rs | 8 ++++++++ 1 file changed, 8 insertions(+) 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. From 105459f4d83dea59fa09f0a30c5a7d6738fe9f09 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Sun, 19 Nov 2023 14:57:55 +0100 Subject: [PATCH 12/23] improve mmap --- xernel/kernel/src/arch/amd64/idt.rs | 34 +++++++++++++++++++---------- xernel/kernel/src/mem/mmap.rs | 22 ++++++++++++++++++- xernel/kernel/src/mem/mod.rs | 4 ++-- xernel/kernel/src/mem/vm.rs | 3 +-- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/xernel/kernel/src/arch/amd64/idt.rs b/xernel/kernel/src/arch/amd64/idt.rs index da685b89..47505f69 100644 --- a/xernel/kernel/src/arch/amd64/idt.rs +++ b/xernel/kernel/src/arch/amd64/idt.rs @@ -1,8 +1,9 @@ -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 libxernel::sync::{Spinlock, SpinlockIRQ}; +use x86_64::structures::idt::PageFaultErrorCode; use crate::arch::amd64::read_cr2; use paste::paste; @@ -238,17 +239,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/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs index a484123a..dfaae0c4 100644 --- a/xernel/kernel/src/mem/mmap.rs +++ b/xernel/kernel/src/mem/mmap.rs @@ -1,6 +1,9 @@ use libxernel::syscall::{MapFlags, ProtectionFlags, SyscallError}; use x86_64::{ - structures::paging::{PageSize, Size4KiB}, + structures::{ + idt::PageFaultErrorCode, + paging::{PageSize, Size4KiB}, + }, VirtAddr, }; @@ -33,3 +36,20 @@ pub fn mmap( _ => 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 { + } else { + return false; + } + + if !error_code.contains(PageFaultErrorCode::PROTECTION_VIOLATION) {} + + false +} diff --git a/xernel/kernel/src/mem/mod.rs b/xernel/kernel/src/mem/mod.rs index f6c7134a..e82bac69 100644 --- a/xernel/kernel/src/mem/mod.rs +++ b/xernel/kernel/src/mem/mod.rs @@ -13,8 +13,8 @@ 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; -pub const MMAP_START_ADDR: usize = 0xffff_a000_0000_0000; -// NOTE: stack grows down +pub const MMAP_START_ADDR: usize = 0xffff_a000_0000_0000; // TODO: move to lower half + // 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/vm.rs b/xernel/kernel/src/mem/vm.rs index d381a8c2..c1da114c 100644 --- a/xernel/kernel/src/mem/vm.rs +++ b/xernel/kernel/src/mem/vm.rs @@ -10,8 +10,7 @@ use super::MMAP_START_ADDR; pub struct VmEntry { start: VirtAddr, - // TODO: should we remove one of these as it is reduntant? - end: VirtAddr, + end: VirtAddr, // TODO: remove end length: usize, prot: ProtectionFlags, flags: MapFlags, From 7a36ebf54667d07360e8b17e51f5d8904ec19b03 Mon Sep 17 00:00:00 2001 From: Raphael O Date: Wed, 29 Nov 2023 11:03:00 +0100 Subject: [PATCH 13/23] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index dc8c178c..38442af1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # 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) From 6d1e834f89ca47ab736f2b22b5a387d79c550a8e Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Sun, 10 Dec 2023 16:24:01 +0100 Subject: [PATCH 14/23] fix mmap base address --- xernel/kernel/src/mem/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xernel/kernel/src/mem/mod.rs b/xernel/kernel/src/mem/mod.rs index e82bac69..d8dc4ec2 100644 --- a/xernel/kernel/src/mem/mod.rs +++ b/xernel/kernel/src/mem/mod.rs @@ -13,8 +13,10 @@ 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; -pub const MMAP_START_ADDR: usize = 0xffff_a000_0000_0000; // TODO: move to lower half - // NOTE: stack grows down +// 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; From 3b8a797b0d523d14e1dde53d9fc0e6d1d11a3fd3 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Fri, 12 Jan 2024 10:01:15 +0100 Subject: [PATCH 15/23] allocate anonymous pages on page fault --- crates/libxernel/src/syscall.rs | 1 + xernel/kernel/src/mem/mmap.rs | 25 ++++++++++++++++++++++--- xernel/kernel/src/mem/vm.rs | 30 ++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/crates/libxernel/src/syscall.rs b/crates/libxernel/src/syscall.rs index 2bb52567..3b1f8e1a 100644 --- a/crates/libxernel/src/syscall.rs +++ b/crates/libxernel/src/syscall.rs @@ -25,6 +25,7 @@ pub enum SyscallError { } bitflags! { + #[derive(Clone, Copy)] pub struct ProtectionFlags: u8 { const READ = 1 << 0; const WRITE = 1 << 1; diff --git a/xernel/kernel/src/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs index dfaae0c4..465cc407 100644 --- a/xernel/kernel/src/mem/mmap.rs +++ b/xernel/kernel/src/mem/mmap.rs @@ -2,13 +2,15 @@ use libxernel::syscall::{MapFlags, ProtectionFlags, SyscallError}; use x86_64::{ structures::{ idt::PageFaultErrorCode, - paging::{PageSize, Size4KiB}, + 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, @@ -45,11 +47,28 @@ pub fn handle_page_fault(addr: VirtAddr, error_code: PageFaultErrorCode) -> bool 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); + + return true; } else { return false; } - if !error_code.contains(PageFaultErrorCode::PROTECTION_VIOLATION) {} - false } diff --git a/xernel/kernel/src/mem/vm.rs b/xernel/kernel/src/mem/vm.rs index c1da114c..8d98bd68 100644 --- a/xernel/kernel/src/mem/vm.rs +++ b/xernel/kernel/src/mem/vm.rs @@ -1,6 +1,7 @@ use alloc::vec::Vec; use libxernel::syscall::{MapFlags, ProtectionFlags}; use x86_64::align_up; +use x86_64::structures::paging::PageTableFlags; use x86_64::{ structures::paging::{PageSize, Size4KiB}, VirtAddr, @@ -12,8 +13,8 @@ pub struct VmEntry { start: VirtAddr, end: VirtAddr, // TODO: remove end length: usize, - prot: ProtectionFlags, - flags: MapFlags, + pub prot: ProtectionFlags, + pub flags: MapFlags, // TODO: add something to represent to which file this entry belongs to file: Option<()>, } @@ -49,8 +50,33 @@ impl Vm { } } + 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 +} From 3066e5721b566a6609676a675933c0e2ca2e76a1 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Fri, 12 Jan 2024 10:04:41 +0100 Subject: [PATCH 16/23] fix clippy warnings --- xernel/kernel/src/arch/amd64/gdt.rs | 3 ++- xernel/kernel/src/arch/amd64/idt.rs | 3 ++- xernel/kernel/src/fs/file.rs | 2 +- xernel/kernel/src/main.rs | 1 - xernel/kernel/src/mem/mmap.rs | 6 ++---- xernel/kernel/src/sched/scheduler.rs | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) 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 47505f69..08085c1a 100644 --- a/xernel/kernel/src/arch/amd64/idt.rs +++ b/xernel/kernel/src/arch/amd64/idt.rs @@ -2,6 +2,7 @@ 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; @@ -166,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(); diff --git a/xernel/kernel/src/fs/file.rs b/xernel/kernel/src/fs/file.rs index e35c3560..5de8095b 100644 --- a/xernel/kernel/src/fs/file.rs +++ b/xernel/kernel/src/fs/file.rs @@ -11,7 +11,7 @@ pub struct File { impl File { pub fn new(node: Arc>) -> Self { Self { - node: node, + node, offset: 0 } } diff --git a/xernel/kernel/src/main.rs b/xernel/kernel/src/main.rs index 33fe82bf..7aacd695 100644 --- a/xernel/kernel/src/main.rs +++ b/xernel/kernel/src/main.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] #![feature(abi_x86_interrupt)] -#![feature(core_intrinsics)] #![feature(naked_functions)] #![feature(exclusive_range_pattern)] #![feature(let_chains)] diff --git a/xernel/kernel/src/mem/mmap.rs b/xernel/kernel/src/mem/mmap.rs index 465cc407..02540c6c 100644 --- a/xernel/kernel/src/mem/mmap.rs +++ b/xernel/kernel/src/mem/mmap.rs @@ -65,10 +65,8 @@ pub fn handle_page_fault(addr: VirtAddr, error_code: PageFaultErrorCode) -> bool pt.map::(frame, Page::from_start_address(base_addr).unwrap(), pt_flags, true); - return true; + true } else { - return false; + false } - - false } 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); From ba0cac32f63f2e68bcc83a5790739da26ae344a6 Mon Sep 17 00:00:00 2001 From: Markus Pfeifenberger Date: Wed, 17 Jan 2024 18:30:08 +0000 Subject: [PATCH 17/23] actions: create lint (#4) * actions: add lint * test * add mtools * fmt --- .github/workflows/check.yml | 13 +++++++++++++ xernel/kernel/src/fs/file.rs | 7 ++----- xernel/kernel/src/fs/vfs.rs | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/check.yml 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/xernel/kernel/src/fs/file.rs b/xernel/kernel/src/fs/file.rs index 5de8095b..47d4e95b 100644 --- a/xernel/kernel/src/fs/file.rs +++ b/xernel/kernel/src/fs/file.rs @@ -5,15 +5,12 @@ use super::vnode::VNode; pub struct File { node: Arc>, - offset: usize + offset: usize, } impl File { pub fn new(node: Arc>) -> Self { - Self { - node, - offset: 0 - } + 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 54ac28c3..6e3028b4 100644 --- a/xernel/kernel/src/fs/vfs.rs +++ b/xernel/kernel/src/fs/vfs.rs @@ -3,8 +3,8 @@ use alloc::{ sync::Arc, vec::Vec, }; -use libxernel::sync::Spinlock; use libxernel::boot::InitAtBoot; +use libxernel::sync::Spinlock; use super::{ mount::{Mount, VfsOps}, From 29e243e60abf1ff9e3839c27179599bc159fcaf0 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Mon, 15 Jan 2024 20:49:56 +0100 Subject: [PATCH 18/23] build image using fatfs crate --- build/xtask/Cargo.toml | 1 + build/xtask/src/main.rs | 62 ++++++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 17 deletions(-) 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..2d8c4a5d 100644 --- a/build/xtask/src/main.rs +++ b/build/xtask/src/main.rs @@ -1,8 +1,11 @@ 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::ptr::slice_from_raw_parts; +use std::{env, fs, vec}; use xshell::{cmd, Shell}; const HELP: &str = "\ @@ -85,14 +88,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,6 +117,35 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> { let build_dir = if rl { "release" } else { "debug" }; let diskname = "xernel.hdd"; + + let data_vec = vec![0_u8; 64 * 1024 * 1024]; + let ptr = data_vec.as_ptr(); + + let mut disk = Cursor::new(data_vec); + + format_volume(&mut disk, FormatVolumeOptions::new().fat_type(fatfs::FatType::Fat32))?; + + let fs = fatfs::FileSystem::new(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, "./xernel/kernel/limine.cfg", "limine.cfg")?; + 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")?; + + // fs.unmount()?; + + let illegal_copy = unsafe { &*slice_from_raw_parts(ptr, 64 * 1024 * 1024) }; + + fs::write(diskname, illegal_copy)?; + + /* let disksize = 64.to_string(); cmd!( @@ -149,6 +174,7 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> { "mcopy -i {diskname} xernel/kernel/limine/BOOTX64.EFI ::/EFI/BOOT" ) .run()?; + */ Ok(()) } @@ -159,10 +185,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 +197,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 +262,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(()) +} From 51f5b5772d4a84c6da7c8eb82702c567d97aea51 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Thu, 18 Jan 2024 09:27:02 +0100 Subject: [PATCH 19/23] build: remove unsafe code --- build/xtask/src/main.rs | 60 +++++++++-------------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/build/xtask/src/main.rs b/build/xtask/src/main.rs index 2d8c4a5d..f39fc400 100644 --- a/build/xtask/src/main.rs +++ b/build/xtask/src/main.rs @@ -4,7 +4,6 @@ use fatfs::{format_volume, FormatVolumeOptions}; use pico_args::Arguments; use std::io::{Cursor, Read, Seek, Write}; use std::path::{Path, PathBuf}; -use std::ptr::slice_from_raw_parts; use std::{env, fs, vec}; use xshell::{cmd, Shell}; @@ -119,62 +118,27 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> { let diskname = "xernel.hdd"; let data_vec = vec![0_u8; 64 * 1024 * 1024]; - let ptr = data_vec.as_ptr(); - let mut disk = Cursor::new(data_vec); format_volume(&mut disk, FormatVolumeOptions::new().fat_type(fatfs::FatType::Fat32))?; - let fs = fatfs::FileSystem::new(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, "./xernel/kernel/limine.cfg", "limine.cfg")?; - 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")?; - - // fs.unmount()?; + let fs = fatfs::FileSystem::new(&mut disk, fatfs::FsOptions::new())?; + { + let root_dir = fs.root_dir(); - let illegal_copy = unsafe { &*slice_from_raw_parts(ptr, 64 * 1024 * 1024) }; + copy_to_image(&root_dir, &format!("./target/{target}/{build_dir}/xernel"), "xernel")?; - fs::write(diskname, illegal_copy)?; + copy_to_image(&root_dir, "./xernel/kernel/limine.cfg", "limine.cfg")?; + copy_to_image(&root_dir, "./logo.bmp", "logo.bmp")?; - /* - let disksize = 64.to_string(); + let dir = root_dir.create_dir("EFI")?; + let dir = dir.create_dir("BOOT")?; - cmd!( - sh, - "dd if=/dev/zero of={diskname} bs=1M count=0 seek={disksize}" - ) - .run()?; - - 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()?; + copy_to_image(&dir, "./xernel/kernel/limine/BOOTX64.EFI", "BOOTX64.EFI")?; + } + fs.unmount()?; - 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()?; - */ + fs::write(diskname, disk.into_inner())?; Ok(()) } From a4a49e18330a2d277f7a1f4c3752b2ddac4701f2 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Thu, 18 Jan 2024 10:30:31 +0100 Subject: [PATCH 20/23] readme: remove mtools depedency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 38442af1..fbe5e785 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ 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. From fe8705a38c33a70267f1b5ac7c7742d9196a1111 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Thu, 18 Jan 2024 11:00:12 +0100 Subject: [PATCH 21/23] clean up image creation --- build/xtask/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/xtask/src/main.rs b/build/xtask/src/main.rs index f39fc400..a644f576 100644 --- a/build/xtask/src/main.rs +++ b/build/xtask/src/main.rs @@ -116,8 +116,9 @@ 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 * 1024 * 1024; // 64 MB - let data_vec = vec![0_u8; 64 * 1024 * 1024]; + let data_vec = vec![0_u8; disksize]; let mut disk = Cursor::new(data_vec); format_volume(&mut disk, FormatVolumeOptions::new().fat_type(fatfs::FatType::Fat32))?; @@ -128,13 +129,13 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> { copy_to_image(&root_dir, &format!("./target/{target}/{build_dir}/xernel"), "xernel")?; - copy_to_image(&root_dir, "./xernel/kernel/limine.cfg", "limine.cfg")?; 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()?; From c76035115cbe8d2714334f4bbcdf10ffd124ca4c Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Fri, 19 Jan 2024 18:06:55 +0100 Subject: [PATCH 22/23] add todo for dropping pagemap --- xernel/kernel/src/mem/paging.rs | 6 ++++++ 1 file changed, 6 insertions(+) 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 From d4a645d0c0ae8110a8ca3133ef5740f2ace0d8f6 Mon Sep 17 00:00:00 2001 From: 0x6D70 Date: Fri, 19 Jan 2024 18:09:28 +0100 Subject: [PATCH 23/23] remove useless member in VmEntry --- xernel/kernel/src/mem/vm.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xernel/kernel/src/mem/vm.rs b/xernel/kernel/src/mem/vm.rs index 8d98bd68..f4691c9e 100644 --- a/xernel/kernel/src/mem/vm.rs +++ b/xernel/kernel/src/mem/vm.rs @@ -11,7 +11,6 @@ use super::MMAP_START_ADDR; pub struct VmEntry { start: VirtAddr, - end: VirtAddr, // TODO: remove end length: usize, pub prot: ProtectionFlags, pub flags: MapFlags, @@ -19,6 +18,12 @@ pub struct VmEntry { file: Option<()>, } +impl VmEntry { + pub fn end(&self) -> VirtAddr { + self.start + self.length + } +} + pub struct Vm { entries: Vec, } @@ -29,10 +34,8 @@ impl Vm { } pub fn add_entry(&mut self, start: VirtAddr, length: usize, prot: ProtectionFlags, flags: MapFlags) { - let end = start + length; self.entries.push(VmEntry { start, - end, length, prot, flags, @@ -44,7 +47,7 @@ impl Vm { let last_entry = self.entries.last(); if let Some(last_entry) = last_entry { - VirtAddr::new(align_up(last_entry.end.as_u64(), Size4KiB::SIZE)) + VirtAddr::new(align_up(last_entry.end().as_u64(), Size4KiB::SIZE)) } else { VirtAddr::new(MMAP_START_ADDR as u64) } @@ -53,7 +56,7 @@ impl Vm { pub fn get_entry_from_address(&self, addr: VirtAddr) -> Option<&VmEntry> { self.entries .iter() - .find(|entry| entry.start <= addr && entry.end > addr) + .find(|entry| entry.start <= addr && entry.end() > addr) } pub fn clean_up(&mut self) {