diff options
| -rwxr-xr-x | arch/riscv64/conf/init | bin | 6072 -> 3600 bytes | |||
| -rw-r--r-- | arch/riscv64/conf/initrd | bin | 6656 -> 4096 bytes | |||
| -rw-r--r-- | common/mem.c | 9 | ||||
| -rw-r--r-- | common/uapi/dispatch.c | 1 | ||||
| -rw-r--r-- | common/uapi/mem.c | 19 | ||||
| -rw-r--r-- | common/vmem.c | 30 | ||||
| -rw-r--r-- | include/apos/mem.h | 8 | ||||
| -rw-r--r-- | include/apos/syscalls.h | 3 | ||||
| -rw-r--r-- | include/apos/types.h | 1 | ||||
| -rw-r--r-- | include/apos/uapi.h | 26 | ||||
| -rw-r--r-- | include/apos/vmem.h | 13 |
11 files changed, 110 insertions, 0 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init Binary files differindex b24a661..c77c048 100755 --- a/arch/riscv64/conf/init +++ b/arch/riscv64/conf/init diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd Binary files differindex 35cf825..fb6f525 100644 --- a/arch/riscv64/conf/initrd +++ b/arch/riscv64/conf/initrd diff --git a/common/mem.c b/common/mem.c index 2cf72e3..f4a0919 100644 --- a/common/mem.c +++ b/common/mem.c @@ -17,6 +17,15 @@ size_t __mm_sizes[10]; size_t __mm_page_shift; enum mm_order __mm_max_order; +enum mm_order nearest_order(size_t size) +{ + for (enum mm_order order = max_order(); order >= MM_MIN; --order) + if (order_size(order) >= size) + return order; + + return MM_O0; +} + void init_mem(size_t max_order, size_t bits[10], size_t page_shift) { __mm_max_order = max_order; diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c index d11e02e..b5cd51e 100644 --- a/common/uapi/dispatch.c +++ b/common/uapi/dispatch.c @@ -51,6 +51,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, case SYS_NOOP: sys_noop(t, a, b, c, d, e); break; case SYS_PUTCH: sys_putch(t, a, b, c, d, e); break; case SYS_REQ_MEM: sys_req_mem(t, a, b, c, d, e); break; + case SYS_REQ_PAGE: sys_req_page(t, a, b, c, d, e); break; case SYS_REQ_PMEM: sys_req_pmem(t, a, b, c, d, e); break; case SYS_REQ_FIXMEM: sys_req_fixmem(t, a, b, c, d, e); break; case SYS_REQ_SHAREDMEM: sys_req_sharedmem(t, a, b, c, d, e); break; diff --git a/common/uapi/mem.c b/common/uapi/mem.c index 099028e..41ebcca 100644 --- a/common/uapi/mem.c +++ b/common/uapi/mem.c @@ -33,6 +33,25 @@ SYSCALL_DEFINE2(req_mem)(struct tcb *t, sys_arg_t size, sys_arg_t flags) } /** + * Allocate single page to program. + * + * @param t Current tcb. + * @param size Size of the allocation. + * @param flags Flags of allocation. + * @return \ref ERR_OOMEM if unsucessful, otherwise \ref OK, virtual address, + * actual size, physical address, in that order. + */ +SYSCALL_DEFINE2(req_page)(struct tcb *t, sys_arg_t size, sys_arg_t flags) +{ + struct tcb *r = get_cproc(t); + vm_t start = 0; pm_t paddr = 0; size_t asize = size; + if (!(start = alloc_uvpage(r, asize, flags, &asize, &paddr))) + return_args(t, SYS_RET1(ERR_OOMEM)); + + return_args(t, SYS_RET4(OK, start, asize, paddr)); +} + +/** * Fixed memory request syscall handler. * * @param t Current tcb. diff --git a/common/vmem.c b/common/vmem.c index f1eed83..b28a3d6 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -200,6 +200,36 @@ vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags) return w; } +vm_t alloc_uvpage(struct tcb *t, size_t size, vmflags_t flags, size_t *asize, + pm_t *paddr) +{ + hard_assert(t && is_proc(t), ERR_INVAL); + + enum mm_order order = nearest_order(size); + size_t actual_size = order_size(order); + stat_t status = OK; + + const vm_t v = alloc_region(&t->sp_r, size, &size, flags); + const vm_t w = __addr(__page(v)); + + pm_t addr = alloc_page(order); + /** @todo should free region */ + if (!addr) + return NULL; + + status = map_vpage(t->proc.vmem, addr, w, flags, order); + if (is_rpc(t) && status == INFO_SEFF) + clone_rpc_maps(t); + + if (asize) + *asize = actual_size; + + if (paddr) + *paddr = addr; + + return w; +} + vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) { hard_assert(t && is_proc(t), ERR_INVAL); diff --git a/include/apos/mem.h b/include/apos/mem.h index 4db7a67..ea61aba 100644 --- a/include/apos/mem.h +++ b/include/apos/mem.h @@ -196,6 +196,14 @@ extern size_t __mm_page_shift; extern enum mm_order __mm_max_order; /** + * Find nearest order to size. + * + * @param size Size to map to an order. + * @return Nearest order larger than \p size. + */ +enum mm_order nearest_order(size_t size); + +/** * Initialize memory subsystem data. Populates __mm_* with data given. * * @param max_order Maximum order the current system supports. diff --git a/include/apos/syscalls.h b/include/apos/syscalls.h index 611765d..40e6504 100644 --- a/include/apos/syscalls.h +++ b/include/apos/syscalls.h @@ -38,6 +38,9 @@ enum { /** Request memory from anywhere. */ SYS_REQ_MEM, + /** Request physical page from ram. */ + SYS_REQ_PAGE, + /** Request memory with physical address. */ SYS_REQ_PMEM, diff --git a/include/apos/types.h b/include/apos/types.h index 431d551..36e918e 100644 --- a/include/apos/types.h +++ b/include/apos/types.h @@ -445,6 +445,7 @@ typedef int_fast8_t stat_t; * is with pids */ typedef int_fast32_t id_t; +/** Maximum ID number. */ #define ID_MAX INT_FAST32_MAX /** Memory region flags. */ diff --git a/include/apos/uapi.h b/include/apos/uapi.h index dda4391..fefd1bf 100644 --- a/include/apos/uapi.h +++ b/include/apos/uapi.h @@ -320,6 +320,32 @@ SYSCALL_DECLARE1(putch, ch); SYSCALL_DECLARE2(req_mem, size, flags); /** + * Request one page of memory. The nearest fitting size is chosen. + * + * This might be better implemented as some number of adjacent physical pages, + * but the underlying physical page allocator doesn't really handle it very + * well. This weird design decision is because I don't know if there are devices + * whose drivers need multiple adjacent physical pages, only that at least + * virtio devices need to be able to access the physical address of a single + * page. Basic adjacent physical pages can be made from higher order pages, + * just with a massive overhead. Still, probably good eough for now. + * + * For example, if you need two adjacent 4K pages, you pass size = 8K and you + * get back a 2M page, if one is available. + * + * @param t Current tcb. + * @param size Required size of region. + * @param flags Mapping flags to use. + * @param c Unused. + * @param d Unused. + * @param e Unused. + * + * Returns \ref ERR_OOMEM if no page is available, otherwise \c OK, virtual + * address, actual size, physical size in that order. + */ +SYSCALL_DECLARE2(req_page, size, flags); + +/** * Request physical memory syscall. * * Allocates at least the specified size of allocation which includes the diff --git a/include/apos/vmem.h b/include/apos/vmem.h index 38bad16..5cbe7db 100644 --- a/include/apos/vmem.h +++ b/include/apos/vmem.h @@ -28,6 +28,19 @@ vm_t alloc_uvmem(struct tcb *r, size_t size, vmflags_t flags); /** + * Allocate one physical page for user virtual memory. + * + * @param r Process to allocate memory in. + * @param size Minimum size of allocation. + * @param flags Flags of allocation. + * @param asize Where to write actual size of allocation. + * @param paddr Where to write physical address of page. + * @return Start of allocation when succesful, \c NULL otherwise. + */ +vm_t alloc_uvpage(struct tcb *r, size_t size, vmflags_t flags, + size_t *asize, pm_t *paddr); + +/** * Allocate fixed user virtual memory. * * Virtual memory start address is chosen so that \c start is within the |
