From de99380f12f8e2fe4acf7734db0e1e37a356c45f Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 11 Jun 2022 15:37:39 +0300 Subject: continue documentation --- include/apos/unaligned.h | 252 ++++++++++++++++++++++++++++++++++++++++------- include/apos/vmem.h | 212 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 425 insertions(+), 39 deletions(-) (limited to 'include/apos') diff --git a/include/apos/unaligned.h b/include/apos/unaligned.h index 85d67b0..332c992 100644 --- a/include/apos/unaligned.h +++ b/include/apos/unaligned.h @@ -9,64 +9,244 @@ #include #include -#define get_unaligned(ptr) \ - _Generic(*(ptr), uint8_t \ - : __get_unaligned_uint8_t, uint16_t \ - : __get_unaligned_uint16_t, uint32_t \ - : __get_unaligned_uint32_t, uint64_t \ - : __get_unaligned_uint64_t, int8_t \ - : __get_unaligned_int8_t, int16_t \ - : __get_unaligned_int16_t, int32_t \ - : __get_unaligned_int32_t, int64_t \ - : __get_unaligned_int64_t)((void *)ptr) - -#define put_unaligned(val, ptr) \ - _Generic(*(ptr), uint8_t \ - : __put_unaligned_uint8_t, uint16_t \ - : __put_unaligned_uint16_t, uint32_t \ - : __put_unaligned_uint32_t, uint64_t \ - : __put_unaligned_uint64_t, int8_t \ - : __put_unaligned_int8_t, int16_t \ - : __put_unaligned_int16_t, int32_t \ - : __put_unaligned_int32_t, int64_t \ - : __put_unaligned_int64_t)(val, (void *)ptr) - -#define DEFINE_GET(type) \ - static inline type __get_unaligned_##type(void *ptr) \ - { \ - const struct __packed { \ - type x; \ - } *__pptr = ptr; \ - return __pptr->x; \ +/** + * Get unaligned value. Type of value is deduced from pointer type. + * + * @param ptr Pointer to possibly unaligned value to read. + * @return Value pointed to by \c ptr. + */ +#define get_unaligned(ptr) \ + _Generic(*(ptr), \ + uint8_t: get_unaligned_uint8_t, \ + uint16_t: get_unaligned_uint16_t, \ + uint32_t: get_unaligned_uint32_t, \ + uint64_t: get_unaligned_uint64_t, \ + \ + int8_t: get_unaligned_int8_t, \ + int16_t: get_unaligned_int16_t, \ + int32_t: get_unaligned_int32_t, \ + int64_t: get_unaligned_int64_t)((void *)ptr) + +/** + * Put unaligned value. Type of value is deduced from pointer type. + * + * @param val Value to write to memory. + * @param ptr Pointer to possibly unaligned address. + */ +#define put_unaligned(val, ptr) \ + _Generic(*(ptr), \ + uint8_t: put_unaligned_uint8_t, \ + uint16_t: put_unaligned_uint16_t, \ + uint32_t: put_unaligned_uint32_t, \ + uint64_t: put_unaligned_uint64_t, \ + \ + int8_t: put_unaligned_int8_t, \ + int16_t: put_unaligned_int16_t, \ + int32_t: put_unaligned_int32_t, \ + int64_t: put_unaligned_int64_t)(val, (void *)ptr) + +/** + * Helper macro for defining an unaligned value reader. + * + * @param type Type of value reader to define. + */ +#define DEFINE_GET(type) \ + static inline type get_unaligned_##type(void *ptr) \ + { \ + const struct __packed { \ + type x; \ + } *__pptr = ptr; \ + return __pptr->x; \ } +/** + * Read possibly unaligned \ref uint8_t. + * + * Technically speaking a byte can't be unaligned, but this is just here for + * cohesion. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref uint8_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(uint8_t); + +/** + * Read possibly unaligned \ref uint16_t. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref uint16_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(uint16_t); + +/** + * Read possibly unaligned \ref uint32_t. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref uint32_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(uint32_t); + +/** + * Read possibly unaligned \ref uint64_t. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref uint64_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(uint64_t); + +/** + * Read possibly unaligned \ref int8_t. + * + * Technically speaking a byte can't be unaligned, but this is just here for + * cohesion. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref int8_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(int8_t); + +/** + * Read possibly unaligned \ref int16_t. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref int16_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(int16_t); + +/** + * Read possibly unaligned \ref int32_t. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref int32_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(int32_t); + +/** + * Read possibly unaligned \ref int64_t. + * + * @warning Prefer using \ref get_unaligned(). + * + * @param ptr Pointer to \ref int64_t to read. + * @return Value pointed to by \c ptr. + */ DEFINE_GET(int64_t); #undef DEFINE_GET -#define DEFINE_PUT(type) \ - static inline void __put_unaligned_##type(type val, void *ptr) \ - { \ - struct __packed { \ - type x; \ - } *__pptr = ptr; \ - __pptr->x = val; \ +/** + * Helper macro for defining an unaligned writer. + * + * @param type Type of value to write. + */ +#define DEFINE_PUT(type) \ + static inline void put_unaligned_##type(type val, void *ptr) \ + { \ + struct __packed { \ + type x; \ + } *__pptr = ptr; \ + __pptr->x = val; \ } +/** + * Write possibly unaligned \ref uint8_t. + * + * Technically speaking a byte can't be unaligned, but this is just here for + * cohesion. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(uint8_t); + +/** + * Write possibly unaligned \ref uint16_t. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(uint16_t); + +/** + * Write possibly unaligned \ref uint32_t. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(uint32_t); + +/** + * Write possibly unaligned \ref uint64_t. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(uint64_t); + +/** + * Write possibly unaligned \ref int8_t. + * + * Technically speaking a byte can't be unaligned, but this is just here for + * cohesion. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(int8_t); + +/** + * Write possibly unaligned \ref int16_t. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(int16_t); + +/** + * Write possibly unaligned \ref int32_t. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(int32_t); + +/** + * Write possibly unaligned \ref int64_t. + * + * @warning Prefer using \ref put_unaligned(). + * + * @param val Value to write. + * @param ptr Address to write to. + */ DEFINE_PUT(int64_t); +#undef DEFINE_PUT + #endif /* APOS_UNALIGNED_H */ diff --git a/include/apos/vmem.h b/include/apos/vmem.h index 96158be..c02d968 100644 --- a/include/apos/vmem.h +++ b/include/apos/vmem.h @@ -11,39 +11,245 @@ #include #include +/** + * Allocate user virtual memory. + * + * Virtual memory start address is chosen according to best fit with regard to + * size. + * + * @param r Process to allocate memory in. + * @param size Minimum size of allocation. + * @param flags Flags of allocation. + * @return Start of allocation when succesful, \c NULL otherwise. + */ vm_t alloc_uvmem(struct tcb *r, size_t size, vmflags_t flags); + +/** + * Allocate fixed user virtual memory. + * + * Virtual memory start address is chosen so that \c start is within the + * allocation and the allocation after \c start is at least \c size bytes large. + * It is unspecified how many bytes are between the start of the allocation and + * \c start. + * + * @param r Process to allocate memory in. + * @param start Address that should be in allocation. + * @param size Minimum size of allocation. + * @param flags Flags of allocation. + * @return Start of allocation when succesful, \c NULL otherwise. + */ vm_t alloc_fixed_uvmem(struct tcb *r, vm_t start, size_t size, vmflags_t flags); + +/** + * Allocate shared user virtual memory. + * + * Only callable by servers, who are the owners of the shared region. + * + * @param r Process to allocate memory in. + * @param size Minimum size of allocation. + * @param flags Flags of allocation. + * @return Start of allocation when succesful, \c NULL otherwise. + */ vm_t alloc_shared_uvmem(struct tcb *r, size_t size, vmflags_t flags); + +/** + * Reference shared user virtual memory. + * + * Only callable by clients. + * + * @param r1 Process in which shared memory resides. + * @param r2 Process to reference shared memory in. + * @param va Virtual address of shared memory in \c r1. + * @param flags Flags of reference in \c r2. + * @return Start of reference in \c r2 when succesful, \c NULL otherwise. + */ vm_t ref_shared_uvmem(struct tcb *r1, struct tcb *r2, vm_t va, vmflags_t flags); -stat_t clear_uvmem(struct tcb *r, bool force); -stat_t free_uvmem(struct tcb *r, vm_t a); +/** + * Free all user virtual memory allocations not marked with \ref MR_KEEP. + * + * @param r Process in which to clear user virtual memory. + * @return \ref OK. + */ +stat_t clear_uvmem(struct tcb *r); + +/** + * Free all user virtual memory allocations, even if marked with \ref MR_KEEP. + * + * @param r Process in which to clear user virtual memory. + * @return \ref OK. + */ +stat_t purge_uvmem(struct tcb *r); + +/** + * Free one user virtual memory allocation. + * + * @param r Process in which to clear user virtual memory. + * @param va Start of user virtual memory allocation to free. + * @return \ref OK. + */ +stat_t free_uvmem(struct tcb *r, vm_t va); +/** + * Initialize user virtual memory instance. + * + * This assumes the user virtual memory is contiguous, with no holes between \c + * base and \c top. + * + * @param r Process in which to initialize user virtual memory. + * @param base Start of user virtual memory. + * @param top Top of user virtual memory. + * @return \see init_region(). + */ stat_t init_uvmem(struct tcb *r, vm_t base, vm_t top); + +/** + * Destroy user virtual memory instance. + * + * @param r Process in which to destroy user virtual memory. + * @return \see destroy_region(). + */ stat_t destroy_uvmem(struct tcb *r); +/** + * User virtual memory worker callback for \ref map_fill_region(). + * + * \c data is a pointer to \ref stat_t, which is set to \ref INFO_SEFF if all + * threads in process should sync their memory mappings. This occurs when the + * top level page table is modified. + * + * @param b Virtual memory to work in. + * @param offset Hint for \ref alloc_page(). + * @param vaddr Current virtual address. + * @param flags Flags of region. + * @param order Suggested page order. + * @param data Pointer to \ref stat_t. + * @return \c OK when suggested order if acceptable, \c INFO_TRGN if suggested + * order not acceptable. Error otherwise. + * again + */ stat_t alloc_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); + +/** + * Shared user virtual memory worker callback for \ref map_fill_region(). + * + * @param b Virtual memory to work in. + * @param offset Hint for \ref alloc_page(). + * @param vaddr Current virtual address. + * @param flags Flags of region. + * @param order Suggested page order. + * @param data Pointer to \ref stat_t. + * @return \see alloc_uvmem_wrapper(). + * + * \see alloc_uvmem_wrapper(). + */ stat_t alloc_shared_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); + +/** + * User virtual memory COW cloning worker callback for \ref map_fill_region(). + * + * Currently unused, but intention is to set up COW clone of some other virtual + * memory region, likely passed through \c data? + * + * @param b Virtual memory to work in. + * @param offset Hint for \ref alloc_page(). + * @param vaddr Current virtual address. + * @param flags Flags of region. + * @param order Suggested page order. + * @param data Pointer to \ref vmem to clone from. + * @return \see alloc_uvmem_wrapper(). + * + * \see alloc_uvmem_wraper(). + * \todo Implement. + */ stat_t clone_allocd_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); + +/** + * User virtual memory freeing worker callback for \ref map_fill_region(). + * + * @param b Virtual memory to work in. + * @param offset Hint for \ref alloc_page(). + * @param vaddr Current virtual address. + * @param flags Flags of region. + * @param order Suggested page order. + * @param data Pointer to \ref stat_t. + * @return \see alloc_uvmem_wrapper(). + * + * \see alloc_uvmem_wrapper(). + */ stat_t free_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); +/** + * Convenience wrapper for \ref map_fill_region() when mapping an allocated + * region. + * + * @param b Virtual memory to work in. + * @param start Start of virtual memory region to map. + * @param bytes Size of virtual memory region. + * @param flags Flags of virtual memory region. + * @param data Pointer to \c stat_t. + * @return \see map_fill_region(). + */ #define map_allocd_region(b, start, bytes, flags, data) \ map_fill_region(b, &alloc_uvmem_wrapper, 0, start, bytes, flags, data) +/** + * Convenience wrapper for \ref map_fill_region() when mapping a shared region. + * + * @param b Virtual memory to work in. + * @param start Start of virtual memory region to map. + * @param bytes Size of virtual memory region. + * @param flags Flags of virtual memory region. + * @param data Pointer to \c stat_t. + * @return \see map_fill_region(). + */ #define map_shared_region(b, start, bytes, flags, data) \ map_fill_region(b, &alloc_shared_wrapper, 0, start, bytes, flags, data) +/** + * Convenience wrapper for \ref map_fill_region() when COW cloning a region. + * + * @param b Virtual memory to work in. + * @param start Start of virtual memory region to map. + * @param bytes Size of virtual memory region. + * @param flags Flags of virtual memory region. + * @param data Pointer to \c vmem to clone. + * @return \see map_fill_region(). + */ #define clone_allocd_region(b, start, bytes, flags, data) \ map_fill_region(b, &clone_allocd_wrapper, 0, start, bytes, flags, data) +/** + * Convenience wrapper for \ref map_fill_region() when freeing region. + * + * @param b Virtual memory to work in. + * @param start Start of virtual memory region to unmap. + * @param bytes Size of virtual memory region. + * @param flags Flags of virtual memory region. Technically unused? + * @param data Pointer to \c stat_t. + * @return \see map_fill_region(). + */ #define unmap_freed_region(b, start, bytes, flags, data) \ map_fill_region(b, &free_uvmem_wrapper, 0, start, bytes, flags, data) +/** + * Extract virtual memory flags (MR_XXX). + * + * @param x Flags to extract virtual memory region flags from. + * @return Virtual memory region flags. + */ #define vm_flags(x) ((x) & ~0xff) -#define vp_flags(x) ((x)&0xff) + +/** + * Extract physical memory page flags (VM_XXX). + * + * @param x Flags to extract physical memory page flags from. + * @return Physical memory page flags. + */ +#define vp_flags(x) ((x) & 0xff) #endif /* APOS_VMEM_H */ -- cgit v1.3