moana_std 0.1.4

moana 用户标准库
Documentation
//! space 系列 syscall 用户态接口

use core::mem::MaybeUninit;

use moa_uapi::{
    error::{ERR_FAULT, ERR_INVAL, ERR_NO_RESOURCE, ERR_NOT_FOUND, ERR_PERM},
    mem::MemSource,
    space::{MapFlags, MapPerms, SpaceFlags, SpaceHandle, SpaceId, Uaddr},
    sysnr::{
        SYSNR_SPACE_CLOSE, SYSNR_SPACE_CREATE, SYSNR_SPACE_GET_ID, SYSNR_SPACE_MAP,
        SYSNR_SPACE_PROTECT, SYSNR_SPACE_READ, SYSNR_SPACE_UNMAP, SYSNR_SPACE_WRITE,
    },
};

/// space 系列 syscall 返回类型
pub type Result<T> = core::result::Result<T, SpaceError>;

define_syscall_error! {
    /// space 系列 syscall 错误
    pub enum SpaceError {
        /// 权限不足
        Perm = ERR_PERM,
        /// 句柄不存在
        NotFound = ERR_NOT_FOUND,
        /// 无效参数
        Inval = ERR_INVAL,
        /// 资源配额耗尽
        NoResource = ERR_NO_RESOURCE,
        /// 无效指针
        Fault = ERR_FAULT,
    }
}

/// 创建地址空间
///
/// 内核分配全局唯一 `SpaceId` 并自动创建默认 channel(slot 0)。
/// 返回 `(SpaceHandle, SpaceId)`,不需要 `SpaceId` 时用 `let (handle, _) = ...`。
pub fn space_create(max_pages: u32, flags: SpaceFlags) -> Result<(SpaceHandle, SpaceId)> {
    let mut id = MaybeUninit::<SpaceId>::uninit();
    let ret = unsafe {
        super::arch::syscall3(
            SYSNR_SPACE_CREATE,
            max_pages as usize,
            flags.bits() as usize,
            id.as_mut_ptr() as usize,
        )
    };
    if ret < 0 {
        Err(SpaceError::from_raw(ret))
    } else {
        Ok((SpaceHandle::from_raw(ret as u32), unsafe { id.assume_init() }))
    }
}

/// 销毁地址空间,关闭句柄表所有 handle、释放页表
pub fn space_close(space: SpaceHandle) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_SPACE_CLOSE, space.raw() as usize) };
    if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}

/// 映射内存到指定地址空间
///
/// `space = SpaceHandle::SELF` 时映射到调用者自身地址空间。
/// `vaddr = Uaddr::NULL` 时由内核选择地址。
/// `source = None` 时为匿名映射(demand paging,私有页)。
pub fn space_map(
    space: SpaceHandle,
    vaddr: Uaddr,
    source: Option<&MemSource>,
    size: usize,
    perms: MapPerms,
    flags: MapFlags,
) -> Result<Uaddr> {
    let source_ptr = match source {
        Some(s) => s as *const MemSource as usize,
        None => 0,
    };
    let ret = unsafe {
        super::arch::syscall6(
            SYSNR_SPACE_MAP,
            space.raw() as usize,
            vaddr.raw(),
            source_ptr,
            size,
            perms.bits() as usize,
            flags.bits() as usize,
        )
    };
    if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(Uaddr::from_raw(ret as usize)) }
}

/// 取消映射,支持部分 unmap
///
/// `space = SpaceHandle::SELF` 时操作调用者自身地址空间。
pub fn space_unmap(space: SpaceHandle, vaddr: Uaddr, size: usize) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall3(SYSNR_SPACE_UNMAP, space.raw() as usize, vaddr.raw(), size)
    };
    if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}

/// 修改映射权限,支持部分修改
///
/// `space = SpaceHandle::SELF` 时操作调用者自身地址空间。
pub fn space_protect(space: SpaceHandle, vaddr: Uaddr, size: usize, perms: MapPerms) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall4(
            SYSNR_SPACE_PROTECT,
            space.raw() as usize,
            vaddr.raw(),
            size,
            perms.bits() as usize,
        )
    };
    if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}

/// 写入目标地址空间
///
/// 将调用者 `data` 写入目标地址空间的 `vaddr` 处。
pub fn space_write(space: SpaceHandle, vaddr: Uaddr, data: &[u8]) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall4(
            SYSNR_SPACE_WRITE,
            space.raw() as usize,
            vaddr.raw(),
            data.as_ptr() as usize,
            data.len(),
        )
    };
    if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}

/// 读取目标地址空间
///
/// 将目标地址空间 `vaddr` 处的数据读入调用者 `buf`。
pub fn space_read(space: SpaceHandle, vaddr: Uaddr, buf: &mut [u8]) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall4(
            SYSNR_SPACE_READ,
            space.raw() as usize,
            vaddr.raw(),
            buf.as_mut_ptr() as usize,
            buf.len(),
        )
    };
    if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}

/// 查询地址空间的全局 ID
pub fn space_get_id(space: SpaceHandle) -> Result<SpaceId> {
    let ret = unsafe { super::arch::syscall1(SYSNR_SPACE_GET_ID, space.raw() as usize) };
    if ret < 0 {
        Err(SpaceError::from_raw(ret))
    } else {
        // ret >= 0 且 SpaceId 是 usize,与寄存器宽度一致
        Ok(SpaceId::from_raw(ret as usize))
    }
}