Rev 4424 | Rev 4619 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4424 | Rev 4608 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Line 7... | Line 7... | ||
7 | 7 | ||
Line -... | Line 8... | ||
- | 8 | $Revision: 4608 $ |
|
- | 9 | ||
Line 8... | Line -... | ||
8 | $Revision: 4424 $ |
- | |
9 | - | ||
10 | - | ||
11 | align 4 |
- | |
12 | proc alloc_page |
- | |
13 | - | ||
14 | pushfd |
- | |
15 | cli |
- | |
16 | push ebx |
- | |
17 | ;//- |
- | |
18 | cmp [pg_data.pages_free], 1 |
- | |
19 | jle .out_of_memory |
- | |
20 | ;//- |
- | |
21 | - | ||
22 | mov ebx, [page_start] |
- | |
23 | mov ecx, [page_end] |
- | |
24 | .l1: |
- | |
25 | bsf eax, [ebx]; |
- | |
26 | jnz .found |
- | |
27 | add ebx, 4 |
- | |
28 | cmp ebx, ecx |
- | |
29 | jb .l1 |
- | |
30 | pop ebx |
- | |
31 | popfd |
- | |
32 | xor eax, eax |
- | |
33 | ret |
- | |
34 | .found: |
- | |
35 | ;//- |
- | |
36 | dec [pg_data.pages_free] |
- | |
37 | jz .out_of_memory |
- | |
38 | ;//- |
- | |
39 | btr [ebx], eax |
- | |
40 | mov [page_start], ebx |
- | |
41 | sub ebx, sys_pgmap |
- | |
42 | lea eax, [eax+ebx*8] |
- | |
43 | shl eax, 12 |
- | |
44 | ;//- dec [pg_data.pages_free] |
- | |
45 | pop ebx |
- | |
46 | popfd |
- | |
47 | ret |
- | |
48 | ;//- |
- | |
49 | .out_of_memory: |
- | |
50 | mov [pg_data.pages_free], 1 |
- | |
51 | xor eax, eax |
- | |
52 | pop ebx |
- | |
53 | popfd |
- | |
54 | ret |
- | |
55 | ;//- |
- | |
56 | endp |
- | |
57 | - | ||
58 | align 4 |
- | |
59 | proc alloc_pages stdcall, count:dword |
- | |
60 | pushfd |
- | |
61 | push ebx |
- | |
62 | push edi |
- | |
63 | cli |
- | |
64 | mov eax, [count] |
- | |
65 | add eax, 7 |
- | |
66 | shr eax, 3 |
- | |
67 | mov [count], eax |
- | |
68 | ;//- |
- | |
69 | mov ebx, [pg_data.pages_free] |
- | |
70 | sub ebx, 9 |
- | |
71 | js .out_of_memory |
- | |
72 | shr ebx, 3 |
- | |
73 | cmp eax, ebx |
- | |
74 | jg .out_of_memory |
- | |
75 | ;//- |
- | |
76 | mov ecx, [page_start] |
- | |
77 | mov ebx, [page_end] |
- | |
78 | .find: |
- | |
79 | mov edx, [count] |
- | |
80 | mov edi, ecx |
- | |
81 | .match: |
- | |
82 | cmp byte [ecx], 0xFF |
- | |
83 | jne .next |
- | |
84 | dec edx |
- | |
85 | jz .ok |
- | |
86 | inc ecx |
- | |
87 | cmp ecx, ebx |
- | |
88 | jb .match |
- | |
89 | .out_of_memory: |
- | |
90 | .fail: |
- | |
91 | xor eax, eax |
- | |
92 | pop edi |
- | |
93 | pop ebx |
- | |
94 | popfd |
- | |
95 | ret |
- | |
96 | .next: |
- | |
97 | inc ecx |
- | |
98 | cmp ecx, ebx |
- | |
99 | jb .find |
- | |
100 | pop edi |
- | |
101 | pop ebx |
- | |
102 | popfd |
- | |
103 | xor eax, eax |
- | |
104 | ret |
- | |
105 | .ok: |
- | |
106 | sub ecx, edi |
- | |
107 | inc ecx |
- | |
108 | push esi |
- | |
109 | mov esi, edi |
- | |
110 | xor eax, eax |
- | |
111 | rep stosb |
- | |
112 | sub esi, sys_pgmap |
- | |
113 | shl esi, 3+12 |
- | |
114 | mov eax, esi |
- | |
115 | mov ebx, [count] |
- | |
116 | shl ebx, 3 |
- | |
117 | sub [pg_data.pages_free], ebx |
- | |
118 | pop esi |
- | |
119 | pop edi |
- | |
120 | pop ebx |
- | |
121 | popfd |
- | |
122 | ret |
- | |
123 | endp |
- | |
124 | - | ||
125 | align 4 |
- | |
126 | ;proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword |
- | |
127 | map_page: |
- | |
128 | push ebx |
- | |
129 | mov eax, [esp+12] ; phis_addr |
- | |
130 | and eax, not 0xFFF |
- | |
131 | or eax, [esp+16] ; flags |
- | |
132 | mov ebx, [esp+8] ; lin_addr |
- | |
133 | shr ebx, 12 |
- | |
134 | mov [page_tabs+ebx*4], eax |
- | |
135 | mov eax, [esp+8] ; lin_addr |
- | |
136 | pop ebx |
- | |
137 | invlpg [eax] |
- | |
138 | ret 12 |
- | |
139 | - | ||
140 | align 4 |
- | |
141 | map_space: ;not implemented |
- | |
142 | - | ||
143 | - | ||
144 | ret |
- | |
145 | - | ||
146 | - | ||
147 | align 4 |
- | |
148 | proc free_page |
- | |
149 | ;arg: eax page address |
- | |
150 | pushfd |
- | |
151 | cli |
- | |
152 | shr eax, 12 ;page index |
- | |
153 | bts dword [sys_pgmap], eax ;that's all! |
- | |
154 | cmc |
- | |
155 | adc [pg_data.pages_free], 0 |
- | |
156 | shr eax, 3 |
- | |
157 | and eax, not 3 ;dword offset from page_map |
- | |
158 | add eax, sys_pgmap |
- | |
159 | cmp [page_start], eax |
- | |
160 | ja @f |
- | |
161 | popfd |
- | |
162 | ret |
- | |
163 | @@: |
- | |
164 | mov [page_start], eax |
- | |
165 | popfd |
- | |
166 | ret |
- | |
167 | endp |
- | |
168 | - | ||
169 | align 4 |
- | |
170 | proc map_io_mem stdcall, base:dword, size:dword, flags:dword |
- | |
171 | - | ||
172 | push ebx |
- | |
173 | push edi |
- | |
174 | mov eax, [size] |
- | |
175 | add eax, [base] |
- | |
176 | add eax, 4095 |
- | |
177 | and eax, -4096 |
- | |
178 | mov ecx, [base] |
- | |
179 | and ecx, -4096 |
- | |
180 | sub eax, ecx |
- | |
181 | mov [size], eax |
- | |
182 | - | ||
183 | stdcall alloc_kernel_space, eax |
- | |
184 | test eax, eax |
- | |
185 | jz .fail |
- | |
186 | push eax |
- | |
187 | - | ||
188 | mov edi, 0x1000 |
- | |
189 | mov ebx, eax |
- | |
190 | mov ecx, [size] |
- | |
191 | mov edx, [base] |
- | |
192 | shr eax, 12 |
- | |
193 | shr ecx, 12 |
- | |
194 | and edx, -4096 |
- | |
195 | or edx, [flags] |
- | |
196 | @@: |
- | |
197 | mov [page_tabs+eax*4], edx |
- | |
198 | invlpg [ebx] |
- | |
199 | inc eax |
- | |
200 | add ebx, edi |
- | |
201 | add edx, edi |
- | |
202 | loop @B |
- | |
203 | - | ||
204 | pop eax |
- | |
205 | mov edx, [base] |
- | |
206 | and edx, 4095 |
- | |
207 | add eax, edx |
- | |
208 | .fail: |
- | |
209 | pop edi |
- | |
210 | pop ebx |
- | |
211 | ret |
- | |
212 | endp |
- | |
213 | - | ||
214 | ; param |
- | |
215 | ; eax= page base + page flags |
- | |
216 | ; ebx= linear address |
- | |
217 | ; ecx= count |
- | |
218 | - | ||
219 | align 4 |
- | |
220 | commit_pages: |
- | |
221 | test ecx, ecx |
- | |
222 | jz .fail |
- | |
223 | - | ||
224 | push edi |
- | |
225 | push eax |
- | |
226 | push ecx |
- | |
227 | mov ecx, pg_data.mutex |
- | |
228 | call mutex_lock |
- | |
229 | pop ecx |
- | |
230 | pop eax |
- | |
231 | - | ||
232 | mov edi, ebx |
- | |
233 | shr edi, 12 |
- | |
234 | lea edi, [page_tabs+edi*4] |
- | |
235 | @@: |
- | |
236 | stosd |
- | |
237 | invlpg [ebx] |
- | |
238 | add eax, 0x1000 |
- | |
239 | add ebx, 0x1000 |
- | |
240 | loop @B |
- | |
241 | - | ||
242 | pop edi |
- | |
243 | - | ||
244 | mov ecx, pg_data.mutex |
- | |
245 | call mutex_unlock |
- | |
246 | .fail: |
- | |
247 | ret |
- | |
248 | - | ||
249 | - | ||
250 | ; param |
- | |
251 | ; eax= base |
- | |
252 | ; ecx= count |
- | |
253 | - | ||
254 | align 4 |
- | |
255 | release_pages: |
- | |
256 | - | ||
257 | push ebp |
- | |
258 | push esi |
- | |
259 | push edi |
- | |
260 | push ebx |
- | |
261 | - | ||
262 | mov esi, eax |
- | |
263 | mov edi, eax |
- | |
264 | - | ||
265 | shr esi, 12 |
- | |
266 | lea esi, [page_tabs+esi*4] |
- | |
267 | - | ||
268 | push ecx |
- | |
269 | mov ecx, pg_data.mutex |
- | |
270 | call mutex_lock |
- | |
271 | pop ecx |
- | |
272 | - | ||
273 | mov ebp, [pg_data.pages_free] |
- | |
274 | mov ebx, [page_start] |
- | |
275 | mov edx, sys_pgmap |
- | |
276 | @@: |
- | |
277 | xor eax, eax |
- | |
278 | xchg eax, [esi] |
- | |
279 | invlpg [edi] |
- | |
280 | - | ||
281 | test eax, 1 |
- | |
282 | jz .next |
- | |
283 | - | ||
284 | shr eax, 12 |
- | |
285 | bts [edx], eax |
- | |
286 | cmc |
- | |
287 | adc ebp, 0 |
- | |
288 | shr eax, 3 |
- | |
289 | and eax, -4 |
- | |
290 | add eax, edx |
- | |
291 | cmp eax, ebx |
- | |
292 | jae .next |
- | |
293 | - | ||
294 | mov ebx, eax |
- | |
295 | .next: |
- | |
296 | add edi, 0x1000 |
- | |
297 | add esi, 4 |
- | |
298 | loop @B |
- | |
299 | - | ||
300 | mov [pg_data.pages_free], ebp |
- | |
301 | mov ecx, pg_data.mutex |
- | |
302 | call mutex_unlock |
- | |
303 | - | ||
304 | pop ebx |
- | |
305 | pop edi |
- | |
306 | pop esi |
- | |
307 | pop ebp |
- | |
308 | ret |
- | |
309 | - | ||
310 | ; param |
- | |
311 | ; eax= base |
- | |
312 | ; ecx= count |
- | |
313 | - | ||
314 | align 4 |
- | |
315 | unmap_pages: |
- | |
316 | - | ||
317 | push edi |
- | |
318 | - | ||
319 | mov edi, eax |
- | |
320 | mov edx, eax |
- | |
321 | - | ||
322 | shr edi, 10 |
- | |
323 | add edi, page_tabs |
- | |
324 | - | ||
325 | xor eax, eax |
- | |
326 | @@: |
- | |
327 | stosd |
- | |
328 | invlpg [edx] |
- | |
329 | add edx, 0x1000 |
- | |
330 | loop @b |
- | |
331 | - | ||
332 | pop edi |
- | |
333 | ret |
- | |
334 | - | ||
335 | - | ||
336 | align 4 |
- | |
337 | proc map_page_table stdcall, lin_addr:dword, phis_addr:dword |
- | |
338 | push ebx |
- | |
339 | mov ebx, [lin_addr] |
- | |
340 | shr ebx, 22 |
- | |
341 | mov eax, [phis_addr] |
- | |
342 | and eax, not 0xFFF |
- | |
343 | or eax, PG_UW ;+PG_NOCACHE |
- | |
344 | mov dword [master_tab+ebx*4], eax |
- | |
345 | mov eax, [lin_addr] |
- | |
346 | shr eax, 10 |
- | |
347 | add eax, page_tabs |
- | |
348 | invlpg [eax] |
- | |
349 | pop ebx |
- | |
350 | ret |
- | |
351 | endp |
- | |
352 | - | ||
353 | align 4 |
- | |
354 | proc init_LFB |
- | |
355 | locals |
- | |
356 | pg_count dd ? |
- | |
357 | endl |
- | |
358 | 10 | ; Initializes MTRRs. |
|
359 | cmp dword [LFBAddress], -1 |
- | |
360 | jne @f |
- | |
361 | mov [BOOT_VARS+BOOT_MTRR], byte 2 |
- | |
362 | ; max VGA=640*480*4=1228800 bytes |
- | |
363 | ; + 32*640*4=81920 bytes for mouse pointer |
- | |
364 | stdcall alloc_pages, ((1228800+81920)/4096) |
- | |
365 | - | ||
366 | push eax |
- | |
367 | call alloc_page |
- | |
368 | stdcall map_page_table, LFB_BASE, eax |
- | |
369 | pop eax |
- | |
370 | or eax, PG_UW |
- | |
371 | mov ebx, LFB_BASE |
- | |
372 | ; max VGA=640*480*4=1228800 bytes |
- | |
373 | ; + 32*640*4=81920 bytes for mouse pointer |
- | |
374 | mov ecx, (1228800+81920)/4096 |
- | |
375 | call commit_pages |
- | |
376 | mov [LFBAddress], dword LFB_BASE |
- | |
377 | ret |
- | |
378 | @@: |
- | |
379 | test [SCR_MODE], word 0100000000000000b |
- | |
380 | jnz @f |
- | |
381 | mov [BOOT_VARS+BOOT_MTRR], byte 2 |
- | |
382 | ret |
- | |
383 | @@: |
- | |
384 | call init_mtrr |
- | |
385 | - | ||
386 | mov edx, LFB_BASE |
- | |
387 | mov esi, [LFBAddress] |
- | |
388 | mov edi, 0x00C00000 |
- | |
389 | mov dword [exp_lfb+4], edx |
- | |
390 | - | ||
391 | shr edi, 12 |
- | |
392 | mov [pg_count], edi |
- | |
393 | shr edi, 10 |
- | |
394 | - | ||
395 | bt [cpu_caps], CAPS_PSE |
- | |
396 | jnc .map_page_tables |
- | |
397 | or esi, PG_LARGE+PG_UW |
- | |
398 | mov edx, sys_pgdir+(LFB_BASE shr 20) |
- | |
399 | @@: |
- | |
400 | mov [edx], esi |
- | |
401 | add edx, 4 |
- | |
402 | add esi, 0x00400000 |
- | |
403 | dec edi |
- | |
404 | jnz @B |
- | |
405 | - | ||
406 | bt [cpu_caps], CAPS_PGE |
- | |
407 | jnc @F |
- | |
408 | or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL |
- | |
409 | @@: |
- | |
410 | mov dword [LFBAddress], LFB_BASE |
- | |
411 | mov eax, cr3 ;flush TLB |
- | |
412 | mov cr3, eax |
- | |
413 | ret |
- | |
414 | - | ||
415 | .map_page_tables: |
- | |
416 | - | ||
417 | @@: |
- | |
418 | call alloc_page |
- | |
419 | stdcall map_page_table, edx, eax |
- | |
420 | add edx, 0x00400000 |
- | |
421 | dec edi |
- | |
422 | jnz @B |
- | |
423 | - | ||
424 | mov eax, [LFBAddress] |
- | |
425 | mov edi, page_tabs + (LFB_BASE shr 10) |
- | |
426 | or eax, PG_UW |
- | |
427 | mov ecx, [pg_count] |
- | |
428 | cld |
- | |
429 | @@: |
- | |
430 | stosd |
- | |
431 | add eax, 0x1000 |
- | |
432 | dec ecx |
- | |
433 | jnz @B |
- | |
434 | - | ||
435 | mov dword [LFBAddress], LFB_BASE |
- | |
436 | mov eax, cr3 ;flush TLB |
- | |
437 | mov cr3, eax |
- | |
438 | - | ||
439 | ret |
- | |
440 | endp |
- | |
441 | - | ||
442 | align 4 |
- | |
443 | proc new_mem_resize stdcall, new_size:dword |
- | |
444 | - | ||
445 | push ebx |
- | |
446 | push esi |
- | |
447 | push edi |
- | |
448 | - | ||
449 | mov edx, [current_slot] |
- | |
450 | cmp [edx+APPDATA.heap_base], 0 |
- | |
451 | jne .exit |
- | |
452 | - | ||
453 | mov edi, [new_size] |
- | |
454 | add edi, 4095 |
- | |
455 | and edi, not 4095 |
- | |
456 | mov [new_size], edi |
- | |
457 | - | ||
458 | mov esi, [edx+APPDATA.mem_size] |
- | |
459 | add esi, 4095 |
- | |
460 | and esi, not 4095 |
- | |
461 | 11 | proc init_mtrr |
|
Line 462... | Line -... | ||
462 | cmp edi, esi |
- | |
463 | ja .expand |
- | |
464 | je .exit |
- | |
465 | - | ||
466 | mov ebx, edi |
- | |
467 | shr edi, 12 |
- | |
468 | shr esi, 12 |
- | |
469 | 12 | ||
470 | mov ecx, pg_data.mutex |
- | |
471 | call mutex_lock |
13 | cmp [BOOT_VARS+BOOT_MTRR], byte 2 |
Line 472... | Line -... | ||
472 | @@: |
- | |
473 | mov eax, [app_page_tabs+edi*4] |
14 | je .exit |
474 | test eax, 1 |
15 | |
Line 475... | Line -... | ||
475 | jz .next |
- | |
476 | - | ||
477 | mov dword [app_page_tabs+edi*4], 0 |
- | |
478 | invlpg [ebx] |
- | |
479 | call free_page |
- | |
480 | - | ||
481 | .next: |
- | |
482 | inc edi |
- | |
483 | add ebx, 0x1000 |
- | |
484 | cmp edi, esi |
- | |
485 | jb @B |
- | |
486 | - | ||
487 | mov ecx, pg_data.mutex |
- | |
488 | call mutex_unlock |
16 | bt [cpu_caps], CAPS_MTRR |
489 | - | ||
490 | .update_size: |
- | |
491 | mov edx, [current_slot] |
- | |
492 | mov ebx, [new_size] |
- | |
493 | call update_mem_size |
- | |
494 | .exit: |
- | |
495 | pop edi |
- | |
496 | pop esi |
- | |
497 | pop ebx |
- | |
498 | xor eax, eax |
- | |
499 | ret |
- | |
500 | - | ||
501 | .expand: |
- | |
502 | - | ||
503 | mov ecx, pg_data.mutex |
- | |
504 | call mutex_lock |
- | |
505 | - | ||
506 | xchg esi, edi |
- | |
507 | - | ||
508 | push esi ;new size |
- | |
509 | push edi ;old size |
- | |
510 | - | ||
511 | add edi, 0x3FFFFF |
- | |
512 | and edi, not(0x3FFFFF) |
- | |
513 | add esi, 0x3FFFFF |
- | |
514 | and esi, not(0x3FFFFF) |
- | |
515 | - | ||
516 | cmp edi, esi |
- | |
517 | jae .grow |
- | |
518 | @@: |
- | |
519 | call alloc_page |
- | |
520 | test eax, eax |
- | |
521 | jz .exit_fail |
- | |
522 | - | ||
523 | stdcall map_page_table, edi, eax |
- | |
524 | - | ||
525 | push edi |
- | |
526 | shr edi, 10 |
- | |
527 | add edi, page_tabs |
- | |
528 | mov ecx, 1024 |
- | |
529 | xor eax, eax |
- | |
530 | cld |
- | |
531 | rep stosd |
- | |
532 | pop edi |
- | |
533 | - | ||
534 | add edi, 0x00400000 |
- | |
535 | cmp edi, esi |
- | |
536 | jb @B |
- | |
537 | .grow: |
- | |
538 | pop edi ;old size |
- | |
539 | pop ecx ;new size |
- | |
540 | - | ||
541 | shr edi, 10 |
- | |
542 | shr ecx, 10 |
- | |
543 | sub ecx, edi |
- | |
544 | shr ecx, 2 ;pages count |
- | |
545 | mov eax, 2 |
- | |
546 | - | ||
547 | add edi, app_page_tabs |
- | |
548 | rep stosd |
- | |
549 | - | ||
550 | mov ecx, pg_data.mutex |
- | |
551 | call mutex_unlock |
- | |
552 | - | ||
553 | jmp .update_size |
- | |
554 | - | ||
555 | .exit_fail: |
- | |
556 | mov ecx, pg_data.mutex |
- | |
557 | call mutex_unlock |
- | |
558 | - | ||
559 | add esp, 8 |
17 | jnc .exit |
560 | pop edi |
18 | |
Line 561... | Line -... | ||
561 | pop esi |
- | |
562 | pop ebx |
- | |
563 | xor eax, eax |
- | |
564 | inc eax |
- | |
565 | ret |
- | |
566 | endp |
- | |
567 | - | ||
568 | 19 | call mtrr_reconfigure |
|
569 | align 4 |
20 | stdcall set_mtrr, [LFBAddress], 0x1000000, MEM_WC |
570 | update_mem_size: |
21 | |
571 | ; in: edx = slot base |
- | |
572 | ; ebx = new memory size |
22 | .exit: |
573 | ; destroys eax,ecx,edx |
- | |
574 | - | ||
575 | mov [APPDATA.mem_size+edx], ebx |
- | |
576 | ;search threads and update |
- | |
577 | ;application memory size infomation |
- | |
578 | mov ecx, [APPDATA.dir_table+edx] |
- | |
579 | mov eax, 2 |
23 | ret |
580 | 24 | endp |
|
581 | .search_threads: |
- | |
582 | ;eax = current slot |
- | |
583 | ;ebx = new memory size |
- | |
584 | ;ecx = page directory |
- | |
585 | cmp eax, [TASK_COUNT] |
- | |
586 | jg .search_threads_end |
25 | |
587 | mov edx, eax |
- | |
588 | shl edx, 5 |
- | |
589 | cmp word [CURRENT_TASK+edx+TASKDATA.state], 9 ;if slot empty? |
- | |
590 | jz .search_threads_next |
- | |
591 | shl edx, 3 |
- | |
592 | cmp [SLOT_BASE+edx+APPDATA.dir_table], ecx ;if it is our thread? |
- | |
593 | jnz .search_threads_next |
- | |
594 | mov [SLOT_BASE+edx+APPDATA.mem_size], ebx ;update memory size |
- | |
595 | .search_threads_next: |
- | |
596 | inc eax |
- | |
597 | jmp .search_threads |
- | |
598 | .search_threads_end: |
- | |
599 | ret |
- | |
600 | - | ||
601 | ; param |
- | |
602 | ; eax= linear address |
- | |
603 | ; |
- | |
604 | ; retval |
- | |
605 | ; eax= phisical page address |
- | |
606 | - | ||
607 | align 4 |
- | |
608 | get_pg_addr: |
- | |
609 | sub eax, OS_BASE |
26 | ; Helper procedure for mtrr_reconfigure and set_mtrr, |
- | 27 | ; called before changes in MTRRs. |
|
Line 610... | Line -... | ||
610 | cmp eax, 0x400000 |
- | |
611 | jb @f |
- | |
612 | shr eax, 12 |
28 | proc mtrr_begin_change |
613 | mov eax, [page_tabs+(eax+(OS_BASE shr 12))*4] |
29 | mov eax, cr0 |
614 | @@: |
- | |
615 | and eax, 0xFFFFF000 |
30 | or eax, 0x60000000 ;disable caching |
616 | ret |
- | |
617 | 31 | mov cr0, eax |
|
618 | - | ||
619 | align 4 |
32 | wbinvd ;invalidate cache |
620 | ; Now it is called from core/sys32::exc_c (see stack frame there) |
- | |
621 | proc page_fault_handler |
- | |
622 | - | ||
623 | .err_addr equ ebp-4 |
33 | ret |
624 | - | ||
625 | push ebx ;save exception number (#PF) |
- | |
626 | mov ebp, esp |
- | |
627 | mov ebx, cr2 |
- | |
628 | push ebx ;that is locals: .err_addr = cr2 |
- | |
629 | inc [pg_data.pages_faults] |
- | |
630 | - | ||
631 | mov eax, [pf_err_code] |
- | |
632 | - | ||
633 | cmp ebx, OS_BASE ;ebx == .err_addr |
- | |
634 | jb .user_space ;страница в памяти приложения ; |
- | |
635 | - | ||
636 | cmp ebx, page_tabs |
- | |
637 | jb .kernel_space ;страница в памяти ядра |
- | |
638 | - | ||
639 | cmp ebx, kernel_tabs |
- | |
640 | jb .alloc;.app_tabs ;таблицы страниц приложения ; |
34 | endp |
641 | ;просто создадим одну |
- | |
642 | if 0 ;пока это просто лишнее |
- | |
643 | cmp ebx, LFB_BASE |
- | |
644 | jb .core_tabs ;таблицы страниц ядра |
- | |
645 | ;Ошибка |
- | |
646 | .lfb: |
- | |
647 | ;область LFB |
35 | |
648 | ;Ошибка |
- | |
649 | jmp .fail |
- | |
650 | end if |
- | |
651 | .core_tabs: |
- | |
652 | .fail: ;simply return to caller |
- | |
653 | mov esp, ebp |
- | |
654 | pop ebx ;restore exception number (#PF) |
- | |
655 | ret |
- | |
656 | - | ||
657 | ; xchg bx, bx |
- | |
658 | ; add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller |
- | |
659 | ; restore_ring3_context |
- | |
660 | ; iretd |
- | |
661 | - | ||
662 | .user_space: |
- | |
663 | test eax, PG_MAP |
- | |
664 | jnz .err_access ;Страница присутствует |
- | |
665 | ;Ошибка доступа ? |
- | |
666 | - | ||
667 | shr ebx, 12 |
- | |
668 | mov ecx, ebx |
- | |
669 | shr ecx, 10 |
- | |
670 | mov edx, [master_tab+ecx*4] |
- | |
671 | test edx, PG_MAP |
- | |
672 | jz .fail ;таблица страниц не создана |
- | |
673 | ;неверный адрес в программе |
- | |
674 | - | ||
675 | mov eax, [page_tabs+ebx*4] |
- | |
676 | test eax, 2 |
- | |
677 | jz .fail ;адрес не зарезервирован для ; |
- | |
678 | ;использования. Ошибка |
- | |
679 | .alloc: |
- | |
680 | call alloc_page |
- | |
681 | test eax, eax |
- | |
682 | jz .fail |
- | |
683 | - | ||
684 | stdcall map_page, [.err_addr], eax, PG_UW |
- | |
685 | - | ||
686 | mov edi, [.err_addr] |
- | |
687 | and edi, 0xFFFFF000 |
- | |
688 | mov ecx, 1024 |
- | |
689 | xor eax, eax |
- | |
690 | ;cld ;caller is duty for this |
- | |
691 | rep stosd |
- | |
692 | .exit: ;iret with repeat fault instruction |
- | |
693 | add esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller |
- | |
694 | restore_ring3_context |
- | |
695 | iretd |
- | |
696 | - | ||
697 | .err_access: |
- | |
698 | ; access denied? this may be a result of copy-on-write protection for DLL |
- | |
699 | ; check list of HDLLs |
- | |
700 | and ebx, not 0xFFF |
- | |
701 | mov eax, [CURRENT_TASK] |
- | |
702 | shl eax, 8 |
- | |
703 | mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
- | |
704 | test eax, eax |
- | |
705 | jz .fail |
- | |
706 | mov esi, [eax+HDLL.fd] |
- | |
707 | .scan_hdll: |
- | |
708 | cmp esi, eax |
- | |
709 | jz .fail |
- | |
710 | mov edx, ebx |
- | |
711 | sub edx, [esi+HDLL.base] |
- | |
712 | cmp edx, [esi+HDLL.size] |
- | |
713 | jb .fault_in_hdll |
- | |
714 | .scan_hdll.next: |
- | |
715 | mov esi, [esi+HDLL.fd] |
- | |
716 | jmp .scan_hdll |
- | |
717 | .fault_in_hdll: |
- | |
718 | ; allocate new page, map it as rw and copy data |
- | |
719 | call alloc_page |
- | |
720 | test eax, eax |
- | |
721 | jz .fail |
- | |
722 | stdcall map_page, ebx, eax, PG_UW |
- | |
723 | mov edi, ebx |
- | |
724 | mov ecx, 1024 |
- | |
725 | sub ebx, [esi+HDLL.base] |
- | |
726 | mov esi, [esi+HDLL.parent] |
- | |
727 | mov esi, [esi+DLLDESCR.data] |
- | |
728 | add esi, ebx |
- | |
729 | rep movsd |
- | |
730 | jmp .exit |
- | |
731 | - | ||
732 | .kernel_space: |
- | |
733 | test eax, PG_MAP |
- | |
734 | jz .fail ;страница не присутствует |
- | |
735 | - | ||
736 | test eax, 12 ;U/S (+below) |
- | |
737 | jnz .fail ;приложение обратилось к памяти |
- | |
738 | ;ядра |
- | |
739 | ;test eax, 8 |
- | |
740 | ;jnz .fail ;установлен зарезервированный бит |
- | |
741 | ;в таблицах страниц. добавлено в P4/Xeon |
- | |
742 | - | ||
743 | ;попытка записи в защищённую страницу ядра |
- | |
744 | - | ||
745 | cmp ebx, tss._io_map_0 |
- | |
746 | jb .fail |
- | |
747 | - | ||
748 | cmp ebx, tss._io_map_0+8192 |
- | |
749 | jae .fail |
- | |
750 | - | ||
751 | ; io permission map |
- | |
752 | ; copy-on-write protection |
- | |
753 | - | ||
754 | call alloc_page |
- | |
755 | test eax, eax |
- | |
756 | jz .fail |
- | |
757 | - | ||
758 | push eax |
- | |
759 | stdcall map_page, [.err_addr], eax, dword PG_SW |
- | |
760 | pop eax |
- | |
761 | mov edi, [.err_addr] |
- | |
762 | and edi, -4096 |
- | |
763 | lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0 |
- | |
764 | - | ||
765 | mov ebx, esi |
- | |
766 | shr ebx, 12 |
- | |
767 | mov edx, [current_slot] |
- | |
768 | or eax, PG_SW |
36 | ; Helper procedure for mtrr_reconfigure and set_mtrr, |
Line 769... | Line 37... | ||
769 | mov [edx+APPDATA.io_map+ebx*4], eax |
37 | ; called after changes in MTRRs. |
770 | 38 | proc mtrr_end_change |
|
771 | add esi, [default_io_map] |
- | |
772 | mov ecx, 4096/4 |
39 | wbinvd ;again invalidate |
773 | ;cld ;caller is duty for this |
40 | mov eax, cr0 |
774 | rep movsd |
41 | and eax, not 0x60000000 |
775 | jmp .exit |
42 | mov cr0, eax ; enable caching |
776 | endp |
- | |
777 | 43 | ret |
|
778 | ; returns number of mapped bytes |
44 | endp |
779 | proc map_mem stdcall, lin_addr:dword,slot:dword,\ |
45 | |
780 | ofs:dword,buf_size:dword,req_access:dword |
46 | ; Some limits to number of structures located in the stack. |
- | 47 | MAX_USEFUL_MTRRS = 16 |
|
781 | push 0 ; initialize number of mapped bytes |
48 | MAX_RANGES = 16 |
782 | - | ||
783 | cmp [buf_size], 0 |
49 | |
784 | jz .exit |
50 | ; mtrr_reconfigure keeps a list of MEM_WB ranges. |
785 | 51 | ; This structure describes one item in the list. |
|
- | 52 | struct mtrr_range |
|
- | 53 | next dd ? ; next item |
|
786 | mov eax, [slot] |
54 | start dq ? ; first byte |
787 | shl eax, 8 |
55 | length dq ? ; length in bytes |
788 | mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
56 | ends |
789 | and eax, 0xFFFFF000 |
- | |
790 | 57 | ||
791 | stdcall map_page, [ipc_pdir], eax, PG_UW |
- | |
792 | mov ebx, [ofs] |
58 | uglobal |
793 | shr ebx, 22 |
59 | align 4 |
794 | mov esi, [ipc_pdir] |
60 | num_variable_mtrrs dd 0 ; number of variable-range MTRRs |
795 | mov edi, [ipc_ptab] |
- | |
796 | mov eax, [esi+ebx*4] |
61 | endg |
797 | and eax, 0xFFFFF000 |
62 | |
798 | jz .exit |
- | |
799 | stdcall map_page, edi, eax, PG_UW |
- | |
800 | ; inc ebx |
63 | ; Helper procedure for MTRR initialization. |
801 | ; add edi, 0x1000 |
64 | ; Takes MTRR configured by BIOS and tries to recongifure them |
802 | ; mov eax, [esi+ebx*4] |
65 | ; in order to allow non-UC data at top of 4G memory. |
803 | ; test eax, eax |
66 | ; Example: if low part of physical memory is 3.5G = 0xE0000000 bytes wide, |
804 | ; jz @f |
67 | ; BIOS can configure two MTRRs so that the first MTRR describes [0, 4G) as WB |
805 | ; and eax, 0xFFFFF000 |
68 | ; and the second MTRR describes [3.5G, 4G) as UC; |
806 | ; stdcall map_page, edi, eax |
- | |
807 | 69 | ; WB+UC=UC, so the resulting memory map would be as needed, |
|
808 | @@: |
70 | ; but in this configuration our attempts to map LFB at (say) 0xE8000000 as WC |
809 | mov edi, [lin_addr] |
71 | ; would be ignored, WB+UC+WC is still UC. |
810 | and edi, 0xFFFFF000 |
72 | ; So we must keep top of 4G memory not covered by MTRRs, |
811 | mov ecx, [buf_size] |
- | |
812 | add ecx, 4095 |
73 | ; using three WB MTRRs [0,2G) + [2G,3G) + [3G,3.5G), |
813 | shr ecx, 12 |
74 | ; this gives the same memory map, but allows to add further entries. |
814 | inc ecx |
75 | ; See mtrrtest.asm for detailed input/output from real hardware+BIOS. |
815 | - | ||
816 | mov edx, [ofs] |
76 | proc mtrr_reconfigure |
817 | shr edx, 12 |
77 | push ebp ; we're called from init_LFB, and it feels hurt when ebp is destroyed |
818 | and edx, 0x3FF |
- | |
819 | mov esi, [ipc_ptab] |
- | |
820 | - | ||
821 | .map: |
- | |
822 | stdcall safe_map_page, [slot], [req_access], [ofs] |
78 | ; 1. Prepare local variables. |
823 | jnc .exit |
- | |
824 | add dword [ebp-4], 4096 |
79 | ; 1a. Create list of MAX_RANGES free (aka not yet allocated) ranges. |
825 | add [ofs], 4096 |
80 | xor eax, eax |
826 | dec ecx |
- | |
827 | jz .exit |
- | |
828 | add edi, 0x1000 |
- | |
829 | inc edx |
81 | lea ecx, [eax+MAX_RANGES] |
- | 82 | .init_ranges: |
|
- | 83 | sub esp, sizeof.mtrr_range - 4 |
|
- | 84 | push eax |
|
- | 85 | mov eax, esp |
|
- | 86 | dec ecx |
|
- | 87 | jnz .init_ranges |
|
830 | cmp edx, 0x400 |
88 | mov eax, esp |
831 | jnz .map |
- | |
- | 89 | ; 1b. Fill individual local variables. |
|
- | 90 | xor edx, edx |
|
832 | inc ebx |
91 | sub esp, MAX_USEFUL_MTRRS * 16 ; .mtrrs |
- | 92 | push edx ; .mtrrs_end |
|
833 | mov eax, [ipc_pdir] |
93 | push edx ; .num_used_mtrrs |
834 | mov eax, [eax+ebx*4] |
94 | push eax ; .first_free_range |
835 | and eax, 0xFFFFF000 |
95 | push edx ; .first_range: no ranges yet |
836 | jz .exit |
- | |
837 | stdcall map_page, esi, eax, PG_UW |
96 | mov cl, [cpu_phys_addr_width] |
838 | xor edx, edx |
97 | or eax, -1 |
839 | jmp .map |
98 | shl eax, cl ; note: this uses cl&31 = cl-32, not the entire cl |
- | 99 | push eax ; .phys_reserved_mask |
|
840 | 100 | virtual at esp |
|
- | 101 | .phys_reserved_mask dd ? |
|
- | 102 | .first_range dd ? |
|
841 | .exit: |
103 | .first_free_range dd ? |
842 | pop eax |
104 | .num_used_mtrrs dd ? |
843 | ret |
- | |
844 | endp |
105 | .mtrrs_end dd ? |
845 | 106 | .mtrrs rq MAX_USEFUL_MTRRS * 2 |
|
846 | proc map_memEx stdcall, lin_addr:dword,slot:dword,\ |
107 | .local_vars_size = $ - esp |
- | 108 | end virtual |
|
847 | ofs:dword,buf_size:dword,req_access:dword |
109 | |
848 | push 0 ; initialize number of mapped bytes |
110 | ; 2. Get the number of variable-range MTRRs from MTRRCAP register. |
849 | 111 | ; Abort if zero. |
|
850 | cmp [buf_size], 0 |
112 | mov ecx, 0xFE |
- | 113 | rdmsr |
|
- | 114 | test al, al |
|
- | 115 | jz .abort |
|
851 | jz .exit |
116 | mov byte [num_variable_mtrrs], al |
852 | 117 | ; 3. Validate MTRR_DEF_TYPE register. |
|
853 | mov eax, [slot] |
118 | mov ecx, 0x2FF |
854 | shl eax, 8 |
119 | rdmsr |
- | 120 | ; If BIOS has not initialized variable-range MTRRs, fallback to step 7. |
|
- | 121 | test ah, 8 |
|
855 | mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
122 | jz .fill_ranges_from_memory_map |
856 | and eax, 0xFFFFF000 |
123 | ; If the default memory type (not covered by MTRRs) is not UC, |
857 | 124 | ; then probably BIOS did something strange, so it is better to exit immediately |
|
858 | stdcall map_page, [proc_mem_pdir], eax, PG_UW |
125 | ; hoping for the best. |
859 | mov ebx, [ofs] |
- | |
860 | shr ebx, 22 |
- | |
- | 126 | cmp al, MEM_UC |
|
861 | mov esi, [proc_mem_pdir] |
127 | jnz .abort |
862 | mov edi, [proc_mem_tab] |
128 | ; 4. Validate all variable-range MTRRs |
863 | mov eax, [esi+ebx*4] |
129 | ; and copy configured MTRRs to the local array [.mtrrs]. |
864 | and eax, 0xFFFFF000 |
130 | ; 4a. Prepare for the loop over existing variable-range MTRRs. |
865 | test eax, eax |
131 | mov ecx, 0x200 |
866 | jz .exit |
132 | lea edi, [.mtrrs] |
867 | stdcall map_page, edi, eax, PG_UW |
- | |
- | 133 | .get_used_mtrrs_loop: |
|
868 | 134 | ; 4b. For every MTRR, read PHYSBASEn and PHYSMASKn. |
|
869 | @@: |
135 | ; In PHYSBASEn, clear upper bits and copy to ebp:ebx. |
870 | mov edi, [lin_addr] |
136 | rdmsr |
871 | and edi, 0xFFFFF000 |
137 | or edx, [.phys_reserved_mask] |
872 | mov ecx, [buf_size] |
- | |
873 | add ecx, 4095 |
- | |
874 | shr ecx, 12 |
138 | xor edx, [.phys_reserved_mask] |
875 | inc ecx |
139 | mov ebp, edx |
876 | 140 | mov ebx, eax |
|
877 | mov edx, [ofs] |
141 | inc ecx |
878 | shr edx, 12 |
142 | ; If PHYSMASKn is not active, ignore this MTRR. |
879 | and edx, 0x3FF |
143 | rdmsr |
880 | mov esi, [proc_mem_tab] |
144 | inc ecx |
881 | - | ||
882 | .map: |
- | |
883 | stdcall safe_map_page, [slot], [req_access], [ofs] |
145 | test ah, 8 |
884 | jnc .exit |
- | |
885 | add dword [ebp-4], 0x1000 |
- | |
886 | add edi, 0x1000 |
- | |
887 | add [ofs], 0x1000 |
146 | jz .get_used_mtrrs_next |
888 | inc edx |
147 | ; 4c. For every active MTRR, check that number of local entries is not too large. |
889 | dec ecx |
148 | inc [.num_used_mtrrs] |
890 | jnz .map |
149 | cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS |
891 | .exit: |
150 | ja .abort |
892 | pop eax |
151 | ; 4d. For every active MTRR, store PHYSBASEn with upper bits cleared. |
893 | ret |
152 | ; This contains the MTRR base and the memory type in low byte. |
894 | endp |
153 | mov [edi], ebx |
895 | 154 | mov [edi+4], ebp |
|
896 | ; in: esi+edx*4 = pointer to page table entry |
155 | ; 4e. For every active MTRR, check that the range is continuous: |
897 | ; in: [slot], [req_access], [ofs] on the stack |
156 | ; PHYSMASKn with upper bits set must be negated power of two, and |
898 | ; in: edi = linear address to map |
- | |
899 | ; out: CF cleared <=> failed |
- | |
900 | ; destroys: only eax |
157 | ; low bits of PHYSBASEn must be zeroes: |
901 | proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword |
158 | ; PHYSMASKn = 1...10...0, |
902 | mov eax, [esi+edx*4] |
- | |
903 | test al, PG_MAP |
159 | ; PHYSBASEn = x...x0...0, |
904 | jz .not_present |
160 | ; this defines a continuous range from x...x0...0 to x...x1...1, |
905 | test al, PG_WRITE |
161 | ; length = 10...0 = negated PHYSMASKn. |
906 | jz .resolve_readonly |
162 | ; Store length in the local array. |
907 | ; normal case: writable page, just map with requested access |
163 | and eax, not 0xFFF |
908 | .map: |
164 | or edx, [.phys_reserved_mask] |
909 | stdcall map_page, edi, eax, [req_access] |
165 | mov dword [edi+8], 0 |
910 | stc |
166 | mov dword [edi+12], 0 |
911 | .fail: |
167 | sub [edi+8], eax |
912 | ret |
168 | sbb [edi+12], edx |
913 | .not_present: |
169 | ; (x and -x) is the maximum power of two that divides x. |
914 | ; check for alloc-on-demand page |
170 | ; Condition for powers of two: (x and -x) equals x. |
915 | test al, 2 |
171 | and eax, [edi+8] |
916 | jz .fail |
172 | and edx, [edi+12] |
917 | ; allocate new page, save it to source page table |
- | |
918 | push ecx |
- | |
919 | call alloc_page |
- | |
920 | pop ecx |
173 | cmp eax, [edi+8] |
921 | test eax, eax |
174 | jnz .abort |
922 | jz .fail |
175 | cmp edx, [edi+12] |
923 | or al, PG_UW |
176 | jnz .abort |
924 | mov [esi+edx*4], eax |
177 | sub eax, 1 |
925 | jmp .map |
178 | sbb edx, 0 |
926 | .resolve_readonly: |
179 | and eax, not 0xFFF |
927 | ; readonly page, probably copy-on-write |
180 | and eax, ebx |
928 | ; check: readonly request of readonly page is ok |
181 | jnz .abort |
929 | test [req_access], PG_WRITE |
182 | and edx, ebp |
930 | jz .map |
183 | jnz .abort |
931 | ; find control structure for this page |
- | |
932 | pushf |
184 | ; 4f. For every active MTRR, validate memory type: it must be either WB or UC. |
933 | cli |
- | |
934 | cld |
185 | add edi, 16 |
935 | push ebx ecx |
186 | cmp bl, MEM_UC |
936 | mov eax, [slot] |
- | |
937 | shl eax, 8 |
- | |
938 | mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
187 | jz .get_used_mtrrs_next |
939 | test eax, eax |
188 | cmp bl, MEM_WB |
940 | jz .no_hdll |
189 | jnz .abort |
941 | mov ecx, [eax+HDLL.fd] |
190 | .get_used_mtrrs_next: |
942 | .scan_hdll: |
- | |
943 | cmp ecx, eax |
- | |
944 | jz .no_hdll |
- | |
945 | mov ebx, [ofs] |
- | |
946 | and ebx, not 0xFFF |
- | |
947 | sub ebx, [ecx+HDLL.base] |
- | |
948 | cmp ebx, [ecx+HDLL.size] |
- | |
949 | jb .hdll_found |
191 | ; 4g. Repeat the loop at 4b-4f for all [num_variable_mtrrs] entries. |
950 | mov ecx, [ecx+HDLL.fd] |
- | |
951 | jmp .scan_hdll |
- | |
952 | .no_hdll: |
- | |
953 | pop ecx ebx |
- | |
954 | popf |
- | |
955 | clc |
- | |
956 | ret |
- | |
957 | .hdll_found: |
192 | mov eax, [num_variable_mtrrs] |
958 | ; allocate page, save it in page table, map it, copy contents from base |
- | |
959 | mov eax, [ecx+HDLL.parent] |
- | |
960 | add ebx, [eax+DLLDESCR.data] |
193 | lea eax, [0x200+eax*2] |
961 | call alloc_page |
194 | cmp ecx, eax |
962 | test eax, eax |
195 | jb .get_used_mtrrs_loop |
963 | jz .no_hdll |
- | |
964 | or al, PG_UW |
- | |
965 | mov [esi+edx*4], eax |
- | |
966 | stdcall map_page, edi, eax, [req_access] |
- | |
967 | push esi edi |
- | |
968 | mov esi, ebx |
- | |
969 | mov ecx, 4096/4 |
- | |
970 | rep movsd |
- | |
971 | pop edi esi |
- | |
972 | pop ecx ebx |
- | |
973 | popf |
- | |
974 | stc |
- | |
975 | ret |
- | |
976 | endp |
- | |
977 | - | ||
978 | sys_IPC: |
- | |
979 | ;input: |
- | |
980 | ; ebx=1 - set ipc buffer area |
- | |
981 | ; ecx=address of buffer |
- | |
982 | ; edx=size of buffer |
- | |
983 | ; eax=2 - send message |
- | |
984 | ; ebx=PID |
- | |
985 | ; ecx=address of message |
- | |
986 | ; edx=size of message |
- | |
987 | - | ||
988 | dec ebx |
196 | ; 4h. If no active MTRRs were detected, fallback to step 7. |
989 | jnz @f |
197 | cmp [.num_used_mtrrs], 0 |
990 | 198 | jz .fill_ranges_from_memory_map |
|
991 | mov eax, [current_slot] |
- | |
992 | pushf |
- | |
993 | cli |
199 | mov [.mtrrs_end], edi |
994 | mov [eax+APPDATA.ipc_start], ecx ;set fields in extended information area |
200 | ; 5. Generate sorted list of ranges marked as WB. |
995 | mov [eax+APPDATA.ipc_size], edx |
- | |
996 | - | ||
997 | add edx, ecx |
- | |
998 | add edx, 4095 |
- | |
999 | and edx, not 4095 |
201 | ; 5a. Prepare for the loop over configured MTRRs filled at step 4. |
1000 | - | ||
1001 | .touch: |
- | |
1002 | mov eax, [ecx] |
- | |
1003 | add ecx, 0x1000 |
- | |
1004 | cmp ecx, edx |
- | |
1005 | jb .touch |
- | |
1006 | - | ||
1007 | popf |
- | |
1008 | mov [esp+32], ebx ;ebx=0 |
202 | lea ecx, [.mtrrs] |
1009 | ret |
- | |
1010 | - | ||
1011 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
- | |
1012 | ;2 |
- | |
1013 | @@: |
- | |
1014 | dec ebx |
- | |
1015 | jnz @f |
- | |
1016 | - | ||
1017 | stdcall sys_ipc_send, ecx, edx, esi |
- | |
1018 | mov [esp+32], eax |
- | |
1019 | ret |
203 | .fill_wb_ranges: |
1020 | @@: |
- | |
1021 | or eax, -1 |
204 | ; 5b. Ignore non-WB MTRRs. |
1022 | mov [esp+32], eax |
205 | mov ebx, [ecx] |
1023 | ret |
- | |
1024 | - | ||
1025 | ;align 4 |
- | |
1026 | ;proc set_ipc_buff |
- | |
1027 | - | ||
1028 | ; mov eax,[current_slot] |
- | |
1029 | ; pushf |
- | |
1030 | ; cli |
- | |
1031 | ; mov [eax+APPDATA.ipc_start],ebx ;set fields in extended information area |
- | |
1032 | ; mov [eax+APPDATA.ipc_size],ecx |
206 | cmp bl, MEM_WB |
1033 | ; |
- | |
1034 | ; add ecx, ebx |
- | |
1035 | ; add ecx, 4095 |
- | |
1036 | ; and ecx, not 4095 |
- | |
1037 | ; |
- | |
1038 | ;.touch: mov eax, [ebx] |
- | |
1039 | ; add ebx, 0x1000 |
- | |
1040 | ; cmp ebx, ecx |
- | |
1041 | ; jb .touch |
- | |
1042 | ; |
- | |
1043 | ; popf |
- | |
1044 | ; xor eax, eax |
- | |
1045 | ; ret |
- | |
1046 | ;endp |
- | |
1047 | - | ||
1048 | proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword |
- | |
1049 | locals |
- | |
1050 | dst_slot dd ? |
207 | jnz .next_wb_range |
1051 | dst_offset dd ? |
- | |
1052 | buf_size dd ? |
- | |
1053 | used_buf dd ? |
- | |
1054 | endl |
- | |
1055 | - | ||
1056 | pushf |
- | |
1057 | cli |
- | |
1058 | 208 | mov ebp, [ecx+4] |
|
1149 | ret |
455 | mov edi, [.first_range] |
- | 456 | cmp dword [edi+mtrr_range.start], eax |
|
- | 457 | jnz .abort |
|
- | 458 | cmp dword [edi+mtrr_range.start+4], eax |
|
- | 459 | jnz .abort |
|
- | 460 | cmp dword [edi+mtrr_range.length+4], eax |
|
- | 461 | jnz .abort |
|
- | 462 | mov edx, [edi+mtrr_range.next] |
|
- | 463 | test edx, edx |
|
1150 | .ipc_blocked: |
464 | jz @f |
- | 465 | cmp dword [edx+mtrr_range.start], eax |
|
- | 466 | jnz .abort |
|
- | 467 | cmp dword [edx+mtrr_range.start+4], 1 |
|
- | 468 | jnz .abort |
|
- | 469 | cmp [edx+mtrr_range.next], eax |
|
- | 470 | jnz .abort |
|
- | 471 | @@: |
|
- | 472 | ; 8b. Initialize: no MTRRs filled. |
|
- | 473 | mov [.num_used_mtrrs], eax |
|
- | 474 | lea esi, [.mtrrs] |
|
- | 475 | .range2mtrr_loop: |
|
- | 476 | ; 8c. If we are dealing with upper-memory range (after 4G) |
|
- | 477 | ; with length > start, create one WB MTRR with [start,2*start), |
|
- | 478 | ; reset start to 2*start and return to this step. |
|
- | 479 | ; Example: [4G,24G) -> [4G,8G) {returning} + [8G,16G) {returning} |
|
- | 480 | ; + [16G,24G) {advancing to ?}. |
|
- | 481 | mov eax, dword [edi+mtrr_range.length+4] |
|
- | 482 | test eax, eax |
|
- | 483 | jz .less4G |
|
- | 484 | mov edx, dword [edi+mtrr_range.start+4] |
|
- | 485 | cmp eax, edx |
|
- | 486 | jb .start_aligned |
|
- | 487 | inc [.num_used_mtrrs] |
|
- | 488 | cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS |
|
- | 489 | ja .abort |
|
- | 490 | mov dword [esi], MEM_WB |
|
- | 491 | mov dword [esi+4], edx |
|
- | 492 | mov dword [esi+8], 0 |
|
- | 493 | mov dword [esi+12], edx |
|
- | 494 | add esi, 16 |
|
- | 495 | add dword [edi+mtrr_range.start+4], edx |
|
- | 496 | sub dword [edi+mtrr_range.length+4], edx |
|
- | 497 | jnz .range2mtrr_loop |
|
- | 498 | cmp dword [edi+mtrr_range.length], 0 |
|
- | 499 | jz .range2mtrr_next |
|
- | 500 | .less4G: |
|
- | 501 | ; 8d. If we are dealing with low-memory range (before 4G) |
|
- | 502 | ; and appending a maximal-size hole would create a range covering top of 4G, |
|
- | 503 | ; create a maximal-size WB range and return to this step. |
|
- | 504 | ; Example: for [0,0xBC000000) the following steps would consider |
|
- | 505 | ; variants [0,0x80000000)+(another range to be splitted) and |
|
- | 506 | ; [0,0x100000000)-(another range to be splitted); we forbid the last variant, |
|
- | 507 | ; so the first variant must be used. |
|
- | 508 | bsr ecx, dword [edi+mtrr_range.length] |
|
- | 509 | xor edx, edx |
|
- | 510 | inc edx |
|
- | 511 | shl edx, cl |
|
- | 512 | lea eax, [edx*2] |
|
- | 513 | add eax, dword [edi+mtrr_range.start] |
|
- | 514 | jnz .start_aligned |
|
- | 515 | inc [.num_used_mtrrs] |
|
- | 516 | cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS |
|
- | 517 | ja .abort |
|
- | 518 | mov eax, dword [edi+mtrr_range.start] |
|
- | 519 | mov dword [esi], eax |
|
- | 520 | or dword [esi], MEM_WB |
|
- | 521 | mov dword [esi+4], 0 |
|
- | 522 | mov dword [esi+8], edx |
|
- | 523 | mov dword [esi+12], 0 |
|
- | 524 | add esi, 16 |
|
- | 525 | add dword [edi+mtrr_range.start], edx |
|
- | 526 | sub dword [edi+mtrr_range.length], edx |
|
- | 527 | jnz .less4G |
|
- | 528 | jmp .range2mtrr_next |
|
- | 529 | .start_aligned: |
|
- | 530 | ; Start is aligned for any allowed length, maximum-size hole is allowed. |
|
- | 531 | ; Select the best MTRR configuration for one range. |
|
- | 532 | ; length=...101101 |
|
- | 533 | ; Without hole at the end, we need one WB MTRR for every 1-bit in length: |
|
- | 534 | ; length=...100000 + ...001000 + ...000100 + ...000001 |
|
- | 535 | ; We can also append one hole at the end so that one 0-bit (selected by us) |
|
- | 536 | ; becomes 1 and all lower bits become 0 for WB-range: |
|
- | 537 | ; length=...110000 - (...00010 + ...00001) |
|
- | 538 | ; In this way, we need one WB MTRR for every 1-bit higher than the selected bit, |
|
- | 539 | ; one WB MTRR for the selected bit, one UC MTRR for every 0-bit between |
|
- | 540 | ; the selected bit and lowest 1-bit (they become 1-bits after negation) |
|
- | 541 | ; and one UC MTRR for lowest 1-bit. |
|
- | 542 | ; So we need to select 0-bit with the maximal difference |
|
- | 543 | ; (number of 0-bits) - (number of 1-bits) between selected and lowest 1-bit, |
|
- | 544 | ; this equals the gain from using a hole. If the difference is negative for |
|
- | 545 | ; all 0-bits, don't append hole. |
|
- | 546 | ; Note that lowest 1-bit is not included when counting, but selected 0-bit is. |
|
- | 547 | ; 8e. Find the optimal bit position for hole. |
|
1151 | push 2 |
548 | ; eax = current difference, ebx = best difference, |
1152 | jmp .ret |
549 | ; ecx = hole bit position, edx = current bit position. |
1153 | .buffer_overflow: |
- | |
1154 | push 3 |
- | |
1155 | .ret: |
- | |
1156 | mov eax, [used_buf] |
- | |
1157 | cmp eax, [ipc_tmp] |
550 | xor eax, eax |
1158 | jz @f |
- | |
1159 | stdcall free_kernel_space, eax |
- | |
1160 | @@: |
- | |
1161 | pop eax |
- | |
1162 | popf |
551 | xor ebx, ebx |
1163 | ret |
- | |
1164 | endp |
- | |
1165 | - | ||
1166 | align 4 |
552 | xor ecx, ecx |
1167 | sysfn_meminfo: |
553 | bsf edx, dword [edi+mtrr_range.length] |
1168 | 554 | jnz @f |
|
1169 | ; add ecx, new_app_base |
- | |
1170 | cmp ecx, OS_BASE |
555 | bsf edx, dword [edi+mtrr_range.length+4] |
1171 | jae .fail |
556 | add edx, 32 |
1172 | - | ||
1173 | mov eax, [pg_data.pages_count] |
557 | @@: |
1174 | mov [ecx], eax |
- | |
1175 | shl eax, 12 |
558 | push edx ; save position of lowest 1-bit for step 8f |
1176 | mov [esp+32], eax |
559 | .calc_stat: |
1177 | mov eax, [pg_data.pages_free] |
- | |
1178 | mov [ecx+4], eax |
560 | inc edx |
1179 | mov eax, [pg_data.pages_faults] |
- | |
1180 | mov [ecx+8], eax |
- | |
1181 | mov eax, [heap_size] |
- | |
1182 | mov [ecx+12], eax |
- | |
1183 | mov eax, [heap_free] |
- | |
1184 | mov [ecx+16], eax |
- | |
1185 | mov eax, [heap_blocks] |
- | |
1186 | mov [ecx+20], eax |
- | |
1187 | mov eax, [free_blocks] |
561 | cmp edx, 64 |
1188 | mov [ecx+24], eax |
562 | jae .stat_done |
1189 | ret |
- | |
1190 | .fail: |
563 | inc eax ; increment difference in hope for 1-bit |
1191 | or dword [esp+32], -1 |
- | |
1192 | ret |
- | |
1193 | 564 | ; Note: bt conveniently works with both .length and .length+4, |
|
1194 | align 4 |
565 | ; depending on whether edx>=32. |
1195 | f68: |
- | |
1196 | cmp ebx, 4 |
- | |
1197 | jbe sys_sheduler |
- | |
1198 | - | ||
1199 | cmp ebx, 11 |
- | |
1200 | jb .fail |
566 | bt dword [edi+mtrr_range.length], edx |
1201 | - | ||
1202 | cmp ebx, 27 |
567 | jc .calc_stat |
1203 | ja .fail |
- | |
1204 | - | ||
1205 | jmp dword [f68call+ebx*4-11*4] |
- | |
1206 | .11: |
- | |
1207 | call init_heap |
- | |
1208 | mov [esp+32], eax |
- | |
1209 | ret |
- | |
1210 | .12: |
- | |
1211 | stdcall user_alloc, ecx |
- | |
1212 | mov [esp+32], eax |
- | |
1213 | ret |
- | |
1214 | .13: |
568 | dec eax ; hope was wrong, decrement difference to correct 'inc' |
1215 | stdcall user_free, ecx |
- | |
1216 | mov [esp+32], eax |
- | |
1217 | ret |
569 | dec eax ; and again, now getting the real difference |
1218 | .14: |
570 | cmp eax, ebx |
1219 | cmp ecx, OS_BASE |
- | |
1220 | jae .fail |
- | |
1221 | mov edi, ecx |
- | |
1222 | call get_event_ex |
- | |
1223 | mov [esp+32], eax |
- | |
1224 | ret |
- | |
1225 | .16: |
- | |
1226 | test ecx, ecx |
- | |
1227 | jz .fail |
- | |
1228 | cmp ecx, OS_BASE |
- | |
1229 | jae .fail |
- | |
1230 | stdcall get_service, ecx |
- | |
1231 | mov [esp+32], eax |
- | |
1232 | ret |
- | |
1233 | .17: |
- | |
1234 | call srv_handlerEx ;ecx |
- | |
1235 | mov [esp+32], eax |
- | |
1236 | ret |
- | |
1237 | .19: |
- | |
1238 | cmp ecx, OS_BASE |
- | |
1239 | jae .fail |
- | |
1240 | stdcall load_library, ecx |
- | |
1241 | mov [esp+32], eax |
- | |
1242 | ret |
- | |
1243 | .20: |
- | |
1244 | mov eax, edx |
- | |
1245 | mov ebx, ecx |
- | |
1246 | call user_realloc ;in: eax = pointer, ebx = new size |
- | |
1247 | mov [esp+32], eax |
- | |
1248 | ret |
- | |
1249 | .21: |
- | |
1250 | cmp ecx, OS_BASE |
- | |
1251 | jae .fail |
- | |
1252 | - | ||
1253 | cmp edx, OS_BASE |
- | |
1254 | jae .fail |
- | |
1255 | - | ||
1256 | stdcall load_pe_driver, ecx, edx |
- | |
1257 | mov [esp+32], eax |
- | |
1258 | ret |
- | |
1259 | .22: |
- | |
1260 | cmp ecx, OS_BASE |
- | |
1261 | jae .fail |
- | |
1262 | - | ||
1263 | stdcall shmem_open, ecx, edx, esi |
- | |
1264 | mov [esp+24], edx |
- | |
1265 | mov [esp+32], eax |
- | |
1266 | ret |
- | |
1267 | - | ||
1268 | .23: |
- | |
1269 | cmp ecx, OS_BASE |
- | |
1270 | jae .fail |
- | |
1271 | - | ||
1272 | stdcall shmem_close, ecx |
- | |
1273 | mov [esp+32], eax |
- | |
1274 | ret |
- | |
1275 | .24: |
- | |
1276 | mov eax, [current_slot] |
- | |
1277 | xchg ecx, [eax+APPDATA.exc_handler] |
- | |
1278 | xchg edx, [eax+APPDATA.except_mask] |
- | |
1279 | mov [esp+32], ecx ; reg_eax+8 |
- | |
1280 | mov [esp+20], edx ; reg_ebx+8 |
- | |
1281 | ret |
571 | jle .calc_stat |
1282 | .25: |
572 | mov ebx, eax |
1283 | cmp ecx, 32 |
- | |
1284 | jae .fail |
- | |
1285 | mov eax, [current_slot] |
573 | mov ecx, edx |
1286 | btr [eax+APPDATA.except_mask], ecx |
574 | jmp .calc_stat |
- | 575 | .stat_done: |
|
1287 | setc byte[esp+32] |
576 | ; 8f. If we decided to create a hole, flip all bits between lowest and selected. |
1288 | jecxz @f |
- | |
1289 | bts [eax+APPDATA.except_mask], ecx |
577 | pop edx ; restore position of lowest 1-bit saved at step 8e |
- | 578 | test ecx, ecx |
|
1290 | @@: |
579 | jz .fill_hi_init |
- | 580 | @@: |
|
- | 581 | inc edx |
|
1291 | ret |
582 | cmp edx, ecx |
1292 | - | ||
1293 | .26: |
583 | ja .fill_hi_init |
- | 584 | btc dword [edi+mtrr_range.length], edx |
|
1294 | stdcall user_unmap, ecx, edx, esi |
585 | jmp @b |
- | 586 | .fill_hi_init: |
|
1295 | mov [esp+32], eax |
587 | ; 8g. Create MTRR ranges corresponding to upper 32 bits. |
- | 588 | sub ecx, 32 |
|
1296 | ret |
589 | .fill_hi_loop: |
1297 | - | ||
1298 | .27: |
- | |
1299 | cmp ecx, OS_BASE |
590 | bsr edx, dword [edi+mtrr_range.length+4] |
1300 | jae .fail |
591 | jz .fill_hi_done |
1301 | 592 | inc [.num_used_mtrrs] |
|
1302 | stdcall load_file_umode, ecx |
- | |
1303 | mov [esp+24], edx |
- | |
1304 | mov [esp+32], eax |
- | |
1305 | ret |
593 | cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS |
1306 | - | ||
1307 | .fail: |
594 | ja .abort |
1308 | xor eax, eax |
595 | mov eax, dword [edi+mtrr_range.start] |
1309 | mov [esp+32], eax |
596 | mov [esi], eax |
1310 | ret |
597 | mov eax, dword [edi+mtrr_range.start+4] |
1311 | 598 | mov [esi+4], eax |
|
1312 | 599 | xor eax, eax |
|
1313 | align 4 |
600 | mov [esi+8], eax |
1314 | f68call: ; keep this table closer to main code |
601 | bts eax, edx |
- | 602 | mov [esi+12], eax |
|
1315 | 603 | cmp edx, ecx |
|
1316 | dd f68.11 ; init_heap |
604 | jl .fill_hi_uc |
1317 | dd f68.12 ; user_alloc |
605 | or dword [esi], MEM_WB |
1318 | dd f68.13 ; user_free |
606 | add dword [edi+mtrr_range.start+4], eax |
1319 | dd f68.14 ; get_event_ex |
607 | jmp @f |
1320 | dd f68.fail ; moved to f68.24 |
608 | .fill_hi_uc: |
- | 609 | sub dword [esi+4], eax |
|
1321 | dd f68.16 ; get_service |
610 | sub dword [edi+mtrr_range.start+4], eax |
1322 | dd f68.17 ; call_service |
611 | @@: |
1323 | dd f68.fail ; moved to f68.25 |
612 | add esi, 16 |
1324 | dd f68.19 ; load_dll |
- | |
1325 | dd f68.20 ; user_realloc |
- | |
1326 | dd f68.21 ; load_driver |
- | |
1327 | dd f68.22 ; shmem_open |
613 | sub dword [edi+mtrr_range.length], eax |
1328 | dd f68.23 ; shmem_close |
614 | jmp .fill_hi_loop |
1329 | dd f68.24 ; set exception handler |
- | |
1330 | dd f68.25 ; unmask exception |
615 | .fill_hi_done: |
1331 | dd f68.26 ; user_unmap |
616 | ; 8h. Create MTRR ranges corresponding to lower 32 bits. |
1332 | dd f68.27 ; load_file_umode |
617 | add ecx, 32 |
1333 | - | ||
1334 | 618 | .fill_lo_loop: |
|
1335 | align 4 |
619 | bsr edx, dword [edi+mtrr_range.length] |
1336 | proc load_pe_driver stdcall, file:dword, cmdline:dword |
620 | jz .range2mtrr_next |
1337 | push esi |
621 | inc [.num_used_mtrrs] |
1338 | 622 | cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS |
|
1339 | stdcall load_PE, [file] |
623 | ja .abort |
1340 | test eax, eax |
624 | mov eax, dword [edi+mtrr_range.start] |
1341 | jz .fail |
625 | mov [esi], eax |
1342 | - | ||
1343 | mov esi, eax |
626 | mov eax, dword [edi+mtrr_range.start+4] |
1344 | push [cmdline] |
627 | mov [esi+4], eax |
1345 | push DRV_ENTRY |
- | |
1346 | call eax |
- | |
1347 | pop ecx |
628 | xor eax, eax |
1348 | pop ecx |
629 | mov [esi+12], eax |
1349 | test eax, eax |
630 | bts eax, edx |
1350 | jz .fail |
- | |
1351 | 631 | mov [esi+8], eax |
|
1352 | mov [eax+SRV.entry], esi |
- | |
1353 | pop esi |
- | |
1354 | ret |
632 | cmp edx, ecx |
1355 | - | ||
1356 | .fail: |
633 | jl .fill_lo_uc |
1357 | xor eax, eax |
634 | or dword [esi], MEM_WB |
1358 | pop esi |
- | |
- | 635 | add dword [edi+mtrr_range.start], eax |
|
- | 636 | jmp @f |
|
1359 | ret |
637 | .fill_lo_uc: |
1360 | endp |
638 | sub dword [esi], eax |
1361 | - | ||
1362 | align 4 |
639 | sub dword [edi+mtrr_range.start], eax |
- | 640 | @@: |
|
- | 641 | add esi, 16 |
|
1363 | proc init_mtrr |
642 | sub dword [edi+mtrr_range.length], eax |
1364 | 643 | jmp .fill_lo_loop |
|
1365 | cmp [BOOT_VARS+BOOT_MTRR], byte 2 |
644 | .range2mtrr_next: |
Line 1366... | Line -... | ||
1366 | je .exit |
- | |
1367 | - | ||
1368 | bt [cpu_caps], CAPS_MTRR |
- | |
1369 | jnc .exit |
- | |
1370 | - | ||
1371 | mov eax, cr0 |
- | |
1372 | or eax, 0x60000000 ;disable caching |
645 | ; 8i. Repeat the loop at 8c-8h for all ranges. |
1373 | mov cr0, eax |
646 | mov edi, [edi+mtrr_range.next] |
Line 1374... | Line -... | ||
1374 | wbinvd ;invalidate cache |
- | |
1375 | 647 | test edi, edi |
|
1376 | mov ecx, 0x2FF |
- | |
1377 | rdmsr ; |
- | |
1378 | ; has BIOS already initialized MTRRs? |
- | |
1379 | test ah, 8 |
- | |
1380 | jnz .skip_init |
- | |
1381 | ; rarely needed, so mainly placeholder |
- | |
1382 | ; main memory - cached |
- | |
1383 | push eax |
648 | jnz .range2mtrr_loop |
1384 | 649 | ; 9. We have calculated needed MTRRs, now setup them in the CPU. |
|
- | 650 | ; 9a. Abort if number of MTRRs is too large. |
|
- | 651 | mov eax, [num_variable_mtrrs] |
|
- | 652 | cmp [.num_used_mtrrs], eax |
|
- | 653 | ja .abort |
|
- | 654 | ||
1385 | mov eax, [MEM_AMOUNT] |
655 | ; 9b. Prepare for changes. |
1386 | ; round eax up to next power of 2 |
- | |
1387 | dec eax |
- | |
1388 | bsr ecx, eax |
- | |
1389 | mov ebx, 2 |
- | |
1390 | shl ebx, cl |
- | |
1391 | dec ebx |
- | |
1392 | ; base of memory range = 0, type of memory range = MEM_WB |
656 | call mtrr_begin_change |
- | 657 | ||
- | 658 | ; 9c. Prepare for loop over MTRRs. |
|
- | 659 | lea esi, [.mtrrs] |
|
- | 660 | mov ecx, 0x200 |
|
- | 661 | @@: |
|
- | 662 | ; 9d. For every MTRR, copy PHYSBASEn as is: step 8 has configured |
|
- | 663 | ; start value and type bits as needed. |
|
- | 664 | mov eax, [esi] |
|
- | 665 | mov edx, [esi+4] |
|
1393 | xor edx, edx |
666 | wrmsr |
- | 667 | inc ecx |
|
- | 668 | ; 9e. For every MTRR, calculate PHYSMASKn = -(length) or 0x800 |
|
- | 669 | ; with upper bits cleared, 0x800 = MTRR is valid. |
|
- | 670 | xor eax, eax |
|
- | 671 | xor edx, edx |
|
1394 | mov eax, MEM_WB |
672 | sub eax, [esi+8] |
1395 | mov ecx, 0x200 |
673 | sbb edx, [esi+12] |
1396 | wrmsr |
674 | or eax, 0x800 |
- | 675 | or edx, [.phys_reserved_mask] |
|
- | 676 | xor edx, [.phys_reserved_mask] |
|
1397 | ; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1 |
677 | wrmsr |
- | 678 | inc ecx |
|
- | 679 | ; 9f. Continue steps 9d and 9e for all MTRRs calculated at step 8. |
|
- | 680 | add esi, 16 |
|
1398 | mov eax, 0xFFFFFFFF |
681 | dec [.num_used_mtrrs] |
1399 | mov edx, 0x0000000F |
682 | jnz @b |
1400 | sub eax, ebx |
683 | ; 9g. Zero other MTRRs. |
1401 | sbb edx, 0 |
684 | xor eax, eax |
1402 | or eax, 0x800 |
685 | xor edx, edx |
1403 | inc ecx |
- | |
- | 686 | mov ebx, [num_variable_mtrrs] |
|
1404 | wrmsr |
687 | lea ebx, [0x200+ebx*2] |
1405 | ; clear unused MTRRs |
- | |
1406 | xor eax, eax |
688 | @@: |
- | 689 | cmp ecx, ebx |
|
- | 690 | jae @f |
|
- | 691 | wrmsr |
|
1407 | xor edx, edx |
692 | inc ecx |
1408 | @@: |
- | |
1409 | inc ecx |
- | |
Line -... | Line 693... | ||
- | 693 | wrmsr |
|
1410 | wrmsr |
694 | inc ecx |
Line 1411... | Line 695... | ||
1411 | cmp ecx, 0x20F |
695 | jmp @b |
1412 | jb @b |
696 | @@: |
1413 | ; enable MTRRs |
697 | |
1414 | pop eax |
- | |
1415 | or ah, 8 |
698 | ; 9i. Configure MTRR_DEF_TYPE. |
1416 | and al, 0xF0; default memtype = UC |
699 | mov ecx, 0x2FF |
Line 1417... | Line 700... | ||
1417 | mov ecx, 0x2FF |
700 | rdmsr |
- | 701 | or ah, 8 ; enable variable-ranges MTRR |
|
1418 | wrmsr |
702 | and al, 0xF0; default memtype = UC |
1419 | .skip_init: |
703 | wrmsr |
1420 | stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC |
704 | |
1421 | 705 | ; 9j. Changes are done. |
|
1422 | wbinvd ;again invalidate |
706 | call mtrr_end_change |
1423 | 707 | ||
1424 | mov eax, cr0 |
708 | .abort: |
1425 | and eax, not 0x60000000 |
709 | add esp, .local_vars_size + MAX_RANGES * sizeof.mtrr_range |
1426 | mov cr0, eax ; enable caching |
710 | pop ebp |
- | 711 | ret |
|
- | 712 | endp |
|
1427 | .exit: |
713 | |
1428 | ret |
714 | ; Allocate&set one MTRR for given range. |
1429 | endp |
715 | ; size must be power of 2 that divides base. |
- | 716 | proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword |
|
1430 | 717 | ; find unused register |
|
- | 718 | mov ecx, 0x201 |
|
- | 719 | .scan: |
|
1431 | align 4 |
720 | rdmsr |
1432 | proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword |
721 | dec ecx |
1433 | ; find unused register |
722 | test ah, 8 |
1434 | mov ecx, 0x201 |
723 | jz .found |
1435 | @@: |
724 | rdmsr |
1436 | rdmsr |
725 | test edx, edx |
1437 | dec ecx |
726 | jnz @f |
- | 727 | and eax, not 0xFFF ; clear reserved bits |
|
1438 | test ah, 8 |
728 | cmp eax, [base] |
1439 | jz .found |
729 | jz .ret |
1440 | rdmsr |
730 | @@: |
1441 | mov al, 0; clear memory type field |
731 | add ecx, 3 |
Line 1442... | Line 732... | ||
1442 | cmp eax, [base] |
732 | mov eax, [num_variable_mtrrs] |
1443 | jz .ret |
733 | lea eax, [0x200+eax*2] |
1444 | add ecx, 3 |
734 | cmp ecx, eax |
1445 | cmp ecx, 0x210 |
735 | jb .scan |
1446 | jb @b |
736 | ; no free registers, ignore the call |
1447 | ; no free registers, ignore the call |
737 | .ret: |
1448 | .ret: |
738 | ret |
1449 | ret |
739 | .found: |
1450 | .found: |
740 | ; found, write values |
- | 741 | call mtrr_begin_change |
|
1451 | ; found, write values |
742 | xor edx, edx |
1452 | xor edx, edx |
743 | mov eax, [base] |
Line 1453... | Line -... | ||
1453 | mov eax, [base] |
- | |
1454 | or eax, [mem_type] |
- | |
1455 | wrmsr |
- | |
1456 | - | ||
1457 | mov ebx, [size] |
- | |
1458 | dec ebx |
- | |
1459 | mov eax, 0xFFFFFFFF |
744 | or eax, [mem_type] |
1460 | mov edx, 0x00000000 |
- | |
1461 | sub eax, ebx |
- | |
1462 | sbb edx, 0 |
- | |
1463 | or eax, 0x800 |
- | |
1464 | inc ecx |
745 | wrmsr |
1465 | wrmsr |
746 | |
1466 | ret |
- | |
1467 | endp |
- | |
1468 | - | ||
1469 | align 4 |
- | |
1470 | proc create_ring_buffer stdcall, size:dword, flags:dword |
747 | mov al, [cpu_phys_addr_width] |
1471 | locals |
- | |
1472 | buf_ptr dd ? |
748 | xor edx, edx |
1473 | endl |
749 | bts edx, eax |
1474 | - | ||
1475 | mov eax, [size] |
- | |
1476 | test eax, eax |
750 | xor eax, eax |
1477 | jz .fail |
- | |
1478 | - | ||
1479 | add eax, eax |
- | |
1480 | stdcall alloc_kernel_space, eax |
- | |
1481 | test eax, eax |
- | |
1482 | jz .fail |
751 | sub eax, [size] |
1483 | - | ||
1484 | push ebx |
- | |
1485 | - | ||
1486 | mov [buf_ptr], eax |
- | |
1487 | 752 | sbb edx, 0 |
|
1488 | mov ebx, [size] |
- | |
1489 | shr ebx, 12 |
- | |
1490 | push ebx |
753 | or eax, 0x800 |
1491 | - | ||
1492 | stdcall alloc_pages, ebx |
754 | inc ecx |
1493 | pop ecx |
- | |
1494 | - | ||
1495 | test eax, eax |
- | |
1496 | jz .mm_fail |
- | |
1497 | 755 | wrmsr |
|
1498 | push edi |
756 | call mtrr_end_change |
- | 757 | ret |
|
1499 | 758 | endp |
|
1500 | or eax, [flags] |
- | |
- | 759 | ||
- | 760 | ; Helper procedure for mtrr_validate. |
|
1501 | mov edi, [buf_ptr] |
761 | ; Calculates memory type for given address according to variable-range MTRRs. |
1502 | mov ebx, [buf_ptr] |
762 | ; Assumes that MTRRs are enabled. |
- | 763 | ; in: ebx = 32-bit physical address |
|
- | 764 | ; out: eax = memory type for ebx |
|
1503 | mov edx, ecx |
765 | proc mtrr_get_real_type |
- | 766 | ; 1. Initialize: we have not yet found any MTRRs covering ebx. |
|
- | 767 | push 0 |
|
- | 768 | mov ecx, 0x201 |
|
1504 | shl edx, 2 |
769 | .mtrr_loop: |
- | 770 | ; 2. For every MTRR, check whether it is valid; if not, continue to the next MTRR. |
|
- | 771 | rdmsr |
|
- | 772 | dec ecx |
|
1505 | shr edi, 10 |
773 | test ah, 8 |
- | 774 | jz .next |
|
- | 775 | ; 3. For every valid MTRR, check whether (ebx and PHYSMASKn) == PHYSBASEn, |
|
1506 | @@: |
776 | ; excluding low 12 bits. |
- | 777 | and eax, ebx |
|
- | 778 | push eax |
|
- | 779 | rdmsr |
|
- | 780 | test edx, edx |
|
- | 781 | pop edx |
|
- | 782 | jnz .next |
|
- | 783 | xor edx, eax |
|
- | 784 | and edx, not 0xFFF |
|
- | 785 | jnz .next |
|
- | 786 | ; 4. If so, set the bit corresponding to memory type defined by this MTRR. |
|
- | 787 | and eax, 7 |
|
- | 788 | bts [esp], eax |
|
- | 789 | .next: |
|
- | 790 | ; 5. Continue loop at 2-4 for all variable-range MTRRs. |
|
1507 | mov [page_tabs+edi], eax |
791 | add ecx, 3 |
- | 792 | mov eax, [num_variable_mtrrs] |
|
1508 | mov [page_tabs+edi+edx], eax |
793 | lea eax, [0x200+eax*2] |
1509 | invlpg [ebx] |
794 | cmp ecx, eax |
- | 795 | jb .mtrr_loop |
|
- | 796 | ; 6. If no MTRRs cover address in ebx, use default MTRR type from MTRR_DEF_CAP. |
|
- | 797 | pop edx |
|
1510 | invlpg [ebx+0x10000] |
798 | test edx, edx |
1511 | add eax, 0x1000 |
799 | jz .default |
Line 1512... | Line -... | ||
1512 | add ebx, 0x1000 |
- | |
- | 800 | ; 7. Find&clear 1-bit in edx. |
|
- | 801 | bsf eax, edx |
|
- | 802 | btr edx, eax |
|
- | 803 | ; 8. If there was only one 1-bit, then all MTRRs are consistent, return that bit. |
|
- | 804 | test edx, edx |
|
1513 | add edi, 4 |
805 | jz .nothing |
- | 806 | ; Otherwise, return MEM_UC (e.g. WB+UC is UC). |
|
- | 807 | xor eax, eax |
|
- | 808 | .nothing: |
|
- | 809 | ret |
|
- | 810 | .default: |
|
1514 | dec ecx |
811 | mov ecx, 0x2FF |
- | 812 | rdmsr |
|
- | 813 | movzx eax, al |
|
- | 814 | ret |
|
- | 815 | endp |
|
- | 816 | ||
- | 817 | ; If MTRRs are configured improperly, this is not obvious to the user; |
|
- | 818 | ; everything works, but the performance can be horrible. |
|
- | 819 | ; Try to detect this and let the user know that the low performance |
|
- | 820 | ; is caused by some problem and is not a global property of the system. |
|
- | 821 | ; Let's hope he would report it to developers... |
|
- | 822 | proc mtrr_validate |
|
1515 | jnz @B |
823 | ; 1. If MTRRs are not supported, they cannot be configured improperly. |
- | 824 | bt [cpu_caps], CAPS_MTRR |
|
1516 | 825 | jnc .exit |
|
- | 826 | ; 2. If variable-range MTRRs are not configured, this is a problem. |
|
- | 827 | mov ecx, 0x2FF |
|
- | 828 | rdmsr |
|
- | 829 | test ah, 8 |
|
- | 830 | jz .fail |
|
1517 | mov eax, [buf_ptr] |
831 | ; 3. Get the memory type for address somewhere inside working memory. |
1518 | pop edi |
832 | ; It must be write-back. |
1519 | pop ebx |
- | |
- | 833 | mov ebx, 0x27FFFF |
|
1520 | ret |
834 | call mtrr_get_real_type |
1521 | .mm_fail: |
835 | cmp al, MEM_WB |
1522 | stdcall free_kernel_space, [buf_ptr] |
836 | jnz .fail |
- | 837 | ; 4. If we're using a mode with LFB, |
|
1523 | xor eax, eax |
838 | ; get the memory type for last pixel of the framebuffer. |
1524 | pop ebx |
839 | ; It must be write-combined. |
1525 | .fail: |
- | |
- | 840 | test word [SCR_MODE], 0x4000 |
|
- | 841 | jz .exit |
|
- | 842 | mov eax, [_display.pitch] |
|
- | 843 | mul [_display.height] |
|
1526 | ret |
844 | dec eax |
- | 845 | ; LFB is mapped to virtual address LFB_BASE, |
|
1527 | endp |
846 | ; it uses global pages if supported by CPU. |
1528 | 847 | mov ebx, [sys_pgdir+(LFB_BASE shr 20)] |
|
- | 848 | test ebx, PG_LARGE |
|
1529 | 849 | jnz @f |
|
- | 850 | mov ebx, [page_tabs+(LFB_BASE shr 10)] |
|
1530 | align 4 |
851 | @@: |
- | 852 | and ebx, not 0xFFF |
|
1531 | proc print_mem |
853 | add ebx, eax |
- | 854 | call mtrr_get_real_type |
|
- | 855 | cmp al, MEM_WC |
|
1532 | mov edi, BOOT_VAR + 0x9104 |
856 | jz .exit |
- | 857 | ; 5. The check at step 4 fails on Bochs: |
|
- | 858 | ; Bochs BIOS configures MTRRs in a strange way not respecting [cpu_phys_addr_width], |
|
- | 859 | ; so mtrr_reconfigure avoids to touch anything. |
|
1533 | mov ecx, [edi-4] |
860 | ; However, Bochs core ignores MTRRs (keeping them only for rdmsr/wrmsr), |
1534 | test ecx, ecx |
861 | ; so we don't care about proper setting for Bochs. |