    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    use riscv::register::sstatus::{self, Sstatus, SPP};
    /// Trap Context
    #[repr(C)]
    pub struct TrapContext {
        /// general regs[0..31]
        pub x: [usize; 32],
        /// CSR sstatus
        pub sstatus: Sstatus,
        /// CSR sepc
        pub sepc: usize,
    }

    impl TrapContext {
        /// set stack pointer to x_2 reg (sp)
        pub fn set_sp(&mut self, sp: usize) {
            self.x[2] = sp;
        }
        /// init app context
        pub fn app_init_context(entry: usize, sp: usize) -> Self {
            let mut sstatus = sstatus::read(); // CSR sstatus
            sstatus.set_spp(SPP::User); //previous privilege mode: user mode
            let mut cx = Self {
                x: [0; 32],
                sstatus,
                sepc: entry, // entry point of app
            };
            cx.set_sp(sp); // app's user stack pointer
            cx // return initial Trap Context of app
        }
    }