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