-
Notifications
You must be signed in to change notification settings - Fork 0
/
syscall.c
132 lines (112 loc) · 3.37 KB
/
syscall.c
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
#include <types.h>
#include <kern/errno.h>
#include <lib.h>
#include <machine/pcb.h>
#include <machine/spl.h>
#include <machine/trapframe.h>
#include <kern/callno.h>
#include <syscall.h>
/*
* System call handler.
*
* A pointer to the trapframe created during exception entry (in
* exception.S) is passed in.
*
* The calling conventions for syscalls are as follows: Like ordinary
* function calls, the first 4 32-bit arguments are passed in the 4
* argument registers a0-a3. In addition, the system call number is
* passed in the v0 register.
*
* On successful return, the return value is passed back in the v0
* register, like an ordinary function call, and the a3 register is
* also set to 0 to indicate success.
*
* On an error return, the error code is passed back in the v0
* register, and the a3 register is set to 1 to indicate failure.
* (Userlevel code takes care of storing the error code in errno and
* returning the value -1 from the actual userlevel syscall function.
* See src/lib/libc/syscalls.S and related files.)
*
* Upon syscall return the program counter stored in the trapframe
* must be incremented by one instruction; otherwise the exception
* return code will restart the "syscall" instruction and the system
* call will repeat forever.
*
* Since none of the OS/161 system calls have more than 4 arguments,
* there should be no need to fetch additional arguments from the
* user-level stack.
*
* Watch out: if you make system calls that have 64-bit quantities as
* arguments, they will get passed in pairs of registers, and not
* necessarily in the way you expect. We recommend you don't do it.
* (In fact, we recommend you don't use 64-bit quantities at all. See
* arch/mips/include/types.h.)
*/
void
mips_syscall(struct trapframe *tf)
{
int callno;
int32_t retval;
int err;
assert(curspl==0);
callno = tf->tf_v0;
/*
* Initialize retval to 0. Many of the system calls don't
* really return a value, just 0 for success and -1 on
* error. Since retval is the value returned on success,
* initialize it to 0 by default; thus it's not necessary to
* deal with it except for calls that return other values,
* like write.
*/
retval = 0;
switch (callno) {
case SYS_reboot:
err = sys_reboot(tf->tf_a0);
break;
case SYS_read:
retval = sys_read(tf->tf_a0, (char *)tf->tf_a1, tf->tf_a2);
err = (retval < 0 ? retval : 0);
break;
case SYS_write:
retval = sys_write(tf->tf_a0, (char *)tf->tf_a1, tf->tf_a2);
err = (retval < 0 ? retval : 0);
break;
/* Add stuff here */
default:
kprintf("Unknown syscall %d\n", callno);
err = ENOSYS;
break;
}
if (err) {
/*
* Return the error code. This gets converted at
* userlevel to a return value of -1 and the error
* code in errno.
*/
tf->tf_v0 = err;
tf->tf_a3 = 1; /* signal an error */
}
else {
/* Success. */
tf->tf_v0 = retval;
tf->tf_a3 = 0; /* signal no error */
}
/*
* Now, advance the program counter, to avoid restarting
* the syscall over and over again.
*/
tf->tf_epc += 4;
/* Make sure the syscall code didn't forget to lower spl */
assert(curspl==0);
}
void
md_forkentry(struct trapframe *tf)
{
/*
* This function is provided as a reminder. You need to write
* both it and the code that calls it.
*
* Thus, you can trash it and do things another way if you prefer.
*/
(void)tf;
}