Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4429 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
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
 
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_proc+PROC.pdt_0+(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_proc+PROC.pdt_0+(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]
4430 Serge 450
        mov     ebx, [edx+APPDATA.process]
451
 
452
        cmp     [ebx+PROC.heap_base], 0
4429 Serge 453
        jne     .exit
454
 
455
        mov     edi, [new_size]
456
        add     edi, 4095
457
        and     edi, not 4095
458
        mov     [new_size], edi
459
 
4430 Serge 460
        mov     esi, [ebx+PROC.mem_used]
4429 Serge 461
        add     esi, 4095
462
        and     esi, not 4095
463
 
464
        cmp     edi, esi
465
        ja      .expand
466
        je      .exit
467
 
468
        mov     ebx, edi
469
        shr     edi, 12
470
        shr     esi, 12
471
 
472
        mov     ecx, pg_data.mutex
473
        call    mutex_lock
474
@@:
475
        mov     eax, [app_page_tabs+edi*4]
476
        test    eax, 1
477
        jz      .next
478
 
479
        mov     dword [app_page_tabs+edi*4], 0
480
        invlpg  [ebx]
481
        call    free_page
482
 
483
.next:
484
        inc     edi
485
        add     ebx, 0x1000
486
        cmp     edi, esi
487
        jb      @B
488
 
489
        mov     ecx, pg_data.mutex
490
        call    mutex_unlock
491
 
492
.update_size:
493
        mov     edx, [current_slot]
494
        mov     ebx, [new_size]
4430 Serge 495
        mov     edx, [edx+APPDATA.process]
496
        mov     [edx+PROC.mem_used], ebx
4429 Serge 497
.exit:
498
        pop     edi
499
        pop     esi
500
        pop     ebx
501
        xor     eax, eax
502
        ret
503
 
504
.expand:
505
 
506
        mov     ecx, pg_data.mutex
507
        call    mutex_lock
508
 
509
        xchg    esi, edi
510
 
511
        push    esi                   ;new size
512
        push    edi                   ;old size
513
 
514
        add     edi, 0x3FFFFF
515
        and     edi, not(0x3FFFFF)
516
        add     esi, 0x3FFFFF
517
        and     esi, not(0x3FFFFF)
518
 
519
        cmp     edi, esi
520
        jae     .grow
521
 @@:
522
        call    alloc_page
523
        test    eax, eax
524
        jz      .exit_fail
525
 
526
        stdcall map_page_table, edi, eax
527
 
528
        push    edi
529
        shr     edi, 10
530
        add     edi, page_tabs
531
        mov     ecx, 1024
532
        xor     eax, eax
533
        cld
534
        rep stosd
535
        pop     edi
536
 
537
        add     edi, 0x00400000
538
        cmp     edi, esi
539
        jb      @B
540
.grow:
541
        pop     edi                   ;old size
542
        pop     ecx                   ;new size
543
 
544
        shr     edi, 10
545
        shr     ecx, 10
546
        sub     ecx, edi
547
        shr     ecx, 2                ;pages count
548
        mov     eax, 2
549
 
550
        add     edi, app_page_tabs
551
        rep stosd
552
 
553
        mov     ecx, pg_data.mutex
554
        call    mutex_unlock
555
 
556
        jmp     .update_size
557
 
558
.exit_fail:
559
        mov     ecx, pg_data.mutex
560
        call    mutex_unlock
561
 
562
        add     esp, 8
563
        pop     edi
564
        pop     esi
565
        pop     ebx
566
        xor     eax, eax
567
        inc     eax
568
        ret
569
endp
570
 
571
 
572
; param
573
;  eax= linear address
574
;
575
; retval
576
;  eax= phisical page address
577
 
578
align 4
579
get_pg_addr:
580
        sub     eax, OS_BASE
581
        cmp     eax, 0x400000
582
        jb      @f
583
        shr     eax, 12
584
        mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
585
@@:
586
        and     eax, 0xFFFFF000
587
        ret
588
 
589
 
590
align 4
591
; Now it is called from core/sys32::exc_c (see stack frame there)
592
proc page_fault_handler
593
 
594
    .err_addr   equ ebp-4
595
 
596
        push    ebx               ;save exception number (#PF)
597
        mov     ebp, esp
598
        mov     ebx, cr2
599
        push    ebx               ;that is locals: .err_addr = cr2
600
        inc     [pg_data.pages_faults]
601
 
602
        mov     eax, [pf_err_code]
603
 
604
        cmp     ebx, OS_BASE      ;ebx == .err_addr
605
        jb      .user_space       ;страница в памяти приложения ;
606
 
607
        cmp     ebx, page_tabs
608
        jb      .kernel_space     ;страница в памяти ядра
609
 
610
        cmp     ebx, kernel_tabs
611
        jb      .alloc;.app_tabs  ;таблицы страниц приложения ;
612
                                  ;просто создадим одну
613
if 0 ;пока это просто лишнее
614
        cmp     ebx, LFB_BASE
615
        jb      .core_tabs        ;таблицы страниц ядра
616
                                  ;Ошибка
617
  .lfb:
618
                                  ;область LFB
619
                                  ;Ошибка
620
        jmp     .fail
621
end if
622
.core_tabs:
623
.fail:  ;simply return to caller
624
        mov     esp, ebp
625
        pop     ebx               ;restore exception number (#PF)
626
        ret
627
 
628
.user_space:
629
        test    eax, PG_MAP
630
        jnz     .err_access       ;Страница присутствует
631
                                  ;Ошибка доступа ?
632
 
633
        shr     ebx, 12
634
        mov     ecx, ebx
635
        shr     ecx, 10
636
        mov     edx, [master_tab+ecx*4]
637
        test    edx, PG_MAP
638
        jz      .fail             ;таблица страниц не создана
639
                                  ;неверный адрес в программе
640
 
641
        mov     eax, [page_tabs+ebx*4]
642
        test    eax, 2
643
        jz      .fail             ;адрес не зарезервирован для ;
644
                                  ;использования. Ошибка
645
.alloc:
646
        call    alloc_page
647
        test    eax, eax
648
        jz      .fail
649
 
650
        stdcall map_page, [.err_addr], eax, PG_UW
651
 
652
        mov     edi, [.err_addr]
653
        and     edi, 0xFFFFF000
654
        mov     ecx, 1024
655
        xor     eax, eax
656
       ;cld     ;caller is duty for this
657
        rep stosd
658
.exit:  ;iret with repeat fault instruction
659
        add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
660
        restore_ring3_context
661
        iretd
662
 
663
.err_access:
664
; access denied? this may be a result of copy-on-write protection for DLL
665
; check list of HDLLs
666
        and     ebx, not 0xFFF
4433 Serge 667
        mov     eax, [current_process]
668
        mov     eax, [eax+PROC.dlls_list_ptr]
4429 Serge 669
        test    eax, eax
670
        jz      .fail
671
        mov     esi, [eax+HDLL.fd]
672
.scan_hdll:
673
        cmp     esi, eax
674
        jz      .fail
675
        mov     edx, ebx
676
        sub     edx, [esi+HDLL.base]
677
        cmp     edx, [esi+HDLL.size]
678
        jb      .fault_in_hdll
679
.scan_hdll.next:
680
        mov     esi, [esi+HDLL.fd]
681
        jmp     .scan_hdll
682
.fault_in_hdll:
683
; allocate new page, map it as rw and copy data
684
        call    alloc_page
685
        test    eax, eax
686
        jz      .fail
687
        stdcall map_page, ebx, eax, PG_UW
688
        mov     edi, ebx
689
        mov     ecx, 1024
690
        sub     ebx, [esi+HDLL.base]
691
        mov     esi, [esi+HDLL.parent]
692
        mov     esi, [esi+DLLDESCR.data]
693
        add     esi, ebx
694
        rep movsd
695
        jmp     .exit
696
 
697
.kernel_space:
698
        test    eax, PG_MAP
699
        jz      .fail   ;страница не присутствует
700
 
701
        test    eax, 12 ;U/S (+below)
702
        jnz     .fail   ;приложение обратилось к памяти
703
                        ;ядра
704
       ;test    eax, 8
705
       ;jnz     .fail   ;установлен зарезервированный бит
706
                        ;в таблицах страниц. добавлено в P4/Xeon
707
 
708
;попытка записи в защищённую страницу ядра
709
 
710
        cmp     ebx, tss._io_map_0
711
        jb      .fail
712
 
713
        cmp     ebx, tss._io_map_0+8192
714
        jae     .fail
715
 
716
; io permission map
717
; copy-on-write protection
718
 
719
        call    alloc_page
720
        test    eax, eax
721
        jz      .fail
722
 
723
        push    eax
724
        stdcall map_page, [.err_addr], eax, dword PG_SW
725
        pop     eax
726
        mov     edi, [.err_addr]
727
        and     edi, -4096
728
        lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
729
 
730
        mov     ebx, esi
731
        shr     ebx, 12
732
        mov     edx, [current_slot]
733
        or      eax, PG_SW
734
        mov     [edx+APPDATA.io_map+ebx*4], eax
735
 
736
        add     esi, [default_io_map]
737
        mov     ecx, 4096/4
738
       ;cld     ;caller is duty for this
739
        rep movsd
740
        jmp     .exit
741
endp
742
 
743
; returns number of mapped bytes
4430 Serge 744
proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
4429 Serge 745
                      ofs:dword,buf_size:dword,req_access:dword
4430 Serge 746
        locals
747
             count   dd ?
748
             process dd ?
749
        endl
4429 Serge 750
 
4430 Serge 751
        mov     [count], 0
4429 Serge 752
        cmp     [buf_size], 0
753
        jz      .exit
754
 
755
        mov     eax, [slot]
756
        shl     eax, 8
757
        mov     eax, [SLOT_BASE+eax+APPDATA.process]
4430 Serge 758
        test    eax, eax
759
        jz      .exit
4429 Serge 760
 
4430 Serge 761
        mov     [process], eax
4429 Serge 762
        mov     ebx, [ofs]
763
        shr     ebx, 22
4430 Serge 764
        mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
765
        mov     esi, [ipc_ptab]
4429 Serge 766
        and     eax, 0xFFFFF000
767
        jz      .exit
4430 Serge 768
        stdcall map_page, esi, eax, PG_SW
4429 Serge 769
@@:
770
        mov     edi, [lin_addr]
771
        and     edi, 0xFFFFF000
772
        mov     ecx, [buf_size]
773
        add     ecx, 4095
774
        shr     ecx, 12
4430 Serge 775
        inc     ecx                  ; ???????????
4429 Serge 776
 
777
        mov     edx, [ofs]
778
        shr     edx, 12
779
        and     edx, 0x3FF
780
.map:
781
        stdcall safe_map_page, [slot], [req_access], [ofs]
782
        jnc     .exit
4430 Serge 783
        add     dword [ebp-4], PAGE_SIZE
784
        add     [ofs], PAGE_SIZE
4429 Serge 785
        dec     ecx
786
        jz      .exit
4430 Serge 787
 
788
        add     edi, PAGE_SIZE
4429 Serge 789
        inc     edx
4430 Serge 790
        cmp     edx, 1024
4429 Serge 791
        jnz     .map
4430 Serge 792
 
4429 Serge 793
        inc     ebx
4430 Serge 794
        mov     eax, [process]
795
        mov     eax, [eax+PROC.pdt_0+ebx*4]
4429 Serge 796
        and     eax, 0xFFFFF000
797
        jz      .exit
4430 Serge 798
 
799
        stdcall map_page, esi, eax, PG_SW
4429 Serge 800
        xor     edx, edx
801
        jmp     .map
802
 
803
.exit:
804
        pop     eax
805
        ret
806
endp
807
 
808
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
809
                        ofs:dword,buf_size:dword,req_access:dword
810
        push    0 ; initialize number of mapped bytes
811
 
812
        cmp     [buf_size], 0
813
        jz      .exit
814
 
815
        mov     eax, [slot]
816
        shl     eax, 8
817
        mov     eax, [SLOT_BASE+eax+APPDATA.process]
818
        mov     eax, [eax+PROC.pdt_0_phys]
819
        and     eax, 0xFFFFF000
820
 
821
        stdcall map_page, [proc_mem_pdir], eax, PG_UW
822
        mov     ebx, [ofs]
823
        shr     ebx, 22
824
        mov     esi, [proc_mem_pdir]
825
        mov     edi, [proc_mem_tab]
826
        mov     eax, [esi+ebx*4]
827
        and     eax, 0xFFFFF000
828
        test    eax, eax
829
        jz      .exit
830
        stdcall map_page, edi, eax, PG_UW
831
 
832
@@:
833
        mov     edi, [lin_addr]
834
        and     edi, 0xFFFFF000
835
        mov     ecx, [buf_size]
836
        add     ecx, 4095
837
        shr     ecx, 12
838
        inc     ecx
839
 
840
        mov     edx, [ofs]
841
        shr     edx, 12
842
        and     edx, 0x3FF
843
        mov     esi, [proc_mem_tab]
844
 
845
.map:
846
        stdcall safe_map_page, [slot], [req_access], [ofs]
847
        jnc     .exit
848
        add     dword [ebp-4], 0x1000
849
        add     edi, 0x1000
850
        add     [ofs], 0x1000
851
        inc     edx
852
        dec     ecx
853
        jnz     .map
854
.exit:
855
        pop     eax
856
        ret
857
endp
858
 
859
; in: esi+edx*4 = pointer to page table entry
860
; in: [slot], [req_access], [ofs] on the stack
861
; in: edi = linear address to map
862
; out: CF cleared <=> failed
863
; destroys: only eax
864
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
865
        mov     eax, [esi+edx*4]
866
        test    al, PG_MAP
867
        jz      .not_present
868
        test    al, PG_WRITE
869
        jz      .resolve_readonly
870
; normal case: writable page, just map with requested access
871
.map:
872
        stdcall map_page, edi, eax, [req_access]
873
        stc
874
.fail:
875
        ret
876
.not_present:
877
; check for alloc-on-demand page
878
        test    al, 2
879
        jz      .fail
880
; allocate new page, save it to source page table
881
        push    ecx
882
        call    alloc_page
883
        pop     ecx
884
        test    eax, eax
885
        jz      .fail
886
        or      al, PG_UW
887
        mov     [esi+edx*4], eax
888
        jmp     .map
889
.resolve_readonly:
890
; readonly page, probably copy-on-write
891
; check: readonly request of readonly page is ok
892
        test    [req_access], PG_WRITE
893
        jz      .map
894
; find control structure for this page
895
        pushf
896
        cli
897
        cld
898
        push    ebx ecx
899
        mov     eax, [slot]
900
        shl     eax, 8
4433 Serge 901
        mov     eax, [SLOT_BASE+eax+APPDATA.process]
902
        mov     eax, [eax+PROC.dlls_list_ptr]
4429 Serge 903
        test    eax, eax
904
        jz      .no_hdll
905
        mov     ecx, [eax+HDLL.fd]
906
.scan_hdll:
907
        cmp     ecx, eax
908
        jz      .no_hdll
909
        mov     ebx, [ofs]
910
        and     ebx, not 0xFFF
911
        sub     ebx, [ecx+HDLL.base]
912
        cmp     ebx, [ecx+HDLL.size]
913
        jb      .hdll_found
914
        mov     ecx, [ecx+HDLL.fd]
915
        jmp     .scan_hdll
916
.no_hdll:
917
        pop     ecx ebx
918
        popf
919
        clc
920
        ret
921
.hdll_found:
922
; allocate page, save it in page table, map it, copy contents from base
923
        mov     eax, [ecx+HDLL.parent]
924
        add     ebx, [eax+DLLDESCR.data]
925
        call    alloc_page
926
        test    eax, eax
927
        jz      .no_hdll
928
        or      al, PG_UW
929
        mov     [esi+edx*4], eax
930
        stdcall map_page, edi, eax, [req_access]
931
        push    esi edi
932
        mov     esi, ebx
933
        mov     ecx, 4096/4
934
        rep movsd
935
        pop     edi esi
936
        pop     ecx ebx
937
        popf
938
        stc
939
        ret
940
endp
941
 
942
sys_IPC:
943
;input:
944
;  ebx=1 - set ipc buffer area
945
;    ecx=address of buffer
946
;    edx=size of buffer
947
;  eax=2 - send message
948
;    ebx=PID
949
;    ecx=address of message
950
;    edx=size of message
951
 
952
        dec     ebx
953
        jnz     @f
954
 
955
        mov     eax, [current_slot]
956
        pushf
957
        cli
958
        mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
959
        mov     [eax+APPDATA.ipc_size], edx
960
 
961
        add     edx, ecx
962
        add     edx, 4095
963
        and     edx, not 4095
964
 
965
.touch:
966
        mov     eax, [ecx]
967
        add     ecx, 0x1000
968
        cmp     ecx, edx
969
        jb      .touch
970
 
971
        popf
972
        mov     [esp+32], ebx   ;ebx=0
973
        ret
974
 
975
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
976
;2
977
@@:
978
        dec     ebx
979
        jnz     @f
980
 
981
        stdcall sys_ipc_send, ecx, edx, esi
982
        mov     [esp+32], eax
983
        ret
984
@@:
985
        or      eax, -1
986
        mov     [esp+32], eax
987
        ret
988
 
989
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
990
           locals
991
             dst_slot   dd ?
992
             dst_offset dd ?
993
             buf_size   dd ?
994
             used_buf   dd ?
995
           endl
996
 
997
        pushf
998
        cli
999
 
1000
        mov     eax, [PID]
1001
        call    pid_to_slot
1002
        test    eax, eax
1003
        jz      .no_pid
1004
 
1005
        mov     [dst_slot], eax
1006
        shl     eax, 8
4430 Serge 1007
        mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
4429 Serge 1008
        test    edi, edi
1009
        jz      .no_ipc_area
1010
 
1011
        mov     ebx, edi
1012
        and     ebx, 0xFFF
1013
        mov     [dst_offset], ebx
1014
 
4430 Serge 1015
        mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
4429 Serge 1016
        mov     [buf_size], esi
1017
 
1018
        mov     ecx, [ipc_tmp]
1019
        cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
1020
        jbe     @f
1021
        push    esi edi
1022
        add     esi, 0x1000
1023
        stdcall alloc_kernel_space, esi
1024
        mov     ecx, eax
1025
        pop     edi esi
1026
@@:
1027
        mov     [used_buf], ecx
4430 Serge 1028
        stdcall map_mem_ipc, ecx, [dst_slot], \
4429 Serge 1029
                edi, esi, PG_SW
1030
 
1031
        mov     edi, [dst_offset]
1032
        add     edi, [used_buf]
1033
        cmp     dword [edi], 0
1034
        jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
1035
 
1036
        mov     edx, dword [edi+4]
1037
        lea     ebx, [edx+8]
1038
        add     ebx, [msg_size]
1039
        cmp     ebx, [buf_size]
1040
        ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
1041
 
1042
        mov     dword [edi+4], ebx
1043
        mov     eax, [TASK_BASE]
1044
        mov     eax, [eax+0x04]        ;eax - our PID
1045
        add     edi, edx
1046
        mov     [edi], eax
1047
        mov     ecx, [msg_size]
1048
 
1049
        mov     [edi+4], ecx
1050
        add     edi, 8
1051
        mov     esi, [msg_addr]
1052
       ;    add esi, new_app_base
1053
        cld
1054
        rep movsb
1055
 
1056
        mov     ebx, [ipc_tmp]
1057
        mov     edx, ebx
1058
        shr     ebx, 12
1059
        xor     eax, eax
1060
        mov     [page_tabs+ebx*4], eax
1061
        invlpg  [edx]
1062
 
1063
        mov     ebx, [ipc_pdir]
1064
        mov     edx, ebx
1065
        shr     ebx, 12
1066
        xor     eax, eax
1067
        mov     [page_tabs+ebx*4], eax
1068
        invlpg  [edx]
1069
 
1070
        mov     ebx, [ipc_ptab]
1071
        mov     edx, ebx
1072
        shr     ebx, 12
1073
        xor     eax, eax
1074
        mov     [page_tabs+ebx*4], eax
1075
        invlpg  [edx]
1076
 
1077
        mov     eax, [dst_slot]
1078
        shl     eax, 8
1079
        or      [eax+SLOT_BASE+0xA8], dword 0x40
1080
        push    0
1081
        jmp     .ret
1082
.no_pid:
1083
        popf
1084
        mov     eax, 4
1085
        ret
1086
.no_ipc_area:
1087
        popf
1088
        xor     eax, eax
1089
        inc     eax
1090
        ret
1091
.ipc_blocked:
1092
        push    2
1093
        jmp     .ret
1094
.buffer_overflow:
1095
        push    3
1096
.ret:
1097
        mov     eax, [used_buf]
1098
        cmp     eax, [ipc_tmp]
4430 Serge 1099
        je      @f
4429 Serge 1100
        stdcall free_kernel_space, eax
1101
@@:
1102
        pop     eax
1103
        popf
1104
        ret
1105
endp
1106
 
1107
align 4
1108
sysfn_meminfo:
1109
 
1110
        ;   add ecx, new_app_base
1111
        cmp     ecx, OS_BASE
1112
        jae     .fail
1113
 
1114
        mov     eax, [pg_data.pages_count]
1115
        mov     [ecx], eax
1116
        shl     eax, 12
1117
        mov     [esp+32], eax
1118
        mov     eax, [pg_data.pages_free]
1119
        mov     [ecx+4], eax
1120
        mov     eax, [pg_data.pages_faults]
1121
        mov     [ecx+8], eax
1122
        mov     eax, [heap_size]
1123
        mov     [ecx+12], eax
1124
        mov     eax, [heap_free]
1125
        mov     [ecx+16], eax
1126
        mov     eax, [heap_blocks]
1127
        mov     [ecx+20], eax
1128
        mov     eax, [free_blocks]
1129
        mov     [ecx+24], eax
1130
        ret
1131
.fail:
1132
        or      dword [esp+32], -1
1133
        ret
1134
 
1135
align 4
1136
f68:
1137
        cmp     ebx, 4
1138
        jbe     sys_sheduler
1139
 
1140
        cmp     ebx, 11
1141
        jb      .fail
1142
 
1143
        cmp     ebx, 27
1144
        ja      .fail
1145
 
1146
        jmp     dword [f68call+ebx*4-11*4]
1147
.11:
1148
        call    init_heap
1149
        mov     [esp+32], eax
1150
        ret
1151
.12:
1152
        stdcall user_alloc, ecx
1153
        mov     [esp+32], eax
1154
        ret
1155
.13:
1156
        stdcall user_free, ecx
1157
        mov     [esp+32], eax
1158
        ret
1159
.14:
1160
        cmp     ecx, OS_BASE
1161
        jae     .fail
1162
        mov     edi, ecx
1163
        call    get_event_ex
1164
        mov     [esp+32], eax
1165
        ret
1166
.16:
1167
        test    ecx, ecx
1168
        jz      .fail
1169
        cmp     ecx, OS_BASE
1170
        jae     .fail
1171
        stdcall get_service, ecx
1172
        mov     [esp+32], eax
1173
        ret
1174
.17:
1175
        call    srv_handlerEx   ;ecx
1176
        mov     [esp+32], eax
1177
        ret
1178
.19:
1179
        cmp     ecx, OS_BASE
1180
        jae     .fail
1181
        stdcall load_library, ecx
1182
        mov     [esp+32], eax
1183
        ret
1184
.20:
1185
        mov     eax, edx
1186
        mov     ebx, ecx
1187
        call    user_realloc            ;in: eax = pointer, ebx = new size
1188
        mov     [esp+32], eax
1189
        ret
1190
.21:
1191
        cmp     ecx, OS_BASE
1192
        jae     .fail
1193
 
1194
        cmp     edx, OS_BASE
1195
        jae     .fail
1196
 
1197
        stdcall load_pe_driver, ecx, edx
1198
        mov     [esp+32], eax
1199
        ret
1200
.22:
1201
        cmp     ecx, OS_BASE
1202
        jae     .fail
1203
 
1204
        stdcall shmem_open, ecx, edx, esi
1205
        mov     [esp+24], edx
1206
        mov     [esp+32], eax
1207
        ret
1208
 
1209
.23:
1210
        cmp     ecx, OS_BASE
1211
        jae     .fail
1212
 
1213
        stdcall shmem_close, ecx
1214
        mov     [esp+32], eax
1215
        ret
1216
.24:
1217
        mov     eax, [current_slot]
1218
        xchg    ecx, [eax+APPDATA.exc_handler]
1219
        xchg    edx, [eax+APPDATA.except_mask]
1220
        mov     [esp+32], ecx ; reg_eax+8
1221
        mov     [esp+20], edx ; reg_ebx+8
1222
        ret
1223
.25:
1224
        cmp     ecx, 32
1225
        jae     .fail
1226
        mov     eax, [current_slot]
1227
        btr     [eax+APPDATA.except_mask], ecx
1228
        setc    byte[esp+32]
1229
        jecxz   @f
1230
        bts     [eax+APPDATA.except_mask], ecx
1231
@@:
1232
        ret
1233
 
1234
.26:
1235
        stdcall user_unmap, ecx, edx, esi
1236
        mov     [esp+32], eax
1237
        ret
1238
 
1239
.27:
1240
        cmp     ecx, OS_BASE
1241
        jae     .fail
1242
 
1243
        stdcall load_file_umode, ecx
1244
        mov     [esp+24], edx
1245
        mov     [esp+32], eax
1246
        ret
1247
 
1248
.fail:
1249
        xor     eax, eax
1250
        mov     [esp+32], eax
1251
        ret
1252
 
1253
 
1254
align 4
1255
f68call:   ; keep this table closer to main code
1256
 
1257
           dd f68.11   ; init_heap
1258
           dd f68.12   ; user_alloc
1259
           dd f68.13   ; user_free
1260
           dd f68.14   ; get_event_ex
1261
           dd f68.fail ; moved to f68.24
1262
           dd f68.16   ; get_service
1263
           dd f68.17   ; call_service
1264
           dd f68.fail ; moved to f68.25
1265
           dd f68.19   ; load_dll
1266
           dd f68.20   ; user_realloc
1267
           dd f68.21   ; load_driver
1268
           dd f68.22   ; shmem_open
1269
           dd f68.23   ; shmem_close
1270
           dd f68.24   ; set exception handler
1271
           dd f68.25   ; unmask exception
1272
           dd f68.26   ; user_unmap
1273
           dd f68.27   ; load_file_umode
1274
 
1275
 
1276
align 4
1277
proc load_pe_driver stdcall, file:dword, cmdline:dword
1278
        push    esi
1279
 
1280
        stdcall load_PE, [file]
1281
        test    eax, eax
1282
        jz      .fail
1283
 
1284
        mov     esi, eax
1285
        push    [cmdline]
1286
        push    DRV_ENTRY
1287
        call    eax
1288
        pop     ecx
1289
        pop     ecx
1290
        test    eax, eax
1291
        jz      .fail
1292
 
1293
        mov     [eax+SRV.entry], esi
1294
        pop     esi
1295
        ret
1296
 
1297
.fail:
1298
        xor     eax, eax
1299
        pop     esi
1300
        ret
1301
endp
1302
 
1303
align 4
1304
proc init_mtrr
1305
 
1306
        cmp     [BOOT_VARS+BOOT_MTRR], byte 2
1307
        je      .exit
1308
 
1309
        bt      [cpu_caps], CAPS_MTRR
1310
        jnc     .exit
1311
 
1312
        mov     eax, cr0
1313
        or      eax, 0x60000000 ;disable caching
1314
        mov     cr0, eax
1315
        wbinvd                  ;invalidate cache
1316
 
1317
        mov     ecx, 0x2FF
1318
        rdmsr                   ;
1319
; has BIOS already initialized MTRRs?
1320
        test    ah, 8
1321
        jnz     .skip_init
1322
; rarely needed, so mainly placeholder
1323
; main memory - cached
1324
        push    eax
1325
 
1326
        mov     eax, [MEM_AMOUNT]
1327
; round eax up to next power of 2
1328
        dec     eax
1329
        bsr     ecx, eax
1330
        mov     ebx, 2
1331
        shl     ebx, cl
1332
        dec     ebx
1333
; base of memory range = 0, type of memory range = MEM_WB
1334
        xor     edx, edx
1335
        mov     eax, MEM_WB
1336
        mov     ecx, 0x200
1337
        wrmsr
1338
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
1339
        mov     eax, 0xFFFFFFFF
1340
        mov     edx, 0x0000000F
1341
        sub     eax, ebx
1342
        sbb     edx, 0
1343
        or      eax, 0x800
1344
        inc     ecx
1345
        wrmsr
1346
; clear unused MTRRs
1347
        xor     eax, eax
1348
        xor     edx, edx
1349
@@:
1350
        inc     ecx
1351
        wrmsr
1352
        cmp     ecx, 0x20F
1353
        jb      @b
1354
; enable MTRRs
1355
        pop     eax
1356
        or      ah, 8
1357
        and     al, 0xF0; default memtype = UC
1358
        mov     ecx, 0x2FF
1359
        wrmsr
1360
.skip_init:
1361
        stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC
1362
 
1363
        wbinvd                  ;again invalidate
1364
 
1365
        mov     eax, cr0
1366
        and     eax, not 0x60000000
1367
        mov     cr0, eax        ; enable caching
1368
.exit:
1369
        ret
1370
endp
1371
 
1372
align 4
1373
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
1374
; find unused register
1375
        mov     ecx, 0x201
1376
@@:
1377
        rdmsr
1378
        dec     ecx
1379
        test    ah, 8
1380
        jz      .found
1381
        rdmsr
1382
        mov     al, 0; clear memory type field
1383
        cmp     eax, [base]
1384
        jz      .ret
1385
        add     ecx, 3
1386
        cmp     ecx, 0x210
1387
        jb      @b
1388
; no free registers, ignore the call
1389
.ret:
1390
        ret
1391
.found:
1392
; found, write values
1393
        xor     edx, edx
1394
        mov     eax, [base]
1395
        or      eax, [mem_type]
1396
        wrmsr
1397
 
1398
        mov     ebx, [size]
1399
        dec     ebx
1400
        mov     eax, 0xFFFFFFFF
1401
        mov     edx, 0x00000000
1402
        sub     eax, ebx
1403
        sbb     edx, 0
1404
        or      eax, 0x800
1405
        inc     ecx
1406
        wrmsr
1407
        ret
1408
endp
1409
 
1410
align 4
1411
proc create_ring_buffer stdcall, size:dword, flags:dword
1412
           locals
1413
             buf_ptr  dd ?
1414
           endl
1415
 
1416
        mov     eax, [size]
1417
        test    eax, eax
1418
        jz      .fail
1419
 
1420
        add     eax, eax
1421
        stdcall alloc_kernel_space, eax
1422
        test    eax, eax
1423
        jz      .fail
1424
 
1425
        push    ebx
1426
 
1427
        mov     [buf_ptr], eax
1428
 
1429
        mov     ebx, [size]
1430
        shr     ebx, 12
1431
        push    ebx
1432
 
1433
        stdcall alloc_pages, ebx
1434
        pop     ecx
1435
 
1436
        test    eax, eax
1437
        jz      .mm_fail
1438
 
1439
        push    edi
1440
 
1441
        or      eax, [flags]
1442
        mov     edi, [buf_ptr]
1443
        mov     ebx, [buf_ptr]
1444
        mov     edx, ecx
1445
        shl     edx, 2
1446
        shr     edi, 10
1447
@@:
1448
        mov     [page_tabs+edi], eax
1449
        mov     [page_tabs+edi+edx], eax
1450
        invlpg  [ebx]
1451
        invlpg  [ebx+0x10000]
1452
        add     eax, 0x1000
1453
        add     ebx, 0x1000
1454
        add     edi, 4
1455
        dec     ecx
1456
        jnz     @B
1457
 
1458
        mov     eax, [buf_ptr]
1459
        pop     edi
1460
        pop     ebx
1461
        ret
1462
.mm_fail:
1463
        stdcall free_kernel_space, [buf_ptr]
1464
        xor     eax, eax
1465
        pop     ebx
1466
.fail:
1467
        ret
1468
endp
1469
 
1470
 
1471
align 4
1472
proc print_mem
1473
        mov     edi, BOOT_VAR + 0x9104
1474
        mov     ecx, [edi-4]
1475
        test    ecx, ecx
1476
        jz      .done
1477
 
1478
@@:
1479
        mov     eax, [edi]
1480
        mov     edx, [edi+4]
1481
        add     eax, [edi+8]
1482
        adc     edx, [edi+12]
1483
 
1484
        DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
1485
                    [edi+4], [edi],\
1486
                    edx, eax, [edi+16]
1487
        add     edi, 20
1488
        dec     ecx
1489
        jnz     @b
1490
.done:
1491
        ret
1492
endp