diff --git a/kernel/src/arch/aarch64/table.rs b/kernel/src/arch/aarch64/table.rs deleted file mode 100644 index b45b021..0000000 --- a/kernel/src/arch/aarch64/table.rs +++ /dev/null @@ -1,422 +0,0 @@ -// -// #[no_mangle] -// static mut KERNEL_TTBR1: FixedTableGroup = FixedTableGroup::empty(); - -/// Transparent wrapper structure representing a single -/// translation table entry -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct Entry(u64); - -/// Structure describing a single level of translation mappings -#[repr(C, align(0x1000))] -pub struct Table { - entries: [Entry; 512], -} - -/// Wrapper for top-most level of address translation tables -#[repr(transparent)] -pub struct Space(Table); - -bitflags! { - /// Attributes attached to each translation [Entry] - pub struct MapAttributes: u64 { - // TODO use 2 lower bits to determine mapping size? - /// nG bit -- determines whether a TLB entry associated with this mapping - /// applies only to current ASID or all ASIDs. - const NOT_GLOBAL = 1 << 11; - /// AF bit -- must be set by software, otherwise Access Error exception is - /// generated when the page is accessed - const ACCESS = 1 << 10; - /// The memory region is outer-shareable - const SH_OUTER = 2 << 8; - /// This page is used for device-MMIO mapping and uses MAIR attribute #1 - const DEVICE = 1 << 2; - - /// Pages marked with this bit are Copy-on-Write - const EX_COW = 1 << 55; - - /// UXN bit -- if set, page may not be used for instruction fetching from EL0 - const UXN = 1 << 54; - /// PXN bit -- if set, page may not be used for instruction fetching from EL1 - const PXN = 1 << 53; - - // AP field - // Default behavior is: read-write for EL1, no access for EL0 - /// If set, the page referred to by this entry is read-only for both EL0/EL1 - const AP_BOTH_READONLY = 3 << 6; - /// If set, the page referred to by this entry is read-write for both EL0/EL1 - const AP_BOTH_READWRITE = 1 << 6; - } -} - -impl Table { - /// Returns next-level translation table reference for `index`, if one is present. - /// If `index` represents a `Block`-type mapping, will return an error. - /// If `index` does not map to any translation table, will try to allocate, init and - /// map a new one, returning it after doing so. - pub fn next_level_table_or_alloc(&mut self, index: usize) -> Result<&'static mut Table, Errno> { - let entry = self[index]; - if entry.is_present() { - if !entry.is_table() { - return Err(Errno::InvalidArgument); - } - - Ok(unsafe { &mut *(mem::virtualize(entry.address_unchecked()) as *mut _) }) - } else { - let phys = phys::alloc_page(PageUsage::Paging)?; - let res = unsafe { &mut *(mem::virtualize(phys) as *mut Self) }; - self[index] = Entry::table(phys, MapAttributes::empty()); - res.entries.fill(Entry::invalid()); - Ok(res) - } - } - - /// Returns next-level translation table reference for `index`, if one is present. - /// Same as [next_level_table_or_alloc], but returns `None` if no table is mapped. - pub fn next_level_table(&mut self, index: usize) -> Option<&'static mut Table> { - let entry = self[index]; - if entry.is_present() { - if !entry.is_table() { - panic!("Entry is not a table: idx={}", index); - } - - Some(unsafe { &mut *(mem::virtualize(entry.address_unchecked()) as *mut _) }) - } else { - None - } - } - - /// Constructs and fills a [Table] with non-present mappings - pub const fn empty() -> Table { - Table { - entries: [Entry::invalid(); 512], - } - } -} - -impl Index for Table { - type Output = Entry; - - fn index(&self, index: usize) -> &Self::Output { - &self.entries[index] - } -} - -impl IndexMut for Table { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.entries[index] - } -} - -impl Entry { - const PRESENT: u64 = 1 << 0; - const TABLE: u64 = 1 << 1; - const PHYS_MASK: u64 = 0x0000FFFFFFFFF000; - - /// Constructs a single non-present mapping - pub const fn invalid() -> Self { - Self(0) - } - - /// Constructs a `Block`-type memory mapping - pub const fn block(phys: usize, attrs: MapAttributes) -> Self { - Self((phys as u64 & Self::PHYS_MASK) | attrs.bits() | Self::PRESENT) - } - - /// Constructs a `Table` or `Page`-type mapping depending on translation level - /// this entry is used at - pub const fn table(phys: usize, attrs: MapAttributes) -> Self { - Self((phys as u64 & Self::PHYS_MASK) | attrs.bits() | Self::PRESENT | Self::TABLE) - } - - /// Returns `true` if this entry is not invalid - pub const fn is_present(self) -> bool { - self.0 & Self::PRESENT != 0 - } - - /// Returns `true` if this entry is a `Table` or `Page`-type mapping - pub const fn is_table(self) -> bool { - self.0 & Self::TABLE != 0 - } - - /// Returns the target address of this translation entry. - /// - /// # Safety - /// - /// Does not check if the entry is actually valid. - pub const unsafe fn address_unchecked(self) -> usize { - (self.0 & Self::PHYS_MASK) as usize - } - - unsafe fn set_address(&mut self, address: usize) { - self.0 &= !Self::PHYS_MASK; - self.0 |= (address as u64) & Self::PHYS_MASK; - } - - unsafe fn fork_flags(self) -> MapAttributes { - MapAttributes::from_bits_unchecked(self.0 & !Self::PHYS_MASK) - } - - fn set_cow(&mut self) { - self.0 |= (MapAttributes::AP_BOTH_READONLY | MapAttributes::EX_COW).bits(); - } - - fn clear_cow(&mut self) { - self.0 &= !(MapAttributes::AP_BOTH_READONLY | MapAttributes::EX_COW).bits(); - self.0 |= MapAttributes::AP_BOTH_READWRITE.bits(); - } - - #[inline] - fn is_cow(self) -> bool { - let attrs = (MapAttributes::AP_BOTH_READONLY | MapAttributes::EX_COW).bits(); - self.0 & attrs == attrs - } -} - -impl Space { - /// Creates a new virtual address space and fills it with [Entry::invalid()] - /// mappings. Does physical memory page allocation. - pub fn alloc_empty() -> Result<&'static mut Self, Errno> { - let phys = phys::alloc_page(PageUsage::Paging)?; - let res = unsafe { &mut *(mem::virtualize(phys) as *mut Self) }; - res.0.entries.fill(Entry::invalid()); - Ok(res) - } - - /// Inserts a single `virt` -> `phys` translation entry to this address space. - /// - /// TODO: only works with 4K-sized pages at this moment. - pub fn map(&mut self, virt: usize, phys: usize, flags: MapAttributes) -> Result<(), Errno> { - let l0i = virt >> 30; - let l1i = (virt >> 21) & 0x1FF; - let l2i = (virt >> 12) & 0x1FF; - - let l1_table = self.0.next_level_table_or_alloc(l0i)?; - let l2_table = l1_table.next_level_table_or_alloc(l1i)?; - - if l2_table[l2i].is_present() { - Err(Errno::AlreadyExists) - } else { - l2_table[l2i] = Entry::table(phys, flags | MapAttributes::ACCESS); - #[cfg(feature = "verbose")] - debugln!("{:#p} Map {:#x} -> {:#x}, {:?}", self, virt, phys, flags); - Ok(()) - } - } - - /// Translates a virtual address into a corresponding physical one. - /// - /// Only works for 4K pages atm. - // TODO extract attributes - pub fn translate(&mut self, virt: usize) -> Result { - let l0i = virt >> 30; - let l1i = (virt >> 21) & 0x1FF; - let l2i = (virt >> 12) & 0x1FF; - - let l1_table = self.0.next_level_table(l0i).ok_or(Errno::DoesNotExist)?; - let l2_table = l1_table.next_level_table(l1i).ok_or(Errno::DoesNotExist)?; - - let entry = l2_table[l2i]; - if entry.is_present() { - Ok(unsafe { entry.address_unchecked() }) - } else { - Err(Errno::DoesNotExist) - } - } - - /// Attempts to resolve a page fault at `virt` address by copying the - /// underlying Copy-on-Write mapping (if any is present) - pub fn try_cow_copy(&mut self, virt: usize) -> Result<(), Errno> { - let virt = virt & !0xFFF; - let l0i = virt >> 30; - let l1i = (virt >> 21) & 0x1FF; - let l2i = (virt >> 12) & 0x1FF; - - let l1_table = self.0.next_level_table(l0i).ok_or(Errno::DoesNotExist)?; - let l2_table = l1_table.next_level_table(l1i).ok_or(Errno::DoesNotExist)?; - - let entry = l2_table[l2i]; - - if !entry.is_present() { - warnln!("Entry is not present: {:#x}", virt); - return Err(Errno::DoesNotExist); - } - - let src_phys = unsafe { entry.address_unchecked() }; - if !entry.is_cow() { - warnln!( - "Entry is not marked as CoW: {:#x}, points to {:#x}", - virt, - src_phys - ); - return Err(Errno::DoesNotExist); - } - - let dst_phys = unsafe { phys::copy_cow_page(src_phys)? }; - unsafe { - l2_table[l2i].set_address(dst_phys); - } - l2_table[l2i].clear_cow(); - - Ok(()) - } - - /// Allocates a contiguous region from the address space and maps - /// physical pages to it - pub fn allocate( - &mut self, - start: usize, - end: usize, - len: usize, - flags: MapAttributes, - usage: PageUsage, - ) -> Result { - 'l0: for page in (start..end).step_by(0x1000) { - for i in 0..len { - if self.translate(page + i * 0x1000).is_ok() { - continue 'l0; - } - } - - for i in 0..len { - let phys = phys::alloc_page(usage).unwrap(); - self.map(page + i * 0x1000, phys, flags).unwrap(); - } - return Ok(page); - } - Err(Errno::OutOfMemory) - } - - /// Removes a single 4K page mapping from the table and - /// releases the underlying physical memory - pub fn unmap_single(&mut self, page: usize) -> Result<(), Errno> { - let l0i = page >> 30; - let l1i = (page >> 21) & 0x1FF; - let l2i = (page >> 12) & 0x1FF; - - let l1_table = self.0.next_level_table(l0i).ok_or(Errno::DoesNotExist)?; - let l2_table = l1_table.next_level_table(l1i).ok_or(Errno::DoesNotExist)?; - - let entry = l2_table[l2i]; - - if !entry.is_present() { - return Err(Errno::DoesNotExist); - } - - let phys = unsafe { entry.address_unchecked() }; - unsafe { - phys::free_page(phys)?; - } - l2_table[l2i] = Entry::invalid(); - - unsafe { - asm!("tlbi vaae1, {}", in(reg) page); - } - - // TODO release paging structure memory - - Ok(()) - } - - /// Releases a range of virtual pages and their corresponding physical pages - pub fn free(&mut self, start: usize, len: usize) -> Result<(), Errno> { - for i in 0..len { - self.unmap_single(start + i * 0x1000)?; - } - Ok(()) - } - - /// Performs a copy of the address space, cloning data owned by it - pub fn fork(&mut self) -> Result<&'static mut Self, Errno> { - let res = Self::alloc_empty()?; - for l0i in 0..512 { - if let Some(l1_table) = self.0.next_level_table(l0i) { - for l1i in 0..512 { - if let Some(l2_table) = l1_table.next_level_table(l1i) { - for l2i in 0..512 { - let entry = l2_table[l2i]; - - if !entry.is_present() { - continue; - } - - assert!(entry.is_table()); - let src_phys = unsafe { entry.address_unchecked() }; - let virt_addr = (l0i << 30) | (l1i << 21) | (l2i << 12); - let dst_phys = unsafe { phys::fork_page(src_phys)? }; - - let mut flags = unsafe { entry.fork_flags() }; - if dst_phys != src_phys { - todo!(); - // res.map(virt_addr, dst_phys, flags)?; - } else { - let writable = flags & MapAttributes::AP_BOTH_READONLY - == MapAttributes::AP_BOTH_READWRITE; - - if writable { - flags |= - MapAttributes::AP_BOTH_READONLY | MapAttributes::EX_COW; - l2_table[l2i].set_cow(); - - unsafe { - asm!("tlbi vaae1, {}", in(reg) virt_addr); - } - } - - res.map(virt_addr, dst_phys, flags)?; - } - } - } - } - } - } - Ok(res) - } - - /// Releases all the mappings from the address space. Frees all - /// memory pages referenced by this space as well as those used for - /// its paging tables. - /// - /// # Safety - /// - /// Unsafe: may invalidate currently active address space - pub unsafe fn release(space: &mut Self) { - for l0i in 0..512 { - let l0_entry = space.0[l0i]; - if !l0_entry.is_present() { - continue; - } - - assert!(l0_entry.is_table()); - let l1_table = &mut *(mem::virtualize(l0_entry.address_unchecked()) as *mut Table); - - for l1i in 0..512 { - let l1_entry = l1_table[l1i]; - if !l1_entry.is_present() { - continue; - } - assert!(l1_entry.is_table()); - let l2_table = &mut *(mem::virtualize(l1_entry.address_unchecked()) as *mut Table); - - for l2i in 0..512 { - let entry = l2_table[l2i]; - if !entry.is_present() { - continue; - } - - assert!(entry.is_table()); - phys::free_page(entry.address_unchecked()).unwrap(); - } - phys::free_page(l1_entry.address_unchecked()).unwrap(); - } - phys::free_page(l0_entry.address_unchecked()).unwrap(); - } - memset(space as *mut Space as *mut u8, 0, 4096); - } - - /// Returns the physical address of this structure - pub fn address_phys(&mut self) -> usize { - (self as *mut _ as usize) - mem::KERNEL_OFFSET - } -} diff --git a/kernel/src/arch/aarch64/virt/mod.rs b/kernel/src/arch/aarch64/virt/mod.rs index 46a707c..8c2abba 100644 --- a/kernel/src/arch/aarch64/virt/mod.rs +++ b/kernel/src/arch/aarch64/virt/mod.rs @@ -85,6 +85,11 @@ impl From for RawAttributesImpl { } } +/// Performs initialization of virtual memory control by kernel +/// +/// # Safety +/// +/// Only safe to be called once during virtual memory init. pub unsafe fn enable() { fixed::init_device_map(); diff --git a/kernel/src/arch/x86_64/boot/mod.rs b/kernel/src/arch/x86_64/boot/mod.rs index e4ff15c..ea23e8e 100644 --- a/kernel/src/arch/x86_64/boot/mod.rs +++ b/kernel/src/arch/x86_64/boot/mod.rs @@ -1,3 +1,4 @@ +//! x86_64 common boot logic use crate::arch::x86_64::{ self, gdt, idt, intc, reg::{CR0, CR4}, @@ -7,22 +8,24 @@ use crate::config::{ConfigKey, CONFIG}; use crate::debug; use crate::dev::{display::FramebufferInfo, irq::IntSource, pseudo, Device}; use crate::font; -use crate::fs::{devfs::{self, CharDeviceType}, sysfs}; +use crate::fs::{ + devfs::{self, CharDeviceType}, + sysfs, +}; use crate::mem::{ self, heap, phys::{self, MemoryRegion, PageUsage, ReservedRegion}, virt, }; use crate::proc; -use core::arch::{asm, global_asm}; +use core::arch::global_asm; use core::mem::MaybeUninit; -use multiboot2::{BootInformation, MemoryArea}; use tock_registers::interfaces::ReadWriteable; static mut RESERVED_REGION_MB2: MaybeUninit = MaybeUninit::uninit(); #[no_mangle] -extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! { +extern "C" fn __x86_64_bsp_main(_mb_checksum: u32, mb_info_ptr: u32) -> ! { CR4.modify(CR4::OSXMMEXCPT::SET + CR4::OSFXSR::SET); CR0.modify(CR0::EM::CLEAR + CR0::MP::SET); diff --git a/kernel/src/arch/x86_64/context.rs b/kernel/src/arch/x86_64/context.rs index ecf567f..f015240 100644 --- a/kernel/src/arch/x86_64/context.rs +++ b/kernel/src/arch/x86_64/context.rs @@ -1,3 +1,4 @@ +//! Thread context use crate::arch::platform::ForkFrame; use crate::mem::{ self, diff --git a/kernel/src/arch/x86_64/exception.rs b/kernel/src/arch/x86_64/exception.rs index e7c9e8c..6519a3d 100644 --- a/kernel/src/arch/x86_64/exception.rs +++ b/kernel/src/arch/x86_64/exception.rs @@ -1,11 +1,12 @@ use crate::arch::{intrin, x86_64}; use crate::debug::Level; use crate::dev::irq::{IntController, IrqContext}; -use core::arch::{asm, global_asm}; -use libsys::{error::Errno, signal::Signal}; use crate::mem::{self, virt::table::Space}; -use crate::proc::{Thread, sched}; +use crate::proc::{sched, Thread}; +use core::arch::asm; +use libsys::{error::Errno, signal::Signal}; +#[allow(dead_code)] #[derive(Debug)] struct ExceptionFrame { r15: u64, @@ -80,7 +81,11 @@ extern "C" fn __x86_64_exception_handler(frame: &mut ExceptionFrame) { }); if res.is_err() { - errorln!("Page fault at {:#x} in user {:?}", frame.rip, thread.owner_id()); + errorln!( + "Page fault at {:#x} in user {:?}", + frame.rip, + thread.owner_id() + ); pfault_dump(Level::Error, frame, cr2); proc.enter_fault_signal(thread, Signal::SegmentationFault); } diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index de21576..1e3f3c9 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -1,6 +1,7 @@ use core::arch::asm; use core::mem::size_of_val; +#[allow(dead_code)] #[repr(packed)] struct Entry { limit_lo: u16, @@ -11,6 +12,7 @@ struct Entry { base_hi: u8, } +#[allow(dead_code)] #[repr(packed)] struct Tss { __res0: u32, @@ -30,6 +32,7 @@ struct Tss { iopb_base: u16, } +#[allow(dead_code)] #[repr(packed)] struct Pointer { size: u16, @@ -123,6 +126,14 @@ static mut GDT: [Entry; SIZE] = [ Entry::null(), ]; +#[inline] +unsafe fn load_gdt(ptr: &Pointer, tr: u16) { + asm!(r#" + lgdt ({}) + ltr %ax + "#, in(reg) ptr, in("ax") tr, options(att_syntax)); +} + pub unsafe fn init() { let tss_addr = &TSS as *const _ as usize; @@ -138,10 +149,5 @@ pub unsafe fn init() { size: size_of_val(&GDT) as u16 - 1, offset: &GDT as *const _ as usize, }; - asm!(r#" - lgdt ({}) - - mov $0x28, %ax - ltr %ax - "#, in(reg) &gdtr, options(att_syntax)); + load_gdt(&gdtr, 0x28); } diff --git a/kernel/src/arch/x86_64/idt.rs b/kernel/src/arch/x86_64/idt.rs index be5d9b0..d035a5c 100644 --- a/kernel/src/arch/x86_64/idt.rs +++ b/kernel/src/arch/x86_64/idt.rs @@ -1,6 +1,7 @@ use core::arch::{asm, global_asm}; use core::mem::size_of_val; +#[allow(dead_code)] #[derive(Clone, Copy)] #[repr(packed)] pub struct Entry { @@ -13,6 +14,7 @@ pub struct Entry { __res1: u32, } +#[allow(dead_code)] #[repr(packed)] struct Pointer { limit: u16, @@ -52,7 +54,12 @@ impl Entry { static mut IDT: [Entry; SIZE] = [Entry::empty(); SIZE]; -pub unsafe fn init ()>(f: F) { +#[inline] +unsafe fn load_idt(ptr: &Pointer) { + asm!("lidt ({})", in(reg) ptr, options(att_syntax)); +} + +pub unsafe fn init(f: F) { extern "C" { static __x86_64_exception_vectors: [usize; 32]; } @@ -67,7 +74,7 @@ pub unsafe fn init ()>(f: F) { limit: size_of_val(&IDT) as u16 - 1, offset: &IDT as *const _ as usize, }; - asm!("lidt ({})", in(reg) &idtr, options(att_syntax)); + load_idt(&idtr); } global_asm!(include_str!("idt.S"), options(att_syntax)); diff --git a/kernel/src/arch/x86_64/intc.rs b/kernel/src/arch/x86_64/intc.rs index f09e265..4d2c7fc 100644 --- a/kernel/src/arch/x86_64/intc.rs +++ b/kernel/src/arch/x86_64/intc.rs @@ -24,13 +24,16 @@ pub(super) struct I8259 { table: IrqSafeSpinLock<[Option<&'static (dyn IntSource + Sync)>; 15]>, } +/// Interrupt line number wrapper struct #[derive(Clone, Copy, Debug)] #[repr(transparent)] pub struct IrqNumber(u32); impl IrqNumber { + /// IRQ line number limit pub const MAX: u32 = 16; + /// Constructs a wrapped IRQ line number pub const fn new(u: u32) -> Self { if u > Self::MAX { panic!(); diff --git a/kernel/src/arch/x86_64/intrin.rs b/kernel/src/arch/x86_64/intrin.rs index 94e3fd2..0d00b83 100644 --- a/kernel/src/arch/x86_64/intrin.rs +++ b/kernel/src/arch/x86_64/intrin.rs @@ -28,8 +28,13 @@ pub unsafe fn flush_tlb_virt(addr: usize) { /// Only safe to use for known [Process]es and their ASIDs // TODO actually implement this on x86-64 #[inline(always)] -pub unsafe fn flush_tlb_asid(asid: usize) {} +pub unsafe fn flush_tlb_asid(_asid: usize) {} +/// Read a value from a model-specific register +/// +/// # Safety +/// +/// Unsafe: arbitrary MSR reads, may cause CPU exceptions #[inline(always)] pub unsafe fn rdmsr(a: u32) -> u64 { let mut eax: u32; @@ -38,6 +43,11 @@ pub unsafe fn rdmsr(a: u32) -> u64 { (eax as u64) | ((edx as u64) << 32) } +/// Writes a value to a model-specific register +/// +/// # Safety +/// +/// Unsafe: arbitrary MSR writes #[inline(always)] pub unsafe fn wrmsr(a: u32, b: u64) { let eax = b as u32; diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index aab3c29..94e3ecd 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,3 +1,4 @@ +//! x86_64 platform implementation details use crate::dev::{display::StaticFramebuffer, irq::IntController, serial::SerialDevice}; use core::arch::asm; @@ -49,14 +50,17 @@ pub unsafe fn irq_restore(state: u64) { } } +/// Returns a reference to interrupt controller device pub fn intc() -> &'static impl IntController { &INTC } +/// Returns a reference to primary console device pub fn console() -> &'static impl SerialDevice { &COM1 } +/// Returns a reference to CPU-local timer device pub fn local_timer() -> &'static Timer { &TIMER } diff --git a/kernel/src/arch/x86_64/reg/mod.rs b/kernel/src/arch/x86_64/reg/mod.rs index 96187a2..f9fab2b 100644 --- a/kernel/src/arch/x86_64/reg/mod.rs +++ b/kernel/src/arch/x86_64/reg/mod.rs @@ -1,10 +1,14 @@ +//! x86_64 model-specific and control register interfaces + macro_rules! wrap_msr { ($struct_name:ident, $name:ident, $address:expr, $fields:tt) => { register_bitfields! { u64, + #[allow(missing_docs)] pub $name $fields } + #[allow(missing_docs)] pub struct $struct_name; impl Readable for $struct_name { @@ -31,6 +35,7 @@ macro_rules! wrap_msr { } } + #[allow(missing_docs)] pub const $name: $struct_name = $struct_name; } } @@ -45,21 +50,31 @@ use crate::arch::x86_64::intrin::{rdmsr, wrmsr}; // CRn registers register_bitfields! { u64, + /// Control register CR4 fields + #[allow(missing_docs)] pub CR4 [ + /// Indicates OS support for FXSR/FXRSTOR instructions OSFXSR OFFSET(9) NUMBITS(1) [], + /// Indicates OS support for unmasked SIMD exceptions OSXMMEXCPT OFFSET(10) NUMBITS(1) [] ] } register_bitfields! { u64, + /// Control register CR0 fields + #[allow(missing_docs)] pub CR0 [ + /// Indicates requirement for x87 emulation EM OFFSET(2) NUMBITS(1) [], + /// Controls x87 exception handling MP OFFSET(1) NUMBITS(1) [] ] } +#[allow(missing_docs)] pub struct Cr4; +#[allow(missing_docs)] pub struct Cr0; impl Readable for Cr4 { @@ -114,7 +129,9 @@ impl Writeable for Cr0 { } } +/// Control register CR4 pub const CR4: Cr4 = Cr4; +/// Control register CR0 pub const CR0: Cr0 = Cr0; wrap_msr!(MsrIa32Efer, MSR_IA32_EFER, 0xC0000080, [ diff --git a/kernel/src/arch/x86_64/syscall.rs b/kernel/src/arch/x86_64/syscall.rs index 3d4fa72..d881707 100644 --- a/kernel/src/arch/x86_64/syscall.rs +++ b/kernel/src/arch/x86_64/syscall.rs @@ -4,12 +4,18 @@ use tock_registers::interfaces::{ReadWriteable, Writeable}; use libsys::abi::SystemCall; use crate::syscall; +/// Syscall registers +#[allow(dead_code)] #[derive(Clone, Debug)] pub struct SyscallFrame { + /// General-purpose registers pub x: [usize; 13], + /// Caller (ring 3) saved stack pointer pub saved_rsp: usize, + /// Caller (ring 3) saved processor flags pub saved_rflags: usize, + /// Caller (ring 3) return address pub saved_rip: usize, } @@ -19,7 +25,7 @@ pub(super) fn init() { } MSR_IA32_SFMASK.write(MSR_IA32_SFMASK::IF::SET); - MSR_IA32_LSTAR.set(__x86_64_syscall_entry as u64); + MSR_IA32_LSTAR.set(__x86_64_syscall_entry as usize as u64); MSR_IA32_STAR .write(MSR_IA32_STAR::SYSRET_CS_SS.val(0x1B - 8) + MSR_IA32_STAR::SYSCALL_CS_SS.val(0x08)); MSR_IA32_EFER.modify(MSR_IA32_EFER::SCE::SET); diff --git a/kernel/src/arch/x86_64/timer.rs b/kernel/src/arch/x86_64/timer.rs index 0ac6006..e95fbb6 100644 --- a/kernel/src/arch/x86_64/timer.rs +++ b/kernel/src/arch/x86_64/timer.rs @@ -8,19 +8,17 @@ use crate::dev::{ Device, }; use crate::proc; +use core::sync::atomic::{AtomicU64, Ordering}; use core::time::Duration; use libsys::error::Errno; -use tock_registers::interfaces::{Readable, Writeable}; -use core::sync::atomic::{AtomicU64, Ordering}; // 1.1931816666 MHz base freq /// Generic timer struct pub struct Timer { data0: PortIo, - cmd: PortIo, counter: AtomicU64, - irq: IrqNumber + irq: IrqNumber, } impl Device for Timer { @@ -45,8 +43,9 @@ impl TimestampSource for Timer { impl IntSource for Timer { fn handle_irq(&self) -> Result<(), Errno> { - self.counter.fetch_add(1, Ordering::Relaxed); + let value = self.counter.fetch_add(1, Ordering::Relaxed); proc::wait::tick(); + pseudo::RANDOM.set_state(value as u32); proc::switch(); Ok(()) } @@ -63,9 +62,8 @@ impl Timer { pub const fn new(irq: IrqNumber) -> Self { Self { data0: unsafe { PortIo::new(0x40) }, - cmd: unsafe { PortIo::new(0x43) }, counter: AtomicU64::new(0), - irq + irq, } } } diff --git a/kernel/src/arch/x86_64/uart.rs b/kernel/src/arch/x86_64/uart.rs index 1af6835..e443a2a 100644 --- a/kernel/src/arch/x86_64/uart.rs +++ b/kernel/src/arch/x86_64/uart.rs @@ -43,7 +43,7 @@ impl IntSource for Uart { fn init_irqs(&'static self) -> Result<(), Errno> { // TODO shared IRQs between COM# ports x86_64::INTC.register_handler(self.irq, self)?; - self.ier.write((1 << 0)); + self.ier.write(1 << 0); x86_64::INTC.enable_irq(self.irq)?; Ok(()) diff --git a/kernel/src/arch/x86_64/virt/fixed.rs b/kernel/src/arch/x86_64/virt/fixed.rs index 8884b84..372b718 100644 --- a/kernel/src/arch/x86_64/virt/fixed.rs +++ b/kernel/src/arch/x86_64/virt/fixed.rs @@ -1,10 +1,10 @@ -use super::{table::TableImpl, SpaceImpl}; +use super::table::TableImpl; #[repr(C, align(0x1000))] pub struct FixedTableGroup { pub pml4: TableImpl, pub pdpt: TableImpl, - pub pd: [TableImpl; 16] + pub pd: [TableImpl; 16], } // Upper mappings @@ -12,5 +12,5 @@ pub struct FixedTableGroup { pub(super) static mut KERNEL_FIXED: FixedTableGroup = FixedTableGroup { pml4: TableImpl::empty(), pdpt: TableImpl::empty(), - pd: [TableImpl::empty(); 16] + pd: [TableImpl::empty(); 16], }; diff --git a/kernel/src/arch/x86_64/virt/mod.rs b/kernel/src/arch/x86_64/virt/mod.rs index 16ced4c..07a0dd7 100644 --- a/kernel/src/arch/x86_64/virt/mod.rs +++ b/kernel/src/arch/x86_64/virt/mod.rs @@ -1,3 +1,4 @@ +//! x86_64 virtual memory management implementation use crate::mem::virt::table::{MapAttributes, Entry}; use core::arch::asm; use libsys::error::Errno; @@ -8,12 +9,19 @@ pub use table::{EntryImpl, SpaceImpl}; use fixed::KERNEL_FIXED; bitflags! { + /// Raw attributes for x86_64 [Entry] implementation pub struct RawAttributesImpl: u64 { + /// Entry is valid and mapped const PRESENT = EntryImpl::PRESENT; + /// Entry is writable by user processes const WRITE = EntryImpl::WRITE; + /// Entry is accessible (readable) by user processes const USER = EntryImpl::USER; + /// Entry points to a block instead of a next-level table const BLOCK = EntryImpl::BLOCK; + /// Entry is global across virtual address spaces const GLOBAL = 1 << 8; + /// Entry is marked as Copy-on-Write const EX_COW = EntryImpl::EX_COW; } } @@ -33,6 +41,11 @@ impl From for RawAttributesImpl { } } +/// Performs initialization of virtual memory control by kernel +/// +/// # Safety +/// +/// Only safe to be called once during virtual memory init. pub unsafe fn enable() { // Remove the lower mapping KERNEL_FIXED.pml4[0] = EntryImpl::EMPTY; @@ -41,6 +54,8 @@ pub unsafe fn enable() { asm!("mov %cr3, %rax; mov %rax, %cr3", options(att_syntax)); } -pub fn map_device_memory(phys: usize, count: usize) -> Result { +/// Allocates a range of virtual memory of requested size and maps +/// it to specified device memory +pub fn map_device_memory(_phys: usize, _count: usize) -> Result { todo!() } diff --git a/kernel/src/arch/x86_64/virt/table.rs b/kernel/src/arch/x86_64/virt/table.rs index f4dfa3b..fd72dbb 100644 --- a/kernel/src/arch/x86_64/virt/table.rs +++ b/kernel/src/arch/x86_64/virt/table.rs @@ -1,3 +1,4 @@ +use crate::arch::intrin; use crate::mem::{ self, phys::{self, PageUsage}, @@ -5,38 +6,44 @@ use crate::mem::{ }; use core::fmt; use core::ops::{Index, IndexMut}; -use libsys::{error::Errno, mem::memset}; +use libsys::error::Errno; use super::{RawAttributesImpl, KERNEL_FIXED}; +/// Transparent wrapper structure representing a single +/// translation table entry #[derive(Clone, Copy)] #[repr(transparent)] pub struct EntryImpl(u64); +/// Structure describing a single level of translation mappings #[derive(Clone, Copy)] #[repr(C, align(0x1000))] pub struct TableImpl { entries: [EntryImpl; 512], } +/// Top-level translation table wrapper #[repr(transparent)] pub struct SpaceImpl(TableImpl); impl EntryImpl { - pub const PRESENT: u64 = 1 << 0; - pub const WRITE: u64 = 1 << 1; - pub const USER: u64 = 1 << 2; - pub const BLOCK: u64 = 1 << 7; - pub const EX_COW: u64 = 1 << 62; + pub(super) const PRESENT: u64 = 1 << 0; + pub(super) const WRITE: u64 = 1 << 1; + pub(super) const USER: u64 = 1 << 2; + pub(super) const BLOCK: u64 = 1 << 7; + pub(super) const EX_COW: u64 = 1 << 62; - pub const PHYS_MASK: u64 = 0x0000FFFFFFFFF000; + const PHYS_MASK: u64 = 0x0000FFFFFFFFF000; } impl fmt::Debug for EntryImpl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("EntryImpl") .field("address", &self.address()) - .field("flags", &unsafe { RawAttributesImpl::from_bits_unchecked(self.0 & 0xFFF) }) + .field("flags", &unsafe { + RawAttributesImpl::from_bits_unchecked(self.0 & 0xFFF) + }) .finish_non_exhaustive() } } @@ -47,38 +54,39 @@ impl Entry for EntryImpl { #[inline] fn normal(addr: usize, attrs: MapAttributes) -> Self { - Self((addr as u64) | RawAttributesImpl::from(attrs).bits() | EntryImpl::PRESENT) + Self((addr as u64) | RawAttributesImpl::from(attrs).bits() | Self::PRESENT) } #[inline] fn block(addr: usize, attrs: MapAttributes) -> Self { - Self((addr as u64) | RawAttributesImpl::from(attrs).bits() | EntryImpl::BLOCK | EntryImpl::PRESENT) + Self((addr as u64) | RawAttributesImpl::from(attrs).bits() | Self::BLOCK | Self::PRESENT) } #[inline] fn address(self) -> usize { - (self.0 & EntryImpl::PHYS_MASK) as usize + (self.0 & Self::PHYS_MASK) as usize } #[inline] fn set_address(&mut self, virt: usize) { - todo!() + self.0 &= !Self::PHYS_MASK; + self.0 |= (virt as u64) & Self::PHYS_MASK; } #[inline] fn is_present(self) -> bool { - self.0 & EntryImpl::PRESENT != 0 + self.0 & Self::PRESENT != 0 } #[inline] fn is_normal(self) -> bool { - self.0 & EntryImpl::BLOCK == 0 + self.0 & Self::BLOCK == 0 } #[inline] fn fork_with_cow(&mut self) -> Self { - self.0 &= !EntryImpl::WRITE; - self.0 |= EntryImpl::EX_COW; + self.0 &= !Self::WRITE; + self.0 |= Self::EX_COW; *self } @@ -90,7 +98,7 @@ impl Entry for EntryImpl { #[inline] fn is_cow(self) -> bool { - self.0 & EntryImpl::EX_COW != 0 + self.0 & Self::EX_COW != 0 } #[inline] @@ -202,9 +210,8 @@ impl Space for SpaceImpl { }; unsafe { - use core::arch::asm; res.write_last_level(virt_addr, new_entry, true, false)?; - asm!("invlpg ({})", in(reg) virt_addr, options(att_syntax)); + intrin::flush_tlb_virt(virt_addr); } } } @@ -240,9 +247,7 @@ impl Space for SpaceImpl { Err(Errno::AlreadyExists) } else { l2_table[l3i] = entry; - unsafe { - core::arch::asm!("invlpg ({})", in(reg) virt, options(att_syntax)); - } + intrin::flush_tlb_virt(virt); Ok(()) } } diff --git a/kernel/src/debug.rs b/kernel/src/debug.rs index c4b049b..196e9b7 100644 --- a/kernel/src/debug.rs +++ b/kernel/src/debug.rs @@ -64,13 +64,14 @@ impl fmt::Write for FramebufferOutput { let fb = self.display.unwrap().framebuffer().unwrap(); for ch in s.chars() { - self.putc(&fb, ch); + self.putc(fb, ch); } Ok(()) } } +/// Sets active display for debug console output pub fn set_display(disp: &'static dyn Display) { DISPLAY.lock().display = Some(disp); } @@ -236,6 +237,8 @@ impl FramebufferOutput { } pub fn putc(&mut self, fb: &FramebufferInfo, ch: char) { + #![allow(clippy::single_match)] + match self.esc { EscapeState::None => { match ch { diff --git a/kernel/src/dev/display.rs b/kernel/src/dev/display.rs index 712d691..2f4108b 100644 --- a/kernel/src/dev/display.rs +++ b/kernel/src/dev/display.rs @@ -1,24 +1,36 @@ +//! Graphical display interfaces use crate::dev::Device; use libsys::error::Errno; use crate::util::InitOnce; +/// Description of a framebuffer pub struct FramebufferInfo { + /// Width in pixels pub width: usize, + /// Height in pixels pub height: usize, + /// Physical start address pub phys_base: usize, + /// Virtual address where the framebuffer is mapped pub virt_base: usize } +/// Generic display interface pub trait Display: Device { + /// Changes currently active display mode fn set_mode(&self, mode: DisplayMode) -> Result<(), Errno>; - fn framebuffer<'a>(&'a self) -> Result<&'a FramebufferInfo, Errno>; + /// Returns currently active framebuffer information + fn framebuffer(&self) -> Result<&FramebufferInfo, Errno>; } +/// Display configuration details +#[allow(dead_code)] pub struct DisplayMode { width: u16, height: u16, } +/// Generic single-mode framebuffer pub struct StaticFramebuffer { framebuffer: InitOnce } @@ -34,7 +46,7 @@ impl Device for StaticFramebuffer { } impl Display for StaticFramebuffer { - fn set_mode(&self, mode: DisplayMode) -> Result<(), Errno> { + fn set_mode(&self, _mode: DisplayMode) -> Result<(), Errno> { Err(Errno::InvalidOperation) } @@ -48,10 +60,12 @@ impl Display for StaticFramebuffer { } impl StaticFramebuffer { + /// Constructs an empty [StaticFramebuffer] object pub const fn uninit() -> Self { Self { framebuffer: InitOnce::new() } } + /// Initializes the device from existing framebuffer object pub fn set_framebuffer(&self, framebuffer: FramebufferInfo) { self.framebuffer.init(framebuffer); } diff --git a/kernel/src/dev/irq.rs b/kernel/src/dev/irq.rs index ff975e0..d0606e5 100644 --- a/kernel/src/dev/irq.rs +++ b/kernel/src/dev/irq.rs @@ -50,6 +50,7 @@ impl<'q> IrqContext<'q> { Self { token, _0: PhantomData } } + /// Returns the value this object was initialized with pub const fn token(&self) -> usize { self.token } diff --git a/kernel/src/font.rs b/kernel/src/font.rs index a97fee7..f67749b 100644 --- a/kernel/src/font.rs +++ b/kernel/src/font.rs @@ -1,3 +1,5 @@ +//! Text drawing routines and font support + use crate::util::InitOnce; use libsys::mem::read_le32; use crate::dev::display::FramebufferInfo; @@ -5,6 +7,7 @@ use crate::dev::display::FramebufferInfo; static FONT_DATA: &[u8] = include_bytes!("../../etc/default8x16.psfu"); static FONT: InitOnce = InitOnce::new(); +/// Font data description structure pub struct Font { char_width: usize, char_height: usize, @@ -13,8 +16,9 @@ pub struct Font { } impl Font { + /// Renders a glyph onto the framebuffer pub fn draw(&self, fb: &FramebufferInfo, bx: usize, by: usize, ch: char, fg: u32, bg: u32) { - if ch >= ' ' && ch < '\x7B' { + if (' ' .. '\x7B').contains(&ch) { let char_data = &self.data[ch as usize * self.bytes_per_glyph..]; for iy in 0..self.char_height { @@ -33,8 +37,9 @@ impl Font { } } +/// Sets up the global [Font] object from PSF pub fn init() { - assert_eq!(read_le32(&FONT_DATA[..]), 0x864ab572); + assert_eq!(read_le32(FONT_DATA), 0x864ab572); FONT.init(Font { char_width: read_le32(&FONT_DATA[28..]) as usize, @@ -44,6 +49,7 @@ pub fn init() { }); } +/// Returns a reference to global [Font] object pub fn get() -> &'static Font { FONT.get() } diff --git a/kernel/src/fs/sysfs.rs b/kernel/src/fs/sysfs.rs index 954a3b4..c5072de 100644 --- a/kernel/src/fs/sysfs.rs +++ b/kernel/src/fs/sysfs.rs @@ -224,8 +224,9 @@ pub fn init() { use crate::dev::timer::TimestampSource; let mut writer = BufferWriter::new(buf); - // let time = machine::local_timer().timestamp()?; - // write!(&mut writer, "{} {}\n", time.as_secs(), time.subsec_nanos()).map_err(|_| Errno::InvalidArgument)?; + let time = machine::local_timer().timestamp()?; + writeln!(&mut writer, "{} {}", time.as_secs(), time.subsec_nanos()) + .map_err(|_| Errno::InvalidArgument)?; Ok(writer.count()) }); } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 35e926d..3d12b50 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -11,7 +11,6 @@ alloc_error_handler, asm_const, core_intrinsics, - const_generics_defaults, )] #![no_std] #![no_main] diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs index a7be2eb..d5f9809 100644 --- a/kernel/src/mem/mod.rs +++ b/kernel/src/mem/mod.rs @@ -6,8 +6,10 @@ pub mod virt; cfg_if! { if #[cfg(target_arch = "x86_64")] { + /// 8-byte padding for x86_64 for user stack alignment pub const USTACK_PADDING: usize = 8; } else { + /// No stack alignment required pub const USTACK_PADDING: usize = 0; } } diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index a4bb57f..ccb3537 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -17,7 +17,6 @@ use libsys::{ signal::Signal, ProgramArgs, }; -use core::arch::asm; /// Wrapper type for a process struct reference pub type ProcessRef = Rc; @@ -123,6 +122,7 @@ impl Process { } } + /// Sets a pending signal for process pub fn set_signal(&self, signal: Signal) { let mut lock = self.inner.lock(); let table = Self::space_phys(&mut lock); diff --git a/kernel/src/proc/sched.rs b/kernel/src/proc/sched.rs index ab48f91..fd14d4b 100644 --- a/kernel/src/proc/sched.rs +++ b/kernel/src/proc/sched.rs @@ -151,7 +151,7 @@ pub fn is_ready() -> bool { #[inline(never)] extern "C" fn idle_fn(_a: usize) -> ! { loop { - // cortex_a::asm::wfi(); + core::hint::spin_loop(); } } diff --git a/kernel/src/proc/wait.rs b/kernel/src/proc/wait.rs index 4b19f3d..28d16a3 100644 --- a/kernel/src/proc/wait.rs +++ b/kernel/src/proc/wait.rs @@ -73,10 +73,10 @@ pub fn sleep(timeout: Duration, remaining: &mut Duration) -> Result<(), Errno> { /// Suspends current process until some file descriptor /// signals data available pub fn select( - thread: ThreadRef, - mut rfds: Option<&mut FdSet>, - mut wfds: Option<&mut FdSet>, - timeout: Option, + _thread: ThreadRef, + _rfds: Option<&mut FdSet>, + _wfds: Option<&mut FdSet>, + _timeout: Option, ) -> Result { todo!(); } diff --git a/kernel/src/syscall/arg.rs b/kernel/src/syscall/arg.rs index 64b2dc3..2dd34d3 100644 --- a/kernel/src/syscall/arg.rs +++ b/kernel/src/syscall/arg.rs @@ -1,7 +1,7 @@ //! System call argument ABI helpers use crate::arch::intrin; -use crate::mem::{self, virt::table::{Entry, Space, SpaceImpl}}; +use crate::mem::{self, virt::table::Space}; use crate::proc::Process; use core::alloc::Layout; use libsys::error::Errno; @@ -13,13 +13,12 @@ macro_rules! invalid_memory { warnln!($($args)+); #[cfg(feature = "aggressive_syscall")] { - todo!() - // use libsys::signal::Signal; - // use crate::proc::Thread; + use libsys::signal::Signal; + use crate::proc::Thread; - // let thread = Thread::current(); - // let proc = thread.owner().unwrap(); - // proc.enter_fault_signal(thread, Signal::SegmentationFault); + let thread = Thread::current(); + let proc = thread.owner().unwrap(); + proc.enter_fault_signal(thread, Signal::SegmentationFault); } return Err(Errno::InvalidArgument); } @@ -43,6 +42,7 @@ cfg_if! { } else { #[inline(always)] fn is_el0_accessible(virt: usize, write: bool) -> bool { + use crate::mem::virt::table::Entry; let proc = Process::current(); proc.manipulate_space(|space| { let entry = space.read_last_level(virt & !0xFFF); @@ -132,7 +132,10 @@ pub fn option_struct_mut<'a, T>(base: usize) -> Result, Errno> } /// Checks given argument and interprets it as a `Option<&'a mut [T]>` -pub fn option_struct_buf_mut<'a, T>(base: usize, count: usize) -> Result, Errno> { +pub fn option_struct_buf_mut<'a, T>( + base: usize, + count: usize, +) -> Result, Errno> { if base == 0 { Ok(None) } else { @@ -152,7 +155,6 @@ pub fn validate_ptr(base: usize, len: usize, write: bool) -> Result<(), Errno> { } let process = Process::current(); - let asid = process.asid(); for i in (base / mem::PAGE_SIZE)..((base + len + mem::PAGE_SIZE - 1) / mem::PAGE_SIZE) { if !is_el0_accessible(i * mem::PAGE_SIZE, write) { diff --git a/kernel/src/util.rs b/kernel/src/util.rs index f4f4e05..6230ec3 100644 --- a/kernel/src/util.rs +++ b/kernel/src/util.rs @@ -20,6 +20,8 @@ impl InitOnce { } } + /// Returns a reference to the initialized value, if one is present. + /// Returns [None] otherwise. pub fn as_ref_option(&self) -> Option<&T> { if self.is_initialized() { Some(self.get()) diff --git a/libusr/src/arch/aarch64.rs b/libusr/src/arch/aarch64.rs index a0062f3..e5ecc2a 100644 --- a/libusr/src/arch/aarch64.rs +++ b/libusr/src/arch/aarch64.rs @@ -2,40 +2,40 @@ macro_rules! syscall { ($num:expr) => {{ let mut res: usize; - asm!("svc #0", out("x0") res, in("x8") $num.repr(), options(nostack)); + core::arch::asm!("svc #0", out("x0") res, in("x8") $num.repr(), options(nostack)); res }}; ($num:expr, $a0:expr) => {{ let mut res: usize = $a0; - asm!("svc #0", + core::arch::asm!("svc #0", inout("x0") res, in("x8") $num.repr(), options(nostack)); res }}; ($num:expr, $a0:expr, $a1:expr) => {{ let mut res: usize = $a0; - asm!("svc #0", + core::arch::asm!("svc #0", inout("x0") res, in("x1") $a1, in("x8") $num.repr(), options(nostack)); res }}; ($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{ let mut res: usize = $a0; - asm!("svc #0", + core::arch::asm!("svc #0", inout("x0") res, in("x1") $a1, in("x2") $a2, in("x8") $num.repr(), options(nostack)); res }}; ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{ let mut res: usize = $a0; - asm!("svc #0", + core::arch::asm!("svc #0", inout("x0") res, in("x1") $a1, in("x2") $a2, in("x3") $a3, in("x8") $num.repr(), options(nostack)); res }}; ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{ let mut res: usize = $a0; - asm!("svc #0", + core::arch::asm!("svc #0", inout("x0") res, in("x1") $a1, in("x2") $a2, in("x3") $a3, in("x4") $a4, in("x8") $num.repr(), options(nostack)); res diff --git a/libusr/src/sys/calls.rs b/libusr/src/sys/calls.rs index 931cd07..db7d1e6 100644 --- a/libusr/src/sys/calls.rs +++ b/libusr/src/sys/calls.rs @@ -10,7 +10,6 @@ use libsys::{ OpenFlags, Stat, UserId, }, }; -use core::arch::asm; use core::time::Duration; // TODO document the syscall ABI diff --git a/libusr/src/thread.rs b/libusr/src/thread.rs index 5bbfbce..62457cc 100644 --- a/libusr/src/thread.rs +++ b/libusr/src/thread.rs @@ -1,10 +1,9 @@ use crate::signal; use crate::sys::{ - sys_ex_clone, sys_ex_gettid, sys_ex_signal, sys_ex_thread_exit, sys_ex_thread_wait, + sys_ex_clone, sys_ex_signal, sys_ex_thread_exit, sys_ex_thread_wait, }; use alloc::{boxed::Box, sync::Arc, vec}; use core::any::Any; -use core::arch::asm; use core::cell::UnsafeCell; use core::fmt; use core::mem::MaybeUninit; diff --git a/user/src/bin/fuzzy.rs b/user/src/bin/fuzzy.rs index 1a54dba..8b4b806 100644 --- a/user/src/bin/fuzzy.rs +++ b/user/src/bin/fuzzy.rs @@ -1,10 +1,9 @@ -// #![feature(asm)] #![no_std] #![no_main] -// -// #![allow(unused_macros)] -// #![allow(dead_code)] -// + +#![allow(unused_macros)] +#![allow(dead_code)] + #[macro_use] extern crate libusr; diff --git a/user/src/init/main.rs b/user/src/init/main.rs index fee2b16..5d1b535 100644 --- a/user/src/init/main.rs +++ b/user/src/init/main.rs @@ -4,8 +4,6 @@ #[macro_use] extern crate libusr; -use core::arch::asm; - use libusr::sys::{stat::MountOptions, sys_execve, sys_fork, sys_mount, sys_waitpid}; #[no_mangle] @@ -36,6 +34,7 @@ fn main() -> i32 { println!("Process {:?} exited with status {}", pid, status); loop { + core::hint::spin_loop(); } } else { sys_execve("/sbin/login", &["/sbin/login", "/dev/ttyS0"]).unwrap();