diff options
| -rw-r--r-- | arch/riscv64/conf/init.c | 2 | ||||
| -rw-r--r-- | arch/riscv64/config.h | 5 | ||||
| -rw-r--r-- | include/arch/vmem.h | 15 | ||||
| -rw-r--r-- | include/kmi/atomic.h | 2 | ||||
| -rw-r--r-- | include/kmi/mem.h | 17 | ||||
| -rw-r--r-- | include/kmi/syscalls.h | 7 | ||||
| -rw-r--r-- | include/kmi/types.h | 6 | ||||
| -rw-r--r-- | include/kmi/uapi.h | 72 | ||||
| -rw-r--r-- | include/kmi/unaligned.h | 32 | ||||
| -rw-r--r-- | include/kmi/utils.h | 66 | ||||
| -rw-r--r-- | include/kmi/vmem.h | 10 | ||||
| -rw-r--r-- | src/debug.c | 4 | ||||
| -rw-r--r-- | src/tcb.c | 36 | ||||
| -rw-r--r-- | src/uapi/conf.c | 12 | ||||
| -rw-r--r-- | src/uapi/mem.c | 36 | ||||
| -rw-r--r-- | src/vmem.c | 131 |
16 files changed, 260 insertions, 193 deletions
diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c index c4e8064..03fdc64 100644 --- a/arch/riscv64/conf/init.c +++ b/arch/riscv64/conf/init.c @@ -273,7 +273,7 @@ static void sys_sleep() #define CSR_TIME "0xc01" #define csr_read(csr, \ - res) __asm__ volatile ("csrr %0, " csr : "=r" (res) :: "memory") + res) __asm__ volatile ("csrr %0, " csr : "=r" (res) :: "memory") #define CSR_CYCLE "0xc00" diff --git a/arch/riscv64/config.h b/arch/riscv64/config.h index 952c0ca..d686ed9 100644 --- a/arch/riscv64/config.h +++ b/arch/riscv64/config.h @@ -51,8 +51,9 @@ */ #define CSTACK_PAGE 248UL -/** User virtual memory space start. */ -#define UVMEM_START (SZ_4K) +/** User virtual memory space start. Should essentially always be the start of + * the NULL page, which is marked reserved in the address space by \ref init_uvmem().*/ +#define UVMEM_START (0) /** User virtual memory space end. */ #define UVMEM_END (SZ_256G - SZ_8G) 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/types.h> /* 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. diff --git a/src/debug.c b/src/debug.c index d87588d..950f73b 100644 --- a/src/debug.c +++ b/src/debug.c @@ -455,7 +455,7 @@ static size_t __print_sign(ssize_t value, size_t flags) * @return \see __integral_val(). */ #define __integral_len(value, base, flags) __integral_val((value), (base), \ - (flags), false) + (flags), false) /** * Print integral value as string. @@ -466,7 +466,7 @@ static size_t __print_sign(ssize_t value, size_t flags) * @return \see __integral_val(). */ #define __integral_print(value, base, flags) __integral_val((value), (base), \ - (flags), true) + (flags), true) /** * Print integral value. @@ -123,11 +123,14 @@ struct tcb *create_thread(struct tcb *p) assert(tcbs); vm_t bottom = alloc_page(KERNEL_STACK_PAGE_ORDER); + if (!bottom) + return NULL; + /* move tcb to top of kernel stack, keeping alignment in check * (hopefully) */ /** \todo check alignment */ - bottom = bottom + order_size(MM_O0) - sizeof(struct tcb); - struct tcb *t = (struct tcb *)align_down(bottom, sizeof(long)); + vm_t top = bottom + order_size(MM_O0) - sizeof(struct tcb); + struct tcb *t = (struct tcb *)align_down(top, sizeof(long)); memset(t, 0, sizeof(struct tcb)); id_t tid = __alloc_tid(t); @@ -141,9 +144,19 @@ struct tcb *create_thread(struct tcb *p) * structure, this works on riscv but in the event that other * systems don't we can easily turn this into a clone_uvmem. */ t->proc.vmem = p->proc.vmem; - } else { - t->proc.vmem = create_vmem(); - init_uvmem(t, UVMEM_START, UVMEM_END); + } + else { + if (!(t->proc.vmem = create_vmem())) { + free_page(MM_O0, bottom); + return NULL; + } + + if (init_uvmem(t)) { + destroy_vmem(t->proc.vmem); + free_page(MM_O0, bottom); + return NULL; + } + t->pid = t->tid; t->rid = t->tid; p = t; @@ -151,7 +164,16 @@ struct tcb *create_thread(struct tcb *p) t->eid = t->pid; t->rid = p->rid; - t->rpc.vmem = create_vmem(); + + if (!(t->rpc.vmem = create_vmem())) { + if (likely(p)) + return NULL; + + destroy_vmem(t->proc.vmem); + free_page(MM_O0, bottom); + return NULL; + } + setup_rpc_stack(t); reference_proc(p); @@ -191,7 +213,7 @@ struct tcb *create_proc(struct tcb *p) /* create a new thread outside the current process */ struct tcb *n = create_thread(NULL); if (!n) - return 0; + return NULL; if (p) __copy_proc(p, n); /* we have a parent process i.e. fork */ diff --git a/src/uapi/conf.c b/src/uapi/conf.c index 3a45d30..c8ec964 100644 --- a/src/uapi/conf.c +++ b/src/uapi/conf.c @@ -42,9 +42,10 @@ size_t rpc_stack_size() * * @param t Current tcb. * @param param Parameter to read. + * @param d0 Optional data argument for parameter. * @return \ref OK and parameter value. */ -SYSCALL_DEFINE1(conf_get)(struct tcb *t, sys_arg_t param) +SYSCALL_DEFINE2(conf_get)(struct tcb *t, sys_arg_t param, sys_arg_t d0) { /* anyone can read any current parameter, I don't think they should be * hidden. */ @@ -66,6 +67,15 @@ SYSCALL_DEFINE1(conf_get)(struct tcb *t, sys_arg_t param) val = get_ram_size(); break; + case CONF_PAGE_SIZE: + if (d0 < 0 || d0 > max_order()) { + val = 0; + break; + } + + val = order_size(d0); + break; + default: return_args1(t, ERR_NF); } diff --git a/src/uapi/mem.c b/src/uapi/mem.c index 49370fc..b4b2df8 100644 --- a/src/uapi/mem.c +++ b/src/uapi/mem.c @@ -24,10 +24,10 @@ SYSCALL_DEFINE2(req_mem)(struct tcb *t, sys_arg_t size, sys_arg_t flags) { struct tcb *r = get_cproc(t); - vm_t start = 0; flags = sanitize_uvflags(flags); - if (!(start = alloc_uvmem(r, size, flags))) - return_args1(t, ERR_OOMEM); + vm_t start = alloc_uvmem(r, size, flags); + if (ERR_CODE(start)) + return_args1(t, start); return_args2(t, OK, start); } @@ -47,10 +47,10 @@ SYSCALL_DEFINE3(req_fixmem)(struct tcb *t, sys_arg_t fixed, sys_arg_t size, sys_arg_t flags) { struct tcb *r = get_cproc(t); - vm_t start = 0; flags = sanitize_uvflags(flags); - if (!(start = alloc_fixed_uvmem(r, fixed, size, flags))) - return_args1(t, ERR_OOMEM); + vm_t start = alloc_fixed_uvmem(r, fixed, size, flags); + if (ERR_CODE(start)) + return_args1(t, start); return_args2(t, OK, start); } @@ -97,10 +97,10 @@ SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size, * that keeps track of used regions outside of RAM. We'll see. */ struct tcb *r = get_cproc(t); - vm_t start = 0; flags = sanitize_uvflags(flags); - if (!(start = alloc_devmem(r, paddr, size, flags))) - return_args1(t, ERR_OOMEM); + vm_t start = alloc_devmem(r, paddr, size, flags); + if (ERR_CODE(start)) + return_args1(t, start); return_args2(t, OK, start); } @@ -127,8 +127,9 @@ SYSCALL_DEFINE2(req_page)(struct tcb *t, sys_arg_t size, sys_arg_t flags) vm_t start = 0; size_t asize = 0; flags = sanitize_uvflags(flags); - if (!(start = alloc_uvpage(r, size, flags, &addr, &asize))) - return_args1(t, ERR_OOMEM); + start = alloc_uvpage(r, size, flags, &addr, &asize); + if (ERR_CODE(start)) + return_args1(t, start); return_args4(t, OK, start, addr, asize); } @@ -148,10 +149,10 @@ SYSCALL_DEFINE2(req_sharedmem)(struct tcb *t, sys_arg_t size, sys_arg_t flags) if (!has_cap(c->caps, CAP_SHARED)) return_args1(t, ERR_PERM); - vm_t start = 0; flags = sanitize_uvflags(flags); - if (!(start = alloc_shared_uvmem(c, size, flags))) - return_args1(t, ERR_OOMEM); + vm_t start = alloc_shared_uvmem(c, size, flags); + if (ERR_CODE(start)) + return_args1(t, start); return_args3(t, OK, start, size); } @@ -178,10 +179,11 @@ SYSCALL_DEFINE3(ref_sharedmem)(struct tcb *t, sys_arg_t tid, sys_arg_t addr, if (!r || zombie(r)) return_args1(t, ERR_INVAL); - vm_t start = 0; size_t size = 0; + size_t size = 0; flags = sanitize_uvflags(flags); - if (!(start = ref_shared_uvmem(r, c, addr, flags))) - return_args1(t, ERR_OOMEM); + vm_t start = ref_shared_uvmem(r, c, addr, flags); + if (ERR_CODE(start)) + return_args1(t, start); return_args3(t, OK, start, size); } @@ -14,11 +14,23 @@ #include <kmi/vmem.h> #include <arch/vmem.h> -stat_t init_uvmem(struct tcb *t, vm_t base, vm_t top) +stat_t init_uvmem(struct tcb *t) { t->uvmem.owner = t->tid; t->uvmem.vmem = t->proc.vmem; - return init_region(&t->uvmem.region, base, top); + + stat_t ret = OK; + if ((ret = init_region(&t->uvmem.region, UVMEM_START, UVMEM_END))) + return ret; + + /* if a user really wants to use the first page for something, they'll + * have to free it first, 'accepting' that no null-page is dangerous. */ + size_t size = 0; + vm_t v = alloc_fixed_region(&t->uvmem.region, + UVMEM_START, BASE_PAGE_SIZE, &size, + MR_NONBACKED); + assert(v == UVMEM_START && size == BASE_PAGE_SIZE); + return OK; } /** @@ -40,6 +52,12 @@ static stat_t __copy_mapped_region(struct tcb *d, struct tcb *s, size_t size = end - start; vm_t v = alloc_fixed_region(&d->uvmem.region, start, size, &size, m->flags); + if (ERR_CODE(v)) + return v; + + if (is_set(m->flags, MR_NONBACKED)) + return v; + assert(v == start); /* note that we use uvmem.vmem instead of proc.vmem, this is just to @@ -76,6 +94,8 @@ static stat_t __copy_shared_region(struct tcb *d, struct mem_region *m) size_t size = end - start; vm_t v = alloc_fixed_region(&d->uvmem.region, start, size, &size, m->flags); + if (ERR_CODE(v)) + return v; assert(v == start); stat_t res = clone_region(d->uvmem.vmem, s->uvmem.vmem, start, v, size, @@ -107,8 +127,11 @@ static vm_t __clone_shared_region(struct tcb *d, struct tcb *s, reference_proc(s); size_t size = end - start; - vm_t v = alloc_shared_region(&d->uvmem.region, size, &size, m->flags, - s->rid); + vm_t v = alloc_shared_region(&d->uvmem.region, size, &size, + MR_NONBACKED | m->flags, s->rid); + if (ERR_CODE(v)) + return v; + stat_t res = clone_region(d->uvmem.vmem, s->uvmem.vmem, start, v, size, flags); if (res == OK) @@ -118,7 +141,7 @@ static vm_t __clone_shared_region(struct tcb *d, struct tcb *s, unreference_proc(s); free_region(&d->uvmem.region, v); unmap_fixed_region(d->uvmem.vmem, v, size); - return NULL; + return res; } /** @@ -127,44 +150,23 @@ static vm_t __clone_shared_region(struct tcb *d, struct tcb *s, * @param t Current thread. * @param m Memory region to free. */ -static void __free_private_mapping(struct tcb *t, struct mem_region *m) +static void __free_mapping(struct tcb *t, struct mem_region *m) { + struct tcb *owner = get_tcb(m->pid); + if (owner) + unreference_proc(owner); + + if (is_set(m->flags, MR_NONBACKED)) + return; + pm_t start = __addr(m->start); pm_t end = __addr(m->end); size_t size = end - start; - unmap_region(t->proc.vmem, start, size); -} - -/** - * Unmap shared region and free associated physical pages if they're not being - * used by the other process. - * - * @param t Current thread. - * @param m Memory region to free. - */ -static void __free_shared_mapping(struct tcb *t, struct mem_region *m) -{ - vm_t start = __addr(m->start); - vm_t end = __addr(m->end); - unreference_proc(get_tcb(m->pid)); - - size_t bytes = end - start; - unmap_fixed_region(t->proc.vmem, start, bytes); -} - -/** - * Convenience function for freeing mapped regions. - * - * @param t Thread to work in. - * @param m Memory region to free. - */ -static void __free_mapping(struct tcb *t, struct mem_region *m) -{ - if (m->pid != 0) - return __free_shared_mapping(t, m); - - return __free_private_mapping(t, m); + if (m->pid) + unmap_fixed_region(t->proc.vmem, start, size); + else + unmap_region(t->proc.vmem, start, size); } void clear_uvmem(struct tcb *t) @@ -174,13 +176,11 @@ void clear_uvmem(struct tcb *t) struct mem_region *m = find_closest_used_region(&t->uvmem.region, 0); for (; m; m = m->next) { - if (is_region_kept(m)) { + if (is_region_kept(m)) continue; - } - if (!is_set(m->flags, MR_USED)) { + if (!is_set(m->flags, MR_USED)) continue; - } __free_mapping(t, m); free_known_region(&t->uvmem.region, m); @@ -243,10 +243,14 @@ vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags) assert(t && is_proc(t)); const vm_t v = alloc_region(&t->uvmem.region, size, &size, flags); - if (map_region(t->proc.vmem, v, size, max_order(), flags)) { + if (ERR_CODE(v)) + return v; + + stat_t ret = OK; + if ((ret = map_region(t->proc.vmem, v, size, max_order(), flags))) { unmap_region(t->proc.vmem, v, size); free_region(&t->uvmem.region, v); - return NULL; + return ret; } return v; @@ -258,10 +262,14 @@ vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) const vm_t v = alloc_fixed_region(&t->uvmem.region, start, size, &size, flags); - if (map_region(t->proc.vmem, v, size, max_order(), flags)) { + if (ERR_CODE(v)) + return v; + + stat_t ret = OK; + if ((ret = map_region(t->proc.vmem, v, size, max_order(), flags))) { unmap_region(t->proc.vmem, v, size); free_region(&t->uvmem.region, v); - return NULL; + return ret; } return v; @@ -269,14 +277,20 @@ vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) vm_t map_fixed_uvmem(struct tcb *t, pm_t start, size_t size, vmflags_t flags) { + assert(is_aligned(start, BASE_PAGE_SIZE)); + const vm_t v = alloc_region(&t->uvmem.region, size, &size, flags); - if (map_fixed_region(t->proc.vmem, v, start, size, flags)) { + if (ERR_CODE(v)) + return v; + + stat_t ret = OK; + if ((ret = map_fixed_region(t->proc.vmem, v, start, size, flags))) { unmap_region(t->proc.vmem, v, size); free_region(&t->uvmem.region, v); - return NULL; + return ret; } - return v + (start % BASE_PAGE_SIZE); + return v; } vm_t alloc_uvpage(struct tcb *t, size_t size, vmflags_t flags, pm_t *startp, @@ -286,19 +300,20 @@ vm_t alloc_uvpage(struct tcb *t, size_t size, vmflags_t flags, pm_t *startp, size = order_size(order); const vm_t v = alloc_region(&t->uvmem.region, size, &size, flags); - if (!v) - return 0; + if (ERR_CODE(v)) + return v; pm_t start = alloc_page(order); if (!start) { free_region(&t->uvmem.region, size); - return 0; + return ERR_OOMEM; } - if (map_fixed_region(t->proc.vmem, v, start, size, flags)) { + stat_t ret = OK; + if ((ret = map_fixed_region(t->proc.vmem, v, start, size, flags))) { unmap_region(t->proc.vmem, v, size); free_region(&t->uvmem.region, v); - return NULL; + return ret; } *startp = (pm_t)__pa(start); @@ -313,11 +328,15 @@ vm_t alloc_shared_uvmem(struct tcb *s, size_t size, vmflags_t flags) assert(s && is_proc(s)); const vm_t v = alloc_region(&s->uvmem.region, size, &size, MR_SHARED | flags); + if (ERR_CODE(v)) + return v; + /* use base pages to make clone more likely to succeed */ - if (map_region(s->proc.vmem, v, size, BASE_PAGE, flags)) { + stat_t ret = OK; + if ((ret = map_region(s->proc.vmem, v, size, BASE_PAGE, flags))) { unmap_region(s->proc.vmem, v, size); free_region(&s->uvmem.region, v); - return NULL; + return ret; } return v; |
