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