From 90ab6923775b2e011f434c92361bc5aabb4ce980 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 13 Nov 2022 00:09:21 +0200 Subject: write init more sensibly + Both easier to look at and now the userspace doesn't play as big of a role in the 'benchmarking' with optimizations turned on. --- arch/riscv64/conf/init | Bin 3448 -> 2720 bytes arch/riscv64/conf/init.c | 152 +++++++++++++++++++++++++-------------------- arch/riscv64/conf/initrd | Bin 4096 -> 3072 bytes arch/riscv64/kernel/vmem.c | 2 + common/uapi/ipc.c | 3 + include/apos/uapi.h | 1 + lib/fdt_dbg.c | 4 +- 7 files changed, 92 insertions(+), 70 deletions(-) diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init index 7ab8388..eba8186 100755 Binary files a/arch/riscv64/conf/init and b/arch/riscv64/conf/init differ diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c index 01e219e..438bff4 100644 --- a/arch/riscv64/conf/init.c +++ b/arch/riscv64/conf/init.c @@ -9,53 +9,63 @@ #include #include "../../../include/apos/syscalls.h" -#define ecall() do { asm volatile ("ecall" \ - : \ - : \ - : "a0", "a1", "a2", "a3", "a4", "a5", \ - "memory"); \ -} while (0) +#define CLOBBER_LIST "a0", "a1", "a2", "a3", "a4", "a5" + +struct sys_ret { + long a0, a1, a2, a3, a4, a5; +}; + +struct sys_ret ecall(struct sys_ret s) +{ + register long a0 asm ("a0") = s.a0; + register long a1 asm ("a1") = s.a1; + register long a2 asm ("a2") = s.a2; + register long a3 asm ("a3") = s.a3; + register long a4 asm ("a4") = s.a4; + register long a5 asm ("a5") = s.a5; + + asm volatile ("ecall" + : "=r"(a0), "=r"(a1), "=r"(a2), "=r"(a3), "=r"(a4), "=r"(a5) + : "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)); + + return (struct sys_ret){a0, a1, a2, a3, a4, a5}; +} static void sys_noop() { - long register a0 asm ("a0") = SYS_NOOP; - ecall(); + struct sys_ret r = {.a0 = SYS_NOOP}; + ecall(r); } static void sys_putch(char c) { - long register a0 asm ("a0") = SYS_PUTCH; - long register a1 asm ("a1") = c; - ecall(); + struct sys_ret r = {.a0 = SYS_PUTCH, .a1 = c}; + ecall(r); } static uint64_t sys_timebase() { - long register a0 asm ("a0") = SYS_TIMEBASE; - long register a1 asm ("a1") = 0; - long register a2 asm ("a2") = 0; - ecall(); + struct sys_ret r = {.a0 = SYS_TIMEBASE}; + r = ecall(r); #if defined(_LP64) - return a1; + return r.a1; #else - uint64_t t = a1; + uint64_t t = r.a1; t <<= 32; - return t + a2; + return t + r.a2; #endif } static uint64_t sys_ticks() { - long register a0 asm ("a0") = SYS_TICKS; - long register a1 asm ("a1") = 0; - long register a2 asm ("a2") = 0; - ecall(); + struct sys_ret r = {.a0 = SYS_TICKS}; + r = ecall(r); #if defined(_LP64) - return a1; + return r.a1; #else - uint64_t t = a1; + uint64_t t = r.a1; t <<= 32; - return t + a2; + return t + r.a2; #endif } @@ -95,71 +105,77 @@ static void print_value(const char *s, uint64_t v) static uint64_t sys_fork() { - long register a0 asm ("a0") = SYS_FORK; - long register a1 asm ("a1") = 0; - ecall(); - if (a0 != 0) - print_value("fork() failed with error ", a0); - return a1; + struct sys_ret r = {.a0 = SYS_FORK}; + r = ecall(r); + + if (r.a0 != 0) + print_value("fork() failed with error ", r.a0); + + return r.a1; } static uint64_t sys_swap(long tid) { - long register a0 asm ("a0") = SYS_SWAP; - long register a1 asm ("a1") = tid; - ecall(); - if (a0 != 0) - print_value("swap() failed with error ", a0); - return a0; + struct sys_ret r = {.a0 = SYS_SWAP, .a1 = tid}; + r = ecall(r); + + if (r.a0 != 0) + print_value("swap() failed with error ", r.a0); + + return r.a0; } static void sys_ipc_server(void *f) { - long register a0 asm ("a0") = SYS_IPC_SERVER; - long register a1 asm ("a1") = (long)f; - ecall(); - if (a0 != 0) - print_value("ipc_server() failed with error ", a0); + struct sys_ret r = {.a0 = SYS_IPC_SERVER, .a1 = (long)f}; + r = ecall(r); + + if (r.a0 != 0) + print_value("ipc_server() failed with error ", r.a0); } -static uint64_t sys_ipc_req(long tid, long *d0, long *d1, long *d2, long *d3) +struct ipc_args { + long a0, a1, a2, a3; +}; + +static struct ipc_args sys_ipc_req(long tid, long d0, long d1, long d2, long d3) { - long register a0 asm ("a0") = SYS_IPC_REQ; - long register a1 asm ("a1") = tid; - long register a2 asm ("a2") = *d0; - long register a3 asm ("a3") = *d1; - long register a4 asm ("a4") = *d2; - long register a5 asm ("a5") = *d3; - ecall(); - if (a0) - print_value("ipc_req() failed with error ", a0); + struct sys_ret r = {.a0 = SYS_IPC_REQ, + .a1 = tid, + .a2 = d0, + .a3 = d1, + .a4 = d2, + .a5 = d3}; - *d0 = a2; - *d1 = a3; - *d2 = a4; - *d3 = a5; - return a0; + r = ecall(r); + + if (r.a0) + print_value("ipc_req() failed with error ", r.a0); + + return (struct ipc_args){r.a2, r.a3, r.a4, r.a5}; } static void sys_ipc_resp(long d0, long d1, long d2, long d3) { - long register a0 asm ("a0") = SYS_IPC_RESP; - long register a1 asm ("a1") = d0; - long register a2 asm ("a2") = d1; - long register a3 asm ("a3") = d2; - long register a4 asm ("a4") = d3; - ecall(); + struct sys_ret r = {.a0 = SYS_IPC_RESP, + .a1 = d0, + .a2 = d1, + .a3 = d2, + .a4 = d3}; + + ecall(r); } static void sys_poweroff(long type) { - long register a0 asm ("a0") = SYS_POWEROFF; - long register a1 asm ("a1") = type; - ecall(); + struct sys_ret r = {.a0 = SYS_POWEROFF, .a1 = type}; + ecall(r); } void callback(long status, long tid, long d0, long d1, long d2, long d3) { + (void)status; + (void)tid; sys_ipc_resp(d0, d1, d2, d3); } @@ -212,11 +228,11 @@ void _start() print_value("Swaps (both ways) per second", n); puts("Doing ipc requests...\n"); - long d0, d1, d2, d3; + long d0 = 0, d1 = 0, d2 = 0, d3 = 0; csr_read(CSR_TIME, i); start = i; n = 0; while (i < start + second) { - sys_ipc_req(1, &d0, &d1, &d2, &d3); + sys_ipc_req(1, d0, d1, d2, d3); csr_read(CSR_TIME, i); n++; } diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd index 492b80c..905bbfe 100644 Binary files a/arch/riscv64/conf/initrd and b/arch/riscv64/conf/initrd differ diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index a3903f1..15daa62 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -345,6 +345,8 @@ vm_t setup_kernel_io(struct vmem *b, vm_t paddr) } #endif +/* something of an optimisation, letting the compiler know which parts to copy + * however it sees best */ struct uvmem_map { struct vmem *leaf[CSTACK_PAGE - 1]; }; diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c index e45c7dd..5041ca2 100644 --- a/common/uapi/ipc.c +++ b/common/uapi/ipc.c @@ -50,9 +50,12 @@ static struct sys_ret do_ipc(sys_arg_t pid, if (!r->callback) return SYS_RET1(ERR_NOINIT); + uint64_t before, after; + clone_uvmem(r->proc.vmem, t->rpc.vmem); use_vmem(t->rpc.vmem); save_context(t); + set_return(t, r->callback); /** @todo associate thread with new proc, should be done in tcb.c I * think */ diff --git a/include/apos/uapi.h b/include/apos/uapi.h index 83de7eb..fea82e4 100644 --- a/include/apos/uapi.h +++ b/include/apos/uapi.h @@ -30,6 +30,7 @@ typedef long sys_arg_t; * Return structure of syscall. * \note Field names are generic, and can be used for whatever, * check documentation of whatever you're doing. + * @todo should this be placed into syscalls.h? */ struct sys_ret { /** Status. */ diff --git a/lib/fdt_dbg.c b/lib/fdt_dbg.c index 5fd4219..d3c4e26 100644 --- a/lib/fdt_dbg.c +++ b/lib/fdt_dbg.c @@ -138,8 +138,8 @@ void __dbg_fdt(const void *fdt, int node_offset, int depth) int property = 0; fdt_for_each_property_offset(property, fdt, node) { - int len; - const char *name; + int len = 0; + const char *name = 0; const void *data = fdt_getprop_by_offset(fdt, property, &name, &len); -- cgit v1.3