RISC-V port mostly links now
[akaros.git] / kern / arch / riscv / env.c
1 #include <arch/trap.h>
2 #include <env.h>
3 #include <assert.h>
4 #include <arch/arch.h>
5 #include <pmap.h>
6
7 void
8 env_push_ancillary_state(env_t* e)
9 {
10         if(e->env_tf.sr & SR_EF)
11                 save_fp_state(&e->env_ancillary_state);
12 }
13
14 void
15 save_fp_state(ancillary_state_t* silly)
16 {
17         uintptr_t sr = mfpcr(PCR_SR);
18         mtpcr(PCR_SR, sr | SR_EF);
19
20         asm("mffsr %0" : "=r"(silly->fsr));
21
22         asm("fsd $f0,%0" : "=m"(silly->fpr[0]));
23         asm("fsd $f1,%0" : "=m"(silly->fpr[1]));
24         asm("fsd $f2,%0" : "=m"(silly->fpr[2]));
25         asm("fsd $f3,%0" : "=m"(silly->fpr[3]));
26         asm("fsd $f4,%0" : "=m"(silly->fpr[4]));
27         asm("fsd $f5,%0" : "=m"(silly->fpr[5]));
28         asm("fsd $f6,%0" : "=m"(silly->fpr[6]));
29         asm("fsd $f7,%0" : "=m"(silly->fpr[7]));
30         asm("fsd $f8,%0" : "=m"(silly->fpr[8]));
31         asm("fsd $f9,%0" : "=m"(silly->fpr[9]));
32         asm("fsd $f10,%0" : "=m"(silly->fpr[10]));
33         asm("fsd $f11,%0" : "=m"(silly->fpr[11]));
34         asm("fsd $f12,%0" : "=m"(silly->fpr[12]));
35         asm("fsd $f13,%0" : "=m"(silly->fpr[13]));
36         asm("fsd $f14,%0" : "=m"(silly->fpr[14]));
37         asm("fsd $f15,%0" : "=m"(silly->fpr[15]));
38         asm("fsd $f16,%0" : "=m"(silly->fpr[16]));
39         asm("fsd $f17,%0" : "=m"(silly->fpr[17]));
40         asm("fsd $f18,%0" : "=m"(silly->fpr[18]));
41         asm("fsd $f19,%0" : "=m"(silly->fpr[19]));
42         asm("fsd $f20,%0" : "=m"(silly->fpr[20]));
43         asm("fsd $f21,%0" : "=m"(silly->fpr[21]));
44         asm("fsd $f22,%0" : "=m"(silly->fpr[22]));
45         asm("fsd $f23,%0" : "=m"(silly->fpr[23]));
46         asm("fsd $f24,%0" : "=m"(silly->fpr[24]));
47         asm("fsd $f25,%0" : "=m"(silly->fpr[25]));
48         asm("fsd $f26,%0" : "=m"(silly->fpr[26]));
49         asm("fsd $f27,%0" : "=m"(silly->fpr[27]));
50         asm("fsd $f28,%0" : "=m"(silly->fpr[28]));
51         asm("fsd $f29,%0" : "=m"(silly->fpr[29]));
52         asm("fsd $f30,%0" : "=m"(silly->fpr[30]));
53         asm("fsd $f31,%0" : "=m"(silly->fpr[31]));
54
55         mtpcr(PCR_SR, sr);
56 }
57
58 void
59 env_pop_ancillary_state(env_t* e)
60
61         if(e->env_tf.sr & SR_EF)
62                 restore_fp_state(&e->env_ancillary_state);
63 }
64
65 void
66 restore_fp_state(ancillary_state_t* silly)
67 {
68         uintptr_t sr = mfpcr(PCR_SR);
69         mtpcr(PCR_SR, sr | SR_EF);
70
71         asm("mtfsr %0" : : "r"(silly->fsr));
72
73         asm("fld $f0,%0" : : "m"(silly->fpr[0]));
74         asm("fld $f1,%0" : : "m"(silly->fpr[1]));
75         asm("fld $f2,%0" : : "m"(silly->fpr[2]));
76         asm("fld $f3,%0" : : "m"(silly->fpr[3]));
77         asm("fld $f4,%0" : : "m"(silly->fpr[4]));
78         asm("fld $f5,%0" : : "m"(silly->fpr[5]));
79         asm("fld $f6,%0" : : "m"(silly->fpr[6]));
80         asm("fld $f7,%0" : : "m"(silly->fpr[7]));
81         asm("fld $f8,%0" : : "m"(silly->fpr[8]));
82         asm("fld $f9,%0" : : "m"(silly->fpr[9]));
83         asm("fld $f10,%0" : : "m"(silly->fpr[10]));
84         asm("fld $f11,%0" : : "m"(silly->fpr[11]));
85         asm("fld $f12,%0" : : "m"(silly->fpr[12]));
86         asm("fld $f13,%0" : : "m"(silly->fpr[13]));
87         asm("fld $f14,%0" : : "m"(silly->fpr[14]));
88         asm("fld $f15,%0" : : "m"(silly->fpr[15]));
89         asm("fld $f16,%0" : : "m"(silly->fpr[16]));
90         asm("fld $f17,%0" : : "m"(silly->fpr[17]));
91         asm("fld $f18,%0" : : "m"(silly->fpr[18]));
92         asm("fld $f19,%0" : : "m"(silly->fpr[19]));
93         asm("fld $f20,%0" : : "m"(silly->fpr[20]));
94         asm("fld $f21,%0" : : "m"(silly->fpr[21]));
95         asm("fld $f22,%0" : : "m"(silly->fpr[22]));
96         asm("fld $f23,%0" : : "m"(silly->fpr[23]));
97         asm("fld $f24,%0" : : "m"(silly->fpr[24]));
98         asm("fld $f25,%0" : : "m"(silly->fpr[25]));
99         asm("fld $f26,%0" : : "m"(silly->fpr[26]));
100         asm("fld $f27,%0" : : "m"(silly->fpr[27]));
101         asm("fld $f28,%0" : : "m"(silly->fpr[28]));
102         asm("fld $f29,%0" : : "m"(silly->fpr[29]));
103         asm("fld $f30,%0" : : "m"(silly->fpr[30]));
104         asm("fld $f31,%0" : : "m"(silly->fpr[31]));
105
106         mtpcr(PCR_SR, sr);
107 }
108
109 static int
110 user_mem_walk_recursive(env_t* e, uintptr_t start, size_t len,
111                         mem_walk_callback_t callback, void* arg,
112                         mem_walk_callback_t pt_callback, void* pt_arg,
113                                                                                                 pte_t* pt, int level)
114 {
115   int pgshift = L1PGSHIFT - level*(L1PGSHIFT-L2PGSHIFT);
116         uintptr_t pgsize = 1UL << pgshift;
117
118         uintptr_t start_idx = (start >> pgshift) & (NPTENTRIES-1);
119         uintptr_t end_idx = (ROUNDUP(start+len, pgsize) >> pgshift) & (NPTENTRIES-1);
120
121         for(uintptr_t idx = start_idx; idx < end_idx; idx++)
122         {
123                 int ret;
124                 uintptr_t pgaddr = ROUNDDOWN(start, pgsize) + idx*pgsize;
125                 pte_t* pte = &pt[idx];
126
127                 if(*pte & PTE_T)
128                 {
129                         assert(level < NPTLEVELS-1);
130                         if((ret = user_mem_walk_recursive(e, pgaddr, MIN(pgsize, start+len),
131                                                           callback, arg,
132                                                                                                                                                                 pt_callback, pt_arg,
133                                                                                                                                                                 KADDR(PTD_ADDR(*pte)), level+1)))
134                                 return ret;
135                         if(pt_callback != NULL && (ret = pt_callback(e, pte, (void*)pgaddr, arg)))
136                                 return ret;
137                 }
138                 else if(callback != NULL && !PAGE_UNMAPPED(*pte))
139                         if((ret = callback(e, pte, (void*)pgaddr, arg)))
140                                 return ret;
141         }
142
143         return 0;
144 }
145
146 int
147 env_user_mem_walk(env_t* e, void* start, size_t len,
148                   mem_walk_callback_t callback, void* arg)
149 {
150         return user_mem_walk_recursive(e, (uintptr_t)start, len, callback, arg,
151                                        NULL, NULL, e->env_pgdir, 0);
152 }
153
154 void
155 env_pagetable_free(env_t* e)
156 {
157         int pt_free(env_t* e, pte_t* pte, void* va, void* arg)
158         {
159                 page_decref(pa2page(PTD_ADDR(*pte)));
160                 return 0;
161         }
162
163         assert(user_mem_walk_recursive(e, 0, KERNBASE, NULL, NULL,
164                                        pt_free, NULL, e->env_pgdir, 0) == 0);
165 }