aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/conf/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv64/conf/init.c')
-rw-r--r--arch/riscv64/conf/init.c397
1 files changed, 0 insertions, 397 deletions
diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c
deleted file mode 100644
index c4e8064..0000000
--- a/arch/riscv64/conf/init.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * Header for silencing scripts/warn-undocumented
- *
- * @file init.c
- *
- * Test init program.
- *
- * This file 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 -Driscv64 -ffreestanding -nostdlib
- *
- * Create initrd with
- * echo init | cpio -H newc -o > initrd
- */
-
-#include <stdint.h>
-#include <stddef.h>
-#include "../../../include/kmi/syscalls.h"
-
-char *strcpy(char * restrict dst, const char * restrict src)
-{
- const char *s1 = src;
- char *s2 = dst;
-
- while (*s1)
- *(s2++) = *(s1++);
-
- return dst;
-}
-
-static inline struct sys_ret ecall(size_t n,
- sys_arg_t arg0, sys_arg_t arg1,
- sys_arg_t arg2, sys_arg_t arg3,
- sys_arg_t arg4, sys_arg_t arg5)
-{
- /* here a static assert of n <= 6 && n >= 1 would be ideal */
-
- register long a0 asm ("a0") = arg0;
- register long a1 asm ("a1") = arg1;
- register long a2 asm ("a2") = arg2;
- register long a3 asm ("a3") = arg3;
- register long a4 asm ("a4") = arg4;
- register long a5 asm ("a5") = arg5;
-
-#define OUTPUTS "+r" (a0), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4), "=r" (a5)
-
- if (n == 1)
- asm volatile ("ecall" : OUTPUTS : "r" (a0));
-
- else if (n == 2)
- asm volatile ("ecall" : OUTPUTS : "r" (a0), "r" (a1));
-
- else if (n == 3)
- asm volatile ("ecall" : OUTPUTS : "r" (a0), "r" (a1), "r" (a2));
-
- else if (n == 4)
- asm volatile ("ecall" : OUTPUTS
- : "r" (a0), "r" (a1), "r" (a2), "r" (a3));
-
- else if (n == 5)
- asm volatile ("ecall" : OUTPUTS
- : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
- "r" (a4));
-
- else if (n == 6)
- asm volatile ("ecall"
- : OUTPUTS
- : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
- "r" (a4), "r" (a5));
-
-#undef OUTPUTS
- return (struct sys_ret){a0, a1, a2, a3, a4, a5};
-}
-
-#define ecall1(a) ecall(1, a, 0, 0, 0, 0, 0)
-#define ecall2(a, b) ecall(2, a, b, 0, 0, 0, 0)
-#define ecall3(a, b, c) ecall(3, a, b, c, 0, 0, 0)
-#define ecall4(a, b, c, d) ecall(4, a, b, c, d, 0, 0)
-#define ecall5(a, b, c, d, e) ecall(5, a, b, c, d, e, 0)
-#define ecall6(a, b, c, d, e, f) ecall(6, a, b, c, d, e, f)
-
-static void sys_noop()
-{
- ecall1(SYS_NOOP);
-}
-
-static void sys_putch(char c)
-{
- ecall2(SYS_PUTCH, c);
-}
-
-static uint64_t sys_timebase()
-{
- struct sys_ret r = ecall1(SYS_TIMEBASE);
-#if defined(_LP64)
- return r.ar0;
-#else
- uint64_t t = r.ar0;
- t <<= 32;
- return t + r.ar1;
-#endif
-}
-
-static uint64_t sys_ticks()
-{
- struct sys_ret r = ecall1(SYS_TICKS);
-#if defined(_LP64)
- return r.ar0;
-#else
- uint64_t t = r.ar0;
- t <<= 32;
- return t + r.ar1;
-#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');
-}
-
-static uint64_t sys_fork()
-{
- struct sys_ret r = ecall1(SYS_FORK);
-
- if (r.s != 0) {
- print_value("fork() failed with error ", r.s);
- return r.s;
- }
-
- return r.ar0;
-}
-
-static uint64_t sys_swap(long tid)
-{
- struct sys_ret r = ecall2(SYS_SWAP, tid);
-
- if (r.s != 0) {
- print_value("swap() failed with error ", r.s);
- return r.s;
- }
-
- return 0;
-}
-
-static inline struct sys_ret sys_ipc_req(sys_arg_t pid,
- sys_arg_t d0, sys_arg_t d1,
- sys_arg_t d2,
- sys_arg_t d3)
-{
- struct sys_ret r = ecall6(SYS_IPC_REQ, pid, d0, d1, d2, d3);
-
- if (r.s)
- print_value("ipc_req() failed with error ", r.s);
-
- return r;
-}
-
-static void sys_ipc_resp(sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
-{
- ecall5(SYS_IPC_RESP, d0, d1, d2, d3);
-}
-
-static void sys_poweroff(long type)
-{
- ecall2(SYS_POWEROFF, type);
-}
-
-static void *sys_req_mem(size_t count)
-{
- struct sys_ret r = ecall3(SYS_REQ_MEM, count, VM_R | VM_W);
- if (r.s) {
- print_value("sys_req_mem() failed with error ", r.s);
- return NULL;
- }
-
- return (void *)r.ar0;
-}
-
-static size_t get_ram_usage()
-{
- struct sys_ret r = ecall2(SYS_CONF_GET, CONF_RAM_USAGE);
- if (r.s) {
- print_value("getting RAM usage failed with error ", r.s);
- return 0;
- }
-
- return r.ar0;
-}
-
-static size_t get_ram_size()
-{
- struct sys_ret r = ecall2(SYS_CONF_GET, CONF_RAM_SIZE);
- if (r.s) {
- print_value("getting RAM size failed with error ", r.s);
- return 0;
- }
-
- return r.ar0;
-}
-
-static void sys_free_mem(void *p)
-{
- struct sys_ret r = ecall2(SYS_FREE_MEM, (long)p);
-
- if (r.s)
- print_value("sys_free_mem() failed with error ", r.s);
-}
-
-static void *sys_req_sharedmem(long tid, unsigned long size, void **cbuf)
-{
- struct sys_ret r = ecall3(SYS_REQ_SHAREDMEM, size, VM_R | VM_W);
- if (r.s) {
- print_value("sys_req_sharedmem() failed with error ", r.s);
- return NULL;
- }
-
- void *rw_buf = (void *)r.ar0;
-
- r = ecall4(SYS_REF_SHAREDMEM, tid, (sys_arg_t)rw_buf, VM_R | VM_W);
- if (r.s) {
- print_value("sys_ref_sharedmem() failed with error ", r.s);
- return NULL;
- }
-
- *cbuf = (void *)r.ar0;
- return rw_buf;
-}
-
-/* I'm guessing my elf parser doesn't handle data pages correctly yet... */
-static char *rw_buf = 0;
-static size_t rw_buf_size = 4096;
-
-static void sys_sleep()
-{
- ecall1(SYS_SLEEP);
-}
-
-#define CSR_TIME "0xc01"
-#define csr_read(csr, \
- res) __asm__ volatile ("csrr %0, " csr : "=r" (res) :: "memory")
-
-#define CSR_CYCLE "0xc00"
-
-static void handle_kernel(long pid, long tid, long d0, long d1, long d2,
- long d3)
-{
- if (d0 != SYS_USER_BOOTED)
- return;
-
- if (tid != 1) {
- puts("Woo, more cores!\n");
- while (1)
- sys_sleep();
- }
-
- /* otherwise */
- sys_noop();
- puts("Hello, world!\n");
-
- uint64_t second = sys_timebase();
- print_value("Timebase", second);
-
- uint64_t n = 0, i, start, cn, cstart, cend;
- start = i = sys_ticks();
- csr_read(CSR_CYCLE, cstart);
- while (i < start + second) {
- i = sys_ticks();
- n++;
- }
- csr_read(CSR_CYCLE, cend);
-
- print_value("Start ticks", start);
- print_value("End ticks", i);
- print_value("Syscalls per second", n);
- print_value("Executed cycles per second", cend - cstart);
-
- puts("Starting fork():\n");
- long cid = sys_fork();
- if (cid != 0) {
- print_value("Child pid", cid);
- puts("Swapping to child...\n");
- while(1) sys_swap(cid);
- }
-
- puts("Hello from child!\n");
-
- puts("Doing swaps...\n");
- csr_read(CSR_TIME, i);
- start = i; n = 0;
- while (i < start + second) {
- sys_swap(1);
- csr_read(CSR_TIME, i);
- n++;
- }
-
- print_value("Swaps (both ways) per second", n);
-
- puts("Doing ipc requests...\n");
- csr_read(CSR_TIME, i);
- start = i; n = 0;
- while (i < start + second) {
- sys_ipc_req(1, 0, 0, 0, 0);
- csr_read(CSR_TIME, i);
- n++;
- }
-
- print_value("IPC requests per second", n);
-
- puts("Doing memory allocations...\n");
-
- size_t ram = get_ram_usage();
- size_t size = get_ram_size();
- print_value("Memory usage before allocations: ", ram);
- print_value("Memory size in total: ", size);
- for (i = 0; i < 1000000; ++i) {
- char *p = sys_req_mem(10);
- *p = 'c';
- sys_free_mem(p);
- }
-
- ram = get_ram_usage();
- print_value("Memory usage after allocations: ", ram);
-
- puts("Checking shared memory\n");
- struct sys_ret r = sys_ipc_req(1, 1, 0, 0, 0);
- rw_buf = (char *)r.ar1;
- rw_buf_size = (size_t)r.ar2;
- print_value("Response from", r.ar0);
- print_value("Shared memory ptr", (uintptr_t)rw_buf);
- print_value("Shared memory size", rw_buf_size);
-
- rw_buf[0] = 0;
- puts("Sending string...\n");
- strcpy(rw_buf, "Hello from the other side!\n");
- sys_ipc_req(1, 2, 0, 0, 0);
-
- sys_poweroff(0);
-}
-
-void _start(long pid, long tid, long d0, long d1, long d2, long d3)
-{
- if (pid == 0)
- handle_kernel(pid, tid, d0, d1, d2, d3);
-
- /* otherwise, implement test functionality */
- if (d0 == 1) {
- void *cbuf = 0;
- rw_buf = sys_req_sharedmem(pid, rw_buf_size, &cbuf);
- sys_ipc_resp((long)cbuf, rw_buf_size, 0, 0);
- __builtin_unreachable();
-
- } else if (d0 == 2) {
- puts("Received string: ");
- puts(rw_buf);
- sys_ipc_resp(0, 0, 0, 0);
- __builtin_unreachable();
- }
-
- sys_ipc_resp(0, 0, 0, 0);
- __builtin_unreachable();
-}