From c649947707d8567a78bb2ee4e39c2f989ae43d8a Mon Sep 17 00:00:00 2001 From: Stephen Marz Date: Fri, 15 May 2020 12:48:05 -0400 Subject: [PATCH] Added Registers to CPU so we don't have to hardcode the register number. This makes it easier to read and figure out what's happening --- risc_v/src/cpu.rs | 36 +++++++++++++++++++++++++++++++++++ risc_v/src/elf.rs | 5 +++-- risc_v/src/process.rs | 15 ++++++++------- risc_v/src/syscall.rs | 44 ++++++++++++++++++------------------------- 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/risc_v/src/cpu.rs b/risc_v/src/cpu.rs index 15e778f..83d16a9 100755 --- a/risc_v/src/cpu.rs +++ b/risc_v/src/cpu.rs @@ -27,6 +27,42 @@ pub enum CpuMode { Machine = 3, } +#[repr(usize)] +pub enum Registers { + Zero = 0, + Ra, + Sp, + Gp, + Tp, + T0, + T1, + T2, + S0, + S1, + A0, /* 10 */ + A1, + A2, + A3, + A4, + A5, + A6, + A7, + S2, + S3, + S4, /* 20 */ + S5, + S6, + S7, + S8, + S9, + S10, + S11, + T3, + T4, + T5, /* 30 */ + T6 +} + /// The trap frame is set into a structure /// and packed into each hart's mscratch register. /// This allows for quick reference and full diff --git a/risc_v/src/elf.rs b/risc_v/src/elf.rs index 06701ce..898ba7f 100755 --- a/risc_v/src/elf.rs +++ b/risc_v/src/elf.rs @@ -10,7 +10,8 @@ use crate::{buffer::Buffer, satp_fence_asid, CpuMode, SatpMode, - TrapFrame}, + TrapFrame, + Registers}, page::{map, zalloc, EntryBits, Table, PAGE_SIZE}, process::{Process, ProcessData, @@ -243,7 +244,7 @@ impl File { (*my_proc.frame).pc = elf_fl.header.entry_addr; // Stack pointer. The stack starts at the bottom and works its // way up, so we have to set the stack pointer to the bottom. - (*my_proc.frame).regs[2] = + (*my_proc.frame).regs[Registers::Sp as usize] = STACK_ADDR as usize + STACK_PAGES * PAGE_SIZE; // USER MODE! This is how we set what'll go into mstatus when we // run the process. diff --git a/risc_v/src/process.rs b/risc_v/src/process.rs index c704279..ace225b 100644 --- a/risc_v/src/process.rs +++ b/risc_v/src/process.rs @@ -8,7 +8,8 @@ use crate::{cpu::{build_satp, satp_fence_asid, CpuMode, SatpMode, - TrapFrame}, + TrapFrame, + Registers}, page::{alloc, dealloc, map, @@ -268,8 +269,8 @@ pub fn add_kernel_process(func: fn()) -> u16 { // 1 is the return address register. This makes it so we // don't have to do syscall_exit() when a kernel process // finishes. - (*ret_proc.frame).regs[1] = ra_delete_proc as usize; - (*ret_proc.frame).regs[2] = + (*ret_proc.frame).regs[Registers::Ra as usize] = ra_delete_proc as usize; + (*ret_proc.frame).regs[Registers::Sp as usize] = ret_proc.stack as usize + STACK_PAGES * 4096; (*ret_proc.frame).mode = CpuMode::Machine as usize; (*ret_proc.frame).pid = ret_proc.pid as usize; @@ -350,12 +351,12 @@ pub fn add_kernel_process_args(func: fn(args_ptr: usize), args: usize) -> u16 { // bottom of the memory and far away from heap allocations. unsafe { (*ret_proc.frame).pc = func_vaddr; - (*ret_proc.frame).regs[10] = args; + (*ret_proc.frame).regs[Registers::A0 as usize] = args; // 1 is the return address register. This makes it so we // don't have to do syscall_exit() when a kernel process // finishes. - (*ret_proc.frame).regs[1] = ra_delete_proc as usize; - (*ret_proc.frame).regs[2] = + (*ret_proc.frame).regs[Registers::Ra as usize] = ra_delete_proc as usize; + (*ret_proc.frame).regs[Registers::Sp as usize] = ret_proc.stack as usize + STACK_PAGES * 4096; (*ret_proc.frame).mode = CpuMode::Machine as usize; (*ret_proc.frame).pid = ret_proc.pid as usize; @@ -519,7 +520,7 @@ impl Process { let saddr = ret_proc.stack as usize; unsafe { (*ret_proc.frame).pc = func_vaddr; - (*ret_proc.frame).regs[2] = + (*ret_proc.frame).regs[Registers::Sp as usize] = STACK_ADDR + PAGE_SIZE * STACK_PAGES; (*ret_proc.frame).mode = CpuMode::User as usize; (*ret_proc.frame).pid = ret_proc.pid as usize; diff --git a/risc_v/src/syscall.rs b/risc_v/src/syscall.rs index a93dab3..7ad7d08 100755 --- a/risc_v/src/syscall.rs +++ b/risc_v/src/syscall.rs @@ -4,7 +4,7 @@ // 3 Jan 2020 use crate::{block::block_op, - cpu::{dump_registers, TrapFrame}, + cpu::{dump_registers, TrapFrame, Registers}, fs, page::{virt_to_phys, Table}, process::{Process, PROCESS_LIST, PROCESS_LIST_MUTEX, delete_process, get_by_pid, set_sleeping, set_waiting}}; @@ -20,7 +20,7 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { // Libgloss expects the system call number in A7, so let's follow // their lead. // A7 is X17, so it's register number 17. - let syscall_number = (*frame).regs[17]; + let syscall_number = (*frame).regs[Registers::A7 as usize]; match syscall_number { 0 | 93 => { // Exit @@ -29,7 +29,7 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { }, 2 => { // Easy putchar - print!("{}", (*frame).regs[10] as u8 as char); + print!("{}", (*frame).regs[Registers::A0 as usize] as u8 as char); mepc + 4 }, 8 => { @@ -38,13 +38,13 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { }, 10 => { // Sleep - set_sleeping((*frame).pid as u16, (*frame).regs[10]); + set_sleeping((*frame).pid as u16, (*frame).regs[Registers::A0 as usize]); 0 }, 11 => { // Add process to the scheduler. This is obviously insecure and // we wouldn't do this realistically. - let my_proc = (*frame).regs[10] as *const Process; + let my_proc = (*frame).regs[Registers::A0 as usize] as *const Process; if PROCESS_LIST_MUTEX.try_lock() { if let Some(mut pl) = PROCESS_LIST.take() { // As soon as we push this process on the list, it'll be @@ -53,10 +53,10 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { PROCESS_LIST.replace(pl); } PROCESS_LIST_MUTEX.unlock(); - (*frame).regs[10] = 1; + (*frame).regs[Registers::A0 as usize] = 1; } else { - (*frame).regs[10] = 0; + (*frame).regs[Registers::A0 as usize] = 0; } mepc + 4 }, @@ -72,7 +72,7 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { // from a user process using virt_to_phys. If this turns // out to be a page fault, we need to NOT proceed with // the read! - let mut physical_buffer = (*frame).regs[12]; + let mut physical_buffer = (*frame).regs[Registers::A2 as usize]; // If the MMU is turned on, we have to translate the // address. Eventually, I will put this code into a // convenient function, but for now, it will show how @@ -86,7 +86,7 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { let paddr = virt_to_phys(table, (*frame).regs[12]); if paddr.is_none() { - (*frame).regs[10] = -1isize as usize; + (*frame).regs[Registers::A0 as usize] = -1isize as usize; return mepc + 4; } physical_buffer = paddr.unwrap(); @@ -98,13 +98,13 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { // could be a missing page somewhere in between. let _ = fs::process_read( (*frame).pid as u16, - (*frame).regs[10] + (*frame).regs[Registers::A0 as usize] as usize, - (*frame).regs[11] as u32, + (*frame).regs[Registers::A1 as usize] as u32, physical_buffer as *mut u8, - (*frame).regs[13] as u32, - (*frame).regs[14] as u32, + (*frame).regs[Registers::A3 as usize] as u32, + (*frame).regs[Registers::A4 as usize] as u32, ); // If we return 0, the trap handler will schedule // another process. @@ -112,24 +112,16 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize { }, 172 => { // A0 = pid - (*frame).regs[10] = (*frame).pid; + (*frame).regs[Registers::A0 as usize] = (*frame).pid; mepc + 4 }, 180 => { - // println!( - // "Pid: {}, Dev: {}, Buffer: 0x{:x}, Size: {}, - // Offset: {}", (*frame).pid, - // (*frame).regs[10], - // (*frame).regs[11], - // (*frame).regs[12], - // (*frame).regs[13] - // ); set_waiting((*frame).pid as u16); let _ = block_op( - (*frame).regs[10], - (*frame).regs[11] as *mut u8, - (*frame).regs[12] as u32, - (*frame).regs[13] as u64, + (*frame).regs[Registers::A0 as usize], + (*frame).regs[Registers::A1 as usize] as *mut u8, + (*frame).regs[Registers::A2 as usize] as u32, + (*frame).regs[Registers::A3 as usize] as u64, false, (*frame).pid as u16, );