5516845cac483ecf52d4e56e9ffcf7d47f1a5266
[akaros.git] / user / parlib / src / syscall.c
1 // System call stubs.
2 #ifdef __DEPUTY__
3 #pragma nodeputy
4 #endif
5
6 #include <arch/x86.h>
7 #include <parlib.h>
8
9 // TODO: modify to take only four parameters
10 static intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
11                                  intreg_t a2, intreg_t a3,
12                                  intreg_t a4, intreg_t a5)
13 {
14         intreg_t ret;
15         asm volatile(
16             "pushl %%ebp\n\t"
17             "pushl %%esi\n\t"
18             "movl %%esp, %%ebp\n\t"
19             "leal after_sysenter, %%esi\n\t"
20             "sysenter\n\t"
21             "after_sysenter:\n\t"
22             "\tpopl %%esi\n"
23             "\tpopl %%ebp\n"
24             :"=a" (ret)
25             : "a" (num),
26               "d" (a1),
27               "c" (a2),
28               "b" (a3),
29               "D" (a4)
30             : "cc", "memory", "%esp");
31         return ret;
32 }
33
34 static intreg_t syscall_trap(uint16_t num, intreg_t a1,
35                              intreg_t a2, intreg_t a3,
36                              intreg_t a4, intreg_t a5)
37 {
38         intreg_t ret;
39         
40         // Generic system call: pass system call number in AX,
41         // up to five parameters in DX, CX, BX, DI, SI.
42         // Interrupt kernel with T_SYSCALL.
43         //
44         // The "volatile" tells the assembler not to optimize
45         // this instruction away just because we don't use the
46         // return value.
47         //
48         // The last clause tells the assembler that this can
49         // potentially change the condition codes and arbitrary
50         // memory locations.
51
52         asm volatile("int %1\n"
53                 : "=a" (ret)
54                 : "i" (T_SYSCALL),
55                   "a" (num),
56                   "d" (a1),
57                   "c" (a2),
58                   "b" (a3),
59                   "D" (a4),
60                   "S" (a5)
61                 : "cc", "memory");
62
63         return ret;
64 }
65
66 static intreg_t syscall(uint16_t num, intreg_t a1,
67                         intreg_t a2, intreg_t a3,
68                         intreg_t a4, intreg_t a5)
69 {
70         #ifndef SYSCALL_TRAP
71                 return syscall_sysenter(num, a1, a2, a3, a4, a5);
72         #else
73                 return syscall_trap(num, a1, a2, a3, a4, a5);
74         #endif
75 }
76
77 void sys_env_destroy(envid_t envid)
78 {
79         syscall(SYS_env_destroy, envid, 0, 0, 0, 0);
80         while(1); //Should never get here...
81 }
82
83 envid_t sys_getenvid(void)
84 {
85          return syscall(SYS_getenvid, 0, 0, 0, 0, 0);
86 }
87
88 envid_t sys_getcpuid(void)
89 {
90          return syscall(SYS_getcpuid, 0, 0, 0, 0, 0);
91 }
92
93 ssize_t sys_cputs(const uint8_t *s, size_t len)
94 {
95     return syscall(SYS_cputs, (intreg_t) s,  len, 0, 0, 0);
96 }
97
98 uint16_t sys_cgetc(void)
99 {
100     return syscall(SYS_cgetc, 0, 0, 0, 0, 0);
101 }
102
103 //Write a buffer over the serial port
104 ssize_t sys_serial_write(void* buf, size_t len) 
105 {
106         return syscall(SYS_serial_write, (intreg_t)buf, len, 0, 0, 0);
107 }
108
109 //Read a buffer over the serial port
110 ssize_t sys_serial_read(void* buf, size_t len) 
111 {
112         return syscall(SYS_serial_read, (intreg_t)buf, len, 0, 0, 0);
113 }
114
115 //Write a buffer over ethernet
116 ssize_t sys_eth_write(void* buf, size_t len) 
117 {
118         return syscall(SYS_eth_write, (intreg_t)buf, len, 0, 0, 0);
119 }
120
121 //Read a buffer via ethernet
122 ssize_t sys_eth_read(void* buf, size_t len) 
123 {
124         return syscall(SYS_eth_read, (intreg_t)buf, len, 0, 0, 0);
125 }