diff --git a/Makefile b/Makefile index 8803ba6..bdbee9a 100644 --- a/Makefile +++ b/Makefile @@ -32,8 +32,6 @@ ifeq ($(ARCH),x86_64) MACH=none QEMU_OPTS+=-cdrom $(O)/image.iso \ -M q35 \ - -cpu host \ - -enable-kvm \ -m 512 \ -serial mon:stdio \ -net none @@ -73,16 +71,10 @@ endif .PHONY: address error etc kernel src -all: kernel +all: image kernel: cd kernel && cargo build $(CARGO_BUILD_OPTS) -ifeq ($(ARCH),x86_64) - mkdir -p $(O)/image/boot/grub - cp etc/x86_64-none.grub $(O)/image/boot/grub/grub.cfg - cp $(O)/kernel $(O)/image/boot/kernel - grub-mkrescue -o $(O)/image.iso $(O)/image -endif ifeq ($(ARCH),aarch64) $(LLVM_BASE)/llvm-strip -o $(O)/kernel.strip $(O)/kernel $(LLVM_BASE)/llvm-size $(O)/kernel.strip @@ -101,6 +93,16 @@ ifeq ($(MACH),orangepi3) $(O)/uImage endif +image: kernel initrd +ifeq ($(ARCH),x86_64) + mkdir -p $(O)/image/boot/grub + cp etc/x86_64-none.grub $(O)/image/boot/grub/grub.cfg + cp $(O)/kernel $(O)/image/boot/kernel + cp $(O)/initrd.img $(O)/image/boot/initrd.img + + grub-mkrescue -o $(O)/image.iso $(O)/image +endif + initrd: cd user && cargo build \ --target=../etc/$(ARCH)-osdev5.json \ @@ -113,7 +115,6 @@ initrd: touch $(O)/rootfs/sys/.do_not_remove cp target/$(ARCH)-osdev5/$(PROFILE)/init $(O)/rootfs/init cp target/$(ARCH)-osdev5/$(PROFILE)/shell $(O)/rootfs/bin - cp target/$(ARCH)-osdev5/$(PROFILE)/fuzzy $(O)/rootfs/bin cp target/$(ARCH)-osdev5/$(PROFILE)/ls $(O)/rootfs/bin cp target/$(ARCH)-osdev5/$(PROFILE)/cat $(O)/rootfs/bin cp target/$(ARCH)-osdev5/$(PROFILE)/hexd $(O)/rootfs/bin diff --git a/etc/x86_64-none.grub b/etc/x86_64-none.grub index cbb5a8d..805932b 100644 --- a/etc/x86_64-none.grub +++ b/etc/x86_64-none.grub @@ -1,3 +1,4 @@ menuentry "OS" { multiboot2 /boot/kernel + module2 /boot/initrd.img } diff --git a/etc/x86_64-osdev5.json b/etc/x86_64-osdev5.json new file mode 100644 index 0000000..4957a5d --- /dev/null +++ b/etc/x86_64-osdev5.json @@ -0,0 +1,21 @@ +{ + "arch": "x86_64", + "cpu": "x86-64", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + + "disable-redzone": true, + "executables": true, + "panic-strategy": "abort", + + "linker": "rust-lld", + "linker-flavor": "ld.lld", + + "llvm-target": "x86_64-unknown-linux-gnu", + "max-atomic-width": 64, + "target-pointer-width": "64", + + "os": "none", + "pre-link-args": { + "ld.lld": [ "-Tetc/aarch64-osdev5.ld" ] + } +} diff --git a/kernel/src/arch/x86_64/boot/entry.S b/kernel/src/arch/x86_64/boot/entry.S index a3f12d2..d02d2c3 100644 --- a/kernel/src/arch/x86_64/boot/entry.S +++ b/kernel/src/arch/x86_64/boot/entry.S @@ -34,6 +34,9 @@ _entry: .code64 _entry_upper: + movabsq $1f, %rax + jmp *%rax +1: lea bsp_stack_top(%rip), %rax mov %rax, %rsp diff --git a/kernel/src/arch/x86_64/boot/mod.rs b/kernel/src/arch/x86_64/boot/mod.rs index 4d31bea..506a795 100644 --- a/kernel/src/arch/x86_64/boot/mod.rs +++ b/kernel/src/arch/x86_64/boot/mod.rs @@ -1,15 +1,17 @@ -use crate::arch::x86_64::{self, intc, gdt, idt}; -use core::arch::{global_asm, asm}; +use crate::arch::x86_64::{self, gdt, idt, intc}; +use crate::config::{ConfigKey, CONFIG}; +use crate::debug; +use crate::dev::{display::FramebufferInfo, pseudo, Device}; +use crate::font; +use crate::fs::{devfs, sysfs}; use crate::mem::{ self, heap, phys::{self, MemoryRegion, PageUsage, ReservedRegion}, virt, }; -use crate::debug; -use crate::fs::{devfs, sysfs}; -use crate::dev::{pseudo, Device, display::FramebufferInfo}; +use crate::proc; +use core::arch::{asm, global_asm}; use core::mem::MaybeUninit; -use crate::font; use multiboot2::{BootInformation, MemoryArea}; static mut RESERVED_REGION_MB2: MaybeUninit = MaybeUninit::uninit(); @@ -73,6 +75,14 @@ extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! { heap::init(heap_base_virt, 16 * 1024 * 1024); } + let initrd_info = mb_info.module_tags().next().unwrap(); + { + let mut cfg = CONFIG.lock(); + + cfg.set_usize(ConfigKey::InitrdBase, initrd_info.start_address() as usize); + cfg.set_usize(ConfigKey::InitrdSize, initrd_info.module_size() as usize); + } + // Setup hardware unsafe { x86_64::INTC.enable().ok(); @@ -80,12 +90,16 @@ extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! { let fb_info = mb_info.framebuffer_tag().unwrap(); let virt = mem::virtualize(fb_info.address as usize); - debugln!("Framebuffer base: phys={:#x}, virt={:#x}", fb_info.address, virt); + debugln!( + "Framebuffer base: phys={:#x}, virt={:#x}", + fb_info.address, + virt + ); x86_64::DISPLAY.set_framebuffer(FramebufferInfo { width: fb_info.width as usize, height: fb_info.height as usize, phys_base: fb_info.address as usize, - virt_base: virt + virt_base: virt, }); font::init(); debug::set_display(&x86_64::DISPLAY); @@ -96,10 +110,8 @@ extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! { devfs::add_named_char_device(&pseudo::ZERO, "zero").unwrap(); devfs::add_named_char_device(&pseudo::RANDOM, "random").unwrap(); - loop { - unsafe { - asm!("sti; hlt"); - } + unsafe { + proc::enter(); } } diff --git a/kernel/src/arch/x86_64/context.S b/kernel/src/arch/x86_64/context.S new file mode 100644 index 0000000..c24d60a --- /dev/null +++ b/kernel/src/arch/x86_64/context.S @@ -0,0 +1,76 @@ +.section .text +.global __x86_64_ctx_switch +.global __x86_64_ctx_switch_to +.global __x86_64_ctx_enter_kernel +.global __x86_64_ctx_enter_from_fork + +__x86_64_ctx_enter_user: + pop %rcx + pop %rdi + pop %rdi + pop %rdx + + push $0x10 + push %rcx + + push $0 // $0x200 + + push $0x08 + push %rdx + + iretq + +__x86_64_ctx_enter_kernel: + pop %rdi + pop %rdx + mov %rsp, %rcx + + push $0x10 + push %rcx + + push $0x200 + + push $0x08 + push %rdx + + iretq + +__x86_64_ctx_enter_from_fork: + jmp . + +__x86_64_ctx_switch: + // %rsi -- src ctx ptr + // %rdi -- dst ctx ptr + + push %r15 + push %r14 + push %r13 + push %r12 + push %rbx + push %rbp + + mov %cr3, %rax + push %rax + // TODO save gs_base + push %rax + + mov %rsp, (%rsi) +__x86_64_ctx_switch_to: + mov (%rdi), %rsp + + pop %rbp + pop %rbx + pop %r12 + pop %r13 + pop %r14 + pop %r15 + + pop %rax + test %rax, %rax + jz 1f + mov %rax, %cr3 +1: + pop %rax + // TODO set gs_base = rax + + ret diff --git a/kernel/src/arch/x86_64/context.rs b/kernel/src/arch/x86_64/context.rs new file mode 100644 index 0000000..51de487 --- /dev/null +++ b/kernel/src/arch/x86_64/context.rs @@ -0,0 +1,150 @@ +use crate::mem::{ + self, + phys::{self, PageUsage}, +}; +use core::mem::size_of; +use core::arch::global_asm; + +struct Stack { + bp: usize, + sp: usize, +} + +/// Structure representing thread context +#[repr(C)] +pub struct Context { + /// Thread's kernel stack pointer + pub k_sp: usize, // 0x00 + + stack_base: usize, + stack_page_count: usize, +} + +impl Context { + /// Constructs a new kernel-space thread context + pub fn kernel(entry: usize, arg: usize) -> Self { + let mut stack = Stack::new(8); + + stack.push(entry); + stack.push(arg); + + stack.setup_common(__x86_64_ctx_enter_kernel as usize, 0); + + Self { + k_sp: stack.sp, + + stack_base: stack.bp, + stack_page_count: 8, + } + } + + /// Constructs a new user-space thread context + pub fn user(entry: usize, arg: usize, cr3: usize, ustack: usize) -> Self { + let cr3 = cr3 & 0xFFFFFFFF; + let mut stack = Stack::new(8); + + stack.push(entry); + stack.push(arg); + stack.push(0); + stack.push(ustack); + + stack.setup_common(__x86_64_ctx_enter_user as usize, cr3); + + Self { + k_sp: stack.sp, + + stack_base: stack.bp, + stack_page_count: 8, + } + } + + /// Constructs an uninitialized thread context + pub fn empty() -> Self { + let stack = Stack::new(8); + Self { + k_sp: stack.sp, + stack_base: stack.bp, + stack_page_count: 8 + } + } + + /// Sets up a context for signal entry + /// + /// # Safety + /// + /// Unsafe: may clobber an already active context + pub unsafe fn setup_signal_entry(&mut self, entry: usize, arg: usize, cr3: usize, ustack: usize) { + todo!() + } + + /// Performs initial thread entry + /// + /// # Safety + /// + /// Unsafe: does not check if any context has already been activated + /// before, so must only be called once. + pub unsafe extern "C" fn enter(&mut self) -> ! { + __x86_64_ctx_switch_to(self); + panic!("This code should not run"); + } + + /// Performs context switch from `self` to `to`. + /// + /// # Safety + /// + /// Unsafe: does not check if `self` is actually an active context. + pub unsafe extern "C" fn switch(&mut self, to: &mut Context) { + __x86_64_ctx_switch(to, self); + } +} + +impl Stack { + pub fn new(page_count: usize) -> Stack { + let phys = phys::alloc_contiguous_pages(PageUsage::Kernel, page_count).unwrap(); + let bp = mem::virtualize(phys); + Stack { + bp, + sp: bp + page_count * mem::PAGE_SIZE, + } + } + + pub unsafe fn from_base_size(bp: usize, page_count: usize) -> Stack { + Stack { + bp, + sp: bp + page_count * mem::PAGE_SIZE + } + } + + pub fn setup_common(&mut self, entry: usize, cr3: usize) { + self.push(entry); // return address + self.push(0); // gs_base + self.push(cr3); + self.push(0); // r15 + self.push(0); // r14 + self.push(0); // r13 + self.push(0); // r12 + self.push(0); // rbx + self.push(0); // rbp + } + + pub fn push(&mut self, value: usize) { + if self.bp == self.sp { + panic!("Stack overflow"); + } + + self.sp -= size_of::(); + unsafe { + *(self.sp as *mut usize) = value; + } + } +} + +extern "C" { + fn __x86_64_ctx_enter_from_fork(); + fn __x86_64_ctx_enter_kernel(); + fn __x86_64_ctx_enter_user(); + fn __x86_64_ctx_switch(dst: *mut Context, src: *mut Context); + fn __x86_64_ctx_switch_to(dst: *mut Context); +} + +global_asm!(include_str!("context.S"), options(att_syntax)); diff --git a/kernel/src/arch/x86_64/exception.rs b/kernel/src/arch/x86_64/exception.rs index d87ff74..f0d8e65 100644 --- a/kernel/src/arch/x86_64/exception.rs +++ b/kernel/src/arch/x86_64/exception.rs @@ -1,7 +1,7 @@ -use core::arch::asm; use crate::arch::x86_64; use crate::debug::Level; -use crate::dev::irq::{IrqContext, IntController}; +use crate::dev::irq::{IntController, IrqContext}; +use core::arch::{asm, global_asm}; #[derive(Debug)] struct ExceptionFrame { @@ -50,7 +50,12 @@ fn pfault_access_type(code: u64) -> &'static str { fn pfault_dump(level: Level, frame: &ExceptionFrame, cr2: u64) { println!(level, "\x1B[41;1mPage fault:"); - println!(level, " Illegal {} at {:#018x}\x1B[0m", pfault_access_type(frame.err_code), cr2); + println!( + level, + " Illegal {} at {:#018x}\x1B[0m", + pfault_access_type(frame.err_code), + cr2 + ); } #[no_mangle] diff --git a/kernel/src/arch/x86_64/irq_vectors.S b/kernel/src/arch/x86_64/irq_vectors.S index eb11403..988769a 100644 --- a/kernel/src/arch/x86_64/irq_vectors.S +++ b/kernel/src/arch/x86_64/irq_vectors.S @@ -31,19 +31,51 @@ __x86_64_irq_\no: __x86_64_irq_0: cli - push %rax - push %rdx - mov $'T', %al + push %rax + push %rcx + push %rdx + push %rbx + push %rbp + push %rsi + push %rdi + + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + mov $0x3F8, %dx + mov $'T', %al outb %al, %dx mov $0x20, %al mov $0x20, %dx outb %al, %dx + call sched_yield + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + + pop %rdi + pop %rsi + pop %rbp + pop %rbx pop %rdx + pop %rcx pop %rax + iretq irq_entry 1 diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 38ca34f..2ade26b 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -12,6 +12,7 @@ pub(self) use io::PortIo; pub mod boot; pub mod virt; pub mod intrin; +pub mod context; pub(self) mod gdt; pub(self) mod idt; pub(self) mod exception; diff --git a/kernel/src/arch/x86_64/virt/mod.rs b/kernel/src/arch/x86_64/virt/mod.rs index b24a56e..d99e284 100644 --- a/kernel/src/arch/x86_64/virt/mod.rs +++ b/kernel/src/arch/x86_64/virt/mod.rs @@ -9,12 +9,26 @@ use fixed::KERNEL_FIXED; bitflags! { pub struct RawAttributesImpl: u64 { + const PRESENT = 1 << 0; + const WRITE = 1 << 1; + const USER = 1 << 2; + const BLOCK = 1 << 7; + const GLOBAL = 1 << 8; } } impl From for RawAttributesImpl { - fn from(src: MapAttributes) -> Self { - todo!() + fn from(i: MapAttributes) -> Self { + let mut res = RawAttributesImpl::empty(); + + if i.contains(MapAttributes::USER_READ) { + res |= RawAttributesImpl::USER; + } + if i.contains(MapAttributes::USER_WRITE) || i.contains(MapAttributes::KERNEL_WRITE) { + res |= RawAttributesImpl::WRITE; + } + + res } } diff --git a/kernel/src/arch/x86_64/virt/table.rs b/kernel/src/arch/x86_64/virt/table.rs index 4a62a84..759ab5b 100644 --- a/kernel/src/arch/x86_64/virt/table.rs +++ b/kernel/src/arch/x86_64/virt/table.rs @@ -6,7 +6,7 @@ use crate::mem::{ use core::ops::{Index, IndexMut}; use libsys::{error::Errno, mem::memset}; -use super::RawAttributesImpl; +use super::{RawAttributesImpl, KERNEL_FIXED}; #[derive(Clone, Copy)] #[repr(transparent)] @@ -29,17 +29,17 @@ impl Entry for EntryImpl { #[inline] fn normal(addr: usize, attrs: MapAttributes) -> Self { - todo!() + Self((addr as u64) | attrs.bits() | (1 << 0)) } #[inline] fn block(addr: usize, attrs: MapAttributes) -> Self { - todo!() + Self((addr as u64) | attrs.bits() | (1 << 7) | (1 << 0)) } #[inline] fn address(self) -> usize { - todo!() + (self.0 & !0xFFF) as usize } #[inline] @@ -49,12 +49,12 @@ impl Entry for EntryImpl { #[inline] fn is_present(self) -> bool { - todo!() + self.0 & (1 << 0) != 0 } #[inline] fn is_normal(self) -> bool { - todo!() + self.0 & (1 << 7) == 0 } #[inline] @@ -82,7 +82,14 @@ impl Space for SpaceImpl { type Entry = EntryImpl; fn alloc_empty() -> Result<&'static mut Self, Errno> { - todo!() + let kernel_pdpt_phys = unsafe { + &KERNEL_FIXED.pdpt as *const _ as usize - mem::KERNEL_OFFSET + }; + let page = phys::alloc_page(PageUsage::Paging)?; + let res = unsafe { &mut *(mem::virtualize(page) as *mut Self) }; + res.0.entries[..511].fill(EntryImpl::EMPTY); + res.0.entries[511] = EntryImpl::normal(kernel_pdpt_phys, MapAttributes::SHARE_OUTER | MapAttributes::KERNEL_EXEC | MapAttributes::KERNEL_WRITE); + Ok(res) } unsafe fn release(space: &'static mut Self) { @@ -100,11 +107,43 @@ impl Space for SpaceImpl { _create_intermediate: bool, // TODO handle this properly overwrite: bool, ) -> Result<(), Errno> { - todo!() + let l0i = virt >> 39; + let l1i = (virt >> 30) & 0x1FF; + let l2i = (virt >> 21) & 0x1FF; + let l3i = (virt >> 12) & 0x1FF; + + let l0_table = self.0.next_level_table_or_alloc(l0i)?; + let l1_table = l0_table.next_level_table_or_alloc(l1i)?; + let l2_table = l1_table.next_level_table_or_alloc(l2i)?; + + if l2_table[l3i].is_present() { + warnln!("Entry already exists for address: virt={:#x}, prev={:#x}, new={:#x}", virt, l2_table[l3i].address(), entry.address()); + Err(Errno::AlreadyExists) + } else { + l2_table[l3i] = entry; + unsafe { + core::arch::asm!("invlpg ({})", in(reg) virt, options(att_syntax)); + } + Ok(()) + } } fn read_last_level(&self, virt: usize) -> Result { - todo!() + let l0i = virt >> 39; + let l1i = (virt >> 30) & 0x1FF; + let l2i = (virt >> 21) & 0x1FF; + let l3i = (virt >> 12) & 0x1FF; + + let l0_table = self.0.next_level_table(l0i).ok_or(Errno::DoesNotExist)?; + let l1_table = l0_table.next_level_table(l1i).ok_or(Errno::DoesNotExist)?; + let l2_table = l1_table.next_level_table(l2i).ok_or(Errno::DoesNotExist)?; + + let entry = l2_table[l3i]; + if entry.is_present() { + Ok(entry) + } else { + Err(Errno::DoesNotExist) + } } } @@ -121,20 +160,51 @@ impl TableImpl { /// 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 Self, Errno> { - todo!() + let entry = self[index]; + if entry.is_present() { + if !entry.is_normal() { + return Err(Errno::InvalidArgument); + } + + Ok(unsafe { &mut *(mem::virtualize(entry.address()) as *mut _) }) + } else { + let phys = phys::alloc_page(PageUsage::Paging)?; + let res = unsafe { &mut *(mem::virtualize(phys) as *mut Self) }; + self[index] = EntryImpl::normal(phys, MapAttributes::USER_WRITE | MapAttributes::USER_READ); + res.entries.fill(EntryImpl::EMPTY); + 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(&self, index: usize) -> Option<&'static Self> { - todo!() + let entry = self[index]; + if entry.is_present() { + if !entry.is_normal() { + panic!("Entry is not a table: idx={}", index); + } + + Some(unsafe { &*(mem::virtualize(entry.address()) as *const _) }) + } else { + None + } } /// Returns mutable 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(&mut self, index: usize) -> Option<&'static mut Self> { - todo!() + let entry = self[index]; + if entry.is_present() { + if !entry.is_normal() { + panic!("Entry is not a table: idx={}", index); + } + + Some(unsafe { &mut *(mem::virtualize(entry.address()) as *mut _) }) + } else { + None + } } } diff --git a/kernel/src/init.rs b/kernel/src/init.rs index f4a254c..6062192 100644 --- a/kernel/src/init.rs +++ b/kernel/src/init.rs @@ -36,26 +36,26 @@ pub extern "C" fn init_fn(_arg: usize) -> ! { proc.io.lock().set_ioctx(ioctx); - // Open stdin/stdout/stderr - { - let devfs_root = devfs::root(); - let tty_node = if console.is_empty() { - devfs_root.lookup("ttyS0") - } else { - devfs_root.lookup(console) - } - .expect("Failed to open stdout for init process"); + // // Open stdin/stdout/stderr + // { + // let devfs_root = devfs::root(); + // let tty_node = if console.is_empty() { + // devfs_root.lookup("ttyS0") + // } else { + // devfs_root.lookup(console) + // } + // .expect("Failed to open stdout for init process"); - let mut io = proc.io.lock(); - let stdin = tty_node.open(OpenFlags::O_RDONLY).unwrap(); - let stdout = tty_node.open(OpenFlags::O_WRONLY).unwrap(); - let stderr = stdout.clone(); + // let mut io = proc.io.lock(); + // let stdin = tty_node.open(OpenFlags::O_RDONLY).unwrap(); + // let stdout = tty_node.open(OpenFlags::O_WRONLY).unwrap(); + // let stderr = stdout.clone(); - io.set_file(FileDescriptor::STDIN, stdin).unwrap(); - io.set_file(FileDescriptor::STDOUT, stdout).unwrap(); - io.set_file(FileDescriptor::STDERR, stderr).unwrap(); - io.set_ctty(tty_node); - } + // io.set_file(FileDescriptor::STDIN, stdin).unwrap(); + // io.set_file(FileDescriptor::STDOUT, stdout).unwrap(); + // io.set_file(FileDescriptor::STDERR, stderr).unwrap(); + // io.set_ctty(tty_node); + // } drop(cfg); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 3fab357..e0ab6a7 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -5,6 +5,7 @@ const_fn_fn_ptr_basics, const_fn_trait_bound, const_trait_impl, + const_btree_new, panic_info_message, alloc_error_handler, asm_const, @@ -31,9 +32,9 @@ pub mod config; pub mod dev; pub mod fs; pub mod font; -// pub mod init; +pub mod init; pub mod mem; -// pub mod proc; +pub mod proc; pub mod sync; // pub mod syscall; pub mod util; diff --git a/kernel/src/mem/virt/table.rs b/kernel/src/mem/virt/table.rs index 7f8232d..05eda27 100644 --- a/kernel/src/mem/virt/table.rs +++ b/kernel/src/mem/virt/table.rs @@ -103,6 +103,40 @@ pub trait Space { create_intermediate: bool, overwrite: bool, ) -> Result<(), Errno>; +// ======= +// bitflags! { +// /// Attributes attached to each translation [Entry] +// pub struct MapAttributes: u64 { +// const USER_READ = 1 << 1; +// const USER_WRITE = 1 << 2; +// const USER_EXEC = 1 << 3; +// const KERNEL_WRITE = 1 << 4; +// const KERNEL_EXEC = 1 << 5; +// +// const SHARE_OUTER = 1 << 6; +// const SHARE_INNER = 2 << 6; +// +// const NOT_GLOBAL = 1 << 8; +// } +// } +// +// pub trait Entry: Clone + Copy { +// fn from_parts(phys: usize, attrs: MapAttributes) -> Self; +// fn target(self) -> usize; +// fn is_present(self) -> bool; +// fn is_table(self) -> bool; +// } +// +// pub trait AddressSpace { +// type Entry: Entry; +// +// fn alloc_empty() -> Result<&'static mut Self, Errno>; +// fn release(space: &mut Self); +// fn address_phys(&mut self) -> usize; +// fn read_last_level_entry(&mut self, virt: usize) -> Result; +// fn write_last_level_entry( +// >>>>>>> d14ca5e (Make x86_64 work (pre-syscalls)) + /// Reads an entry corresponding to `virt` address fn read_last_level(&self, virt: usize) -> Result; diff --git a/kernel/src/proc/mod.rs b/kernel/src/proc/mod.rs index 64bcceb..d143b4f 100644 --- a/kernel/src/proc/mod.rs +++ b/kernel/src/proc/mod.rs @@ -27,6 +27,11 @@ pub fn switch() { SCHED.switch(false); } +#[no_mangle] +extern "C" fn sched_yield() { + SCHED.switch(false); +} + pub(self) static PROCESSES: IrqSafeSpinLock> = IrqSafeSpinLock::new(BTreeMap::new()); diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index ea1e7db..17712c1 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -1,5 +1,4 @@ //! Process data and control -use crate::arch::{aarch64::exception::ExceptionFrame, intrin}; use crate::mem::{ self, phys::{self, PageUsage}, @@ -8,7 +7,8 @@ use crate::mem::{ use crate::proc::{ wait::Wait, Context, ProcessIo, Thread, ThreadRef, ThreadState, Tid, PROCESSES, SCHED, }; -use crate::sync::IrqSafeSpinLock; +use crate::arch::intrin; +use crate::sync::{IrqSafeSpinLock, IrqSafeSpinLockGuard}; use alloc::{rc::Rc, vec::Vec}; use core::sync::atomic::{AtomicU32, Ordering}; use libsys::{ @@ -17,6 +17,7 @@ use libsys::{ signal::Signal, ProgramArgs, }; +use core::arch::asm; /// Wrapper type for a process struct reference pub type ProcessRef = Rc; @@ -154,193 +155,19 @@ impl Process { None } - /// Handles all pending signals (when returning from aborted syscall) - pub fn handle_pending_signals(&self) { - let mut lock = self.inner.lock(); - let ttbr0 = lock.space.as_mut().unwrap().address_phys() | ((lock.id.asid() as usize) << 48); - let main_thread = Thread::get(lock.threads[0]).unwrap(); - drop(lock); - - loop { - let state = self.signal_state.load(Ordering::Acquire); - if let Some(signal) = Self::find1(state).map(|e| Signal::try_from(e as u32).unwrap()) { - self.signal_state - .fetch_and(!(1 << (signal as u32)), Ordering::Release); - main_thread.clone().enter_signal(signal, ttbr0); - } else { - break; - } - } - } - - /// Sets a pending signal for a process - pub fn set_signal(&self, signal: Signal) { - let mut lock = self.inner.lock(); - let ttbr0 = lock.space.as_mut().unwrap().address_phys() | ((lock.id.asid() as usize) << 48); - let main_thread = Thread::get(lock.threads[0]).unwrap(); - drop(lock); - - // TODO check that `signal` is not a fault signal - // it is illegal to call this function with - // fault signals - - match main_thread.state() { - ThreadState::Running => { - main_thread.enter_signal(signal, ttbr0); - } - ThreadState::Waiting => { - self.signal_state - .fetch_or(1 << (signal as u32), Ordering::Release); - main_thread.interrupt_wait(true); - } - ThreadState::Ready => { - main_thread.clone().setup_signal(signal, ttbr0); - main_thread.interrupt_wait(false); - } - ThreadState::Finished => { - // TODO report error back - todo!() - } - } - } - - /// Immediately delivers a signal to requested thread - pub fn enter_fault_signal(&self, thread: ThreadRef, signal: Signal) { - let mut lock = self.inner.lock(); - let ttbr0 = lock.space.as_mut().unwrap().address_phys() | ((lock.id.asid() as usize) << 48); - drop(lock); - thread.enter_signal(signal, ttbr0); - } - - /// Crates a new thread in the process - pub fn new_user_thread(&self, entry: usize, stack: usize, arg: usize) -> Result { - let mut lock = self.inner.lock(); - - let space_phys = lock.space.as_mut().unwrap().address_phys(); - let ttbr0 = space_phys | ((lock.id.asid() as usize) << 48); - - let thread = Thread::new_user(lock.id, entry, stack, arg, ttbr0)?; - let tid = thread.id(); - lock.threads.push(tid); - SCHED.enqueue(tid); - - Ok(tid) - } - - /// Creates a "fork" of the process, cloning its address space and - /// resources - pub fn fork(&self, frame: &mut ExceptionFrame) -> Result { - let src_io = self.io.lock(); - let mut src_inner = self.inner.lock(); - - let dst_id = new_user_pid(); - let dst_space = src_inner.space.as_mut().unwrap().fork()?; - let dst_space_phys = (dst_space as *mut _ as usize) - mem::KERNEL_OFFSET; - let dst_ttbr0 = dst_space_phys | ((dst_id.asid() as usize) << 48); - - let mut threads = Vec::new(); - let tid = Thread::fork(Some(dst_id), frame, dst_ttbr0)?.id(); - threads.push(tid); - - let dst = Rc::new(Self { - exit_wait: Wait::new("process_exit"), - io: IrqSafeSpinLock::new(src_io.fork()?), - signal_state: AtomicU32::new(0), - inner: IrqSafeSpinLock::new(ProcessInner { - threads, - exit: None, - space: Some(dst_space), - state: ProcessState::Active, - id: dst_id, - pgid: src_inner.pgid, - ppid: Some(src_inner.id), - sid: src_inner.sid, - }), - }); - - debugln!("Process {:?} forked into {:?}", src_inner.id, dst_id); - assert!(PROCESSES.lock().insert(dst_id, dst).is_none()); - - SCHED.enqueue(tid); - - Ok(dst_id) + fn space_phys(lock: &mut IrqSafeSpinLockGuard) -> usize { + lock.space.as_mut().unwrap().address_phys() | ((lock.id.asid() as usize) << 48) } /// Terminates a process. pub fn exit(self: ProcessRef, status: ExitCode) { - let thread = Thread::current(); - let mut lock = self.inner.lock(); - let is_running = thread.owner_id().map(|e| e == lock.id).unwrap_or(false); - - infoln!("Process {:?} is exiting: {:?}", lock.id, status); - assert!(lock.exit.is_none()); - lock.exit = Some(status); - lock.state = ProcessState::Finished; - - for &tid in lock.threads.iter() { - let thread = Thread::get(tid).unwrap(); - if thread.state() == ThreadState::Waiting { - todo!() - } - thread.terminate(status); - SCHED.dequeue(tid); - } - - if let Some(space) = lock.space.take() { - unsafe { - SpaceImpl::release(space); - intrin::flush_tlb_asid((lock.id.asid() as usize) << 48); - } - } - - // TODO when exiting from signal handler interrupting an IO operation - // deadlock is achieved - self.io.lock().handle_exit(); - - drop(lock); - - self.exit_wait.wakeup_all(); - - if is_running { - SCHED.switch(true); - panic!("This code should never run"); - } + todo!() } /// Terminates a thread of the process. If the thread is the only /// one remaining, process itself is exited (see [Process::exit]) pub fn exit_thread(thread: ThreadRef, status: ExitCode) { - let switch = { - let switch = thread.state() == ThreadState::Running; - let process = thread.owner().unwrap(); - let mut lock = process.inner.lock(); - let tid = thread.id(); - - if lock.threads.len() == 1 { - // TODO call Process::exit instead? - drop(lock); - process.exit(status); - return; - } - - lock.threads.retain(|&e| e != tid); - - thread.terminate(status); - SCHED.dequeue(tid); - debugln!("Thread {:?} terminated", tid); - - switch - }; - - if switch { - // TODO retain thread ID in process "finished" list and - // drop it when process finishes - SCHED.switch(true); - panic!("This code should not run"); - } else { - // Can drop this thread: it's not running - todo!(); - } + todo!() } fn collect(&self) -> Option { @@ -418,13 +245,6 @@ impl Process { (self.id().asid() as usize) << 48 } - /// Flushes TLB cache for the process address space - pub fn invalidate_tlb(&self) { - unsafe { - intrin::flush_tlb_asid(self.asid()); - } - } - /// Loads a new program into current process address space pub fn execve Result>( loader: F, @@ -488,7 +308,7 @@ impl Process { // TODO drop old context let ctx = thread.ctx.get(); let asid = (process_lock.id.asid() as usize) << 48; - intrin::flush_tlb_asid(asid); + // Process::invalidate_asid(asid); ctx.write(Context::user( entry, diff --git a/kernel/src/proc/sched.rs b/kernel/src/proc/sched.rs index 918da2e..ab48f91 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(); + // cortex_a::asm::wfi(); } } diff --git a/kernel/src/proc/thread.rs b/kernel/src/proc/thread.rs index ec79803..687b815 100644 --- a/kernel/src/proc/thread.rs +++ b/kernel/src/proc/thread.rs @@ -1,6 +1,6 @@ //! Facilities for controlling threads - smallest units of //! execution in the operating system -use crate::arch::aarch64::exception::ExceptionFrame; +// use crate::arch::aarch64::exception::ExceptionFrame; use crate::proc::{ wait::{Wait, WaitStatus}, Process, ProcessRef, SCHED, THREADS, @@ -143,34 +143,34 @@ impl Thread { Ok(res) } - /// Creates a fork thread cloning `frame` context - pub fn fork( - owner: Option, - frame: &ExceptionFrame, - ttbr0: usize, - ) -> Result { - let id = new_tid(); + // /// Creates a fork thread cloning `frame` context + // pub fn fork( + // owner: Option, + // frame: &ExceptionFrame, + // ttbr0: usize, + // ) -> Result { + // let id = new_tid(); - let res = Rc::new(Self { - ctx: UnsafeCell::new(Context::fork(frame, ttbr0)), - signal_ctx: UnsafeCell::new(Context::empty()), - signal_pending: AtomicU32::new(0), - exit_wait: Wait::new("thread_exit"), - exit_status: InitOnce::new(), - inner: IrqSafeSpinLock::new(ThreadInner { - signal_entry: 0, - signal_stack: 0, - id, - owner, - pending_wait: None, - wait_status: WaitStatus::Done, - state: State::Ready, - }), - }); - debugln!("Forked new user thread: {:?}", id); - assert!(THREADS.lock().insert(id, res.clone()).is_none()); - Ok(res) - } + // let res = Rc::new(Self { + // ctx: UnsafeCell::new(Context::fork(frame, ttbr0)), + // signal_ctx: UnsafeCell::new(Context::empty()), + // signal_pending: AtomicU32::new(0), + // exit_wait: Wait::new("thread_exit"), + // exit_status: InitOnce::new(), + // inner: IrqSafeSpinLock::new(ThreadInner { + // signal_entry: 0, + // signal_stack: 0, + // id, + // owner, + // pending_wait: None, + // wait_status: WaitStatus::Done, + // state: State::Ready, + // }), + // }); + // debugln!("Forked new user thread: {:?}", id); + // assert!(THREADS.lock().insert(id, res.clone()).is_none()); + // Ok(res) + // } /// Returns the thread ID #[inline] diff --git a/kernel/src/proc/wait.rs b/kernel/src/proc/wait.rs index 023fd5a..c10c3ca 100644 --- a/kernel/src/proc/wait.rs +++ b/kernel/src/proc/wait.rs @@ -39,35 +39,12 @@ pub static WAIT_SELECT: Wait = Wait::new("select"); /// Checks for any timed out wait channels and interrupts them pub fn tick() { - let time = machine::local_timer().timestamp().unwrap(); - let mut list = TICK_LIST.lock(); - let mut cursor = list.cursor_front_mut(); - - while let Some(item) = cursor.current() { - if time > item.deadline { - let tid = item.tid; - cursor.remove_current(); - SCHED.enqueue(tid); - } else { - cursor.move_next(); - } - } + todo!(); } /// Suspends current process for given duration pub fn sleep(timeout: Duration, remaining: &mut Duration) -> Result<(), Errno> { - // Dummy wait descriptor which will never receive notifications - static SLEEP_NOTIFY: Wait = Wait::new("sleep"); - let deadline = machine::local_timer().timestamp()? + timeout; - match SLEEP_NOTIFY.wait(Some(deadline)) { - Err(Errno::Interrupt) => { - *remaining = deadline - machine::local_timer().timestamp()?; - Err(Errno::Interrupt) - } - Err(Errno::TimedOut) => Ok(()), - Ok(_) => panic!("Impossible result"), - res => res, - } + todo!() } /// Suspends current process until some file descriptor @@ -78,49 +55,7 @@ pub fn select( mut wfds: Option<&mut FdSet>, timeout: Option, ) -> Result { - if wfds.is_none() && rfds.is_none() { - todo!(); - } - let read = rfds.as_deref().map(FdSet::clone); - let write = wfds.as_deref().map(FdSet::clone); - if let Some(rfds) = &mut rfds { - rfds.reset(); - } - if let Some(wfds) = &mut wfds { - wfds.reset(); - } - - let deadline = timeout.map(|v| v + machine::local_timer().timestamp().unwrap()); - let proc = thread.owner().unwrap(); - let mut io = proc.io.lock(); - - loop { - if let Some(read) = &read { - for fd in read.iter() { - let file = io.file(fd)?; - if file.borrow().ready(false)? { - rfds.as_mut().unwrap().set(fd); - return Ok(1); - } - } - } - if let Some(write) = &write { - for fd in write.iter() { - let file = io.file(fd)?; - if file.borrow().ready(true)? { - wfds.as_mut().unwrap().set(fd); - return Ok(1); - } - } - } - - // Suspend - match WAIT_SELECT.wait(deadline) { - Err(Errno::TimedOut) => return Ok(0), - Err(e) => return Err(e), - Ok(_) => {} - } - } + todo!(); } impl Wait { @@ -134,61 +69,11 @@ impl Wait { /// Interrupt wait pending on the channel pub fn abort(&self, tid: Tid, enqueue: bool) { - let mut queue = self.queue.lock(); - let mut tick_lock = TICK_LIST.lock(); - let mut cursor = tick_lock.cursor_front_mut(); - while let Some(item) = cursor.current() { - if tid == item.tid { - cursor.remove_current(); - break; - } else { - cursor.move_next(); - } - } - - let mut cursor = queue.cursor_front_mut(); - while let Some(item) = cursor.current() { - if tid == *item { - cursor.remove_current(); - let thread = Thread::get(tid).unwrap(); - thread.set_wait_status(WaitStatus::Interrupted); - if enqueue { - SCHED.enqueue(tid); - } - break; - } else { - cursor.move_next(); - } - } + todo!(); } fn wakeup_some(&self, mut limit: usize) -> usize { - // No IRQs will arrive now == safe to manipulate tick list - let mut queue = self.queue.lock(); - let mut count = 0; - while limit != 0 && !queue.is_empty() { - let tid = queue.pop_front(); - if let Some(tid) = tid { - let mut tick_lock = TICK_LIST.lock(); - let mut cursor = tick_lock.cursor_front_mut(); - while let Some(item) = cursor.current() { - if tid == item.tid { - cursor.remove_current(); - break; - } else { - cursor.move_next(); - } - } - drop(tick_lock); - - Thread::get(tid).unwrap().set_wait_status(WaitStatus::Done); - SCHED.enqueue(tid); - } - - limit -= 1; - count += 1; - } - count + todo!(); } /// Notifies all processes waiting for this event @@ -204,51 +89,6 @@ impl Wait { /// Suspends current process until event is signalled or /// (optional) deadline is reached pub fn wait(&self, deadline: Option) -> Result<(), Errno> { - let thread = Thread::current(); - //let deadline = timeout.map(|t| machine::local_timer().timestamp().unwrap() + t); - let mut queue_lock = self.queue.lock(); - - queue_lock.push_back(thread.id()); - thread.setup_wait(self); - - if let Some(deadline) = deadline { - TICK_LIST.lock().push_back(Timeout { - tid: thread.id(), - deadline, - }); - } - - loop { - match thread.wait_status() { - WaitStatus::Pending => {} - WaitStatus::Done => { - return Ok(()); - } - WaitStatus::Interrupted => { - return Err(Errno::Interrupt); - } - }; - - drop(queue_lock); - thread.enter_wait(); - queue_lock = self.queue.lock(); - - if let Some(deadline) = deadline { - if machine::local_timer().timestamp()? > deadline { - let mut cursor = queue_lock.cursor_front_mut(); - - while let Some(&mut item) = cursor.current() { - if thread.id() == item { - cursor.remove_current(); - break; - } else { - cursor.move_next(); - } - } - - return Err(Errno::TimedOut); - } - } - } + todo!(); } } diff --git a/libsys/src/calls.rs b/libsys/src/calls.rs index ef1019b..86cc63e 100644 --- a/libsys/src/calls.rs +++ b/libsys/src/calls.rs @@ -18,44 +18,54 @@ use core::time::Duration; // TODO move this to libusr macro_rules! syscall { ($num:expr) => {{ - let mut res: usize; - asm!("svc #0", out("x0") res, in("x8") $num.repr(), options(nostack)); - res + // let mut res: usize; + // asm!("svc #0", out("x0") res, in("x8") $num.repr(), options(nostack)); + // res + loop {} + 0 }}; ($num:expr, $a0:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, - in("x8") $num.repr(), options(nostack)); - res + // let mut res: usize = $a0; + // asm!("svc #0", + // inout("x0") res, + // in("x8") $num.repr(), options(nostack)); + // res + loop {} + 0 }}; ($num:expr, $a0:expr, $a1:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, - in("x8") $num.repr(), options(nostack)); - res + // let mut res: usize = $a0; + // asm!("svc #0", + // inout("x0") res, in("x1") $a1, + // in("x8") $num.repr(), options(nostack)); + // res + loop {} + 0 }}; ($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{ let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, in("x2") $a2, - in("x8") $num.repr(), options(nostack)); + asm!("syscall", + inout("rax") res, in("rdi") $a1, in("rsi") $a2, + in("rdx") $num.repr(), options(nostack)); res }}; ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, in("x2") $a2, - in("x3") $a3, in("x8") $num.repr(), options(nostack)); - res + // let mut res: usize = $a0; + // asm!("svc #0", + // inout("x0") res, in("x1") $a1, in("x2") $a2, + // in("x3") $a3, in("x8") $num.repr(), options(nostack)); + // res + loop {} + 0 }}; ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{ - let mut res: usize = $a0; - 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 + // let mut res: usize = $a0; + // 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 + loop {} + 0 }}; } diff --git a/libusr/src/lib.rs b/libusr/src/lib.rs index d375d3e..50ae82e 100644 --- a/libusr/src/lib.rs +++ b/libusr/src/lib.rs @@ -26,11 +26,14 @@ extern "C" fn _start(arg: &'static ProgramArgs) -> ! { fn main() -> i32; } - unsafe { - allocator::init(); - thread::init_main(); - env::setup_env(arg); - } + trace!(TraceLevel::Debug, "Test!"); + loop {} + + // unsafe { + // allocator::init(); + // thread::init_main(); + // env::setup_env(arg); + // } let res = unsafe { main() }; sys::sys_exit(ExitCode::from(res)); diff --git a/libusr/src/thread.rs b/libusr/src/thread.rs index 1757065..000090e 100644 --- a/libusr/src/thread.rs +++ b/libusr/src/thread.rs @@ -61,16 +61,16 @@ impl JoinHandle { } unsafe fn init_common(signal_stack_pointer: *mut u8) { - let tid = u32::from(sys_ex_gettid()) as u64; - asm!("msr tpidr_el0, {:x}", in(reg) tid); + // let tid = u32::from(sys_ex_gettid()) as u64; + // asm!("msr tpidr_el0, {:x}", in(reg) tid); // thread::current() should be valid at this point - sys_ex_signal( - signal::signal_handler as usize, - signal_stack_pointer as usize, - ) - .unwrap(); + // sys_ex_signal( + // signal::signal_handler as usize, + // signal_stack_pointer as usize, + // ) + // .unwrap(); } pub(crate) unsafe fn init_main() { @@ -83,13 +83,7 @@ pub(crate) unsafe fn init_main() { } pub fn current() -> Thread { - let mut id: u64; - unsafe { - asm!("mrs {:x}, tpidr_el0", out(reg) id); - } - Thread { - id: Tid::from(id as u32), - } + todo!() } pub fn spawn(f: F) -> JoinHandle diff --git a/user/Cargo.toml b/user/Cargo.toml index e4be2ea..52ebd67 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -17,9 +17,9 @@ path = "src/bin/mkdir.rs" name = "shell" path = "src/bin/shell.rs" -[[bin]] -name = "fuzzy" -path = "src/bin/fuzzy.rs" +# [[bin]] +# name = "fuzzy" +# path = "src/bin/fuzzy.rs" [[bin]] name = "ls" diff --git a/user/src/bin/fuzzy.rs b/user/src/bin/fuzzy.rs index 593b5de..9915108 100644 --- a/user/src/bin/fuzzy.rs +++ b/user/src/bin/fuzzy.rs @@ -1,146 +1,141 @@ +// #![feature(asm)] #![no_std] #![no_main] -#![allow(unused_macros)] -#![allow(dead_code)] - +// +// #![allow(unused_macros)] +// #![allow(dead_code)] +// #[macro_use] extern crate libusr; - -use core::arch::asm; -use libusr::sys::{abi::SystemCall, stat::Stat}; - -static mut STATE: u64 = 0; - -macro_rules! syscall { - ($num:expr) => {{ - let mut res: usize; - asm!("svc #0", out("x0") res, in("x8") $num, options(nostack)); - res - }}; - ($num:expr, $a0:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, - in("x8") $num, options(nostack)); - res - }}; - ($num:expr, $a0:expr, $a1:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, - in("x8") $num, options(nostack)); - res - }}; - ($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, in("x2") $a2, - in("x8") $num, options(nostack)); - res - }}; - ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, in("x2") $a2, - in("x3") $a3, in("x8") $num, options(nostack)); - res - }}; - ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{ - let mut res: usize = $a0; - asm!("svc #0", - inout("x0") res, in("x1") $a1, in("x2") $a2, - in("x3") $a3, in("x4") $a4, in("x8") $num, options(nostack)); - res - }}; -} - -/// Integer/size argument -macro_rules! argn { - ($a:expr) => { - $a as usize - }; -} -/// Pointer/base argument -macro_rules! argp { - ($a:expr) => { - $a as usize - }; -} - -fn random_set_seed(seed: u64) { - unsafe { - STATE = seed; - } -} - -fn random_u64() -> u64 { - let mut x = unsafe { STATE }; - x ^= x << 13; - x ^= x >> 7; - x ^= x << 17; - unsafe { - STATE = x; - } - x -} - -fn random_ascii_char() -> u8 { - ((random_u64() % (0x7F - 0x20)) as u8) + 0x20 -} - -fn random_str_range(buf: &mut [u8], min: usize, max: usize) -> &str { - let max = core::cmp::min(buf.len(), max); - assert!(max > min); - let len = ((random_u64() as usize) % (max - min)) + min; - for c in buf[..len].iter_mut() { - *c = random_ascii_char(); - } - core::str::from_utf8(&buf[..len]).unwrap() -} - -fn random_str(buf: &mut [u8]) -> &str { - random_str_range(buf, 0, buf.len()) -} - -fn random_bytes(buf: &mut [u8]) { - for byte in buf.iter_mut() { - *byte = (random_u64() & 0xFF) as u8; - } -} - +// +// use libusr::sys::{abi::SystemCall, stat::Stat}; +// +// static mut STATE: u64 = 0; +// +// macro_rules! syscall { +// ($num:expr) => {{ +// let mut res: usize; +// asm!("svc #0", out("x0") res, in("x8") $num, options(nostack)); +// res +// }}; +// ($num:expr, $a0:expr) => {{ +// let mut res: usize = $a0; +// asm!("svc #0", +// inout("x0") res, +// in("x8") $num, options(nostack)); +// res +// }}; +// ($num:expr, $a0:expr, $a1:expr) => {{ +// let mut res: usize = $a0; +// asm!("svc #0", +// inout("x0") res, in("x1") $a1, +// in("x8") $num, options(nostack)); +// res +// }}; +// ($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{ +// let mut res: usize = $a0; +// asm!("svc #0", +// inout("x0") res, in("x1") $a1, in("x2") $a2, +// in("x8") $num, options(nostack)); +// res +// }}; +// ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{ +// let mut res: usize = $a0; +// asm!("svc #0", +// inout("x0") res, in("x1") $a1, in("x2") $a2, +// in("x3") $a3, in("x8") $num, options(nostack)); +// res +// }}; +// ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{ +// let mut res: usize = $a0; +// asm!("svc #0", +// inout("x0") res, in("x1") $a1, in("x2") $a2, +// in("x3") $a3, in("x4") $a4, in("x8") $num, options(nostack)); +// res +// }}; +// } +// +// /// Integer/size argument +// macro_rules! argn { +// ($a:expr) => { +// $a as usize +// }; +// } +// /// Pointer/base argument +// macro_rules! argp { +// ($a:expr) => { +// $a as usize +// }; +// } +// +// fn random_set_seed(seed: u64) { +// unsafe { STATE = seed; } +// } +// +// fn random_u64() -> u64 { +// let mut x = unsafe { STATE }; +// x ^= x << 13; +// x ^= x >> 7; +// x ^= x << 17; +// unsafe { +// STATE = x; +// } +// x +// } +// +// fn random_ascii_char() -> u8 { +// ((random_u64() % (0x7F - 0x20)) as u8) + 0x20 +// } +// +// fn random_str_range(buf: &mut [u8], min: usize, max: usize) -> &str { +// let max = core::cmp::min(buf.len(), max); +// assert!(max > min); +// let len = ((random_u64() as usize) % (max - min)) + min; +// for c in buf[..len].iter_mut() { +// *c = random_ascii_char(); +// } +// core::str::from_utf8(&buf[..len]).unwrap() +// } +// +// fn random_str(buf: &mut [u8]) -> &str { +// random_str_range(buf, 0, buf.len()) +// } +// +// fn random_bytes(buf: &mut [u8]) { +// for byte in buf.iter_mut() { +// *byte = (random_u64() & 0xFF) as u8; +// } +// } +// #[no_mangle] fn main() -> i32 { - let seed = libusr::sys::sys_ex_getcputime().unwrap().as_nanos() as u64 / 13; - println!("Using seed: {:#x}", seed); - random_set_seed(seed); - - let mut buf = [0; 256]; - - // Test sys_ex_getcputime() - let mut prev_time = libusr::sys::sys_ex_getcputime().unwrap().as_nanos(); - for _ in 0..1000 { - let t = libusr::sys::sys_ex_getcputime().unwrap().as_nanos(); - assert!(t >= prev_time); - prev_time = t; - } - - // Test non-utf8 input fed into syscalls expecting strings - // let old_signal = signal::set_handler(Signal::InvalidSystemCall, SignalHandler::Ignore); - for _ in 0..10000 { - random_bytes(&mut buf); - let mut stat = Stat::default(); - - unsafe { - syscall!( - SystemCall::FileStatus.repr(), - (-2i32) as usize, - buf.as_mut_ptr() as usize, - buf.len(), - (&mut stat) as *mut _ as usize - ); - } - } - // signal::set_handler(Signal::InvalidSystemCall, old_signal); - - 0 + loop {} } +// let seed = libusr::sys::sys_ex_getcputime().unwrap().as_nanos() as u64 / 13; +// println!("Using seed: {:#x}", seed); +// random_set_seed(seed); +// +// let mut buf = [0; 256]; +// +// // Test sys_ex_getcputime() +// let mut prev_time = libusr::sys::sys_ex_getcputime().unwrap().as_nanos(); +// for _ in 0..1000 { +// let t = libusr::sys::sys_ex_getcputime().unwrap().as_nanos(); +// assert!(t >= prev_time); +// prev_time = t; +// } +// +// // Test non-utf8 input fed into syscalls expecting strings +// // let old_signal = signal::set_handler(Signal::InvalidSystemCall, SignalHandler::Ignore); +// for _ in 0..10000 { +// random_bytes(&mut buf); +// let mut stat = Stat::default(); +// +// unsafe { +// syscall!(SystemCall::FileStatus.repr(), (-2i32) as usize, buf.as_mut_ptr() as usize, buf.len(), (&mut stat) as *mut _ as usize); +// } +// } +// // signal::set_handler(Signal::InvalidSystemCall, old_signal); +// +// 0 +// } diff --git a/user/src/init/main.rs b/user/src/init/main.rs index 1deea48..a8c6729 100644 --- a/user/src/init/main.rs +++ b/user/src/init/main.rs @@ -10,6 +10,8 @@ use libusr::sys::{stat::MountOptions, sys_execve, sys_fork, sys_mount, sys_waitp #[no_mangle] fn main() -> i32 { + loop {} + sys_mount( "/dev", &MountOptions { @@ -33,9 +35,6 @@ fn main() -> i32 { println!("Process {:?} exited with status {}", pid, status); loop { - unsafe { - asm!("nop"); - } } } else { sys_execve("/sbin/login", &["/sbin/login", "/dev/ttyS0"]).unwrap();