Diff markup
001 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 #include <sos/physmem.h> 018 #include <sos/physmem.h>
019 #include <sos/klibc.h> 019 #include <sos/klibc.h>
020 #include <sos/assert.h> 020 #include <sos/assert.h>
021 021
022 #include "mm_context.h" <<
023 <<
024 #include "paging.h" 022 #include "paging.h"
025 023
026 <<
027 <<
028 <<
029 <<
030 <<
031 <<
032 <<
033 <<
034 <<
035 <<
036 <<
037 <<
038 <<
039 <<
040 <<
041 <<
042 <<
043 <<
044 <<
045 024
046 025
047 struct x86_pde 026 struct x86_pde
048 { 027 {
049 sos_ui32_t present :1; 028 sos_ui32_t present :1;
050 sos_ui32_t write :1; 029 sos_ui32_t write :1;
051 sos_ui32_t user :1; 030 sos_ui32_t user :1;
052 sos_ui32_t write_through :1; 031 sos_ui32_t write_through :1;
053 sos_ui32_t cache_disabled :1; 032 sos_ui32_t cache_disabled :1;
054 sos_ui32_t accessed :1; 033 sos_ui32_t accessed :1;
055 sos_ui32_t zero :1; 034 sos_ui32_t zero :1;
056 sos_ui32_t page_size :1; 035 sos_ui32_t page_size :1;
057 sos_ui32_t global_page :1; 036 sos_ui32_t global_page :1;
058 sos_ui32_t custom :3; 037 sos_ui32_t custom :3;
059 sos_ui32_t pt_paddr :20; 038 sos_ui32_t pt_paddr :20;
060 } __attribute__ ((packed)); 039 } __attribute__ ((packed));
061 040
062 041
063 <<
064 typedef union { <<
065 struct x86_pde pde; <<
066 sos_ui32_t ui32; <<
067 } x86_pde_val_t; <<
068 <<
069 <<
070 042
071 043
072 struct x86_pte 044 struct x86_pte
073 { 045 {
074 sos_ui32_t present :1; 046 sos_ui32_t present :1;
075 sos_ui32_t write :1; 047 sos_ui32_t write :1;
076 sos_ui32_t user :1; 048 sos_ui32_t user :1;
077 sos_ui32_t write_through :1; 049 sos_ui32_t write_through :1;
078 sos_ui32_t cache_disabled :1; 050 sos_ui32_t cache_disabled :1;
079 sos_ui32_t accessed :1; 051 sos_ui32_t accessed :1;
080 sos_ui32_t dirty :1; 052 sos_ui32_t dirty :1;
081 sos_ui32_t zero :1; 053 sos_ui32_t zero :1;
082 sos_ui32_t global_page :1; 054 sos_ui32_t global_page :1;
083 055
084 sos_ui32_t custom :3; 056 sos_ui32_t custom :3;
085 sos_ui32_t paddr :20; 057 sos_ui32_t paddr :20;
086 } __attribute__ ((packed)); 058 } __attribute__ ((packed));
087 059
088 060
089 <<
090 typedef union { <<
091 struct x86_pte pte; <<
092 sos_ui32_t ui32; <<
093 } x86_pte_val_t; <<
094 <<
095 <<
096 061
097 062
098 struct x86_pdbr 063 struct x86_pdbr
099 { 064 {
100 sos_ui32_t zero1 :3; 065 sos_ui32_t zero1 :3;
101 sos_ui32_t write_through :1; 066 sos_ui32_t write_through :1;
102 sos_ui32_t cache_disabled :1; 067 sos_ui32_t cache_disabled :1;
103 sos_ui32_t zero2 :7; 068 sos_ui32_t zero2 :7;
104 sos_ui32_t pd_paddr :20; 069 sos_ui32_t pd_paddr :20;
105 } __attribute__ ((packed)); 070 } __attribute__ ((packed));
106 071
107 072
108 073
109 074
110 075
111 076
112 077
113 #define invlpg(vaddr) \ 078 #define invlpg(vaddr) \
114 do { \ 079 do { \
115 __asm__ __volatile__("invlpg %0"::"m"(* 080 __asm__ __volatile__("invlpg %0"::"m"(*((unsigned *)(vaddr)))); \
116 } while(0) 081 } while(0)
117 082
118 083
119 084
120 085
121 086
122 087
123 #define flush_tlb() \ 088 #define flush_tlb() \
124 do { \ 089 do { \
125 unsigned long tmpreg; \ 090 unsigned long tmpreg; \
126 asm volatile("movl %%cr3,%0\n\tmovl %0 091 asm volatile("movl %%cr3,%0\n\tmovl %0,%%cr3" :"=r" \
127 (tmpreg) : :"memory"); \ 092 (tmpreg) : :"memory"); \
128 } while (0) 093 } while (0)
129 094
130 095
131 096
132 097
133 098
134 099
135 #define virt_to_pd_index(vaddr) \ 100 #define virt_to_pd_index(vaddr) \
136 (((unsigned)(vaddr)) >> 22) 101 (((unsigned)(vaddr)) >> 22)
137 102
138 103
139 104
140 105
141 106
142 107
143 #define virt_to_pt_index(vaddr) \ 108 #define virt_to_pt_index(vaddr) \
144 ( (((unsigned)(vaddr)) >> 12) & 0x3ff ) 109 ( (((unsigned)(vaddr)) >> 12) & 0x3ff )
145 110
146 111
147 112
148 113
149 114
150 115
151 #define virt_to_page_offset(vaddr) \ 116 #define virt_to_page_offset(vaddr) \
152 (((unsigned)(vaddr)) & SOS_PAGE_MASK) 117 (((unsigned)(vaddr)) & SOS_PAGE_MASK)
153 118
154 119
155 120
156 121
157 122
158 123
159 124
160 static sos_ret_t paging_setup_map_helper(struc 125 static sos_ret_t paging_setup_map_helper(struct x86_pde * pd,
161 sos_p 126 sos_paddr_t ppage,
162 sos_v 127 sos_vaddr_t vaddr)
163 { 128 {
164 129
165 130
166 unsigned index_in_pd = virt_to_pd_index(vadd 131 unsigned index_in_pd = virt_to_pd_index(vaddr);
167 unsigned index_in_pt = virt_to_pt_index(vadd 132 unsigned index_in_pt = virt_to_pt_index(vaddr);
168 133
169 134
170 struct x86_pte * pt; 135 struct x86_pte * pt;
171 if (pd[index_in_pd].present) 136 if (pd[index_in_pd].present)
172 { 137 {
173 pt = (struct x86_pte*) (pd[index_in_pd]. 138 pt = (struct x86_pte*) (pd[index_in_pd].pt_paddr << 12);
174 139
175 !! 140
176 !! 141
177 !! 142
178 !! 143
179 if (pt[index_in_pt].present) !! 144
>> 145
>> 146 if (! pt[index_in_pt].present)
>> 147 sos_physmem_ref_physpage_at((sos_paddr_t)pt);
>> 148
>> 149
>> 150 else
180 SOS_ASSERT_FATAL(FALSE); 151 SOS_ASSERT_FATAL(FALSE);
181 } 152 }
182 else 153 else
183 { 154 {
184 155
185 pt = (struct x86_pte*) sos_physmem_ref_p 156 pt = (struct x86_pte*) sos_physmem_ref_physpage_new(FALSE);
186 if (! pt) 157 if (! pt)
187 return -SOS_ENOMEM; 158 return -SOS_ENOMEM;
188 159
189 memset((void*)pt, 0x0, SOS_PAGE_SIZE); 160 memset((void*)pt, 0x0, SOS_PAGE_SIZE);
190 161
191 pd[index_in_pd].present = TRUE; 162 pd[index_in_pd].present = TRUE;
192 pd[index_in_pd].write = 1; 163 pd[index_in_pd].write = 1;
193 164
194 165
195 166
196 167
197 pd[index_in_pd].pt_paddr = ((sos_paddr_t 168 pd[index_in_pd].pt_paddr = ((sos_paddr_t)pt) >> 12;
198 } 169 }
199 170
200 171
201 172
202 pt[index_in_pt].present = 1; 173 pt[index_in_pt].present = 1;
203 pt[index_in_pt].write = 1; 174 pt[index_in_pt].write = 1;
204 175
205 176
206 177
207 pt[index_in_pt].user = 0; 178 pt[index_in_pt].user = 0;
208 pt[index_in_pt].paddr = ppage >> 12; 179 pt[index_in_pt].paddr = ppage >> 12;
209 180
210 <<
211 <<
212 sos_physmem_inc_physpage_occupation((sos_pad <<
213 <<
214 return SOS_OK; 181 return SOS_OK;
215 } 182 }
216 183
217 184
218 sos_ret_t sos_paging_subsystem_setup(sos_paddr 185 sos_ret_t sos_paging_subsystem_setup(sos_paddr_t identity_mapping_base,
219 sos_paddr 186 sos_paddr_t identity_mapping_top)
220 { 187 {
221 188
222 struct x86_pdbr cr3; 189 struct x86_pdbr cr3;
223 190
224 191
225 struct x86_pde * pd 192 struct x86_pde * pd
226 = (struct x86_pde*) sos_physmem_ref_physpa 193 = (struct x86_pde*) sos_physmem_ref_physpage_new(FALSE);
227 194
228 195
229 sos_paddr_t paddr; 196 sos_paddr_t paddr;
230 197
231 198
232 199
233 memset((void*)pd, 200 memset((void*)pd,
234 0x0, 201 0x0,
235 SOS_PAGE_SIZE); 202 SOS_PAGE_SIZE);
236 203
237 204
238 for (paddr = identity_mapping_base ; 205 for (paddr = identity_mapping_base ;
239 paddr < identity_mapping_top ; 206 paddr < identity_mapping_top ;
240 paddr += SOS_PAGE_SIZE) 207 paddr += SOS_PAGE_SIZE)
241 { 208 {
242 if (paging_setup_map_helper(pd, paddr, p 209 if (paging_setup_map_helper(pd, paddr, paddr))
243 return -SOS_ENOMEM; 210 return -SOS_ENOMEM;
244 } 211 }
245 212
246 213
247 for (paddr = BIOS_N_VIDEO_START ; 214 for (paddr = BIOS_N_VIDEO_START ;
248 paddr < BIOS_N_VIDEO_END ; 215 paddr < BIOS_N_VIDEO_END ;
249 paddr += SOS_PAGE_SIZE) 216 paddr += SOS_PAGE_SIZE)
250 { 217 {
251 if (paging_setup_map_helper(pd, paddr, p 218 if (paging_setup_map_helper(pd, paddr, paddr))
252 return -SOS_ENOMEM; 219 return -SOS_ENOMEM;
253 } 220 }
254 221
255 222
256 223
257 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 224 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].present = TRUE;
258 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 225 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].write = 1;
259 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 226 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].user = 0;
260 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 227 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].pt_paddr
261 = ((sos_paddr_t)pd)>>12; 228 = ((sos_paddr_t)pd)>>12;
262 229
263 230
264 231
265 memset(& cr3, 0x0, sizeof(struct x86_pdbr)); 232 memset(& cr3, 0x0, sizeof(struct x86_pdbr));
266 cr3.pd_paddr = ((sos_paddr_t)pd) >> 12; 233 cr3.pd_paddr = ((sos_paddr_t)pd) >> 12;
267 234
268 235
269 236
270 237
271 asm volatile ("movl %0,%%cr3\n\t" 238 asm volatile ("movl %0,%%cr3\n\t"
272 "movl %%cr0,%%eax\n\t" 239 "movl %%cr0,%%eax\n\t"
273 "orl $0x80010000, %%eax\n\t" 240 "orl $0x80010000, %%eax\n\t"
274 "movl %%eax,%%cr0\n\t" 241 "movl %%eax,%%cr0\n\t"
275 "jmp 1f\n\t" 242 "jmp 1f\n\t"
276 "1:\n\t" 243 "1:\n\t"
277 "movl $2f, %%eax\n\t" 244 "movl $2f, %%eax\n\t"
278 "jmp *%%eax\n\t" 245 "jmp *%%eax\n\t"
279 "2:\n\t" ::"r"(cr3):"memory"," 246 "2:\n\t" ::"r"(cr3):"memory","eax");
280 247
281 248
282 249
283 250
284 251
285 252
286 253
287 254
288 255
289 return SOS_OK; 256 return SOS_OK;
290 } 257 }
291 258
292 259
293 260
294 261
295 sos_ret_t sos_paging_map(sos_paddr_t ppage_pad 262 sos_ret_t sos_paging_map(sos_paddr_t ppage_paddr,
296 sos_vaddr_t vpage_vad 263 sos_vaddr_t vpage_vaddr,
297 sos_bool_t is_user_pa 264 sos_bool_t is_user_page,
298 sos_ui32_t flags) 265 sos_ui32_t flags)
299 { 266 {
300 267
301 268
302 unsigned index_in_pd = virt_to_pd_index(vpag 269 unsigned index_in_pd = virt_to_pd_index(vpage_vaddr);
303 unsigned index_in_pt = virt_to_pt_index(vpag 270 unsigned index_in_pt = virt_to_pt_index(vpage_vaddr);
304 271
305 272
306 struct x86_pde *pd = (struct x86_pde*) 273 struct x86_pde *pd = (struct x86_pde*)
307 (SOS_PAGING_MIRROR_VADDR 274 (SOS_PAGING_MIRROR_VADDR
308 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 275 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
309 276
310 277
311 struct x86_pte * pt = (struct x86_pte*) (SOS 278 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
312 + S 279 + SOS_PAGE_SIZE*index_in_pd);
313 280
314 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(ppage_p <<
315 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(vpage_v <<
316 <<
317 <<
318 flags &= ~SOS_VM_MAP_PROT_EXEC; <<
319 <<
320 281
321 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR) 282 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR)
322 && (vpage_vaddr < SOS_PAGING_MIRROR_VADD 283 && (vpage_vaddr < SOS_PAGING_MIRROR_VADDR + SOS_PAGING_MIRROR_SIZE))
323 return -SOS_EINVAL; 284 return -SOS_EINVAL;
324 285
325 286
326 if (! pd[index_in_pd].present) 287 if (! pd[index_in_pd].present)
327 { 288 {
328 x86_pde_val_t u; <<
329 <<
330 289
331 sos_paddr_t pt_ppage 290 sos_paddr_t pt_ppage
332 = sos_physmem_ref_physpage_new(! (flag 291 = sos_physmem_ref_physpage_new(! (flags & SOS_VM_MAP_ATOMIC));
333 if (! pt_ppage) 292 if (! pt_ppage)
334 { 293 {
335 return -SOS_ENOMEM; 294 return -SOS_ENOMEM;
336 } 295 }
337 296
338 !! 297 pd[index_in_pd].present = TRUE;
339 u.pde = (struct x86_pde){ !! 298 pd[index_in_pd].write = 1;
340 .present = TRUE, !! 299
341 .write = 1, !! 300 pd[index_in_pd].user |= (is_user_page)?1:0;
342 .pt_paddr = ((sos_paddr_t)pt_ppage) >> !! 301 pd[index_in_pd].pt_paddr = ((sos_paddr_t)pt_ppage) >> 12;
343 }; <<
344 <<
345 <<
346 if (vpage_vaddr < SOS_PAGING_MIRROR_VADD <<
347 { <<
348 <<
349 <<
350 <<
351 <<
352 u.pde.user = 0; <<
353 <<
354 <<
355 SOS_ASSERT_FATAL(SOS_OK == <<
356 sos_mm_context_sync <<
357 <<
358 } <<
359 else <<
360 <<
361 <<
362 <<
363 { <<
364 <<
365 <<
366 <<
367 <<
368 u.pde.user = 1; <<
369 <<
370 <<
371 pd[index_in_pd] = u.pde; <<
372 } <<
373 302
374 303
375 304
376 305
377 306
378 307
379 invlpg(pt); 308 invlpg(pt);
380 309
381 310
382 memset((void*)pt, 0x0, SOS_PAGE_SIZE); 311 memset((void*)pt, 0x0, SOS_PAGE_SIZE);
383 } 312 }
384 313
385 !! 314
386 315
387 if (! pt[index_in_pt].present) !! 316 else if (! pt[index_in_pt].present)
388 sos_physmem_inc_physpage_occupation(pd[ind !! 317 sos_physmem_ref_physpage_at(pd[index_in_pd].pt_paddr << 12);
389 318
390 319
391 320
392 else 321 else
393 sos_physmem_unref_physpage(pt[index_in_pt] 322 sos_physmem_unref_physpage(pt[index_in_pt].paddr << 12);
394 323
395 324
396 pt[index_in_pt].present = TRUE; 325 pt[index_in_pt].present = TRUE;
397 pt[index_in_pt].write = (flags & SOS_VM_MA 326 pt[index_in_pt].write = (flags & SOS_VM_MAP_PROT_WRITE)?1:0;
398 pt[index_in_pt].user = (is_user_page)?1:0 327 pt[index_in_pt].user = (is_user_page)?1:0;
399 pt[index_in_pt].paddr = ppage_paddr >> 12; 328 pt[index_in_pt].paddr = ppage_paddr >> 12;
400 sos_physmem_ref_physpage_at(ppage_paddr); 329 sos_physmem_ref_physpage_at(ppage_paddr);
401 330
402 <<
403 331
404 332
405 333
406 334
407 335
408 invlpg(vpage_vaddr); 336 invlpg(vpage_vaddr);
409 337
410 return SOS_OK; 338 return SOS_OK;
411 } 339 }
412 340
413 341
414 sos_ret_t sos_paging_unmap(sos_vaddr_t vpage_v 342 sos_ret_t sos_paging_unmap(sos_vaddr_t vpage_vaddr)
415 { 343 {
416 sos_ret_t pt_dec_occupation_retval; !! 344 sos_ret_t pt_unref_retval;
417 345
418 346
419 347
420 unsigned index_in_pd = virt_to_pd_index(vpag 348 unsigned index_in_pd = virt_to_pd_index(vpage_vaddr);
421 unsigned index_in_pt = virt_to_pt_index(vpag 349 unsigned index_in_pt = virt_to_pt_index(vpage_vaddr);
422 350
423 351
424 struct x86_pde *pd = (struct x86_pde*) 352 struct x86_pde *pd = (struct x86_pde*)
425 (SOS_PAGING_MIRROR_VADDR 353 (SOS_PAGING_MIRROR_VADDR
426 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 354 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
427 355
428 356
429 struct x86_pte * pt = (struct x86_pte*) (SOS 357 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
430 + S 358 + SOS_PAGE_SIZE*index_in_pd);
431 359
432 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(vpage_v <<
433 <<
434 360
435 if (! pd[index_in_pd].present) 361 if (! pd[index_in_pd].present)
436 return -SOS_EINVAL; 362 return -SOS_EINVAL;
437 if (! pt[index_in_pt].present) 363 if (! pt[index_in_pt].present)
438 return -SOS_EINVAL; 364 return -SOS_EINVAL;
439 365
440 366
441 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR) 367 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR)
442 && (vpage_vaddr < SOS_PAGING_MIRROR_VADD 368 && (vpage_vaddr < SOS_PAGING_MIRROR_VADDR + SOS_PAGING_MIRROR_SIZE))
443 return -SOS_EINVAL; 369 return -SOS_EINVAL;
444 370
445 371
446 sos_physmem_unref_physpage(pt[index_in_pt].p 372 sos_physmem_unref_physpage(pt[index_in_pt].paddr << 12);
447 373
448 374
449 memset(pt + index_in_pt, 0x0, sizeof(struct 375 memset(pt + index_in_pt, 0x0, sizeof(struct x86_pte));
450 376
451 377
452 invlpg(vpage_vaddr); 378 invlpg(vpage_vaddr);
453 379
454 380
455 pt_dec_occupation_retval !! 381 pt_unref_retval = sos_physmem_unref_physpage(pd[index_in_pd].pt_paddr << 12);
456 = sos_physmem_dec_physpage_occupation(pd[i !! 382 SOS_ASSERT_FATAL(pt_unref_retval >= 0);
457 SOS_ASSERT_FATAL(pt_dec_occupation_retval >= !! 383 if (pt_unref_retval > 0)
458 if (pt_dec_occupation_retval > 0) <<
459 384
460 { 385 {
461 x86_pde_val_t u; !! 386
462 !! 387 memset(pd + index_in_pd, 0x0, sizeof(struct x86_pde));
463 <<
464 <<
465 <<
466 <<
467 sos_physmem_unref_physpage(pd[index_in_p <<
468 <<
469 <<
470 <<
471 <<
472 <<
473 <<
474 <<
475 u.ui32 = 0; <<
476 <<
477 <<
478 if (vpage_vaddr < SOS_PAGING_MIRROR_VADD <<
479 { <<
480 <<
481 SOS_ASSERT_FATAL(SOS_OK == <<
482 sos_mm_context_sync <<
483 <<
484 } <<
485 else <<
486 <<
487 <<
488 <<
489 { <<
490 <<
491 <<
492 pd[index_in_pd] = u.pde; <<
493 } <<
494 388
495 389
496 invlpg(pt); 390 invlpg(pt);
497 } 391 }
498 392
499 return SOS_OK; 393 return SOS_OK;
500 } 394 }
501 395
502 396
503 sos_ret_t sos_paging_unmap_interval(sos_vaddr_ !! 397 int sos_paging_get_prot(sos_vaddr_t vaddr)
504 sos_size_t <<
505 { 398 {
506 sos_ret_t retval = 0; !! 399 int retval;
507 <<
508 if (! SOS_IS_PAGE_ALIGNED(vaddr)) <<
509 return -SOS_EINVAL; <<
510 if (! SOS_IS_PAGE_ALIGNED(size)) <<
511 return -SOS_EINVAL; <<
512 <<
513 for ( ; <<
514 size >= SOS_PAGE_SIZE ; <<
515 vaddr += SOS_PAGE_SIZE, size -= SOS_PA <<
516 if (SOS_OK == sos_paging_unmap(vaddr)) <<
517 retval += SOS_PAGE_SIZE; <<
518 <<
519 return retval; <<
520 } <<
521 <<
522 <<
523 sos_ui32_t sos_paging_get_prot(sos_vaddr_t vad <<
524 { <<
525 sos_ui32_t retval; <<
526 400
527 401
528 402
529 unsigned index_in_pd = virt_to_pd_index(vadd 403 unsigned index_in_pd = virt_to_pd_index(vaddr);
530 unsigned index_in_pt = virt_to_pt_index(vadd 404 unsigned index_in_pt = virt_to_pt_index(vaddr);
531 405
532 406
533 struct x86_pde *pd = (struct x86_pde*) 407 struct x86_pde *pd = (struct x86_pde*)
534 (SOS_PAGING_MIRROR_VADDR 408 (SOS_PAGING_MIRROR_VADDR
535 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 409 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
536 410
537 411
538 struct x86_pte * pt = (struct x86_pte*) (SOS 412 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
539 + S 413 + SOS_PAGE_SIZE*index_in_pd);
540 414
541 415
542 if (! pd[index_in_pd].present) 416 if (! pd[index_in_pd].present)
543 return SOS_VM_MAP_PROT_NONE; 417 return SOS_VM_MAP_PROT_NONE;
544 if (! pt[index_in_pt].present) 418 if (! pt[index_in_pt].present)
545 return SOS_VM_MAP_PROT_NONE; 419 return SOS_VM_MAP_PROT_NONE;
546 420
547 421
548 retval = SOS_VM_MAP_PROT_READ; 422 retval = SOS_VM_MAP_PROT_READ;
549 if (pd[index_in_pd].write && pt[index_in_pt] 423 if (pd[index_in_pd].write && pt[index_in_pt].write)
550 retval |= SOS_VM_MAP_PROT_WRITE; 424 retval |= SOS_VM_MAP_PROT_WRITE;
551 425
552 return retval; 426 return retval;
553 } 427 }
554 428
555 429
556 sos_ret_t sos_paging_set_prot(sos_vaddr_t vadd <<
557 sos_ui32_t new_ <<
558 { <<
559 <<
560 <<
561 unsigned index_in_pd = virt_to_pd_index(vadd <<
562 unsigned index_in_pt = virt_to_pt_index(vadd <<
563 <<
564 <<
565 struct x86_pde *pd = (struct x86_pde*) <<
566 (SOS_PAGING_MIRROR_VADDR <<
567 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI <<
568 <<
569 <<
570 struct x86_pte * pt = (struct x86_pte*) (SOS <<
571 + S <<
572 <<
573 <<
574 new_prot &= ~SOS_VM_MAP_PROT_EXEC; <<
575 <<
576 <<
577 if (new_prot & ~(SOS_VM_MAP_PROT_READ | SOS_ <<
578 return -SOS_EINVAL; <<
579 if (! (new_prot & SOS_VM_MAP_PROT_READ)) <<
580 <<
581 return -SOS_ENOSUP; <<
582 <<
583 <<
584 if (! pd[index_in_pd].present) <<
585 return -SOS_EINVAL; <<
586 if (! pt[index_in_pt].present) <<
587 return -SOS_EINVAL; <<
588 <<
589 <<
590 pt[index_in_pt].write = ((new_prot & SOS_VM_ <<
591 invlpg(vaddr); <<
592 <<
593 return SOS_OK; <<
594 } <<
595 <<
596 <<
597 sos_ret_t sos_paging_set_prot_of_interval(sos_ <<
598 sos_ <<
599 sos_ <<
600 { <<
601 if (! SOS_IS_PAGE_ALIGNED(vaddr)) <<
602 return -SOS_EINVAL; <<
603 if (! SOS_IS_PAGE_ALIGNED(size)) <<
604 return -SOS_EINVAL; <<
605 <<
606 for ( ; size >= SOS_PAGE_SIZE ; vaddr += SOS <<
607 sos_paging_set_prot(vaddr, new_prot); <<
608 <<
609 return SOS_OK; <<
610 } <<
611 <<
612 <<
613 sos_bool_t sos_paging_is_dirty(sos_vaddr_t vad <<
614 { <<
615 <<
616 <<
617 unsigned index_in_pd = virt_to_pd_index(vadd <<
618 unsigned index_in_pt = virt_to_pt_index(vadd <<
619 <<
620 <<
621 struct x86_pde *pd = (struct x86_pde*) <<
622 (SOS_PAGING_MIRROR_VADDR <<
623 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI <<
624 <<
625 <<
626 struct x86_pte * pt = (struct x86_pte*) (SOS <<
627 + S <<
628 <<
629 <<
630 if (! pd[index_in_pd].present) <<
631 return FALSE; <<
632 if (! pt[index_in_pt].present) <<
633 return FALSE; <<
634 <<
635 return (pt[index_in_pt].dirty != 0); <<
636 } <<
637 <<
638 <<
639 sos_ret_t sos_paging_set_dirty(sos_vaddr_t vad <<
640 sos_bool_t is_d <<
641 { <<
642 <<
643 <<
644 unsigned index_in_pd = virt_to_pd_index(vadd <<
645 unsigned index_in_pt = virt_to_pt_index(vadd <<
646 <<
647 <<
648 struct x86_pde *pd = (struct x86_pde*) <<
649 (SOS_PAGING_MIRROR_VADDR <<
650 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI <<
651 <<
652 <<
653 struct x86_pte * pt = (struct x86_pte*) (SOS <<
654 + S <<
655 <<
656 <<
657 if (! pd[index_in_pd].present) <<
658 return -SOS_EFAULT; <<
659 if (! pt[index_in_pt].present) <<
660 return -SOS_EFAULT; <<
661 <<
662 pt[index_in_pt].dirty = is_dirty; <<
663 return SOS_OK; <<
664 } <<
665 <<
666 <<
667 sos_paddr_t sos_paging_get_paddr(sos_vaddr_t v 430 sos_paddr_t sos_paging_get_paddr(sos_vaddr_t vaddr)
668 { 431 {
669 432
670 433
671 unsigned index_in_pd = virt_to_pd_index(vadd 434 unsigned index_in_pd = virt_to_pd_index(vaddr);
672 unsigned index_in_pt = virt_to_pt_index(vadd 435 unsigned index_in_pt = virt_to_pt_index(vaddr);
673 unsigned offset_in_page = virt_to_page_offse 436 unsigned offset_in_page = virt_to_page_offset(vaddr);
674 437
675 438
676 struct x86_pde *pd = (struct x86_pde*) 439 struct x86_pde *pd = (struct x86_pde*)
677 (SOS_PAGING_MIRROR_VADDR 440 (SOS_PAGING_MIRROR_VADDR
678 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 441 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
679 442
680 443
681 struct x86_pte * pt = (struct x86_pte*) (SOS 444 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
682 + S 445 + SOS_PAGE_SIZE*index_in_pd);
683 446
684 447
685 if (! pd[index_in_pd].present) 448 if (! pd[index_in_pd].present)
686 return (sos_paddr_t)NULL; 449 return (sos_paddr_t)NULL;
687 if (! pt[index_in_pt].present) 450 if (! pt[index_in_pt].present)
688 return (sos_paddr_t)NULL; 451 return (sos_paddr_t)NULL;
689 452
690 return (pt[index_in_pt].paddr << 12) + offse 453 return (pt[index_in_pt].paddr << 12) + offset_in_page;
691 } 454 }
692 455
693 <<
694 <<
695 <<
696 <<
697 <<
698 <<
699 sos_paddr_t sos_paging_get_current_PD_paddr(vo <<
700 { <<
701 struct x86_pdbr pdbr; <<
702 asm volatile("movl %%cr3, %0\n": "=r"(pdbr)) <<
703 return (pdbr.pd_paddr << 12); <<
704 } <<
705 <<
706 <<
707 sos_ret_t sos_paging_set_current_PD_paddr(sos_ <<
708 { <<
709 struct x86_pdbr pdbr; <<
710 <<
711 SOS_ASSERT_FATAL(paddr_PD != 0); <<
712 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(paddr_P <<
713 <<
714 <<
715 memset(& pdbr, 0x0, sizeof(struct x86_pdbr)) <<
716 pdbr.pd_paddr = (paddr_PD >> 12); <<
717 <<
718 <<
719 asm volatile ("movl %0,%%cr3\n" ::"r"(pdbr)) <<
720 <<
721 return SOS_OK; <<
722 } <<
723 <<
724 <<
725 sos_ret_t sos_paging_dispose(sos_vaddr_t vaddr <<
726 { <<
727 x86_pde_val_t *pd = (x86_pde_val_t*) vaddr_P <<
728 x86_pte_val_t *pt; <<
729 int index_in_pd; <<
730 <<
731 <<
732 <<
733 pt = (x86_pte_val_t *)sos_kmem_vmm_alloc(1, <<
734 if (! pt) <<
735 return -SOS_ENOMEM; <<
736 <<
737 <<
738 <<
739 <<
740 for (index_in_pd = (SOS_PAGING_BASE_USER_ADD <<
741 index_in_pd < 1024 ; <<
742 <<
743 <<
744 index_in_pd ++) <<
745 { <<
746 sos_paddr_t paddr_pt = (pd[index_in_pd]. <<
747 int index_in_pt; <<
748 <<
749 <<
750 if (! pd[index_in_pd].pde.present) <<
751 { <<
752 pd[index_in_pd].ui32 = 0; <<
753 continue; <<
754 } <<
755 <<
756 <<
757 SOS_ASSERT_FATAL(SOS_OK <<
758 == sos_paging_map(paddr <<
759 (sos_ <<
760 SOS_V <<
761 | SOS <<
762 <<
763 <<
764 for (index_in_pt = 0 ; index_in_pt < 102 <<
765 { <<
766 <<
767 if (! pt[index_in_pt].pte.present) <<
768 { <<
769 pt[index_in_pt].ui32 = 0; <<
770 continue; <<
771 } <<
772 <<
773 <<
774 sos_physmem_unref_physpage(pt[index_ <<
775 <<
776 <<
777 sos_physmem_dec_physpage_occupation( <<
778 <<
779 <<
780 pt[index_in_pt].ui32 = 0; <<
781 } <<
782 <<
783 <<
784 SOS_ASSERT_FATAL(SOS_OK == sos_paging_un <<
785 <<
786 <<
787 pd[index_in_pd].ui32 = 0; <<
788 <<
789 <<
790 sos_physmem_unref_physpage(paddr_pt); <<
791 } <<
792 <<
793 <<
794 SOS_ASSERT_FATAL(SOS_OK == sos_kmem_vmm_free <<
795 <<
796 return SOS_OK; <<
797 } <<
798 <<
799 <<
800 sos_ret_t sos_paging_copy_kernel_space(sos_vad <<
801 sos_vad <<
802 { <<
803 x86_pde_val_t *src_pd = (x86_pde_val_t <<
804 x86_pde_val_t *dest_pd = (x86_pde_val_t <<
805 sos_paddr_t dest_paddr_PD = sos_paging_get <<
806 x86_pde_val_t mirror_pde; <<
807 int index_in_pd; <<
808 <<
809 <<
810 memset((void*)dest_vaddr_PD, 0x0, SOS_PAGE_S <<
811 <<
812 <<
813 <<
814 for (index_in_pd = 0 ; <<
815 index_in_pd < (SOS_PAGING_MIRROR_VADDR <<
816 <<
817 <<
818 index_in_pd ++) <<
819 { <<
820 <<
821 dest_pd[index_in_pd].ui32 = src_pd[index <<
822 <<
823 <<
824 <<
825 <<
826 <<
827 <<
828 <<
829 <<
830 <<
831 } <<
832 <<
833 <<
834 mirror_pde.ui32 = 0; <<
835 mirror_pde.pde.present = TRUE; <<
836 mirror_pde.pde.write = 1; <<
837 mirror_pde.pde.user = 0; <<
838 mirror_pde.pde.pt_paddr = (dest_paddr_PD >> <<
839 dest_pd[SOS_PAGING_MIRROR_VADDR >> 22].ui32 <<
840 <<
841 return SOS_OK; <<
842 } <<
843 <<
844 <<
845 sos_ret_t sos_paging_copy_user_space(sos_vaddr <<
846 sos_vaddr <<
847 { <<
848 x86_pde_val_t *src_pd = (x86_pde_val_t*) sr <<
849 x86_pde_val_t *dest_pd = (x86_pde_val_t*) de <<
850 x86_pte_val_t *tmp_src_pt, *tmp_dest_pt; <<
851 int index_in_pd; <<
852 <<
853 <<
854 <<
855 tmp_src_pt = (x86_pte_val_t *)sos_kmem_vmm_ <<
856 if (! tmp_src_pt) <<
857 return -SOS_ENOMEM; <<
858 <<
859 tmp_dest_pt = (x86_pte_val_t *)sos_kmem_vmm_ <<
860 if (! tmp_dest_pt) <<
861 { <<
862 sos_kmem_vmm_free((sos_vaddr_t)tmp_dest_ <<
863 return -SOS_ENOMEM; <<
864 } <<
865 <<
866 <<
867 for (index_in_pd = (SOS_PAGING_BASE_USER_ADD <<
868 index_in_pd < 1024 ; <<
869 <<
870 <<
871 index_in_pd ++) <<
872 { <<
873 sos_paddr_t paddr_dest_pt; <<
874 int index_in_pt; <<
875 <<
876 <<
877 <<
878 <<
879 <<
880 <<
881 dest_pd[index_in_pd].ui32 = src_pd[index <<
882 <<
883 <<
884 if (! src_pd[index_in_pd].pde.present) <<
885 continue; <<
886 <<
887 <<
888 paddr_dest_pt = sos_physmem_ref_physpage <<
889 if (NULL == (void*)paddr_dest_pt) <<
890 { <<
891 sos_paging_dispose((sos_vaddr_t)dest <<
892 <<
893 <<
894 sos_kmem_vmm_free((sos_vaddr_t)tmp_s <<
895 sos_kmem_vmm_free((sos_vaddr_t)tmp_d <<
896 return -SOS_ENOMEM; <<
897 } <<
898 <<
899 <<
900 SOS_ASSERT_FATAL(SOS_OK <<
901 == sos_paging_map(src_p <<
902 (sos_ <<
903 SOS_V <<
904 SOS_ASSERT_FATAL(SOS_OK <<
905 == sos_paging_map(paddr <<
906 (sos_ <<
907 SOS_V <<
908 | SOS <<
909 <<
910 <<
911 <<
912 for (index_in_pt = 0 ; index_in_pt < 102 <<
913 { <<
914 <<
915 tmp_dest_pt[index_in_pt].ui32 = tmp_ <<
916 <<
917 <<
918 if (! tmp_dest_pt[index_in_pt].pte.p <<
919 continue; <<
920 <<
921 <<
922 tmp_dest_pt[index_in_pt].pte.accesse <<
923 tmp_dest_pt[index_in_pt].pte.dirty <<
924 <<
925 <<
926 sos_physmem_ref_physpage_at(tmp_src_ <<
927 <<
928 <<
929 sos_physmem_inc_physpage_occupation( <<
930 } <<
931 <<
932 <<
933 SOS_ASSERT_FATAL(SOS_OK == sos_paging_un <<
934 SOS_ASSERT_FATAL(SOS_OK == sos_paging_un <<
935 <<
936 <<
937 dest_pd[index_in_pd].pde.pt_paddr = (pad <<
938 <<
939 <<
940 dest_pd[index_in_pd].pde.accessed = 0; <<
941 } <<
942 <<
943 <<
944 <<
945 SOS_ASSERT_FATAL(SOS_OK == sos_kmem_vmm_free <<
946 SOS_ASSERT_FATAL(SOS_OK == sos_kmem_vmm_free <<
947 <<
948 return SOS_OK; <<
949 } <<
950 <<
951 <<
952 sos_ret_t sos_paging_prepare_COW(sos_uaddr_t b <<
953 sos_size_t le <<
954 { <<
955 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(base_ad <<
956 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(length) <<
957 SOS_ASSERT_FATAL(SOS_PAGING_BASE_USER_ADDRES <<
958 <<
959 <<
960 <<
961 for ( ; <<
962 length > 0 ; <<
963 length -= SOS_PAGE_SIZE, base_address + <<
964 { <<
965 sos_paging_set_prot(base_address, <<
966 SOS_VM_MAP_PROT_READ <<
967 } <<
968 <<
969 return SOS_OK; <<
970 } <<
971 <<
972 <<
973 sos_ret_t sos_paging_try_resolve_COW(sos_uaddr <<
974 { <<
975 sos_ret_t refcnt; <<
976 <<
977 <<
978 <<
979 unsigned index_in_pd = virt_to_pd_index(uadd <<
980 unsigned index_in_pt = virt_to_pt_index(uadd <<
981 <<
982 <<
983 struct x86_pde *pd = (struct x86_pde*) <<
984 (SOS_PAGING_MIRROR_VADDR <<
985 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI <<
986 <<
987 <<
988 struct x86_pte * pt = (struct x86_pte*) (SOS <<
989 + S <<
990 <<
991 <<
992 if (! pd[index_in_pd].present) <<
993 return -SOS_EFAULT; <<
994 if (! pt[index_in_pt].present) <<
995 return -SOS_EFAULT; <<
996 <<
997 <<
998 if (! pd[index_in_pd].write) <<
999 return -SOS_EFAULT; <<
1000 <<
1001 <<
1002 <<
1003 SOS_ASSERT_FATAL(! pt[index_in_pt].write); <<
1004 <<
1005 <<
1006 <<
1007 refcnt = sos_physmem_get_physpage_refcount( <<
1008 SOS_ASSERT_FATAL(refcnt > 0); <<
1009 <<
1010 if (refcnt == 1) <<
1011 { <<
1012 <<
1013 <<
1014 pt[index_in_pt].write = 1; <<
1015 invlpg(pt[index_in_pt].paddr << 12); <<
1016 } <<
1017 <<
1018 <<
1019 else <<
1020 { <<
1021 sos_paddr_t new_ppage; <<
1022 sos_vaddr_t vpage_src, tmp_dest; <<
1023 <<
1024 <<
1025 <<
1026 <<
1027 tmp_dest = sos_kmem_vmm_alloc(1, SOS_KM <<
1028 if (! tmp_dest) <<
1029 return -SOS_ENOMEM; <<
1030 <<
1031 <<
1032 vpage_src = SOS_PAGE_ALIGN_INF(uaddr); <<
1033 memcpy((void*)tmp_dest, (void*)vpage_sr <<
1034 <<
1035 <<
1036 <<
1037 <<
1038 new_ppage = sos_paging_get_paddr(tmp_de <<
1039 SOS_ASSERT_FATAL(new_ppage != (sos_vadd <<
1040 if (SOS_OK != sos_paging_map(new_ppage, <<
1041 TRUE, <<
1042 SOS_VM_MAP <<
1043 | SOS_VM_M <<
1044 { <<
1045 sos_kmem_vmm_free(tmp_dest); <<
1046 return -SOS_ENOMEM; <<
1047 } <<
1048 <<
1049 <<
1050 <<
1051 SOS_ASSERT_FATAL(SOS_OK == sos_kmem_vmm <<
1052 } <<
1053 <<
1054 <<
1055 return SOS_OK; <<
1056 } <<