From f6d842b02b0aa079b9dccc72c2a47a3f6686d934 Mon Sep 17 00:00:00 2001 From: Stephen Marz Date: Wed, 3 Jun 2020 21:33:04 -0400 Subject: [PATCH] Added syscalls and information to support syscalls. --- risc_v/src/elf.rs | 1 + risc_v/src/process.rs | 7 +++++ risc_v/src/syscall.rs | 61 ++++++++++++++++++++++++++++++------------- risc_v/src/trap.rs | 22 ++++++++-------- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/risc_v/src/elf.rs b/risc_v/src/elf.rs index 23e5810..9c261e9 100755 --- a/risc_v/src/elf.rs +++ b/risc_v/src/elf.rs @@ -208,6 +208,7 @@ impl File { } // println!("DEBUG: Map 0x{:08x} to 0x{:08x} {:02x}", vaddr, paddr, bits); } + my_proc.brk += 0x1000; } // This will map all of the program pages. Notice that in linker.lds in // userspace we set the entry point address to 0x2000_0000. This is the diff --git a/risc_v/src/process.rs b/risc_v/src/process.rs index 124f895..5526a66 100644 --- a/risc_v/src/process.rs +++ b/risc_v/src/process.rs @@ -402,6 +402,11 @@ impl Drop for Process { } dealloc(self.mmu_table as *mut u8); dealloc(self.frame as *mut u8); + for i in self.data.pages.drain(..) { + dealloc(i as *mut u8); + } + // Kernel processes don't have a program, instead the program is linked + // directly in the kernel. if !self.program.is_null() { dealloc(self.program); } @@ -425,6 +430,7 @@ pub struct ProcessData { pub environ: BTreeMap, pub fdesc: BTreeMap, pub cwd: String, + pub pages: VecDeque, } // This is private data that we can query with system calls. @@ -436,6 +442,7 @@ impl ProcessData { environ: BTreeMap::new(), fdesc: BTreeMap::new(), cwd: String::new(), + pages: VecDeque::new(), } } } diff --git a/risc_v/src/syscall.rs b/risc_v/src/syscall.rs index 15a4b20..7e56742 100755 --- a/risc_v/src/syscall.rs +++ b/risc_v/src/syscall.rs @@ -10,7 +10,7 @@ use crate::{block::block_op, fs, gpu, input::{Event, ABS_EVENTS, KEY_EVENTS}, - page::{map, virt_to_phys, EntryBits, Table, PAGE_SIZE}, + page::{map, virt_to_phys, EntryBits, Table, PAGE_SIZE, zalloc}, process::{add_kernel_process_args, delete_process, get_by_pid, set_sleeping, set_waiting, PROCESS_LIST, PROCESS_LIST_MUTEX}}; use alloc::{boxed::Box, string::String}; @@ -125,6 +125,10 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { (*frame).regs[gp(Registers::A0)] = -1isize as usize; 0 } + 57 => { + // #define SYS_close 57 + 0 + } 63 => { // Read system call // This is an asynchronous call. This will get the @@ -174,19 +178,20 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { let mut buf = (*frame).regs[gp(Registers::A1)] as *const u8; let size = (*frame).regs[gp(Registers::A2)]; let process = get_by_pid((*frame).pid as u16); - if (*frame).satp >> 60 != 0 { - let table = ((*process).mmu_table).as_mut().unwrap(); - let paddr = virt_to_phys(table, buf as usize); - if let Some(bufaddr) = paddr { - buf = bufaddr as *const u8; - } - else { - (*frame).regs[gp(Registers::A0)] = -1isize as usize; - return 0; - } - } + // if (*frame).satp >> 60 != 0 { + // let table = ((*process).mmu_table).as_mut().unwrap(); + // let paddr = virt_to_phys(table, buf as usize); + // if let Some(bufaddr) = paddr { + // buf = bufaddr as *const u8; + // } + // else { + // (*frame).regs[gp(Registers::A0)] = -1isize as usize; + // return 0; + // } + // } if fd == 1 || fd == 2 { // stdout / stderr + // println!("WRITE {}, 0x{:08x}, {}", fd, bu/f as usize, size); let mut iter = 0; for _ in 0..size { iter += 1; @@ -194,7 +199,8 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { let table = ((*process).mmu_table).as_mut().unwrap(); let paddr = virt_to_phys(table, buf as usize); if let Some(bufaddr) = paddr { - buf = bufaddr as *const u8; + let output = *(bufaddr as *const u8) as char; + print!("{}", output); } else { (*frame).regs[gp(Registers::A0)] = -1isize as usize; @@ -215,6 +221,12 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { (*frame).regs[gp(Registers::A0)] = -1isize as usize; 0 } + // #define SYS_fstat 80 + 80 => { + // int fstat(int filedes, struct stat *buf) + (*frame).regs[gp(Registers::A0)] = 0; + 0 + } 172 => { // A0 = pid (*frame).regs[Registers::A0 as usize] = (*frame).pid; @@ -236,8 +248,21 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { // #define SYS_brk 214 // int brk(void *addr); let addr = (*frame).regs[gp(Registers::A0)]; - println!("BRK Addr = 0x{:08x}", addr); - (*frame).regs[gp(Registers::A0)] = -1isize as usize; + let process = get_by_pid((*frame).pid as u16).as_mut().unwrap(); + // println!("Break move from 0x{:08x} to 0x{:08x}", process.brk, addr); + if addr > process.brk { + if (*frame).satp >> 60 != 0 { + let table = ((*process).mmu_table).as_mut().unwrap(); + let diff = (addr + PAGE_SIZE - process.brk) / PAGE_SIZE; + for i in 0..diff { + let new_addr = zalloc(1) as usize; + process.data.pages.push_back(new_addr); + map(table, process.brk + (i << 12), new_addr, EntryBits::UserReadWrite.val(), 0); + } + } + process.brk = addr; + } + (*frame).regs[gp(Registers::A0)] = process.brk; 0 } // System calls 1000 and above are "special" system calls for our OS. I'll @@ -393,11 +418,12 @@ fn exec_func(args: usize) { println!("Failed to launch process."); } else { + let process = proc.ok().unwrap(); // If we hold this lock, we can still be preempted, but the scheduler will // return control to us. This required us to use try_lock in the scheduler. PROCESS_LIST_MUTEX.sleep_lock(); if let Some(mut proc_list) = PROCESS_LIST.take() { - proc_list.push_back(proc.ok().unwrap()); + proc_list.push_back(process); PROCESS_LIST.replace(proc_list); } PROCESS_LIST_MUTEX.unlock(); @@ -412,14 +438,13 @@ fn exec_func(args: usize) { // #define SYS_faccessat 48 // #define SYS_chdir 49 // #define SYS_openat 56 -// #define SYS_close 57 // #define SYS_getdents 61 // #define SYS_lseek 62 // #define SYS_read 63 // #define SYS_pread 67 // #define SYS_pwrite 68 // #define SYS_fstatat 79 -// #define SYS_fstat 80 + // #define SYS_kill 129 // #define SYS_rt_sigaction 134 // #define SYS_times 153 diff --git a/risc_v/src/trap.rs b/risc_v/src/trap.rs index 11eff26..7a0bc9c 100755 --- a/risc_v/src/trap.rs +++ b/risc_v/src/trap.rs @@ -45,7 +45,7 @@ extern "C" fn m_trap(epc: usize, // We will use this to awaken our other CPUs so they can process // processes. println!("Machine software interrupt CPU #{}", hart); - }, + } 7 => { // This is the context-switch timer. // We would typically invoke the scheduler here to pick another @@ -56,7 +56,7 @@ extern "C" fn m_trap(epc: usize, if new_frame != 0 { rust_switch_to_user(new_frame); } - }, + } 11 => { // Machine external (interrupt from Platform Interrupt Controller (PLIC)) // println!("Machine external interrupt CPU#{}", hart); @@ -65,10 +65,10 @@ extern "C" fn m_trap(epc: usize, // get an interrupt from a non-PLIC source. This is the main reason that the PLIC // hardwires the id 0 to 0, so that we can use it as an error case. plic::handle_interrupt(); - }, + } _ => { panic!("Unhandled async trap CPU#{} -> {}\n", hart, cause_num); - }, + } } } else { @@ -85,7 +85,7 @@ extern "C" fn m_trap(epc: usize, let frame = schedule(); schedule_next_context_switch(1); rust_switch_to_user(frame); - }, + } 3 => { // breakpoint println!("BKPT\n\n"); @@ -97,7 +97,7 @@ extern "C" fn m_trap(epc: usize, let frame = schedule(); schedule_next_context_switch(1); rust_switch_to_user(frame); - }, + } 8 | 9 | 11 => unsafe { // Environment (system) call from User, Supervisor, and Machine modes // println!("E-call from User mode! CPU#{} -> 0x{:08x}", hart, epc); @@ -110,7 +110,7 @@ extern "C" fn m_trap(epc: usize, schedule_next_context_switch(1); rust_switch_to_user(frame); } - }, + } // Page faults 12 => unsafe { // Instruction page fault @@ -119,7 +119,7 @@ extern "C" fn m_trap(epc: usize, let frame = schedule(); schedule_next_context_switch(1); rust_switch_to_user(frame); - }, + } 13 => unsafe { // Load page fault println!("Load page fault CPU#{} -> 0x{:08x}: 0x{:08x}", hart, epc, tval); @@ -127,7 +127,7 @@ extern "C" fn m_trap(epc: usize, let frame = schedule(); schedule_next_context_switch(1); rust_switch_to_user(frame); - }, + } 15 => unsafe { // Store page fault println!("Store page fault CPU#{} -> 0x{:08x}: 0x{:08x}", hart, epc, tval); @@ -135,13 +135,13 @@ extern "C" fn m_trap(epc: usize, let frame = schedule(); schedule_next_context_switch(1); rust_switch_to_user(frame); - }, + } _ => { panic!( "Unhandled sync trap {}. CPU#{} -> 0x{:08x}: 0x{:08x}\n", cause_num, hart, epc, tval ); - }, + } } }; // Finally, return the updated program counter