moros 0.7.0

MOROS: Obscure Rust Operating System
Documentation
diff --git a/Makefile b/Makefile
index 861f360..dd1f30a 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ image: $(img)
 	cargo bootimage --no-default-features --features $(output),$(nic) --release --bin moros
 	dd conv=notrunc if=$(bin) of=$(img)
 
-opts = -m 32 -cpu max -nic model=$(nic) -hda $(img) -soundhw pcspk
+opts = -m 64 -cpu max -nic model=$(nic) -hda $(img) -soundhw pcspk
 ifeq ($(output),serial)
 	opts += -display none -serial stdio
 endif
diff --git a/dsk/bin/hello b/dsk/bin/hello
index e4301e6..e76d474 100755
Binary files a/dsk/bin/hello and b/dsk/bin/hello differ
diff --git a/dsk/bin/sleep b/dsk/bin/sleep
index a1081a5..73ddf4c 100644
Binary files a/dsk/bin/sleep and b/dsk/bin/sleep differ
diff --git a/src/sys/allocator.rs b/src/sys/allocator.rs
index a3df1dd..6cb8690 100644
--- a/src/sys/allocator.rs
+++ b/src/sys/allocator.rs
@@ -18,7 +18,7 @@ static ALLOCATOR: LockedHeap = LockedHeap::empty();
 
 pub fn init_heap(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<(), MapToError<Size4KiB>> {
     // Use half of the memory for the heap, caped to 16 MB because the allocator is too slow
-    let heap_size = cmp::min(sys::mem::memory_size() / 2, 16 << 20);
+    let heap_size = cmp::min(sys::mem::memory_size() / 2, 32 << 20);
 
     let pages = {
         let heap_start = VirtAddr::new(HEAP_START as u64);
diff --git a/src/sys/gdt.rs b/src/sys/gdt.rs
index 625f864..a3109ee 100644
--- a/src/sys/gdt.rs
+++ b/src/sys/gdt.rs
@@ -5,7 +5,7 @@ use x86_64::instructions::tables::load_tss;
 use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
 use x86_64::structures::tss::TaskStateSegment;
 
-const STACK_SIZE: usize = 8192;
+const STACK_SIZE: usize = 32 << 10;
 pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
 pub const PAGE_FAULT_IST_INDEX: u16 = 1;
 pub const GENERAL_PROTECTION_FAULT_IST_INDEX: u16 = 2;
diff --git a/src/sys/idt.rs b/src/sys/idt.rs
index 7ba0638..a5959f8 100644
--- a/src/sys/idt.rs
+++ b/src/sys/idt.rs
@@ -172,8 +172,11 @@ wrap!(syscall_handler => wrapped_syscall_handler);
 // return a result in the RAX register and it will be overwritten when the
 // context of the caller is restored.
 extern "sysv64" fn syscall_handler(_stack_frame: &mut InterruptStackFrame, regs: &mut Registers) {
-    printk!("DEBUG syscall handler: begin\n");
-    sys::process::set_registers(*regs);
+    printk!("DEBUG: syscall handler {}\n", regs.rax);
+    use x86_64::registers::segmentation::{Segment, CS, DS};
+    let cs = CS::get_reg();
+    let ds = DS::get_reg();
+    printk!("DEBUG: syscall handler cs={:?}, ds={:?}\n", cs, ds);
 
     // The registers order follow the System V ABI convention
     let n    = regs.rax;
@@ -181,7 +184,13 @@ extern "sysv64" fn syscall_handler(_stack_frame: &mut InterruptStackFrame, regs:
     let arg2 = regs.rsi;
     let arg3 = regs.rdx;
 
-    printk!("DEBUG syscall handler: n={:#x}, arg1={:#x}, arg2={:#x}, arg3={:#x}\n", n, arg1, arg2, arg3);
+    if n == sys::syscall::number::EXIT || n == sys::syscall::number::SPAWN {
+        //printk!("DEBUG: syscall handler regs before\n");
+        sys::process::set_registers(*regs);
+        //printk!("DEBUG: syscall handler regs after\n");
+    }
+
+    printk!("DEBUG: syscall handler -> n={}, arg1={}, arg2={}, arg3={}\n", n, arg1, arg2, arg3);
     regs.rax = sys::syscall::dispatcher(n, arg1, arg2, arg3);
     printk!("DEBUG syscall handler: end\n");
     unsafe { sys::pic::PICS.lock().notify_end_of_interrupt(0x80) };
diff --git a/src/sys/process.rs b/src/sys/process.rs
index d081f88..b2dd177 100644
--- a/src/sys/process.rs
+++ b/src/sys/process.rs
@@ -9,7 +9,7 @@ use lazy_static::lazy_static;
 use object::{Object, ObjectSegment};
 use spin::RwLock;
 
-const MAX_FILE_HANDLES: usize = 64;
+const MAX_FILE_HANDLES: usize = 32;
 
 lazy_static! {
     pub static ref PROCESS_TABLE: RwLock<Vec<Process>> = RwLock::new(Vec::new());
@@ -49,10 +49,14 @@ impl ProcessData {
 }
 
 pub fn id() -> usize {
-    PID.load(Ordering::SeqCst)
+    //PID.load(Ordering::SeqCst)
+    let id = PID.load(Ordering::SeqCst);
+    printk!("DEBUG: get pid {}\n", id);
+    id
 }
 
 pub fn set_id(id: usize) {
+    printk!("DEBUG: set pid {}\n", id);
     PID.store(id, Ordering::SeqCst)
 }
 
@@ -132,7 +136,9 @@ pub fn file_handle(handle: usize) -> Option<Resource> {
 }
 
 pub fn code_addr() -> u64 {
+    printk!("DEBUG: code_addr\n");
     let table = PROCESS_TABLE.read();
+    printk!("DEBUG: code_addr pid={}\n", id());
     let proc = &table[id()];
     proc.code_addr
 }
@@ -144,6 +150,7 @@ pub fn set_code_addr(addr: u64) {
 }
 
 pub fn ptr_from_addr(addr: u64) -> *mut u8 {
+    printk!("DEBUG: ptr_from_addr\n");
     (code_addr() + addr) as *mut u8
 }
 
@@ -218,6 +225,7 @@ impl Process {
     }
 
     fn create(bin: &[u8]) -> Result<usize, ()> {
+        printk!("DEBUG: process create\n");
         let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) };
         let mut frame_allocator = unsafe { sys::mem::BootInfoFrameAllocator::init(sys::mem::MEMORY_MAP.unwrap()) };
 
@@ -242,6 +250,7 @@ impl Process {
         let mut entry_point = 0;
         let code_ptr = code_addr as *mut u8;
         if &bin[1..4] == b"ELF" { // ELF binary
+            printk!("DEBUG: process create: ELF binary\n");
             if let Ok(obj) = object::File::parse(bin) {
                 entry_point = obj.entry();
                 for segment in obj.segments() {
@@ -257,6 +266,7 @@ impl Process {
                 }
             }
         } else { // Raw binary
+            printk!("DEBUG: process create: Raw binary\n");
             for (i, op) in bin.iter().enumerate() {
                 unsafe {
                     let ptr = code_ptr.add(i);
@@ -265,17 +275,28 @@ impl Process {
             }
         }
 
+        printk!("DEBUG: process create: read table\n");
         let mut table = PROCESS_TABLE.write();
+        printk!("DEBUG: process create: parent pid={}\n", id());
         let parent = &table[id()];
-        let dir = parent.data.dir.clone();
-        let user = parent.data.user.clone();
-        let data = ProcessData::new(&dir, user.as_deref());
+        //let data = parent.data.clone();
+        let dir = &parent.data.dir;
+        //printk!("DEBUG: process create: created dir '{}'\n", dir);
+        let user = parent.data.user.as_deref();
+        //printk!("DEBUG: process create: created user '{:?}'\n", user);
+        //printk!("DEBUG: process create: create data\n");
+        //let data = ProcessData::new(&dir, user.as_deref());
+        let data = ProcessData::new(dir, user);
+        //printk!("DEBUG: process create: created data\n");
         let id = table.len();
+        printk!("DEBUG: process create: child pid={}\n", id);
         let registers = Registers::default();
         let proc = Process { id, code_addr, code_size, entry_point, data, registers };
+        printk!("DEBUG: process create: {:?}\n", proc);
         table.push(proc);
         //printk!("DEBUG: create proc: release write lock\n");
 
+        printk!("DEBUG: process create: ok\n");
         Ok(id)
     }
 
diff --git a/src/sys/syscall/mod.rs b/src/sys/syscall/mod.rs
index f843656..68cb735 100644
--- a/src/sys/syscall/mod.rs
+++ b/src/sys/syscall/mod.rs
@@ -1,6 +1,8 @@
 pub mod number;
 pub mod service;
 
+pub use number::*;
+
 use crate::sys;
 use crate::sys::fs::FileStat;
 
@@ -46,7 +48,9 @@ pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
         }
         number::WRITE => {
             let handle = arg1;
+            printk!("DEBUG: write arg={:#x}\n", arg2 as u64);
             let ptr = sys::process::ptr_from_addr(arg2 as u64);
+            printk!("DEBUG: write ptr={:#x}\n", ptr as u64);
             let len = arg3;
             let mut buf = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
             service::write(handle, &mut buf) as usize