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 024
027 <<
028 <<
029 <<
030 <<
031 <<
032 <<
033 <<
034 <<
035 <<
036 <<
037 <<
038 <<
039 <<
040 <<
041 <<
042 <<
043 <<
044 <<
045 025
046 026
047 struct x86_pde 027 struct x86_pde
048 { 028 {
049 sos_ui32_t present :1; 029 sos_ui32_t present :1;
050 sos_ui32_t write :1; 030 sos_ui32_t write :1;
051 sos_ui32_t user :1; 031 sos_ui32_t user :1;
052 sos_ui32_t write_through :1; 032 sos_ui32_t write_through :1;
053 sos_ui32_t cache_disabled :1; 033 sos_ui32_t cache_disabled :1;
054 sos_ui32_t accessed :1; 034 sos_ui32_t accessed :1;
055 sos_ui32_t zero :1; 035 sos_ui32_t zero :1;
056 sos_ui32_t page_size :1; 036 sos_ui32_t page_size :1;
057 sos_ui32_t global_page :1; 037 sos_ui32_t global_page :1;
058 sos_ui32_t custom :3; 038 sos_ui32_t custom :3;
059 sos_ui32_t pt_paddr :20; 039 sos_ui32_t pt_paddr :20;
060 } __attribute__ ((packed)); 040 } __attribute__ ((packed));
061 041
062 042
063 <<
064 typedef union { <<
065 struct x86_pde pde; <<
066 sos_ui32_t ui32; <<
067 } x86_pde_val_t; <<
068 <<
069 <<
070 043
071 044
072 struct x86_pte 045 struct x86_pte
073 { 046 {
074 sos_ui32_t present :1; 047 sos_ui32_t present :1;
075 sos_ui32_t write :1; 048 sos_ui32_t write :1;
076 sos_ui32_t user :1; 049 sos_ui32_t user :1;
077 sos_ui32_t write_through :1; 050 sos_ui32_t write_through :1;
078 sos_ui32_t cache_disabled :1; 051 sos_ui32_t cache_disabled :1;
079 sos_ui32_t accessed :1; 052 sos_ui32_t accessed :1;
080 sos_ui32_t dirty :1; 053 sos_ui32_t dirty :1;
081 sos_ui32_t zero :1; 054 sos_ui32_t zero :1;
082 sos_ui32_t global_page :1; 055 sos_ui32_t global_page :1;
083 056
084 sos_ui32_t custom :3; 057 sos_ui32_t custom :3;
085 sos_ui32_t paddr :20; 058 sos_ui32_t paddr :20;
086 } __attribute__ ((packed)); 059 } __attribute__ ((packed));
087 060
088 061
089 <<
090 typedef union { <<
091 struct x86_pte pte; <<
092 sos_ui32_t ui32; <<
093 } x86_pte_val_t; <<
094 <<
095 <<
096 062
097 063
098 struct x86_pdbr 064 struct x86_pdbr
099 { 065 {
100 sos_ui32_t zero1 :3; 066 sos_ui32_t zero1 :3;
101 sos_ui32_t write_through :1; 067 sos_ui32_t write_through :1;
102 sos_ui32_t cache_disabled :1; 068 sos_ui32_t cache_disabled :1;
103 sos_ui32_t zero2 :7; 069 sos_ui32_t zero2 :7;
104 sos_ui32_t pd_paddr :20; 070 sos_ui32_t pd_paddr :20;
105 } __attribute__ ((packed)); 071 } __attribute__ ((packed));
106 072
107 073
108 074
109 075
110 076
111 077
112 078
113 #define invlpg(vaddr) \ 079 #define invlpg(vaddr) \
114 do { \ 080 do { \
115 __asm__ __volatile__("invlpg %0"::"m"(* 081 __asm__ __volatile__("invlpg %0"::"m"(*((unsigned *)(vaddr)))); \
116 } while(0) 082 } while(0)
117 083
118 084
119 085
120 086
121 087
122 088
123 #define flush_tlb() \ 089 #define flush_tlb() \
124 do { \ 090 do { \
125 unsigned long tmpreg; \ 091 unsigned long tmpreg; \
126 asm volatile("movl %%cr3,%0\n\tmovl %0 092 asm volatile("movl %%cr3,%0\n\tmovl %0,%%cr3" :"=r" \
127 (tmpreg) : :"memory"); \ 093 (tmpreg) : :"memory"); \
128 } while (0) 094 } while (0)
129 095
130 096
131 097
132 098
133 099
134 100
135 #define virt_to_pd_index(vaddr) \ 101 #define virt_to_pd_index(vaddr) \
136 (((unsigned)(vaddr)) >> 22) 102 (((unsigned)(vaddr)) >> 22)
137 103
138 104
139 105
140 106
141 107
142 108
143 #define virt_to_pt_index(vaddr) \ 109 #define virt_to_pt_index(vaddr) \
144 ( (((unsigned)(vaddr)) >> 12) & 0x3ff ) 110 ( (((unsigned)(vaddr)) >> 12) & 0x3ff )
145 111
146 112
147 113
148 114
149 115
150 116
151 #define virt_to_page_offset(vaddr) \ 117 #define virt_to_page_offset(vaddr) \
152 (((unsigned)(vaddr)) & SOS_PAGE_MASK) 118 (((unsigned)(vaddr)) & SOS_PAGE_MASK)
153 119
154 120
155 121
156 122
157 123
158 124
159 125
160 static sos_ret_t paging_setup_map_helper(struc 126 static sos_ret_t paging_setup_map_helper(struct x86_pde * pd,
161 sos_p 127 sos_paddr_t ppage,
162 sos_v 128 sos_vaddr_t vaddr)
163 { 129 {
164 130
165 131
166 unsigned index_in_pd = virt_to_pd_index(vadd 132 unsigned index_in_pd = virt_to_pd_index(vaddr);
167 unsigned index_in_pt = virt_to_pt_index(vadd 133 unsigned index_in_pt = virt_to_pt_index(vaddr);
168 134
169 135
170 struct x86_pte * pt; 136 struct x86_pte * pt;
171 if (pd[index_in_pd].present) 137 if (pd[index_in_pd].present)
172 { 138 {
173 pt = (struct x86_pte*) (pd[index_in_pd]. 139 pt = (struct x86_pte*) (pd[index_in_pd].pt_paddr << 12);
174 140
175 !! 141
176 !! 142
177 !! 143
178 !! 144
179 if (pt[index_in_pt].present) !! 145
>> 146
>> 147 if (! pt[index_in_pt].present)
>> 148 sos_physmem_ref_physpage_at((sos_paddr_t)pt);
>> 149
>> 150
>> 151 else
180 SOS_ASSERT_FATAL(FALSE); 152 SOS_ASSERT_FATAL(FALSE);
181 } 153 }
182 else 154 else
183 { 155 {
184 156
185 pt = (struct x86_pte*) sos_physmem_ref_p 157 pt = (struct x86_pte*) sos_physmem_ref_physpage_new(FALSE);
186 if (! pt) 158 if (! pt)
187 return -SOS_ENOMEM; 159 return -SOS_ENOMEM;
188 160
189 memset((void*)pt, 0x0, SOS_PAGE_SIZE); 161 memset((void*)pt, 0x0, SOS_PAGE_SIZE);
190 162
191 pd[index_in_pd].present = TRUE; 163 pd[index_in_pd].present = TRUE;
192 pd[index_in_pd].write = 1; 164 pd[index_in_pd].write = 1;
193 165
194 166
195 167
196 168
197 pd[index_in_pd].pt_paddr = ((sos_paddr_t 169 pd[index_in_pd].pt_paddr = ((sos_paddr_t)pt) >> 12;
198 } 170 }
199 171
200 172
201 173
202 pt[index_in_pt].present = 1; 174 pt[index_in_pt].present = 1;
203 pt[index_in_pt].write = 1; 175 pt[index_in_pt].write = 1;
204 176
205 177
206 178
207 pt[index_in_pt].user = 0; 179 pt[index_in_pt].user = 0;
208 pt[index_in_pt].paddr = ppage >> 12; 180 pt[index_in_pt].paddr = ppage >> 12;
209 181
210 <<
211 <<
212 sos_physmem_inc_physpage_occupation((sos_pad <<
213 <<
214 return SOS_OK; 182 return SOS_OK;
215 } 183 }
216 184
217 185
218 sos_ret_t sos_paging_subsystem_setup(sos_paddr 186 sos_ret_t sos_paging_subsystem_setup(sos_paddr_t identity_mapping_base,
219 sos_paddr 187 sos_paddr_t identity_mapping_top)
220 { 188 {
221 189
222 struct x86_pdbr cr3; 190 struct x86_pdbr cr3;
223 191
224 192
225 struct x86_pde * pd 193 struct x86_pde * pd
226 = (struct x86_pde*) sos_physmem_ref_physpa 194 = (struct x86_pde*) sos_physmem_ref_physpage_new(FALSE);
227 195
228 196
229 sos_paddr_t paddr; 197 sos_paddr_t paddr;
230 198
231 199
232 200
233 memset((void*)pd, 201 memset((void*)pd,
234 0x0, 202 0x0,
235 SOS_PAGE_SIZE); 203 SOS_PAGE_SIZE);
236 204
237 205
238 for (paddr = identity_mapping_base ; 206 for (paddr = identity_mapping_base ;
239 paddr < identity_mapping_top ; 207 paddr < identity_mapping_top ;
240 paddr += SOS_PAGE_SIZE) 208 paddr += SOS_PAGE_SIZE)
241 { 209 {
242 if (paging_setup_map_helper(pd, paddr, p 210 if (paging_setup_map_helper(pd, paddr, paddr))
243 return -SOS_ENOMEM; 211 return -SOS_ENOMEM;
244 } 212 }
245 213
246 214
247 for (paddr = BIOS_N_VIDEO_START ; 215 for (paddr = BIOS_N_VIDEO_START ;
248 paddr < BIOS_N_VIDEO_END ; 216 paddr < BIOS_N_VIDEO_END ;
249 paddr += SOS_PAGE_SIZE) 217 paddr += SOS_PAGE_SIZE)
250 { 218 {
251 if (paging_setup_map_helper(pd, paddr, p 219 if (paging_setup_map_helper(pd, paddr, paddr))
252 return -SOS_ENOMEM; 220 return -SOS_ENOMEM;
253 } 221 }
254 222
255 223
256 224
257 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 225 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].present = TRUE;
258 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 226 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].write = 1;
259 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 227 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].user = 0;
260 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR) 228 pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].pt_paddr
261 = ((sos_paddr_t)pd)>>12; 229 = ((sos_paddr_t)pd)>>12;
262 230
263 231
264 232
265 memset(& cr3, 0x0, sizeof(struct x86_pdbr)); 233 memset(& cr3, 0x0, sizeof(struct x86_pdbr));
266 cr3.pd_paddr = ((sos_paddr_t)pd) >> 12; 234 cr3.pd_paddr = ((sos_paddr_t)pd) >> 12;
267 235
268 236
269 237
270 238
271 asm volatile ("movl %0,%%cr3\n\t" 239 asm volatile ("movl %0,%%cr3\n\t"
272 "movl %%cr0,%%eax\n\t" 240 "movl %%cr0,%%eax\n\t"
273 "orl $0x80010000, %%eax\n\t" 241 "orl $0x80010000, %%eax\n\t"
274 "movl %%eax,%%cr0\n\t" 242 "movl %%eax,%%cr0\n\t"
275 "jmp 1f\n\t" 243 "jmp 1f\n\t"
276 "1:\n\t" 244 "1:\n\t"
277 "movl $2f, %%eax\n\t" 245 "movl $2f, %%eax\n\t"
278 "jmp *%%eax\n\t" 246 "jmp *%%eax\n\t"
279 "2:\n\t" ::"r"(cr3):"memory"," 247 "2:\n\t" ::"r"(cr3):"memory","eax");
280 248
281 249
282 250
283 251
284 252
285 253
286 254
287 255
288 256
289 return SOS_OK; 257 return SOS_OK;
290 } 258 }
291 259
292 260
293 261
294 262
295 sos_ret_t sos_paging_map(sos_paddr_t ppage_pad 263 sos_ret_t sos_paging_map(sos_paddr_t ppage_paddr,
296 sos_vaddr_t vpage_vad 264 sos_vaddr_t vpage_vaddr,
297 sos_bool_t is_user_pa 265 sos_bool_t is_user_page,
298 sos_ui32_t flags) 266 sos_ui32_t flags)
299 { 267 {
300 268
301 269
302 unsigned index_in_pd = virt_to_pd_index(vpag 270 unsigned index_in_pd = virt_to_pd_index(vpage_vaddr);
303 unsigned index_in_pt = virt_to_pt_index(vpag 271 unsigned index_in_pt = virt_to_pt_index(vpage_vaddr);
304 272
305 273
306 struct x86_pde *pd = (struct x86_pde*) 274 struct x86_pde *pd = (struct x86_pde*)
307 (SOS_PAGING_MIRROR_VADDR 275 (SOS_PAGING_MIRROR_VADDR
308 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 276 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
309 277
310 278
311 struct x86_pte * pt = (struct x86_pte*) (SOS 279 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
312 + S 280 + SOS_PAGE_SIZE*index_in_pd);
313 281
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 282
321 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR) 283 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR)
322 && (vpage_vaddr < SOS_PAGING_MIRROR_VADD 284 && (vpage_vaddr < SOS_PAGING_MIRROR_VADDR + SOS_PAGING_MIRROR_SIZE))
323 return -SOS_EINVAL; 285 return -SOS_EINVAL;
324 286
325 287
326 if (! pd[index_in_pd].present) 288 if (! pd[index_in_pd].present)
327 { 289 {
328 x86_pde_val_t u; <<
329 290
330 291
331 sos_paddr_t pt_ppage 292 sos_paddr_t pt_ppage
332 = sos_physmem_ref_physpage_new(! (flag 293 = sos_physmem_ref_physpage_new(! (flags & SOS_VM_MAP_ATOMIC));
333 if (! pt_ppage) 294 if (! pt_ppage)
334 { 295 {
335 return -SOS_ENOMEM; 296 return -SOS_ENOMEM;
336 } 297 }
337 298
338 !! 299 pd[index_in_pd].present = TRUE;
339 u.pde = (struct x86_pde){ !! 300 pd[index_in_pd].write = 1;
340 .present = TRUE, !! 301
341 .write = 1, !! 302 pd[index_in_pd].user = (is_user_page)?1:0;
342 .pt_paddr = ((sos_paddr_t)pt_ppage) >> !! 303 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 304
374 305
375 306
376 307
377 308
378 309
379 invlpg(pt); 310 invlpg(pt);
380 311
381 312
382 memset((void*)pt, 0x0, SOS_PAGE_SIZE); 313 memset((void*)pt, 0x0, SOS_PAGE_SIZE);
383 } 314 }
384 315
385 !! 316
386 317
387 if (! pt[index_in_pt].present) !! 318 else if (! pt[index_in_pt].present)
388 sos_physmem_inc_physpage_occupation(pd[ind !! 319 sos_physmem_ref_physpage_at(pd[index_in_pd].pt_paddr << 12);
389 320
390 321
391 322
392 else 323 else
393 sos_physmem_unref_physpage(pt[index_in_pt] 324 sos_physmem_unref_physpage(pt[index_in_pt].paddr << 12);
394 325
395 326
396 pt[index_in_pt].present = TRUE; 327 pt[index_in_pt].present = TRUE;
397 pt[index_in_pt].write = (flags & SOS_VM_MA 328 pt[index_in_pt].write = (flags & SOS_VM_MAP_PROT_WRITE)?1:0;
398 pt[index_in_pt].user = (is_user_page)?1:0 329 pt[index_in_pt].user = (is_user_page)?1:0;
399 pt[index_in_pt].paddr = ppage_paddr >> 12; 330 pt[index_in_pt].paddr = ppage_paddr >> 12;
400 sos_physmem_ref_physpage_at(ppage_paddr); 331 sos_physmem_ref_physpage_at(ppage_paddr);
401 332
402 <<
403 333
404 334
405 335
406 336
407 337
408 invlpg(vpage_vaddr); 338 invlpg(vpage_vaddr);
409 339
410 return SOS_OK; 340 return SOS_OK;
411 } 341 }
412 342
413 343
414 sos_ret_t sos_paging_unmap(sos_vaddr_t vpage_v 344 sos_ret_t sos_paging_unmap(sos_vaddr_t vpage_vaddr)
415 { 345 {
416 sos_ret_t pt_dec_occupation_retval; !! 346 sos_ret_t pt_unref_retval;
417 347
418 348
419 349
420 unsigned index_in_pd = virt_to_pd_index(vpag 350 unsigned index_in_pd = virt_to_pd_index(vpage_vaddr);
421 unsigned index_in_pt = virt_to_pt_index(vpag 351 unsigned index_in_pt = virt_to_pt_index(vpage_vaddr);
422 352
423 353
424 struct x86_pde *pd = (struct x86_pde*) 354 struct x86_pde *pd = (struct x86_pde*)
425 (SOS_PAGING_MIRROR_VADDR 355 (SOS_PAGING_MIRROR_VADDR
426 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 356 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
427 357
428 358
429 struct x86_pte * pt = (struct x86_pte*) (SOS 359 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
430 + S 360 + SOS_PAGE_SIZE*index_in_pd);
431 361
432 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(vpage_v <<
433 <<
434 362
435 if (! pd[index_in_pd].present) 363 if (! pd[index_in_pd].present)
436 return -SOS_EINVAL; 364 return -SOS_EINVAL;
437 if (! pt[index_in_pt].present) 365 if (! pt[index_in_pt].present)
438 return -SOS_EINVAL; 366 return -SOS_EINVAL;
439 367
440 368
441 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR) 369 if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR)
442 && (vpage_vaddr < SOS_PAGING_MIRROR_VADD 370 && (vpage_vaddr < SOS_PAGING_MIRROR_VADDR + SOS_PAGING_MIRROR_SIZE))
443 return -SOS_EINVAL; 371 return -SOS_EINVAL;
444 372
445 373
446 sos_physmem_unref_physpage(pt[index_in_pt].p 374 sos_physmem_unref_physpage(pt[index_in_pt].paddr << 12);
447 375
448 376
449 memset(pt + index_in_pt, 0x0, sizeof(struct 377 memset(pt + index_in_pt, 0x0, sizeof(struct x86_pte));
450 378
451 379
452 invlpg(vpage_vaddr); 380 invlpg(vpage_vaddr);
453 381
454 382
455 pt_dec_occupation_retval !! 383 pt_unref_retval = sos_physmem_unref_physpage(pd[index_in_pd].pt_paddr << 12);
456 = sos_physmem_dec_physpage_occupation(pd[i !! 384 SOS_ASSERT_FATAL(pt_unref_retval >= 0);
457 SOS_ASSERT_FATAL(pt_dec_occupation_retval >= !! 385 if (pt_unref_retval == TRUE)
458 if (pt_dec_occupation_retval > 0) <<
459 386
460 { 387 {
461 x86_pde_val_t u; !! 388 union { struct x86_pde pde; sos_ui32_t ui32; } u;
462 <<
463 <<
464 <<
465 <<
466 <<
467 sos_physmem_unref_physpage(pd[index_in_p <<
468 <<
469 389
470 390
471 391
472 392
473 393
474 394
475 u.ui32 = 0; 395 u.ui32 = 0;
476 396
477 !! 397
478 if (vpage_vaddr < SOS_PAGING_MIRROR_VADD !! 398 pd[index_in_pd] = u.pde;
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 399
495 400
496 invlpg(pt); 401 invlpg(pt);
497 } 402 }
498 403
499 return SOS_OK; 404 return SOS_OK;
500 } 405 }
501 406
502 407
503 sos_ret_t sos_paging_unmap_interval(sos_vaddr_ !! 408 int sos_paging_get_prot(sos_vaddr_t vaddr)
504 sos_size_t <<
505 { <<
506 sos_ret_t retval = 0; <<
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 { 409 {
525 sos_ui32_t retval; !! 410 int retval;
526 411
527 412
528 413
529 unsigned index_in_pd = virt_to_pd_index(vadd 414 unsigned index_in_pd = virt_to_pd_index(vaddr);
530 unsigned index_in_pt = virt_to_pt_index(vadd 415 unsigned index_in_pt = virt_to_pt_index(vaddr);
531 416
532 417
533 struct x86_pde *pd = (struct x86_pde*) 418 struct x86_pde *pd = (struct x86_pde*)
534 (SOS_PAGING_MIRROR_VADDR 419 (SOS_PAGING_MIRROR_VADDR
535 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 420 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
536 421
537 422
538 struct x86_pte * pt = (struct x86_pte*) (SOS 423 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
539 + S 424 + SOS_PAGE_SIZE*index_in_pd);
540 425
541 426
542 if (! pd[index_in_pd].present) 427 if (! pd[index_in_pd].present)
543 return SOS_VM_MAP_PROT_NONE; 428 return SOS_VM_MAP_PROT_NONE;
544 if (! pt[index_in_pt].present) 429 if (! pt[index_in_pt].present)
545 return SOS_VM_MAP_PROT_NONE; 430 return SOS_VM_MAP_PROT_NONE;
546 431
547 432
548 retval = SOS_VM_MAP_PROT_READ; 433 retval = SOS_VM_MAP_PROT_READ;
549 if (pd[index_in_pd].write && pt[index_in_pt] 434 if (pd[index_in_pd].write && pt[index_in_pt].write)
550 retval |= SOS_VM_MAP_PROT_WRITE; 435 retval |= SOS_VM_MAP_PROT_WRITE;
551 436
552 return retval; 437 return retval;
553 } 438 }
554 439
555 440
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 441 sos_paddr_t sos_paging_get_paddr(sos_vaddr_t vaddr)
668 { 442 {
669 443
670 444
671 unsigned index_in_pd = virt_to_pd_index(vadd 445 unsigned index_in_pd = virt_to_pd_index(vaddr);
672 unsigned index_in_pt = virt_to_pt_index(vadd 446 unsigned index_in_pt = virt_to_pt_index(vaddr);
673 unsigned offset_in_page = virt_to_page_offse 447 unsigned offset_in_page = virt_to_page_offset(vaddr);
674 448
675 449
676 struct x86_pde *pd = (struct x86_pde*) 450 struct x86_pde *pd = (struct x86_pde*)
677 (SOS_PAGING_MIRROR_VADDR 451 (SOS_PAGING_MIRROR_VADDR
678 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGI 452 + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
679 453
680 454
681 struct x86_pte * pt = (struct x86_pte*) (SOS 455 struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
682 + S 456 + SOS_PAGE_SIZE*index_in_pd);
683 457
684 458
685 if (! pd[index_in_pd].present) 459 if (! pd[index_in_pd].present)
686 return (sos_paddr_t)NULL; 460 return (sos_paddr_t)NULL;
687 if (! pt[index_in_pt].present) 461 if (! pt[index_in_pt].present)
688 return (sos_paddr_t)NULL; 462 return (sos_paddr_t)NULL;
689 463
690 return (pt[index_in_pt].paddr << 12) + offse 464 return (pt[index_in_pt].paddr << 12) + offset_in_page;
691 } <<
692 <<
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 } 465 }