aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xarch/riscv64/conf/initbin1232 -> 2136 bytes
-rw-r--r--arch/riscv64/conf/init.c106
-rw-r--r--arch/riscv64/conf/initrdbin1536 -> 2560 bytes
-rw-r--r--common/uapi/dispatch.c3
-rw-r--r--common/uapi/timers.c40
-rw-r--r--include/apos/syscalls.h3
-rw-r--r--include/apos/timer.h1
-rw-r--r--include/apos/uapi.h11
8 files changed, 158 insertions, 6 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index 23c3097..d9a585d 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
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
index efba349..f05e035 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files differ
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.