xref: /openbsd/sys/arch/riscv64/riscv64/syscall.c (revision 82f13a27)
1 /*	$OpenBSD: syscall.c,v 1.19 2024/01/11 19:16:27 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 2020 Brian Bamsch <bbamsch@google.com>
5  * Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/proc.h>
22 #include <sys/user.h>
23 #include <sys/syscall.h>
24 #include <sys/syscall_mi.h>
25 
26 #include <uvm/uvm_extern.h>
27 
28 #include <machine/syscall.h>
29 
30 static __inline struct trapframe *
process_frame(struct proc * p)31 process_frame(struct proc *p)
32 {
33 	return p->p_addr->u_pcb.pcb_tf;
34 }
35 
36 void
svc_handler(trapframe_t * frame)37 svc_handler(trapframe_t *frame)
38 {
39 	struct proc *p = curproc;
40 	const struct sysent *callp = sysent;
41 	int code, error = ENOSYS;
42 	register_t *args, rval[2];
43 
44 	uvmexp.syscalls++;
45 
46 	code = frame->tf_t[0];
47 	if (code <= 0 || code >= SYS_MAXSYSCALL)
48 		goto bad;
49 
50 	callp += code;
51 
52 	args = &frame->tf_a[0];
53 
54 	rval[0] = 0;
55 	rval[1] = 0;
56 
57 	error = mi_syscall(p, code, callp, args, rval);
58 
59 	switch (error) {
60 	case 0:
61 		frame->tf_a[0] = rval[0];
62 		frame->tf_t[0] = 0;		/* syscall succeeded */
63 		break;
64 	case ERESTART:
65 		frame->tf_sepc -= 4;		/* prev instruction */
66 		break;
67 	case EJUSTRETURN:
68 		break;
69 	default:
70 	bad:
71 		frame->tf_a[0] = error;
72 		frame->tf_t[0] = 1;		/* syscall error */
73 		break;
74 	}
75 
76 	mi_syscall_return(p, code, error, rval);
77 }
78 
79 void
child_return(void * arg)80 child_return(void *arg)
81 {
82 	struct proc *p = arg;
83 	struct trapframe *frame = process_frame(p);
84 
85 	frame->tf_a[0] = 0;
86 	frame->tf_t[0] = 0;			/* no error */
87 
88 	KERNEL_UNLOCK();
89 
90 	mi_child_return(p);
91 }
92