## Jove syscalls Every syscall in Jove is passed to the kernel via a `JOVE_OBJ_MESSAGE` object. To pass a message object to the kernel, the message object must be close to the root directory of the calling PCB. To resolve the message object, the kernel requires an object path and a path length encoded in argument registers. On x86_64, the encoding is as follows: | Message Path | Message Path Length | |--------------|---------------------| | rdi | rsi | If the message path exceeds the width of the message path register, the kernel will return `-EBADPATH`. If the message path does not point to a `JOVE_OBJ_MESSAGE` object, the kernel will return `-EBADOBJ`. If the message path points to an object locked by a mutex, the kernel will return `-EBUSY`. ### Syscall header | Size (bytes) | 2 | 2 | path_len * 2 | |--------------|---------|------------------------|--------------| | Data | Call ID | Path length (path_len) | Target path | All system calls must start with these bytes at the start of the passed message object. 1. `Call ID`: ID of the system call to invoke. 2. `Path length`: Length of the target path. 3. `Object path`: Path to the target object starting from the PCB's root directory. If the target path length exceeds the width of the message object, the kernel will return `-ETOOSMALL`. If the target path points to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. If the target object does not support the call id, the kernel will return `-EBADCALL`. Further behavior is specified by the target syscall specification. Target syscalls may have further required bytes in the message. If the syscall does not have the correct permissions for the syscall, the kernel will return `-ENOPERM`. ### JOVE_OBJ_UNTYPED | Syscall | Permissions Required | |---------------------------------|-----------------------------------| | SYSCALL_UNTYPED_ADDRESS | JOVE_PERM_READ | | SYSCALL_UNTYPED_SIZE | JOVE_PERM_READ | | SYSCALL_UNTYPED_SPLIT | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | SYSCALL_UNTYPED_MERGE | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | SYSCALL_UNTYPED_RETYPE_OBJDIR | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | SYSCALL_UNTYPED_RETYPE_PAGEDIR | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | SYSCALL_UNTYPED_RETYPE_SHMEMORY | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | SYSCALL_UNTYPED_RETYPE_PCB | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | #### SYSCALL_UNTYPED_ADDRESS Returns the physical address of the untyped memory span. #### SYSCALL_UNTYPED_SIZE Returns the size of the untyped memory span. #### SYSCALL_UNTYPED_SPLIT Splits the untyped memory span into the destination path sized by the split size. | Data | Split size | Destination Path Length | Destination Path | |--------------|----------------|-------------------------|------------------| | Size (bytes) | sizeof(size_t) | 2 | path_len * 2 | If the split size exceeds the size of the target untyped, the kernel will return `-ETOOBIG`. If the split size is less than `JOVE_UNTYPED_MINSIZE`, the kernel will return `-ETOOSMALL`. If the destination path length exceeds the size of the message, the kernel will return `-EBADPATH`. If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. #### SYSCALL_UNTYPED_MERGE Merges two adjacent untyped memory spans into one untyped memory span at the first untyped object. | Data | Untyped Path Length | Untyped Path | |--------------|---------------------|--------------| | Size (bytes) | 2 | path_len * 2 | If the untyped path length exceeds the size of the message, the kernel will return `-EBADPATH`. If the untyped path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. Successful merges return 0 #### SYSCALL_UNTYPED_RETYPE_OBJDIR Creates an empty `JOVE_OBJ_OBJDIR` object from a page sized untyped memory object. Each entry is populated with `JOVE_OBJ_NONE` objects. If the untyped object's size is not `0x1000`, the kernel will return `-EBADSIZE`. If the untyped object's alignment is not `0x1000`, the kernel will return `-EALIGN`. Successful retypes return 0. #### SYSCALL_UNTYPED_RETYPE_PAGEDIR Creates and prepares a `JOVE_OBJ_PAGEDIR` object from a page sized untyped memory object. Kernel pages are automatically populated and restricted. If the untyped object's size is not `0x1000`, the kernel will return `-EBADSIZE`. If the untyped object's alignment is not `0x1000`, the kernel will return `-EALIGN`. Successful retypes return 0. #### SYSCALL_UNTYPED_RETYPE_SHMEMORY Creates and prepares a `JOVE_OBJ_SHMEMORY` object from a page aligned untyped memory object. New shared memory pages are filled with zero. If the untyped object's size is not a multiple of `0x1000`, the kernel will return `-EBADSIZE`. If the untyped object's size is greater than `SHMEMORY_LIMIT`, the kernel will return `-ETOOBIG`. If the untyped object's alignment is not `0x1000`, the kernel will return `-EALIGN`. Successful retypes return 0. #### SYSCALL_UNTYPED_RETYPE_PCB Creates and prepares a `JOVE_OBJ_PCB` object from a large enough untyped memory object. New PCB's are automatically added to the PCB tree with state `PCB_STATE_EMBRYO`. User programs are expected to create and populate a `JOVE_OBJ_PAGEDIR` object in `PCB_ROOTDIR_PAGEDIR_I`. If the untyped object's size is less than `PCB_MINSIZE`, the kernel will return `-ETOOSMALL`. If the untyped object's parent objdir does not have `JOVE_PERM_ALL`, the kernel will return `-EPERM`. If the untyped object is not in entry `PCB_ROOTDIR_SELF_I`, the kernel will return `-EBADPATH`. Successful retypes return 0. ### JOVE_OBJ_OBJDIR | Syscall | Target Permissions | |------------------------|--------------------------------------| | SYSCALL_OBJDIR_OBJTYPE | JOVE_PERM_READ | | SYSCALL_OBJDIR_UNTYPE | JOVE_PERM_WRITE
JOVE_PERM_MUTATE | | SYSCALL_OBJDIR_SEND | JOVE_PERM_MUTATE | #### SYSCALL_OBJDIR_OBJTYPE Returns the object type at the given entry index. | Data | Entry Index | |--------------|-------------| | Size (bytes) | 2 | If the message is too small to hold the payload, the kernel will return `-ETOOSMALL`. If the entry index exceeds `JOVE_OBJDIR_ENTRIES`, the kernel returns `-EOOB`. #### SYSCALL_OBJDIR_UNTYPE Converts the target object to an untyped object if possible. | Data | Entry Index | |--------------|-------------| | Size (bytes) | 2 | If the target object does not have underlying memory, the kernel will replace the object with `JOVE_OBJ_NONE`. If the target object has underlying memory, the kernel will replace the object with `JOVE_OBJ_UNTYPED`. ### JOVE_OBJ_PAGEDIR | Syscall | Target Permissions | Subject Permissions | Subject Conditional Permissions | |-----------------------------|:-------------------------------:|:-------------------------------------------------:|:-------------------------------:| | SYSCALL_PAGEDIR_MAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_MUTATE | JOVE_PERM_READ, JOVE_PERM_WRITE | | SYSCALL_PAGEDIR_MAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_READ, JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | | SYSCALL_PAGEDIR_MAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_READ | JOVE_PERM_WRITE | | SYSCALL_PAGEDIR_UNMAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | | | | SYSCALL_PAGEDIR_UNMAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | | | | SYSCALL_PAGEDIR_UNMAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | | #### SYSCALL_PAGEDIR_MAP_FRAME Attempts to map a given untyped memory span to the given virtual address with passed permissions. | Data | Page flags | Untyped Path Length | Virtual address | Untyped Path | |--------------|------------|---------------------|-------------------|--------------| | Size (bytes) | 1 | 2 | sizeof(void*) | path_len * 2 | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. If the untyped path does not point to a `JOVE_OBJ_UNTYPED` object, the kernel will return `-EBADOBJ`. If the untyped object is not aligned to `0x1000` bytes, the kernel will return `-EALIGN`. If the untyped object is not exactly `0x1000` bytes wide, the kernel will return `-EBADSIZE`. If the untyped object does not have `JOVE_PERM_MUTATE` and `JOVE_PERM_READ`, the kernel will return `-ENOPERM`. If the untyped object does not have `JOVE_PERM_WRITE` and the passed flags include the writeable bit, the kernel will return `-ENOPERM.`. If the virtual address does not have enough page table structures to support the page mapping, the kernel will return `-ENOMAP`. If the virtual address already has a page mapping, the kernel will return `-EHASMAP`. Successful mapping replaces the untyped object with a `JOVE_OBJ_NONE` object and returns `0`. #### SYSCALL_PAGEDIR_MAP_TABLE Attempts to map a given untyped memory span as a table for mapping further page frames onto `virtual address`. | Data | Virtual address | Untyped Path Length | Untyped Path | |--------------|-----------------|---------------------|--------------| | Size (bytes) | sizeof(void*) | 2 | path_len * 2 | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. If the untyped path does not point to a `JOVE_OBJ_UNTYPED` object, the kernel will return `-EBADOBJ`. If the untyped object is not aligned to `0x1000` bytes, the kernel will return `-EALIGN`. If the untyped object is not exactly `0x1000` bytes wide, the kernel will return `-EBADSIZE`. If the untyped object does not have `JOVE_PERM_MUTATE`, `JOVE_PERM_READ`, and `JOVE_PERM_WRITE`, the kernel will return `-ENOPERM`. If the virtual address already has enough tables to allocate a page frame onto them, the kernel will return `-EHASMAP`. Successful mapping replaces the untyped object with a `JOVE_OBJ_NONE` object and returns `0`. #### SYSCALL_PAGEDIR_MAP_SHMEM Attempts to map a shared memory page at `virtual address`. Does not consume the shared memory object. | Data | Page flags | Page offset | Shared Memory Path Length | Virtual address | Shared Memory Path | |--------------|------------|-------------|---------------------------|-----------------|--------------------| | Size (bytes) | 1 | 1 | 2 | sizeof(void*) | path_len * 2 | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. If the shmem path does not point to a `JOVE_OBJ_SHMEMORY` object, the kernel will return `-EBADOBJ`. If the shmem object does not have `JOVE_PERM_READ`, the kernel will return `-ENOPERM`. If the shmem object does not have `JOVE_PERM_WRITE` and the passed flags include the writeable bit, the kernel will return `-ENOPERM.`. If the virtual address does not have enough page table structures to support the page mapping, the kernel will return `-ENOMAP`. If the virtual address already has a page mapping, the kernel will return `-EHASMAP`. Successful mapping returns `0`. #### SYSCALL_PAGEDIR_UNMAP_FRAME Attempts to remove an untyped memory mapping from the page table at `virtual address`. | Data | Virtual address | Destination Path Length | Destination Path | |--------------|-----------------|-------------------------|------------------| | Size (bytes) | sizeof(void*) | 2 | path_len * 2 | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`. If the virtual address does not have a page mapping, the kernel will return `-ENOMAP`. If the virtual address does not map to an untyped page frame, the kernel will return `-EBADARG`. Successful unmapping fills the destination path with a page-sized `JOVE_OBJ_UNTYPED` object with correct permissions and return 0. #### SYSCALL_PAGEDIR_UNMAP_TABLE Attempts to remove a page table mapping from the page directory heirarchy at `virtual address` | Data | Virtual address | Destination Path Length | Destination Path | |--------------|-----------------|-------------------------|------------------| | Size (bytes) | sizeof(void*) | 2 | path_len * 2 | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`. If the table mapping the virtual address has any occupied entries, the kernel will return `-EHASMAP`. If no table mapping exists for this virtual address, the kernel will return `-ENOMAP`. Successful unmapping fills the destination path with a page-sized `JOVE_OBJ_UNTYPED` object with correct permissions and return 0. #### SYSCALL_PAGEDIR_UNMAP_SHMEM Attempts to unmap a shared memory page at `virtual address`. | Data | Virtual address | |--------------|-----------------| | Size (bytes) | sizeof(void*) | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. If the virtual address does not have a page frame associated with it, the kernel will return `-ENOMAP`. If the page frame pointed to by virtual address does not correspond to a shared memory frame, the kernel will return `-EBADOBJ`. Successful unmapping returns `0`. ### JOVE_OBJ_PCB | Syscall | Target Permissions | Subject Permissions | |-------------------|--------------------|---------------------| | SYSCALL_PCB_PID | JOVE_PERM_READ | | | SYSCALL_PCB_YIELD | JOVE_PERM_WRITE | | | SYSCALL_PCB_SEND | JOVE_PERM_MUTATE | JOVE_PERM_MUTATE | | SYSCALL_PCB_RECV | JOVE_PERM_MUTATE | JOVE_PERM_MUTATE | #### SYSCALL_PCB_YIELD Yields control to the specified process. | Data | Yield target | |--------------|---------------| | Size (bytes) | sizeof(pid_t) | If the yield target = `0`, the scheduler will determine the next process. If the yield target does not exist, the kernel will return `-ENOPROC`. #### SYSCALL_PCB_SEND Attempts to send the target object to a process specified by destination process. If blocking timeout is zero, then the process will wait for the destination process to recieve the object forever. If the blocking timeout is non-zero, then the process will wait for the destination process to recieve the object for the specified number of scheduler ticks. | Data | Destination Process | Blocking Timeout | Send Path Length | Send Path | |--------------|---------------------|-------------------|------------------------|-------------------------------------------| | Size (bytes) | sizeof(pid_t) | sizeof(uintmax_t) | sizeof(objpath_part_t) | sizeof(objpath_part_t) * send_path_length | While the object is being sent, the kernel will lock the object and copy a pointer to it into the send mailbox. If the target path does not represent a valid object, the kernel will return `-EBADPATH`. If the target path represents a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. If the target object does not have the `JOVE_PERM_MUTATE` permission, the kernel will return `-EPERM`. If the destination process does not represent a valid process, the kernel will return `-EBADPROC`. If the blocking timeout expires and the message was not sent, the kernel will return `-ETIMEOUT`. If the send is successful, the sent object is replaced by a `JOVE_OBJ_NONE` object and the kernel will return 0. #### SYSCALL_PCB_RECV Recieves kernel objects from the PCB mailbox. If a sender is specified, then the mailbox will only accept mail from that specific sender. Blocks on recieve until blocking timeout expires or forever if blocking timeout was zero. Destination object is locked until the timeout expires or an object is placed in the destination path. | Data | Sending Process | Blocking Timeout | Dest Path Length | Dest path | |--------------|-----------------|-------------------|------------------|-------------------| | Size (bytes) | sizeof(pid_t) | sizeof(uintmax_t) | 2 | 2 * dest_path_len | If the specified pid does not correspond to a process, the kernel will return `-ENOPROC`. If the destination path does not correspond to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`. If the destination path does not have the `JOVE_PERM_MUTATE` permission, the kernel will return `-EPERM`. Recieved messages will be sent to the specified destination path. Successful retrieval returns `0`. ### JOVE_OBJ_INITRD_FILE | Syscall | Target Permissions | |--------------------------|--------------------| | SYSCALL_INITRD_FILE_NAME | JOVE_PERM_READ | | SYSCALL_INITRD_FILE_SIZE | JOVE_PERM_READ | | SYSCALL_INITRD_FILE_READ | JOVE_PERM_READ | #### SYSCALL_INITRD_FILE_NAME Populates the message with the name of the target file. Names start with a size_t length specifier, which is followed by a NULL-terminated c-string. | Data | Name Length | Name | Null Terminator | |--------------|----------------|-------------|-----------------| | Size (bytes) | sizeof(size_t) | Name Length | 1 | If the message is too small for the file name, the kernel will return `-ETOOSMALL`. #### SYSCALL_INITRD_FILE_SIZE Returns the size of the target file in bytes. #### SYSCALL_INITRD_FILE_READ Populates the message with the bytes read from the target file. ##### Payload | Data | Starting index | Read size | |--------------|----------------|----------------| | Size (bytes) | sizeof(size_t) | sizeof(size_t) | ##### Return | Data | Data | |--------------|-----------| | Size (bytes) | Read size | If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. If the starting index exceeds the file length, the kernel will return `-EOOB`. If the read size + starting index > file size, the kernel will return `-EOOB`. If the message is too small for the read bytes, the kernel will return `-ETOOBIG`. Successful reading returns `0`. ### JOVE_OBJ_MESSAGE