aboutsummaryrefslogtreecommitdiff
path: root/common/uapi/dispatch.c
blob: 30f29b37999f019a3f9d9ae9b942e6dc4c28b6e7 (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */

/**
 * @file dispatch.c
 * Syscall dispatch.
 */

#include <apos/canary.h>
#include <apos/debug.h>
#include <apos/uapi.h>

#include <arch/proc.h>

/** Syscall number to syscall handler conversion. */
static const sys_t syscall_table[] = {
	/* noop */
	[SYS_NOOP] = sys_noop,

	/* debugging */
	[SYS_PUTCH] = sys_putch,

	/* mem */
	[SYS_REQ_MEM] = sys_req_mem,
	[SYS_REQ_PMEM] = sys_req_pmem,
	[SYS_REQ_FIXMEM] = sys_req_fixmem,
	[SYS_FREE_MEM] = sys_free_mem,

	/* 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,

	/* ipc */
	[SYS_IPC_SERVER] = sys_ipc_server,
	[SYS_IPC_REQ] = sys_ipc_req,
	[SYS_IPC_FWD] = sys_ipc_fwd,
	[SYS_IPC_RESP] = sys_ipc_resp,
	[SYS_IPC_NOTIFY] = sys_ipc_notify,

	/* proc */
	[SYS_CREATE] = sys_create,
	[SYS_FORK] = sys_fork,
	[SYS_EXEC] = sys_exec,
	[SYS_SPAWN] = sys_spawn,
	[SYS_SWAP] = sys_swap,

	/* conf */
	[SYS_CONF_SET] = sys_conf_set,
	[SYS_CONF_GET] = sys_conf_get,

	[SYS_SET_CAP] = sys_set_cap,
	[SYS_GET_CAP] = sys_get_cap,
	[SYS_CLEAR_CAP] = sys_clear_cap,

	[SYS_POWEROFF] = sys_poweroff,
};

/**
 * Noop syscall handler.
 *
 * @return \ref OK and \c 0.
 */
SYSCALL_DEFINE0(noop)(struct tcb *t)
{
	UNUSED(t);
	info("sys_noop\n");
	return SYS_RET1(OK);
}

/**
 * Putch syscall handler.
 *
 * @param a Character to put.
 * @return \ref OK and 0.
 */
SYSCALL_DEFINE1(putch)(struct tcb *t, sys_arg_t a)
{
	UNUSED(t);

	const char c[2] = {a, 0};
	MAYBE_UNUSED(c);
	dbg((const char *)&c);
	return SYS_RET1(OK);
}

struct sys_ret handle_syscall(struct tcb *t,
		sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
		sys_arg_t c, sys_arg_t d, sys_arg_t e)
{
	adjust_syscall(t);

	struct sys_ret r;
	switch (syscall) {
	case SYS_NOOP: r = sys_noop(t, a, b, c, d, e); break;
	case SYS_PUTCH: r = sys_putch(t, a, b, c, d, e); break;
	case SYS_REQ_MEM: r = sys_req_mem(t, a, b, c, d, e); break;
	case SYS_REQ_PMEM: r = sys_req_pmem(t, a, b, c, d, e); break;
	case SYS_REQ_FIXMEM: r = sys_req_fixmem(t, a, b, c, d, e); break;
	case SYS_FREE_MEM: r = sys_free_mem(t, a, b, c, d, e); break;
	case SYS_TIMEBASE: r = sys_timebase(t, a, b, c, d, e); break;
	case SYS_TICKS: r = sys_ticks(t, a, b, c, d, e); break;
	case SYS_REQ_REL_TIMER: r = sys_req_rel_timer(t, a, b, c, d, e); break;
	case SYS_REQ_ABS_TIMER: r = sys_req_abs_timer(t, a, b, c, d, e); break;
	case SYS_IPC_SERVER: r = sys_ipc_server(t, a, b, c, d, e); break;
	case SYS_IPC_REQ: r = sys_ipc_req(t, a, b, c, d, e); break;
	case SYS_IPC_FWD: r = sys_ipc_fwd(t, a, b, c, d, e); break;
	case SYS_IPC_RESP: r = sys_ipc_resp(t, a, b, c, d, e); break;
	case SYS_IPC_NOTIFY: r = sys_ipc_notify(t, a, b, c, d, e); break;
	case SYS_CREATE: r = sys_create(t, a, b, c, d, e); break;
	case SYS_FORK: r = sys_fork(t, a, b, c, d, e); break;
	case SYS_EXEC: r = sys_exec(t, a, b, c, d, e); break;
	case SYS_SPAWN: r = sys_spawn(t, a, b, c, d, e); break;
	case SYS_KILL: r = sys_kill(t, a, b, c, d, e); break;
	case SYS_SWAP: r = sys_swap(t, a, b, c, d, e); break;
	case SYS_CONF_SET: r = sys_conf_set(t, a, b, c, d, e); break;
	case SYS_CONF_GET: r = sys_conf_get(t, a, b, c, d, e); break;
	case SYS_SET_CAP: r = sys_set_cap(t, a, b, c, d, e); break;
	case SYS_GET_CAP: r = sys_get_cap(t, a, b, c, d, e); break;
	case SYS_CLEAR_CAP: r = sys_clear_cap(t, a, b, c, d, e); break;
	case SYS_POWEROFF: r = sys_poweroff(t, a, b, c, d, e); break;
	default:
			   error("Syscall %zu outside allowed range [0 - %i]\n", syscall,
					   SYS_NUM - 1);
			   r = SYS_RET1(ERR_INVAL);
	};

	if (check_canary(t)) {
		bug("Syscall %zu overwrote stack canary\n", syscall);
	}

	return r;
}