Subversion Repositories Kolibri OS

Rev

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.