Added mprotect; made mmap work (dumbly) for files
[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, uint32_t translate_args)
17 {
18         // really, we just want to pin pages, but irqdisable works
19         static spinlock_t lock = SPINLOCK_INITIALIZER;
20         spin_lock_irqsave(&lock);
21
22         uint32_t arg[3] = {arg0,arg1,arg2};
23         for(int i = 0; i < 3; i++)
24         {
25                 int flags = (translate_args & (1 << (i+3))) ? PTE_USER_RW :
26                            ((translate_args & (1 << i)) ? PTE_USER_RO : 0);
27                 if(flags)
28                 {
29                         pte_t* pte = pgdir_walk(p->env_pgdir,(void*)arg[i],0);
30                         if(pte == NULL || !(*pte & flags))
31                         {
32                                 spin_unlock_irqsave(&lock);
33                                 return -1;
34                         }
35                         arg[i] = PTE_ADDR(*pte) | PGOFF(arg[i]);
36                 }
37         }
38
39         int32_t errno;
40         int32_t ret = frontend_syscall(p->pid,syscall_num,arg[0],arg[1],arg[2],0,&errno);
41         set_errno(current_tf,errno);
42
43         spin_unlock_irqsave(&lock);
44         return ret;
45 }
46
47 int32_t frontend_syscall(pid_t pid, int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, int32_t* errno)
48 {
49         static spinlock_t lock = SPINLOCK_INITIALIZER;
50         int32_t ret;
51
52         // only one frontend request at a time.
53         // interrupts could try to do frontend requests,
54         // which would deadlock, so disable them
55         spin_lock_irqsave(&lock);
56
57         // write syscall into magic memory
58         magic_mem[7] = 0;
59         magic_mem[1] = syscall_num;
60         magic_mem[2] = arg0;
61         magic_mem[3] = arg1;
62         magic_mem[4] = arg2;
63         magic_mem[5] = arg3;
64         magic_mem[6] = pid;
65         magic_mem[0] = 0x80;
66
67         // wait for front-end response
68         while(magic_mem[7] == 0)
69                 ;
70
71         ret = magic_mem[1];
72         *errno = magic_mem[2];
73
74         spin_unlock_irqsave(&lock);
75
76         return ret;
77 }
78
79 int32_t sys_nbputch(char ch)
80 {
81         static spinlock_t putch_lock = SPINLOCK_INITIALIZER;
82         spin_lock_irqsave(&putch_lock);
83
84         int ret = -1;
85         if(magic_mem[8] == 0)
86         {
87                 magic_mem[8] = (unsigned int)(unsigned char)ch;
88                 ret = 0;
89         }
90
91         spin_unlock_irqsave(&putch_lock);
92         return ret;
93 }
94
95 int32_t sys_nbgetch()
96 {
97         static spinlock_t getch_lock = SPINLOCK_INITIALIZER;
98         spin_lock_irqsave(&getch_lock);
99
100         int result = -1;
101         if(magic_mem[9]) 
102         {
103                 result = magic_mem[9];
104                 magic_mem[9] = 0;
105         }
106
107         spin_unlock_irqsave(&getch_lock);
108         return result;
109 }
110
111 void __diediedie(trapframe_t* tf, uint32_t srcid, uint32_t code, uint32_t a1, uint32_t a2)
112 {
113         int32_t errno;
114         frontend_syscall(0,RAMP_SYSCALL_exit,(int)code,0,0,0,&errno);
115         while(1);
116 }
117
118 void appserver_die(int code)
119 {
120         int i;
121         for(i = 0; i < num_cpus; i++)
122                 if(i != core_id())
123                         while(send_active_message(i,(amr_t)&__diediedie,(void*)code,0,0));
124
125         // just in case.
126         __diediedie(0,0,code,0,0);
127 }