aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/conf/init.c
blob: 4bd6a4e7e4aa7dc04d74ee70e340db99476e291f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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);
}