Memory protection and page fault handling
[akaros.git] / kern / syscall.c
1 /* See COPYRIGHT for copyright information. */
2
3 #include <inc/x86.h>
4 #include <inc/error.h>
5 #include <inc/string.h>
6 #include <inc/assert.h>
7
8 #include <kern/env.h>
9 #include <kern/pmap.h>
10 #include <kern/trap.h>
11 #include <kern/syscall.h>
12 #include <kern/console.h>
13
14 // Print a string to the system console.
15 // The string is exactly 'len' characters long.
16 // Destroys the environment on memory errors.
17 static void
18 sys_cputs(const char *s, size_t len)
19 {
20         // Check that the user has permission to read memory [s, s+len).
21         // Destroy the environment if not.
22         user_mem_assert(curenv, s, len, PTE_U);
23
24         // Print the string supplied by the user.
25         cprintf("%.*s", len, s);
26 }
27
28 // Read a character from the system console.
29 // Returns the character.
30 static int
31 sys_cgetc(void)
32 {
33         int c;
34
35         // The cons_getc() primitive doesn't wait for a character,
36         // but the sys_cgetc() system call does.
37         while ((c = cons_getc()) == 0)
38                 /* do nothing */;
39
40         return c;
41 }
42
43 // Returns the current environment's envid.
44 static envid_t
45 sys_getenvid(void)
46 {
47         return curenv->env_id;
48 }
49
50 // Destroy a given environment (possibly the currently running environment).
51 //
52 // Returns 0 on success, < 0 on error.  Errors are:
53 //      -E_BAD_ENV if environment envid doesn't currently exist,
54 //              or the caller doesn't have permission to change envid.
55 static int
56 sys_env_destroy(envid_t envid)
57 {
58         int r;
59         struct Env *e;
60
61         if ((r = envid2env(envid, &e, 1)) < 0)
62                 return r;
63         if (e == curenv)
64                 cprintf("[%08x] exiting gracefully\n", curenv->env_id);
65         else
66                 cprintf("[%08x] destroying %08x\n", curenv->env_id, e->env_id);
67         env_destroy(e);
68         return 0;
69 }
70
71
72
73 // Dispatches to the correct kernel function, passing the arguments.
74 uint32_t
75 syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
76 {
77         // Call the function corresponding to the 'syscallno' parameter.
78         // Return any appropriate return value.
79
80         //cprintf("Incoming syscall number: %d\n    a1: %x\n    a2: %x\n    a3: %x\n    a4: %x\n    a5: %x\n", syscallno, a1, a2, a3, a4, a5);
81
82         if (syscallno >= NSYSCALLS)
83                 return -E_INVAL;
84         
85         switch (syscallno) {
86                 case 0:
87                         sys_cputs((void*)a1, a2);
88                         return 0;
89                 case 1:
90                         return sys_cgetc();
91                 case 2:
92                         return sys_getenvid();
93                 case 3:
94                         return sys_env_destroy((envid_t)a1);
95                 default:
96                         panic("invalid syscall number!");
97         }
98         return 0xdeadbeef;
99 }
100