From 298636079d912d0936f8156a609fe74b839c547b Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 9 Jul 2024 17:35:56 +0300 Subject: allow mapping null page + User has to 'free' the 0 page before it becomes accessible to mapping. Probably worth noting that this is likely VERY niche and mainly concerns stuff like certain kinds of emulators that I'm still eons from implementing, but still. Unbacked pages can also be useful for some kinds of notifications, like 'if someone writes to this page, please report it to me with this ID' or whatever, I remember seeing some discussion about it somewhere but that's also not really relevant for the moment. Most significantly, at least with the current design, after the null page is freed it becomes available for use to regular req_mem() calls, so users should probably using locks around memory requests. That's probably a good idea anyway as internally the kernal has to lock the virtual memory, and without a scheduler it might cause threads to spin for a while in the kernel which is rather bad. --- include/arch/vmem.h | 15 ++++------- include/kmi/atomic.h | 2 +- include/kmi/mem.h | 17 ++++++++++++ include/kmi/syscalls.h | 7 +++++ include/kmi/types.h | 6 ----- include/kmi/uapi.h | 72 ++++++++++++++++++++++++------------------------- include/kmi/unaligned.h | 32 +++++++++++----------- include/kmi/utils.h | 66 ++++++++++++++++++++++----------------------- include/kmi/vmem.h | 10 +++---- 9 files changed, 120 insertions(+), 107 deletions(-) (limited to 'include') diff --git a/include/arch/vmem.h b/include/arch/vmem.h index a19f555..1674e95 100644 --- a/include/arch/vmem.h +++ b/include/arch/vmem.h @@ -24,9 +24,6 @@ /** * Map one virtual page to physical page. * - * If \ref INFO_SEFF is returned, the caller is responsible for synchronizing - * all other threads that are in the same virtual address space. - * * The caller is responsible for checking that both virtual and physical page of * the correct order are available. * @@ -35,7 +32,8 @@ * @param vaddr Virtual address to map page to. * @param flags Page flags. * @param order Order of page. - * @return \ref INFO_SEFF when top level table modified, \ref OK otherwise. + * @return \ref OK when succesful, possibly \ref ERR_OOMEM if we don't have + * enough pages to create the mapping. */ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags, enum mm_order order); @@ -56,8 +54,7 @@ stat_t unmap_vpage(struct vmem *branch, vm_t vaddr); * @param branch Branch in which to work. * @param vaddr Virtual address of page. * @param flags Flags to set. - * @return \ref ERR_NF if no page could be found at \p vaddr, - * \ref INFO_SEFF if modification has side effects, otherwise \ref OK. + * @return \ref ERR_NF if no page could be found at \p vaddr, otherwise \ref OK. */ stat_t set_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags); @@ -68,7 +65,7 @@ stat_t set_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags); * @param vaddr Virtual address of page. * @param flags Flags to clear. * @return \ref ERR_NF if no page could be found at \p vaddr, - * \ref INFO_SEFF if modification has side effects, otherwise \ref OK. + * otherwise \ref OK. */ stat_t clear_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags); @@ -82,9 +79,7 @@ stat_t clear_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags); * @param vaddr Virtual address of map to modify. * @param paddr Physical address to map to. * @param flags Flags to set. - * @return \ref ERR_NF if no virtual page is found at \c vaddr. - * \ref INFO_SEFF if modding takes place in top page table but otherwise - * succesful, \ref OK otherwise. + * @return \ref ERR_NF if no virtual page is found at \c vaddr, \ref OK otherwise. */ stat_t mod_vpage(struct vmem *branch, vm_t vaddr, pm_t paddr, vmflags_t flags); diff --git a/include/kmi/atomic.h b/include/kmi/atomic.h index 88ffdfa..76d50e4 100644 --- a/include/kmi/atomic.h +++ b/include/kmi/atomic.h @@ -404,7 +404,7 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t; */ #define atomic_compare_exchange_weak(obj, val, des) \ atomic_compare_exchange_weak_explicit(obj, val, des, __ATOMIC_SEQ_CST, \ - __ATOMIC_SEQ_CST) + __ATOMIC_SEQ_CST) /** * Explicit atomic in-place addition. diff --git a/include/kmi/mem.h b/include/kmi/mem.h index 6c62d31..8c66eb5 100644 --- a/include/kmi/mem.h +++ b/include/kmi/mem.h @@ -177,12 +177,17 @@ size_t page_shift(); /** Memory region is used. */ #define MR_USED (1 << (ARCH_VP_FLAGS + 0)) + /** Don't free memory on clear. */ #define MR_KEEP (1 << (ARCH_VP_FLAGS + 1)) + /** Memory region in shared, but owned. Note: regions that are shared but no * owned don't use this flag, they just set the tid field for the region. */ #define MR_SHARED (1 << (ARCH_VP_FLAGS + 2)) +/** Memory region is private but not backed by memory. */ +#define MR_NONBACKED (1 << (ARCH_VP_FLAGS + 3)) + /** @} */ /** @@ -243,4 +248,16 @@ pm_t get_load_addr(); /** Base page order. */ #define BASE_PAGE (MM_O0) +/** + * Check if value is in range of error codes. + * The absolute top page of a virtual address space is -BASE_PAGE_SIZE, which + * will NEVER be used, so we can use it as a baseline. This allows quite a few + * error codes to be added in the future if need be. + * Although I guess the errors could be defined as positive and then just add a + * minus sign to every use to turn them negative? Dunno. + * + * @param x Value to check. + */ +#define ERR_CODE(x) ((vm_t)(x) > (vm_t)-BASE_PAGE_SIZE) + #endif /* KMI_MEM_H */ diff --git a/include/kmi/syscalls.h b/include/kmi/syscalls.h index b6cde34..1efd0d4 100644 --- a/include/kmi/syscalls.h +++ b/include/kmi/syscalls.h @@ -235,6 +235,13 @@ enum conf_param { * \c R. */ CONF_RAM_SIZE, + + /** + * Size of page of some order. + * Uses `d0` to signify which order to request. + * \c R + */ + CONF_PAGE_SIZE, }; /** diff --git a/include/kmi/types.h b/include/kmi/types.h index 2b1492f..1da5248 100644 --- a/include/kmi/types.h +++ b/include/kmi/types.h @@ -489,12 +489,6 @@ enum status_codes { ERR_NF = -1, /** OK. */ OK = 0, - /** Try again. */ - INFO_TRGN = 1, - /** Side effects. */ - INFO_SEFF = 2, - /** Continue. */ - INFO_CONT = 3, }; #include /* arch-specific type definitions (pm_t/vm_t etc) */ diff --git a/include/kmi/uapi.h b/include/kmi/uapi.h index 8047632..65a4d93 100644 --- a/include/kmi/uapi.h +++ b/include/kmi/uapi.h @@ -50,11 +50,11 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DECLARE0(name) \ void sys_##name(struct tcb *t, \ - sys_arg_t a, \ - sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, \ - sys_arg_t e); + sys_arg_t a, \ + sys_arg_t b, \ + sys_arg_t c, \ + sys_arg_t d, \ + sys_arg_t e); /** * Helper macro for declaring syscalls with one argument. @@ -64,8 +64,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DECLARE1(name, a) \ void sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e); + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e); /** * Helper macro for declaring syscalls with two arguments. @@ -76,8 +76,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DECLARE2(name, a, b) \ void sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e); + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e); /** * Helper macro for declaring syscalls with three arguments. @@ -89,8 +89,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DECLARE3(name, a, b, c) \ void sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e); + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e); /** * Helper macro for declaring syscalls with four arguments. @@ -103,8 +103,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DECLARE4(name, a, b, c, d) \ void sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e); + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e); /** * Helper macro for declaring syscalls with five arguments. @@ -118,8 +118,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DECLARE5(name, a, b, c, d, e) \ void sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e); + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e); /** * Helper macro for defining syscall with zero arguments. @@ -135,8 +135,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); #define SYSCALL_DEFINE0(name) \ static inline void __##name(struct tcb *t); \ void __noinline sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e) \ + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e) \ { \ UNUSED(a); \ UNUSED(b); \ @@ -155,8 +155,8 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); #define SYSCALL_DEFINE1(name) \ static inline void __##name(struct tcb *, sys_arg_t); \ void __noinline sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e) \ + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e) \ { \ UNUSED(b); \ UNUSED(c); \ @@ -173,10 +173,10 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DEFINE2(name) \ static inline void __##name(struct tcb *, sys_arg_t, \ - sys_arg_t); \ + sys_arg_t); \ void __noinline sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e) \ + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e) \ { \ UNUSED(c); \ UNUSED(d); \ @@ -192,11 +192,11 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DEFINE3(name) \ static inline void __##name(struct tcb *, sys_arg_t, \ - sys_arg_t, \ - sys_arg_t); \ + sys_arg_t, \ + sys_arg_t); \ void __noinline sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e) \ + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e) \ { \ UNUSED(d); \ UNUSED(e); \ @@ -211,11 +211,11 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DEFINE4(name) \ static inline void __##name(struct tcb *, sys_arg_t, \ - sys_arg_t, sys_arg_t, \ - sys_arg_t); \ + sys_arg_t, sys_arg_t, \ + sys_arg_t); \ void __noinline sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e) \ + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e) \ { \ UNUSED(e); \ __##name(t, a, b, c, d); \ @@ -229,11 +229,11 @@ typedef void (*sys_t)(struct tcb *t, long, long, long, long, long); */ #define SYSCALL_DEFINE5(name) \ static inline void __##name(struct tcb *, sys_arg_t, \ - sys_arg_t, sys_arg_t, \ - sys_arg_t, sys_arg_t); \ + sys_arg_t, sys_arg_t, \ + sys_arg_t, sys_arg_t); \ void __noinline sys_##name(struct tcb *t, sys_arg_t a, sys_arg_t b, \ - sys_arg_t c, \ - sys_arg_t d, sys_arg_t e) \ + sys_arg_t c, \ + sys_arg_t d, sys_arg_t e) \ { \ __##name(t, a, b, c, d, e); \ } \ @@ -706,14 +706,14 @@ SYSCALL_DECLARE2(conf_set, param, val); * * @param t Current tcb. * @param param Parameter to get. - * @param b Unused. + * @param d0 Optional data argument to parameter. * @param c Unused. * @param d Unused. * @param e Unused. * * Returns \ref OK. */ -SYSCALL_DECLARE1(conf_get, param); +SYSCALL_DECLARE2(conf_get, param, d0); /** * Set capabilities. diff --git a/include/kmi/unaligned.h b/include/kmi/unaligned.h index 89f5894..fac5146 100644 --- a/include/kmi/unaligned.h +++ b/include/kmi/unaligned.h @@ -20,15 +20,15 @@ */ #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, \ + 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) + 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. @@ -38,15 +38,15 @@ */ #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, \ + 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) + 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. diff --git a/include/kmi/utils.h b/include/kmi/utils.h index a37f4bb..62d32da 100644 --- a/include/kmi/utils.h +++ b/include/kmi/utils.h @@ -251,18 +251,18 @@ */ #define align_down(x, y) \ _Generic((x), signed char \ - : align_down_c, signed short \ - : align_down_s, signed int \ - : align_down_i, signed long \ - : align_down_l, signed long long \ - : align_down_ll, \ + : align_down_c, signed short \ + : align_down_s, signed int \ + : align_down_i, signed long \ + : align_down_l, signed long long \ + : align_down_ll, \ \ - unsigned char \ - : align_down_uc, unsigned short \ - : align_down_us, unsigned int \ - : align_down_ui, unsigned long \ - : align_down_ul, unsigned long long \ - : align_down_ull)((x), (y)) + unsigned char \ + : align_down_uc, unsigned short \ + : align_down_us, unsigned int \ + : align_down_ui, unsigned long \ + : align_down_ul, unsigned long long \ + : align_down_ull)((x), (y)) /** * Helper macro for defining type specific aligning. @@ -385,18 +385,18 @@ DEFINE_ALIGN_DOWN(ull, unsigned long long); */ #define align_up(x, y) \ _Generic((x), signed char \ - : align_up_c, signed short \ - : align_up_s, signed int \ - : align_up_i, signed long \ - : align_up_l, signed long long \ - : align_up_ll, \ + : align_up_c, signed short \ + : align_up_s, signed int \ + : align_up_i, signed long \ + : align_up_l, signed long long \ + : align_up_ll, \ \ - unsigned char \ - : align_up_uc, unsigned short \ - : align_up_us, unsigned int \ - : align_up_ui, unsigned long \ - : align_up_ul, unsigned long long \ - : align_up_ull)((x), (y)) + unsigned char \ + : align_up_uc, unsigned short \ + : align_up_us, unsigned int \ + : align_up_ui, unsigned long \ + : align_up_ul, unsigned long long \ + : align_up_ull)((x), (y)) /** * Helper macro for defining type specific aligning. @@ -515,18 +515,18 @@ DEFINE_ALIGN_UP(ull, unsigned long long); */ #define is_aligned(x, y) \ _Generic((x), signed char \ - : is_aligned_c, signed short \ - : is_aligned_s, signed int \ - : is_aligned_i, signed long \ - : is_aligned_l, signed long long \ - : is_aligned_ll, \ + : is_aligned_c, signed short \ + : is_aligned_s, signed int \ + : is_aligned_i, signed long \ + : is_aligned_l, signed long long \ + : is_aligned_ll, \ \ - unsigned char \ - : is_aligned_uc, unsigned short \ - : is_aligned_us, unsigned int \ - : is_aligned_ui, unsigned long \ - : is_aligned_ul, unsigned long long \ - : is_aligned_ll)((x), (y)) + unsigned char \ + : is_aligned_uc, unsigned short \ + : is_aligned_us, unsigned int \ + : is_aligned_ui, unsigned long \ + : is_aligned_ul, unsigned long long \ + : is_aligned_ll)((x), (y)) /** * Helper macro for defining type specific alignment checks. diff --git a/include/kmi/vmem.h b/include/kmi/vmem.h index dd968ca..eb46da5 100644 --- a/include/kmi/vmem.h +++ b/include/kmi/vmem.h @@ -98,17 +98,17 @@ 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. + * This assumes the user virtual memory is contiguous, with no holes between + * \ref UVMEM_START and \ref UVMEM_END. One base page at the start of the region + * is reserved for use as a NULL page, which can be freed by the user to + * 'accept' that it's dangerous to not have a NULL page. * * Requires that \p t already has a vmem allocated. * * @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); +stat_t init_uvmem(struct tcb *r); /** * Destroy user virtual memory instance. -- cgit v1.3