ahrightos-process 0.1.0

Portable process and scheduler primitives for the AhRightOS teaching kernel.
Documentation
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProcessContext {
    pub x: [usize; 31],
    pub sepc: usize,
    pub sstatus: usize,
    pub satp: usize,
}

pub const PROCESS_CONTEXT_X_OFFSET: usize = core::mem::offset_of!(ProcessContext, x);
pub const PROCESS_CONTEXT_SEPC_OFFSET: usize = core::mem::offset_of!(ProcessContext, sepc);
pub const PROCESS_CONTEXT_SSTATUS_OFFSET: usize = core::mem::offset_of!(ProcessContext, sstatus);
pub const PROCESS_CONTEXT_SATP_OFFSET: usize = core::mem::offset_of!(ProcessContext, satp);
pub const PROCESS_CONTEXT_SIZE: usize = core::mem::size_of::<ProcessContext>();

const _: [(); 31 * core::mem::size_of::<usize>()] = [(); PROCESS_CONTEXT_SEPC_OFFSET];
const _: [(); 32 * core::mem::size_of::<usize>()] = [(); PROCESS_CONTEXT_SSTATUS_OFFSET];
const _: [(); 33 * core::mem::size_of::<usize>()] = [(); PROCESS_CONTEXT_SATP_OFFSET];
const _: [(); 34 * core::mem::size_of::<usize>()] = [(); PROCESS_CONTEXT_SIZE];

impl ProcessContext {
    pub fn new() -> Self {
        Self {
            x: [0; 31],
            sepc: 0,
            sstatus: 0,
            satp: 0,
        }
    }

    pub fn set_ra(&mut self, ra: usize) {
        self.x[0] = ra;
    }

    pub fn set_sp(&mut self, sp: usize) {
        self.x[1] = sp;
    }

    pub fn ra(&self) -> usize {
        self.x[0]
    }

    pub fn sp(&self) -> usize {
        self.x[1]
    }

    pub fn set_sepc(&mut self, sepc: usize) {
        self.sepc = sepc;
    }

    pub fn set_sstatus(&mut self, sstatus: usize) {
        self.sstatus = sstatus;
    }

    pub fn set_satp(&mut self, satp: usize) {
        self.satp = satp;
    }
}

impl Default for ProcessContext {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn context_helpers_set_arch_registers() {
        let mut ctx = ProcessContext::new();
        ctx.set_ra(0x8020_0000);
        ctx.set_sp(0x8030_0000);
        ctx.set_sepc(0x8040_0000);
        ctx.set_sstatus(0x20);
        ctx.set_satp(0x8000);
        assert_eq!(ctx.ra(), 0x8020_0000);
        assert_eq!(ctx.sp(), 0x8030_0000);
        assert_eq!(ctx.sepc, 0x8040_0000);
        assert_eq!(ctx.sstatus, 0x20);
        assert_eq!(ctx.satp, 0x8000);
    }

    #[test]
    fn context_layout_matches_switch_abi() {
        assert_eq!(PROCESS_CONTEXT_X_OFFSET, 0);
        assert_eq!(PROCESS_CONTEXT_SEPC_OFFSET, 248);
        assert_eq!(PROCESS_CONTEXT_SSTATUS_OFFSET, 256);
        assert_eq!(PROCESS_CONTEXT_SATP_OFFSET, 264);
        assert_eq!(PROCESS_CONTEXT_SIZE, 272);
    }
}