diff options
| -rwxr-xr-x | arch/riscv64/conf/init | bin | 1232 -> 2136 bytes | |||
| -rw-r--r-- | arch/riscv64/conf/init.c | 106 | ||||
| -rw-r--r-- | arch/riscv64/conf/initrd | bin | 1536 -> 2560 bytes | |||
| -rw-r--r-- | common/uapi/dispatch.c | 3 | ||||
| -rw-r--r-- | common/uapi/timers.c | 40 | ||||
| -rw-r--r-- | include/apos/syscalls.h | 3 | ||||
| -rw-r--r-- | include/apos/timer.h | 1 | ||||
| -rw-r--r-- | include/apos/uapi.h | 11 |
8 files changed, 158 insertions, 6 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init Binary files differindex 23c3097..d9a585d 100755 --- a/arch/riscv64/conf/init +++ b/arch/riscv64/conf/init diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c new file mode 100644 index 0000000..4bd6a4e --- /dev/null +++ b/arch/riscv64/conf/init.c @@ -0,0 +1,106 @@ +/* This file is allowed to be undocumented as it is only temporarily in this + * tree. At some point in the (hopefully) near future, I intend to move the + * kernel code and initrd generation stuff into separate repositories, to make + * things easier for myself. For now though, this is good enough. + */ + +/* compile with riscv64-unknown-elf-gcc -ffreestanding -nostdlib */ +/* create initrd with echo init | cpio -H newc -o > initrd */ +#include <stdint.h> +#include "../../../include/apos/syscalls.h" + +static void sys_noop() +{ + long register a0 asm ("a0") = SYS_NOOP; + asm ("ecall" : : : "a0", "a1"); +} + +static void sys_putch(char c) +{ + long register a0 asm ("a0") = SYS_PUTCH; + long register a1 asm ("a1") = c; + asm ("ecall" : : : "a0", "a1"); +} + +static uint64_t sys_timebase() +{ + long register a0 asm ("a0") = SYS_TIMEBASE; + long register a1 asm ("a1") = 0; + asm ("ecall" : : : "a0", "a1"); +#if defined(_LP64) + return a1; +#else + uint64_t t = a0; + t <<= 32; + return t + a1; +#endif +} + +static uint64_t sys_ticks() +{ + long register a0 asm ("a0") = SYS_TICKS; + long register a1 asm ("a1") = 0; + asm ("ecall" : : : "a0", "a1"); +#if defined(_LP64) + return a1; +#else + uint64_t t = a0; + t <<= 32; + return t + a1; +#endif +} + +static void puts(const char *s) +{ + while (*s) + sys_putch(*s++); +} + +static void _print_number(uint64_t v) +{ + if (v == 0) + return; + + _print_number(v / 10); + sys_putch((v % 10) + '0'); +} + +static void print_number(uint64_t v) +{ + if (v == 0) { + sys_putch('0'); + return; + } + + _print_number(v); +} + +static void print_value(const char *s, uint64_t v) +{ + puts(s); + puts(": "); + + print_number(v); + sys_putch('\n'); +} + +void _start() +{ + sys_noop(); + puts("Hello, world!\n"); + + uint64_t second = sys_timebase(); + print_value("Timebase", second); + + uint64_t n = 0, i, start; + start = i = sys_ticks(); + print_value("Start ticks", start); + + while (i < start + second) { + i = sys_ticks(); + n++; + } + + print_value("End ticks", i); + print_value("Syscalls per second", n); +} diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd Binary files differindex efba349..f05e035 100644 --- a/arch/riscv64/conf/initrd +++ b/arch/riscv64/conf/initrd diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c index b16b255..fe86df0 100644 --- a/common/uapi/dispatch.c +++ b/common/uapi/dispatch.c @@ -26,6 +26,7 @@ static const sys_t syscall_table[] = { /* timers */ [SYS_TIMEBASE] = sys_timebase, + [SYS_TICKS] = sys_ticks, [SYS_REQ_REL_TIMER] = sys_req_rel_timer, [SYS_REQ_ABS_TIMER] = sys_req_abs_timer, [SYS_FREE_TIMER] = sys_free_timer, @@ -93,6 +94,8 @@ struct sys_ret syscall_dispatch(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, if (check_canary(t)) { bug("Syscall %zu overwrote stack canary\n", syscall); + /** @todo should probably halt, as the system is likely in an + * unstable state. */ return (struct sys_ret){ ERR_INT, 0 }; } diff --git a/common/uapi/timers.c b/common/uapi/timers.c index b6f9b95..d6c6286 100644 --- a/common/uapi/timers.c +++ b/common/uapi/timers.c @@ -9,8 +9,10 @@ #include <apos/timer.h> #include <apos/uapi.h> +#include <arch/timer.h> + /** - * Convert arch-specific register values \c ticks and \c repeat to \c ticks_t. + * Convert arch-specific register values \p ticks and \p mult to \ref ticks_t. * * If we're on a 32bit system, one register can't contain a tick value, * so we use two registers and combine them into one value and let the compiler @@ -18,7 +20,7 @@ * * @param ticks Register width tick value. * @param mult Register width repeat value. - * @return Corresponding \c ticks_t value. + * @return Corresponding \ref ticks_t value. */ static ticks_t scaled_ticks(sys_arg_t ticks, sys_arg_t mult) { @@ -33,17 +35,45 @@ static ticks_t scaled_ticks(sys_arg_t ticks, sys_arg_t mult) /** * Timebase syscall handler. * - * @return \ref OK and resolution of system timer in Hz. + * @return \ref OK and resolution of system timer in Hz if on 64bit system, + * otherwise high bits of resolutio in first register and low bits in second. */ SYSCALL_DEFINE0(timebase)() { - return (struct sys_ret){ OK, secs_to_ticks(1) }; + ticks_t t = secs_to_ticks(1); +#if defined(_LP64) + return (struct sys_ret){ OK, t }; +#else + return (struct sys_ret){ t >> 32, t }; +#endif +} + +/** + * Current ticks syscall handler. + * + * Note that most platforms allow user level read access to hardware timers, and + * should be preferred over this syscall on such platforms. Still, for + * completeness sake. + * + * @return \ref OK and the current ticks when on 64bit systems, otherwise high + * 32 bits of ticks in first register and low 32 bits in second. + * \todo 32bit systems are arguably a bit unsafe with this method, should I + * instead provide ticks_low and ticks_high or something? + */ +SYSCALL_DEFINE0(ticks)() +{ + ticks_t t = current_ticks(); +#if defined(_LP64) + return (struct sys_ret){ OK, t }; +#else + return (struct sys_ret){ t >> 32, t }; +#endif } /** * Relative timer request syscall handler. * - * \note On 64bit systems, \c repeat is ignored as \c ticks register is large + * \note On 64bit systems, \p mult is ignored as \p ticks register is large * enough to contain essentially any timepoint we want. A couple thousand years * when the clock runs at 5GHz, if I'm not completely mistaken. * diff --git a/include/apos/syscalls.h b/include/apos/syscalls.h index 84d9e07..4bbcdc5 100644 --- a/include/apos/syscalls.h +++ b/include/apos/syscalls.h @@ -53,6 +53,9 @@ enum { /** Get accuracy of clock in Hertz. */ SYS_TIMEBASE, + /** Get current ticks. */ + SYS_TICKS, + /** Request relative timer (number of ticks from now). */ SYS_REQ_REL_TIMER, diff --git a/include/apos/timer.h b/include/apos/timer.h index 7a5d73d..6f83d23 100644 --- a/include/apos/timer.h +++ b/include/apos/timer.h @@ -22,7 +22,6 @@ */ typedef uint64_t ticks_t; - /** * tunit_t typedef, whichever time unit we're dealing with. */ diff --git a/include/apos/uapi.h b/include/apos/uapi.h index 1ebdc21..29e15dc 100644 --- a/include/apos/uapi.h +++ b/include/apos/uapi.h @@ -312,6 +312,17 @@ SYSCALL_DECLARE1(free_mem, start); SYSCALL_DECLARE0(timebase); /** + * Get current ticks. + * + * @param a Unused. + * @param b Unused. + * @param c Unused. + * @param d Unused. + * @return Current ticks. + */ +SYSCALL_DECLARE0(ticks); + +/** * Request relative timer syscall. * * Request timer that triggers a number of ticks in the future. |
