/* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ /** * @file mem.c * Memory handling syscall implementations. * \todo Should we return more error information? */ #include #include #include #include /** * Memory request syscall handler. * * @param size Minimum size of allocation. * @param flags Flags of allocation. * @return \ref OK and start of allocation when succesful, * \ref ERR_OOMEM and \c NULL otherwise. */ SYSCALL_DEFINE2(req_mem)(sys_arg_t size, sys_arg_t flags) { /* get current effective process */ struct tcb *r = cur_proc(); vm_t start = 0; if ((start = alloc_uvmem(r, size, flags))) return SYS_RET1(ERR_OOMEM); return SYS_RET2(OK, start); } /** * Fixed memory request syscall handler. * * @param fixed Address which should be included in allocation. * @param size Minimum size of allocation after \c start. * @param flags Flags of allocation. * @return \ref OK and start of allocation when succesful, * \ref ERR_OOMEM and \c NULL otherwise. */ SYSCALL_DEFINE3(req_fixmem)(sys_arg_t fixed, sys_arg_t size, sys_arg_t flags) { struct tcb *r = cur_proc(); vm_t start = 0; if ((start = alloc_fixed_uvmem(r, fixed, size, flags))) return SYS_RET1(ERR_OOMEM); return SYS_RET2(OK, start); } /** * Free memory syscall handler. * * @param start Start of allocation to free. * @return \ref OK and \c 0 when succesful, \ref ERR_NF and \c 0 otherwise. */ SYSCALL_DEFINE1(free_mem)(sys_arg_t start) { struct tcb *r = cur_proc(); vm_t vm_start = (vm_t)start; stat_t status = OK; if (vm_start > __pre_top && vm_start < __post_base) status = free_uvmem(r, vm_start); else status = free_devmem(r, vm_start); if (status) return SYS_RET1(ERR_NF); return SYS_RET1(OK); } /** * Request physical memory syscall handler. * * @param paddr Physical address to map. * @param size Minimum size of allocation. * @param flags Flags of allocation. * @return \ref OK and start of allocation when succesful, * \ref ERR_OOMEM and \c NULL otherwise. */ SYSCALL_DEFINE3(req_pmem)(sys_arg_t paddr, sys_arg_t size, sys_arg_t flags) { /* this will require some pondering, but essentially this syscall should * only be used for device access, so any addresses requested should be * outside the RAM area, and I'll probably have to implement some method * that keeps track of used regions outside of RAM. We'll see. */ struct tcb *r = cur_proc(); vm_t start = 0; if ((start = alloc_devmem(r, paddr, size, flags))) return SYS_RET1(ERR_OOMEM); return SYS_RET2(OK, start); } /** * Request shared memory syscall handler. * * @param size Minimum size of allocation. * @param flags Flags of allocation. * @return \ref OK and start of allocation when succesful, * \ref ERR_OOMEM and \c NULL otherwise. */ SYSCALL_DEFINE2(req_sharedmem)(sys_arg_t size, sys_arg_t flags) { /** \todo check that requester is server */ struct tcb *t = cur_proc(); vm_t start = 0; if ((start = alloc_shared_uvmem(t, size, flags))) return SYS_RET1(ERR_OOMEM); return SYS_RET2(OK, start); } /** * Reference shared memory syscall handler. * * @param tid Thread ID of shared memory owner. * @param va Start of shared memory in \c tid. * @param flags Flags of reference. * @return \ref OK and start of reference when succesful, * \ref ERR_OOMEM and \c NULL otherwise. */ SYSCALL_DEFINE3(ref_sharedmem)(sys_arg_t tid, sys_arg_t va, sys_arg_t flags) { struct tcb *t1 = cur_tcb(); struct tcb *t2 = get_tcb(tid); vm_t start = 0; if ((start = ref_shared_uvmem(t1, t2, va, flags))) return SYS_RET1(ERR_OOMEM); return SYS_RET2(OK, start); } /** \todo add some way to specify who gets to access the shared memory? */