|
|
@ -1,52 +1,53 @@
|
|
|
|
use mips::registers;
|
|
|
|
use mips::registers::cp0;
|
|
|
|
|
|
|
|
use crate::arch::paging::root_page_table_ptr;
|
|
|
|
|
|
|
|
|
|
|
|
/// Saved registers on a trap.
|
|
|
|
/// Saved registers on a trap.
|
|
|
|
#[derive(Clone)]
|
|
|
|
#[derive(Clone)]
|
|
|
|
#[repr(C)]
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct TrapFrame {
|
|
|
|
pub struct TrapFrame {
|
|
|
|
/// CP0 status register
|
|
|
|
/// CP0 status register
|
|
|
|
pub status: u32,
|
|
|
|
pub status: cp0::status::Status,
|
|
|
|
/// CP0 cause register
|
|
|
|
/// CP0 cause register
|
|
|
|
pub cause: u32,
|
|
|
|
pub cause: cp0::cause::Cause,
|
|
|
|
/// CP0 EPC register
|
|
|
|
/// CP0 EPC register
|
|
|
|
pub epc: u32,
|
|
|
|
pub epc: usize,
|
|
|
|
/// CP0 vaddr register
|
|
|
|
/// CP0 vaddr register
|
|
|
|
pub vaddr: u32,
|
|
|
|
pub vaddr: usize,
|
|
|
|
/// HI/LO registers
|
|
|
|
/// HI/LO registers
|
|
|
|
pub hi: u32,
|
|
|
|
pub hi: usize,
|
|
|
|
pub lo: u32,
|
|
|
|
pub lo: usize,
|
|
|
|
/// General registers
|
|
|
|
/// General registers
|
|
|
|
pub at: u32,
|
|
|
|
pub at: usize,
|
|
|
|
pub v0: u32,
|
|
|
|
pub v0: usize,
|
|
|
|
pub v1: u32,
|
|
|
|
pub v1: usize,
|
|
|
|
pub a0: u32,
|
|
|
|
pub a0: usize,
|
|
|
|
pub a1: u32,
|
|
|
|
pub a1: usize,
|
|
|
|
pub a2: u32,
|
|
|
|
pub a2: usize,
|
|
|
|
pub a3: u32,
|
|
|
|
pub a3: usize,
|
|
|
|
pub t0: u32,
|
|
|
|
pub t0: usize,
|
|
|
|
pub t1: u32,
|
|
|
|
pub t1: usize,
|
|
|
|
pub t2: u32,
|
|
|
|
pub t2: usize,
|
|
|
|
pub t3: u32,
|
|
|
|
pub t3: usize,
|
|
|
|
pub t4: u32,
|
|
|
|
pub t4: usize,
|
|
|
|
pub t5: u32,
|
|
|
|
pub t5: usize,
|
|
|
|
pub t6: u32,
|
|
|
|
pub t6: usize,
|
|
|
|
pub t7: u32,
|
|
|
|
pub t7: usize,
|
|
|
|
pub s0: u32,
|
|
|
|
pub s0: usize,
|
|
|
|
pub s1: u32,
|
|
|
|
pub s1: usize,
|
|
|
|
pub s2: u32,
|
|
|
|
pub s2: usize,
|
|
|
|
pub s3: u32,
|
|
|
|
pub s3: usize,
|
|
|
|
pub s4: u32,
|
|
|
|
pub s4: usize,
|
|
|
|
pub s5: u32,
|
|
|
|
pub s5: usize,
|
|
|
|
pub s6: u32,
|
|
|
|
pub s6: usize,
|
|
|
|
pub s7: u32,
|
|
|
|
pub s7: usize,
|
|
|
|
pub t8: u32,
|
|
|
|
pub t8: usize,
|
|
|
|
pub t9: u32,
|
|
|
|
pub t9: usize,
|
|
|
|
pub k0: u32,
|
|
|
|
pub k0: usize,
|
|
|
|
pub k1: u32,
|
|
|
|
pub k1: usize,
|
|
|
|
pub gp: u32,
|
|
|
|
pub gp: usize,
|
|
|
|
pub sp: u32,
|
|
|
|
pub sp: usize,
|
|
|
|
pub fp: u32,
|
|
|
|
pub fp: usize,
|
|
|
|
pub ra: u32,
|
|
|
|
pub ra: usize,
|
|
|
|
/// Reserve space for hartid
|
|
|
|
/// Reserve space for hartid
|
|
|
|
pub _hartid: usize,
|
|
|
|
pub _hartid: usize,
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -59,13 +60,13 @@ impl TrapFrame {
|
|
|
|
fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self {
|
|
|
|
fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self {
|
|
|
|
use core::mem::zeroed;
|
|
|
|
use core::mem::zeroed;
|
|
|
|
let mut tf: Self = unsafe { zeroed() };
|
|
|
|
let mut tf: Self = unsafe { zeroed() };
|
|
|
|
tf.x[10] = arg; // a0
|
|
|
|
tf.a0 = arg;
|
|
|
|
tf.x[2] = sp;
|
|
|
|
tf.sp = sp;
|
|
|
|
tf.sepc = entry as usize;
|
|
|
|
tf.epc = entry as usize;
|
|
|
|
tf.sstatus = sstatus::read();
|
|
|
|
tf.status = cp0::status::read();
|
|
|
|
tf.sstatus.set_spie(true);
|
|
|
|
tf.status.set_kernel_mode();
|
|
|
|
tf.sstatus.set_sie(false);
|
|
|
|
tf.status.set_ie();
|
|
|
|
tf.sstatus.set_spp(sstatus::SPP::Supervisor);
|
|
|
|
tf.status.set_exl();
|
|
|
|
tf
|
|
|
|
tf
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -76,12 +77,12 @@ impl TrapFrame {
|
|
|
|
fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
|
|
|
|
fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
|
|
|
|
use core::mem::zeroed;
|
|
|
|
use core::mem::zeroed;
|
|
|
|
let mut tf: Self = unsafe { zeroed() };
|
|
|
|
let mut tf: Self = unsafe { zeroed() };
|
|
|
|
tf.x[2] = sp;
|
|
|
|
tf.sp = sp;
|
|
|
|
tf.sepc = entry_addr;
|
|
|
|
tf.epc = entry_addr;
|
|
|
|
tf.sstatus = sstatus::read();
|
|
|
|
tf.status = cp0::status::read();
|
|
|
|
tf.sstatus.set_spie(true);
|
|
|
|
tf.status.set_user_mode();
|
|
|
|
tf.sstatus.set_sie(false);
|
|
|
|
tf.status.set_ie();
|
|
|
|
tf.sstatus.set_spp(sstatus::SPP::User);
|
|
|
|
tf.status.set_exl();
|
|
|
|
tf
|
|
|
|
tf
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -89,23 +90,11 @@ impl TrapFrame {
|
|
|
|
use core::fmt::{Debug, Formatter, Error};
|
|
|
|
use core::fmt::{Debug, Formatter, Error};
|
|
|
|
impl Debug for TrapFrame {
|
|
|
|
impl Debug for TrapFrame {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
|
|
struct Regs<'a>(&'a [usize; 32]);
|
|
|
|
|
|
|
|
impl<'a> Debug for Regs<'a> {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
|
|
|
|
|
|
const REG_NAME: [&str; 32] = [
|
|
|
|
|
|
|
|
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
|
|
|
|
|
|
|
|
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
|
|
|
|
|
|
|
|
"s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
|
|
|
|
|
|
|
|
"t3", "t4", "t5", "t6"];
|
|
|
|
|
|
|
|
f.debug_map().entries(REG_NAME.iter().zip(self.0)).finish()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
f.debug_struct("TrapFrame")
|
|
|
|
f.debug_struct("TrapFrame")
|
|
|
|
.field("regs", &Regs(&self.x))
|
|
|
|
.field("status", &self.status.bits)
|
|
|
|
.field("sstatus", &self.sstatus)
|
|
|
|
.field("epc", &self.epc.bits)
|
|
|
|
.field("sepc", &self.sepc)
|
|
|
|
.field("cause", &self.cause.bits)
|
|
|
|
.field("stval", &self.stval)
|
|
|
|
.field("vaddr", &self.vaddr.bits)
|
|
|
|
.field("scause", &self.scause.cause())
|
|
|
|
|
|
|
|
.finish()
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -167,7 +156,6 @@ impl Context {
|
|
|
|
#[naked]
|
|
|
|
#[naked]
|
|
|
|
#[inline(never)]
|
|
|
|
#[inline(never)]
|
|
|
|
pub unsafe extern fn switch(&mut self, _target: &mut Self) {
|
|
|
|
pub unsafe extern fn switch(&mut self, _target: &mut Self) {
|
|
|
|
#[cfg(target_arch = "riscv32")]
|
|
|
|
|
|
|
|
asm!(r"
|
|
|
|
asm!(r"
|
|
|
|
.equ XLENB, 4
|
|
|
|
.equ XLENB, 4
|
|
|
|
.macro Load reg, mem
|
|
|
|
.macro Load reg, mem
|
|
|
@ -176,15 +164,6 @@ impl Context {
|
|
|
|
.macro Store reg, mem
|
|
|
|
.macro Store reg, mem
|
|
|
|
sw \reg, \mem
|
|
|
|
sw \reg, \mem
|
|
|
|
.endm");
|
|
|
|
.endm");
|
|
|
|
#[cfg(target_arch = "riscv64")]
|
|
|
|
|
|
|
|
asm!(r"
|
|
|
|
|
|
|
|
.equ XLENB, 8
|
|
|
|
|
|
|
|
.macro Load reg, mem
|
|
|
|
|
|
|
|
ld \reg, \mem
|
|
|
|
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro Store reg, mem
|
|
|
|
|
|
|
|
sd \reg, \mem
|
|
|
|
|
|
|
|
.endm");
|
|
|
|
|
|
|
|
asm!("
|
|
|
|
asm!("
|
|
|
|
// save from's registers
|
|
|
|
// save from's registers
|
|
|
|
addi sp, sp, (-XLENB*14)
|
|
|
|
addi sp, sp, (-XLENB*14)
|
|
|
@ -199,16 +178,16 @@ impl Context {
|
|
|
|
Store s6, 8*XLENB(sp)
|
|
|
|
Store s6, 8*XLENB(sp)
|
|
|
|
Store s7, 9*XLENB(sp)
|
|
|
|
Store s7, 9*XLENB(sp)
|
|
|
|
Store s8, 10*XLENB(sp)
|
|
|
|
Store s8, 10*XLENB(sp)
|
|
|
|
Store s9, 11*XLENB(sp)
|
|
|
|
Store gp, 11*XLENB(sp)
|
|
|
|
Store s10, 12*XLENB(sp)
|
|
|
|
Store ra, 12*XLENB(sp)
|
|
|
|
Store s11, 13*XLENB(sp)
|
|
|
|
Store sp, 13*XLENB(sp)
|
|
|
|
csrr s11, satp
|
|
|
|
|
|
|
|
Store s11, 1*XLENB(sp)
|
|
|
|
Store $1, 1*XLENB(sp)
|
|
|
|
|
|
|
|
|
|
|
|
// restore to's registers
|
|
|
|
// restore to's registers
|
|
|
|
Load sp, 0(a1)
|
|
|
|
Load sp, 0(a1)
|
|
|
|
Load s11, 1*XLENB(sp)
|
|
|
|
Load $0, 1*XLENB(sp)
|
|
|
|
csrw satp, s11
|
|
|
|
|
|
|
|
Load ra, 0*XLENB(sp)
|
|
|
|
Load ra, 0*XLENB(sp)
|
|
|
|
Load s0, 2*XLENB(sp)
|
|
|
|
Load s0, 2*XLENB(sp)
|
|
|
|
Load s1, 3*XLENB(sp)
|
|
|
|
Load s1, 3*XLENB(sp)
|
|
|
@ -219,14 +198,15 @@ impl Context {
|
|
|
|
Load s6, 8*XLENB(sp)
|
|
|
|
Load s6, 8*XLENB(sp)
|
|
|
|
Load s7, 9*XLENB(sp)
|
|
|
|
Load s7, 9*XLENB(sp)
|
|
|
|
Load s8, 10*XLENB(sp)
|
|
|
|
Load s8, 10*XLENB(sp)
|
|
|
|
Load s9, 11*XLENB(sp)
|
|
|
|
Load gp, 11*XLENB(sp)
|
|
|
|
Load s10, 12*XLENB(sp)
|
|
|
|
Load ra, 12*XLENB(sp)
|
|
|
|
Load s11, 13*XLENB(sp)
|
|
|
|
Load sp, 13*XLENB(sp)
|
|
|
|
addi sp, sp, (XLENB*14)
|
|
|
|
addi sp, sp, (XLENB*14)
|
|
|
|
|
|
|
|
|
|
|
|
Store zero, 0(a1)
|
|
|
|
Store zero, 0(a1)
|
|
|
|
ret"
|
|
|
|
jr ra
|
|
|
|
: : : : "volatile" )
|
|
|
|
nop"
|
|
|
|
|
|
|
|
:"=r"(root_page_table_ptr) :"r"(root_page_table_ptr) : : "volatile" )
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Constructs a null Context for the current running thread.
|
|
|
|
/// Constructs a null Context for the current running thread.
|
|
|
@ -269,7 +249,7 @@ impl Context {
|
|
|
|
tf: {
|
|
|
|
tf: {
|
|
|
|
let mut tf = tf.clone();
|
|
|
|
let mut tf = tf.clone();
|
|
|
|
// fork function's ret value, the new process is 0
|
|
|
|
// fork function's ret value, the new process is 0
|
|
|
|
tf.x[10] = 0; // a0
|
|
|
|
tf.a0 = 0;
|
|
|
|
tf
|
|
|
|
tf
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}.push_at(kstack_top)
|
|
|
|
}.push_at(kstack_top)
|
|
|
@ -287,9 +267,9 @@ impl Context {
|
|
|
|
context: ContextData::new(satp),
|
|
|
|
context: ContextData::new(satp),
|
|
|
|
tf: {
|
|
|
|
tf: {
|
|
|
|
let mut tf = tf.clone();
|
|
|
|
let mut tf = tf.clone();
|
|
|
|
tf.x[2] = ustack_top; // sp
|
|
|
|
tf.sp = ustack_top; // sp
|
|
|
|
tf.x[4] = tls; // tp
|
|
|
|
tf.v1 = tls; // tp
|
|
|
|
tf.x[10] = 0; // a0
|
|
|
|
tf.a0 = 0; // a0
|
|
|
|
tf
|
|
|
|
tf
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}.push_at(kstack_top)
|
|
|
|
}.push_at(kstack_top)
|
|
|
|