Added FPU emulation to SPARC port
[akaros.git] / kern / arch / sparc / frontend.c
1 #ifdef __SHARC__
2 #pragma nosharc
3 #endif
4
5 #ifdef __DEPUTY__
6 #pragma nodeputy
7 #endif
8
9 #include <atomic.h>
10 #include <pmap.h>
11 #include <arch/frontend.h>
12 #include <smp.h>
13
14 volatile int magic_mem[10];
15
16 int32_t frontend_syscall_from_user(env_t* p, int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2)
17 {
18         int32_t ret;
19         #define KBUFSIZE 1024
20         char buf[KBUFSIZE];
21
22         switch(syscall_num)
23         {
24                 case RAMP_SYSCALL_write:
25                         arg2 = arg2 > KBUFSIZE ? KBUFSIZE : arg2;
26                         if(memcpy_from_user(p,buf,(void*)arg1,arg2))
27                                 return -1;
28                         arg1 = PADDR((uint32_t)buf);
29
30                         extern spinlock_t output_lock;
31                         spin_lock(&output_lock);
32
33                         if(arg0 == 1 || arg0 == 2)
34                         {
35                                 int i;
36                                 for(i = 0; i < arg2; i++)
37                                         cputchar(buf[i]);
38                                 ret = arg2;
39                         }
40                         else
41                                 ret = frontend_syscall(syscall_num,arg0,arg1,arg2);
42
43                         spin_unlock(&output_lock);
44
45                         break;
46
47                 case RAMP_SYSCALL_open:
48                         if(memcpy_from_user(p,buf,(void*)arg0,KBUFSIZE))
49                                 return -1;
50                         arg0 = PADDR((uint32_t)buf);
51                         ret = frontend_syscall(syscall_num,arg0,arg1,arg2);
52                         break;
53
54                 case RAMP_SYSCALL_fstat:
55                         ret = frontend_syscall(syscall_num,arg0,PADDR((uint32_t)buf),arg2);
56                         if(memcpy_to_user(p,(void*)arg1,buf,64))
57                                 return -1;
58                         break;
59
60                 case RAMP_SYSCALL_read:
61                         arg2 = arg2 > KBUFSIZE ? KBUFSIZE : arg2;
62
63                         if(arg0 == 0)
64                         {
65                                 if(arg2 > 0)
66                                 {
67                                         int ch = getchar();
68                                         buf[0] = (char)ch;
69                                         ret = 1;
70                                 }
71                                 else
72                                         ret = 0;
73                         }
74                         else
75                                 ret = frontend_syscall(syscall_num,arg0,PADDR((uint32_t)buf),arg2);
76
77                         if(memcpy_to_user(p,(void*)arg1,buf,arg2))
78                                 return -1;
79                         break;
80
81                 case RAMP_SYSCALL_getch:
82                         return frontend_syscall(RAMP_SYSCALL_getch,0,0,0);
83
84                 case RAMP_SYSCALL_gettimeofday:
85                 {
86                         struct timeval
87                         {
88                                 size_t tv_sec;
89                                 size_t tv_usec;
90                         };
91
92                         static spinlock_t gettimeofday_lock = 0;
93                         static size_t t0 = 0;
94                         spin_lock(&gettimeofday_lock);
95
96                         if(!t0)
97                         {
98                                 volatile struct timeval tp;
99                                 ret = frontend_syscall(RAMP_SYSCALL_gettimeofday,(int)PADDR((uint32_t)&tp),0,0);
100                                 if(ret == 0)
101                                         t0 = tp.tv_sec;
102                         }
103                         else ret = 0;
104
105                         spin_unlock(&gettimeofday_lock);
106
107                         if(ret == 0)
108                         {
109                                 struct timeval tp;
110                                 long long dt = read_tsc();
111                                 tp.tv_sec = t0 + dt/system_timing.tsc_freq;
112                                 tp.tv_usec = (dt % system_timing.tsc_freq)*1000000/system_timing.tsc_freq;
113
114                                 ret = memcpy_to_user(p,(void*)arg0,&tp,sizeof(tp));
115                         }
116                 }
117                 default:
118                         ret = -1;
119                         break;
120         }
121
122         return ret;
123 }
124
125 int32_t frontend_syscall(int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2)
126 {
127         static spinlock_t lock = 0;
128         int32_t ret;
129
130         // only one frontend request at a time.
131         // interrupts could try to do frontend requests,
132         // which would deadlock, so disable them
133         spin_lock_irqsave(&lock);
134
135         // write syscall into magic memory
136         magic_mem[7] = 0;
137         magic_mem[1] = syscall_num;
138         magic_mem[2] = arg0;
139         magic_mem[3] = arg1;
140         magic_mem[4] = arg2;
141         magic_mem[0] = 0x80;
142
143         // wait for front-end response
144         while(magic_mem[7] == 0)
145                 ;
146
147         ret = magic_mem[1];
148
149         spin_unlock_irqsave(&lock);
150
151         return ret;
152 }
153
154 int32_t sys_nbputch(char ch)
155 {
156         static spinlock_t putch_lock = 0;
157         spin_lock_irqsave(&putch_lock);
158
159         int ret = -1;
160         if(magic_mem[8] == 0)
161         {
162                 magic_mem[8] = (unsigned int)(unsigned char)ch;
163                 ret = 0;
164         }
165
166         spin_unlock_irqsave(&putch_lock);
167         return ret;
168 }
169
170 int32_t sys_nbgetch()
171 {
172         static spinlock_t getch_lock = 0;
173         spin_lock_irqsave(&getch_lock);
174
175         int result = -1;
176         if(magic_mem[9]) 
177         {
178                 result = magic_mem[9];
179                 magic_mem[9] = 0;
180         }
181
182         spin_unlock_irqsave(&getch_lock);
183         return result;
184 }
185
186 void __diediedie(trapframe_t* tf, uint32_t srcid, uint32_t code, uint32_t a1, uint32_t a2)
187 {
188         frontend_syscall(RAMP_SYSCALL_exit,(int)code,0,0);
189         while(1);
190 }
191
192 void appserver_die(int code)
193 {
194         int i;
195         for(i = 0; i < num_cpus; i++)
196                 if(i != core_id())
197                         while(send_active_message(i,(amr_t)&__diediedie,(void*)code,0,0));
198
199         // just in case.
200         __diediedie(0,0,code,0,0);
201 }