Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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]
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
 
462
        cmp     edi, esi
463
        ja      .expand
464
        je      .exit
465
 
466
        mov     ebx, edi
467
        shr     edi, 12
468
        shr     esi, 12
469
 
470
        mov     ecx, pg_data.mutex
471
        call    mutex_lock
472
@@:
473
        mov     eax, [app_page_tabs+edi*4]
474
        test    eax, 1
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
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
560
        pop     edi
561
        pop     esi
562
        pop     ebx
563
        xor     eax, eax
564
        inc     eax
565
        ret
566
endp
567
 
568
 
569
align 4
570
update_mem_size:
571
; in: edx = slot base
572
;     ebx = new memory size
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.process+edx]
579
        mov     eax, 2
580
 
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
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.process], 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
610
        cmp     eax, 0x400000
611
        jb      @f
612
        shr     eax, 12
613
        mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
614
@@:
615
        and     eax, 0xFFFFF000
616
        ret
617
 
618
 
619
align 4
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
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  ;таблицы страниц приложения ;
641
                                  ;просто создадим одну
642
if 0 ;пока это просто лишнее
643
        cmp     ebx, LFB_BASE
644
        jb      .core_tabs        ;таблицы страниц ядра
645
                                  ;Ошибка
646
  .lfb:
647
                                  ;область LFB
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
769
        mov     [edx+APPDATA.io_map+ebx*4], eax
770
 
771
        add     esi, [default_io_map]
772
        mov     ecx, 4096/4
773
       ;cld     ;caller is duty for this
774
        rep movsd
775
        jmp     .exit
776
endp
777
 
778
; returns number of mapped bytes
779
proc map_mem stdcall, lin_addr:dword,slot:dword,\
780
                      ofs:dword,buf_size:dword,req_access:dword
781
        push    0 ; initialize number of mapped bytes
782
 
783
        cmp     [buf_size], 0
784
        jz      .exit
785
 
786
        mov     eax, [slot]
787
        shl     eax, 8
788
        mov     eax, [SLOT_BASE+eax+APPDATA.process]
789
        mov     eax, [eax+PROC.pdt_0_phys]
790
        and     eax, 0xFFFFF000
791
 
792
        stdcall map_page, [ipc_pdir], eax, PG_UW
793
        mov     ebx, [ofs]
794
        shr     ebx, 22
795
        mov     esi, [ipc_pdir]
796
        mov     edi, [ipc_ptab]
797
        mov     eax, [esi+ebx*4]
798
        and     eax, 0xFFFFF000
799
        jz      .exit
800
        stdcall map_page, edi, eax, PG_UW
801
 
802
@@:
803
        mov     edi, [lin_addr]
804
        and     edi, 0xFFFFF000
805
        mov     ecx, [buf_size]
806
        add     ecx, 4095
807
        shr     ecx, 12
808
        inc     ecx
809
 
810
        mov     edx, [ofs]
811
        shr     edx, 12
812
        and     edx, 0x3FF
813
        mov     esi, [ipc_ptab]
814
 
815
.map:
816
        stdcall safe_map_page, [slot], [req_access], [ofs]
817
        jnc     .exit
818
        add     dword [ebp-4], 4096
819
        add     [ofs], 4096
820
        dec     ecx
821
        jz      .exit
822
        add     edi, 0x1000
823
        inc     edx
824
        cmp     edx, 0x400
825
        jnz     .map
826
        inc     ebx
827
        mov     eax, [ipc_pdir]
828
        mov     eax, [eax+ebx*4]
829
        and     eax, 0xFFFFF000
830
        jz      .exit
831
        stdcall map_page, esi, eax, PG_UW
832
        xor     edx, edx
833
        jmp     .map
834
 
835
.exit:
836
        pop     eax
837
        ret
838
endp
839
 
840
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
841
                        ofs:dword,buf_size:dword,req_access:dword
842
        push    0 ; initialize number of mapped bytes
843
 
844
        cmp     [buf_size], 0
845
        jz      .exit
846
 
847
        mov     eax, [slot]
848
        shl     eax, 8
849
        mov     eax, [SLOT_BASE+eax+APPDATA.process]
850
        mov     eax, [eax+PROC.pdt_0_phys]
851
        and     eax, 0xFFFFF000
852
 
853
        stdcall map_page, [proc_mem_pdir], eax, PG_UW
854
        mov     ebx, [ofs]
855
        shr     ebx, 22
856
        mov     esi, [proc_mem_pdir]
857
        mov     edi, [proc_mem_tab]
858
        mov     eax, [esi+ebx*4]
859
        and     eax, 0xFFFFF000
860
        test    eax, eax
861
        jz      .exit
862
        stdcall map_page, edi, eax, PG_UW
863
 
864
@@:
865
        mov     edi, [lin_addr]
866
        and     edi, 0xFFFFF000
867
        mov     ecx, [buf_size]
868
        add     ecx, 4095
869
        shr     ecx, 12
870
        inc     ecx
871
 
872
        mov     edx, [ofs]
873
        shr     edx, 12
874
        and     edx, 0x3FF
875
        mov     esi, [proc_mem_tab]
876
 
877
.map:
878
        stdcall safe_map_page, [slot], [req_access], [ofs]
879
        jnc     .exit
880
        add     dword [ebp-4], 0x1000
881
        add     edi, 0x1000
882
        add     [ofs], 0x1000
883
        inc     edx
884
        dec     ecx
885
        jnz     .map
886
.exit:
887
        pop     eax
888
        ret
889
endp
890
 
891
; in: esi+edx*4 = pointer to page table entry
892
; in: [slot], [req_access], [ofs] on the stack
893
; in: edi = linear address to map
894
; out: CF cleared <=> failed
895
; destroys: only eax
896
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
897
        mov     eax, [esi+edx*4]
898
        test    al, PG_MAP
899
        jz      .not_present
900
        test    al, PG_WRITE
901
        jz      .resolve_readonly
902
; normal case: writable page, just map with requested access
903
.map:
904
        stdcall map_page, edi, eax, [req_access]
905
        stc
906
.fail:
907
        ret
908
.not_present:
909
; check for alloc-on-demand page
910
        test    al, 2
911
        jz      .fail
912
; allocate new page, save it to source page table
913
        push    ecx
914
        call    alloc_page
915
        pop     ecx
916
        test    eax, eax
917
        jz      .fail
918
        or      al, PG_UW
919
        mov     [esi+edx*4], eax
920
        jmp     .map
921
.resolve_readonly:
922
; readonly page, probably copy-on-write
923
; check: readonly request of readonly page is ok
924
        test    [req_access], PG_WRITE
925
        jz      .map
926
; find control structure for this page
927
        pushf
928
        cli
929
        cld
930
        push    ebx ecx
931
        mov     eax, [slot]
932
        shl     eax, 8
933
        mov     eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
934
        test    eax, eax
935
        jz      .no_hdll
936
        mov     ecx, [eax+HDLL.fd]
937
.scan_hdll:
938
        cmp     ecx, eax
939
        jz      .no_hdll
940
        mov     ebx, [ofs]
941
        and     ebx, not 0xFFF
942
        sub     ebx, [ecx+HDLL.base]
943
        cmp     ebx, [ecx+HDLL.size]
944
        jb      .hdll_found
945
        mov     ecx, [ecx+HDLL.fd]
946
        jmp     .scan_hdll
947
.no_hdll:
948
        pop     ecx ebx
949
        popf
950
        clc
951
        ret
952
.hdll_found:
953
; allocate page, save it in page table, map it, copy contents from base
954
        mov     eax, [ecx+HDLL.parent]
955
        add     ebx, [eax+DLLDESCR.data]
956
        call    alloc_page
957
        test    eax, eax
958
        jz      .no_hdll
959
        or      al, PG_UW
960
        mov     [esi+edx*4], eax
961
        stdcall map_page, edi, eax, [req_access]
962
        push    esi edi
963
        mov     esi, ebx
964
        mov     ecx, 4096/4
965
        rep movsd
966
        pop     edi esi
967
        pop     ecx ebx
968
        popf
969
        stc
970
        ret
971
endp
972
 
973
sys_IPC:
974
;input:
975
;  ebx=1 - set ipc buffer area
976
;    ecx=address of buffer
977
;    edx=size of buffer
978
;  eax=2 - send message
979
;    ebx=PID
980
;    ecx=address of message
981
;    edx=size of message
982
 
983
        dec     ebx
984
        jnz     @f
985
 
986
        mov     eax, [current_slot]
987
        pushf
988
        cli
989
        mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
990
        mov     [eax+APPDATA.ipc_size], edx
991
 
992
        add     edx, ecx
993
        add     edx, 4095
994
        and     edx, not 4095
995
 
996
.touch:
997
        mov     eax, [ecx]
998
        add     ecx, 0x1000
999
        cmp     ecx, edx
1000
        jb      .touch
1001
 
1002
        popf
1003
        mov     [esp+32], ebx   ;ebx=0
1004
        ret
1005
 
1006
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1007
;2
1008
@@:
1009
        dec     ebx
1010
        jnz     @f
1011
 
1012
        stdcall sys_ipc_send, ecx, edx, esi
1013
        mov     [esp+32], eax
1014
        ret
1015
@@:
1016
        or      eax, -1
1017
        mov     [esp+32], eax
1018
        ret
1019
 
1020
;align 4
1021
;proc set_ipc_buff
1022
 
1023
;           mov  eax,[current_slot]
1024
;           pushf
1025
;           cli
1026
;           mov  [eax+APPDATA.ipc_start],ebx     ;set fields in extended information area
1027
;           mov  [eax+APPDATA.ipc_size],ecx
1028
;
1029
;           add ecx, ebx
1030
;           add ecx, 4095
1031
;           and ecx, not 4095
1032
;
1033
;.touch:    mov eax, [ebx]
1034
;           add ebx, 0x1000
1035
;           cmp ebx, ecx
1036
;           jb  .touch
1037
;
1038
;           popf
1039
;           xor eax, eax
1040
;           ret
1041
;endp
1042
 
1043
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
1044
           locals
1045
             dst_slot   dd ?
1046
             dst_offset dd ?
1047
             buf_size   dd ?
1048
             used_buf   dd ?
1049
           endl
1050
 
1051
        pushf
1052
        cli
1053
 
1054
        mov     eax, [PID]
1055
        call    pid_to_slot
1056
        test    eax, eax
1057
        jz      .no_pid
1058
 
1059
        mov     [dst_slot], eax
1060
        shl     eax, 8
1061
        mov     edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined?
1062
        test    edi, edi
1063
        jz      .no_ipc_area
1064
 
1065
        mov     ebx, edi
1066
        and     ebx, 0xFFF
1067
        mov     [dst_offset], ebx
1068
 
1069
        mov     esi, [eax+SLOT_BASE+0xa4]
1070
        mov     [buf_size], esi
1071
 
1072
        mov     ecx, [ipc_tmp]
1073
        cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
1074
        jbe     @f
1075
        push    esi edi
1076
        add     esi, 0x1000
1077
        stdcall alloc_kernel_space, esi
1078
        mov     ecx, eax
1079
        pop     edi esi
1080
@@:
1081
        mov     [used_buf], ecx
1082
        stdcall map_mem, ecx, [dst_slot], \
1083
                edi, esi, PG_SW
1084
 
1085
        mov     edi, [dst_offset]
1086
        add     edi, [used_buf]
1087
        cmp     dword [edi], 0
1088
        jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
1089
 
1090
        mov     edx, dword [edi+4]
1091
        lea     ebx, [edx+8]
1092
        add     ebx, [msg_size]
1093
        cmp     ebx, [buf_size]
1094
        ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
1095
 
1096
        mov     dword [edi+4], ebx
1097
        mov     eax, [TASK_BASE]
1098
        mov     eax, [eax+0x04]        ;eax - our PID
1099
        add     edi, edx
1100
        mov     [edi], eax
1101
        mov     ecx, [msg_size]
1102
 
1103
        mov     [edi+4], ecx
1104
        add     edi, 8
1105
        mov     esi, [msg_addr]
1106
       ;    add esi, new_app_base
1107
        cld
1108
        rep movsb
1109
 
1110
        mov     ebx, [ipc_tmp]
1111
        mov     edx, ebx
1112
        shr     ebx, 12
1113
        xor     eax, eax
1114
        mov     [page_tabs+ebx*4], eax
1115
        invlpg  [edx]
1116
 
1117
        mov     ebx, [ipc_pdir]
1118
        mov     edx, ebx
1119
        shr     ebx, 12
1120
        xor     eax, eax
1121
        mov     [page_tabs+ebx*4], eax
1122
        invlpg  [edx]
1123
 
1124
        mov     ebx, [ipc_ptab]
1125
        mov     edx, ebx
1126
        shr     ebx, 12
1127
        xor     eax, eax
1128
        mov     [page_tabs+ebx*4], eax
1129
        invlpg  [edx]
1130
 
1131
        mov     eax, [dst_slot]
1132
        shl     eax, 8
1133
        or      [eax+SLOT_BASE+0xA8], dword 0x40
1134
        push    0
1135
        jmp     .ret
1136
.no_pid:
1137
        popf
1138
        mov     eax, 4
1139
        ret
1140
.no_ipc_area:
1141
        popf
1142
        xor     eax, eax
1143
        inc     eax
1144
        ret
1145
.ipc_blocked:
1146
        push    2
1147
        jmp     .ret
1148
.buffer_overflow:
1149
        push    3
1150
.ret:
1151
        mov     eax, [used_buf]
1152
        cmp     eax, [ipc_tmp]
1153
        jz      @f
1154
        stdcall free_kernel_space, eax
1155
@@:
1156
        pop     eax
1157
        popf
1158
        ret
1159
endp
1160
 
1161
align 4
1162
sysfn_meminfo:
1163
 
1164
        ;   add ecx, new_app_base
1165
        cmp     ecx, OS_BASE
1166
        jae     .fail
1167
 
1168
        mov     eax, [pg_data.pages_count]
1169
        mov     [ecx], eax
1170
        shl     eax, 12
1171
        mov     [esp+32], eax
1172
        mov     eax, [pg_data.pages_free]
1173
        mov     [ecx+4], eax
1174
        mov     eax, [pg_data.pages_faults]
1175
        mov     [ecx+8], eax
1176
        mov     eax, [heap_size]
1177
        mov     [ecx+12], eax
1178
        mov     eax, [heap_free]
1179
        mov     [ecx+16], eax
1180
        mov     eax, [heap_blocks]
1181
        mov     [ecx+20], eax
1182
        mov     eax, [free_blocks]
1183
        mov     [ecx+24], eax
1184
        ret
1185
.fail:
1186
        or      dword [esp+32], -1
1187
        ret
1188
 
1189
align 4
1190
f68:
1191
        cmp     ebx, 4
1192
        jbe     sys_sheduler
1193
 
1194
        cmp     ebx, 11
1195
        jb      .fail
1196
 
1197
        cmp     ebx, 27
1198
        ja      .fail
1199
 
1200
        jmp     dword [f68call+ebx*4-11*4]
1201
.11:
1202
        call    init_heap
1203
        mov     [esp+32], eax
1204
        ret
1205
.12:
1206
        stdcall user_alloc, ecx
1207
        mov     [esp+32], eax
1208
        ret
1209
.13:
1210
        stdcall user_free, ecx
1211
        mov     [esp+32], eax
1212
        ret
1213
.14:
1214
        cmp     ecx, OS_BASE
1215
        jae     .fail
1216
        mov     edi, ecx
1217
        call    get_event_ex
1218
        mov     [esp+32], eax
1219
        ret
1220
.16:
1221
        test    ecx, ecx
1222
        jz      .fail
1223
        cmp     ecx, OS_BASE
1224
        jae     .fail
1225
        stdcall get_service, ecx
1226
        mov     [esp+32], eax
1227
        ret
1228
.17:
1229
        call    srv_handlerEx   ;ecx
1230
        mov     [esp+32], eax
1231
        ret
1232
.19:
1233
        cmp     ecx, OS_BASE
1234
        jae     .fail
1235
        stdcall load_library, ecx
1236
        mov     [esp+32], eax
1237
        ret
1238
.20:
1239
        mov     eax, edx
1240
        mov     ebx, ecx
1241
        call    user_realloc            ;in: eax = pointer, ebx = new size
1242
        mov     [esp+32], eax
1243
        ret
1244
.21:
1245
        cmp     ecx, OS_BASE
1246
        jae     .fail
1247
 
1248
        cmp     edx, OS_BASE
1249
        jae     .fail
1250
 
1251
        stdcall load_pe_driver, ecx, edx
1252
        mov     [esp+32], eax
1253
        ret
1254
.22:
1255
        cmp     ecx, OS_BASE
1256
        jae     .fail
1257
 
1258
        stdcall shmem_open, ecx, edx, esi
1259
        mov     [esp+24], edx
1260
        mov     [esp+32], eax
1261
        ret
1262
 
1263
.23:
1264
        cmp     ecx, OS_BASE
1265
        jae     .fail
1266
 
1267
        stdcall shmem_close, ecx
1268
        mov     [esp+32], eax
1269
        ret
1270
.24:
1271
        mov     eax, [current_slot]
1272
        xchg    ecx, [eax+APPDATA.exc_handler]
1273
        xchg    edx, [eax+APPDATA.except_mask]
1274
        mov     [esp+32], ecx ; reg_eax+8
1275
        mov     [esp+20], edx ; reg_ebx+8
1276
        ret
1277
.25:
1278
        cmp     ecx, 32
1279
        jae     .fail
1280
        mov     eax, [current_slot]
1281
        btr     [eax+APPDATA.except_mask], ecx
1282
        setc    byte[esp+32]
1283
        jecxz   @f
1284
        bts     [eax+APPDATA.except_mask], ecx
1285
@@:
1286
        ret
1287
 
1288
.26:
1289
        stdcall user_unmap, ecx, edx, esi
1290
        mov     [esp+32], eax
1291
        ret
1292
 
1293
.27:
1294
        cmp     ecx, OS_BASE
1295
        jae     .fail
1296
 
1297
        stdcall load_file_umode, ecx
1298
        mov     [esp+24], edx
1299
        mov     [esp+32], eax
1300
        ret
1301
 
1302
.fail:
1303
        xor     eax, eax
1304
        mov     [esp+32], eax
1305
        ret
1306
 
1307
 
1308
align 4
1309
f68call:   ; keep this table closer to main code
1310
 
1311
           dd f68.11   ; init_heap
1312
           dd f68.12   ; user_alloc
1313
           dd f68.13   ; user_free
1314
           dd f68.14   ; get_event_ex
1315
           dd f68.fail ; moved to f68.24
1316
           dd f68.16   ; get_service
1317
           dd f68.17   ; call_service
1318
           dd f68.fail ; moved to f68.25
1319
           dd f68.19   ; load_dll
1320
           dd f68.20   ; user_realloc
1321
           dd f68.21   ; load_driver
1322
           dd f68.22   ; shmem_open
1323
           dd f68.23   ; shmem_close
1324
           dd f68.24   ; set exception handler
1325
           dd f68.25   ; unmask exception
1326
           dd f68.26   ; user_unmap
1327
           dd f68.27   ; load_file_umode
1328
 
1329
 
1330
align 4
1331
proc load_pe_driver stdcall, file:dword, cmdline:dword
1332
        push    esi
1333
 
1334
        stdcall load_PE, [file]
1335
        test    eax, eax
1336
        jz      .fail
1337
 
1338
        mov     esi, eax
1339
        push    [cmdline]
1340
        push    DRV_ENTRY
1341
        call    eax
1342
        pop     ecx
1343
        pop     ecx
1344
        test    eax, eax
1345
        jz      .fail
1346
 
1347
        mov     [eax+SRV.entry], esi
1348
        pop     esi
1349
        ret
1350
 
1351
.fail:
1352
        xor     eax, eax
1353
        pop     esi
1354
        ret
1355
endp
1356
 
1357
align 4
1358
proc init_mtrr
1359
 
1360
        cmp     [BOOT_VARS+BOOT_MTRR], byte 2
1361
        je      .exit
1362
 
1363
        bt      [cpu_caps], CAPS_MTRR
1364
        jnc     .exit
1365
 
1366
        mov     eax, cr0
1367
        or      eax, 0x60000000 ;disable caching
1368
        mov     cr0, eax
1369
        wbinvd                  ;invalidate cache
1370
 
1371
        mov     ecx, 0x2FF
1372
        rdmsr                   ;
1373
; has BIOS already initialized MTRRs?
1374
        test    ah, 8
1375
        jnz     .skip_init
1376
; rarely needed, so mainly placeholder
1377
; main memory - cached
1378
        push    eax
1379
 
1380
        mov     eax, [MEM_AMOUNT]
1381
; round eax up to next power of 2
1382
        dec     eax
1383
        bsr     ecx, eax
1384
        mov     ebx, 2
1385
        shl     ebx, cl
1386
        dec     ebx
1387
; base of memory range = 0, type of memory range = MEM_WB
1388
        xor     edx, edx
1389
        mov     eax, MEM_WB
1390
        mov     ecx, 0x200
1391
        wrmsr
1392
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
1393
        mov     eax, 0xFFFFFFFF
1394
        mov     edx, 0x0000000F
1395
        sub     eax, ebx
1396
        sbb     edx, 0
1397
        or      eax, 0x800
1398
        inc     ecx
1399
        wrmsr
1400
; clear unused MTRRs
1401
        xor     eax, eax
1402
        xor     edx, edx
1403
@@:
1404
        inc     ecx
1405
        wrmsr
1406
        cmp     ecx, 0x20F
1407
        jb      @b
1408
; enable MTRRs
1409
        pop     eax
1410
        or      ah, 8
1411
        and     al, 0xF0; default memtype = UC
1412
        mov     ecx, 0x2FF
1413
        wrmsr
1414
.skip_init:
1415
        stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC
1416
 
1417
        wbinvd                  ;again invalidate
1418
 
1419
        mov     eax, cr0
1420
        and     eax, not 0x60000000
1421
        mov     cr0, eax        ; enable caching
1422
.exit:
1423
        ret
1424
endp
1425
 
1426
align 4
1427
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
1428
; find unused register
1429
        mov     ecx, 0x201
1430
@@:
1431
        rdmsr
1432
        dec     ecx
1433
        test    ah, 8
1434
        jz      .found
1435
        rdmsr
1436
        mov     al, 0; clear memory type field
1437
        cmp     eax, [base]
1438
        jz      .ret
1439
        add     ecx, 3
1440
        cmp     ecx, 0x210
1441
        jb      @b
1442
; no free registers, ignore the call
1443
.ret:
1444
        ret
1445
.found:
1446
; found, write values
1447
        xor     edx, edx
1448
        mov     eax, [base]
1449
        or      eax, [mem_type]
1450
        wrmsr
1451
 
1452
        mov     ebx, [size]
1453
        dec     ebx
1454
        mov     eax, 0xFFFFFFFF
1455
        mov     edx, 0x00000000
1456
        sub     eax, ebx
1457
        sbb     edx, 0
1458
        or      eax, 0x800
1459
        inc     ecx
1460
        wrmsr
1461
        ret
1462
endp
1463
 
1464
align 4
1465
proc create_ring_buffer stdcall, size:dword, flags:dword
1466
           locals
1467
             buf_ptr  dd ?
1468
           endl
1469
 
1470
        mov     eax, [size]
1471
        test    eax, eax
1472
        jz      .fail
1473
 
1474
        add     eax, eax
1475
        stdcall alloc_kernel_space, eax
1476
        test    eax, eax
1477
        jz      .fail
1478
 
1479
        push    ebx
1480
 
1481
        mov     [buf_ptr], eax
1482
 
1483
        mov     ebx, [size]
1484
        shr     ebx, 12
1485
        push    ebx
1486
 
1487
        stdcall alloc_pages, ebx
1488
        pop     ecx
1489
 
1490
        test    eax, eax
1491
        jz      .mm_fail
1492
 
1493
        push    edi
1494
 
1495
        or      eax, [flags]
1496
        mov     edi, [buf_ptr]
1497
        mov     ebx, [buf_ptr]
1498
        mov     edx, ecx
1499
        shl     edx, 2
1500
        shr     edi, 10
1501
@@:
1502
        mov     [page_tabs+edi], eax
1503
        mov     [page_tabs+edi+edx], eax
1504
        invlpg  [ebx]
1505
        invlpg  [ebx+0x10000]
1506
        add     eax, 0x1000
1507
        add     ebx, 0x1000
1508
        add     edi, 4
1509
        dec     ecx
1510
        jnz     @B
1511
 
1512
        mov     eax, [buf_ptr]
1513
        pop     edi
1514
        pop     ebx
1515
        ret
1516
.mm_fail:
1517
        stdcall free_kernel_space, [buf_ptr]
1518
        xor     eax, eax
1519
        pop     ebx
1520
.fail:
1521
        ret
1522
endp
1523
 
1524
 
1525
align 4
1526
proc print_mem
1527
        mov     edi, BOOT_VAR + 0x9104
1528
        mov     ecx, [edi-4]
1529
        test    ecx, ecx
1530
        jz      .done
1531
 
1532
@@:
1533
        mov     eax, [edi]
1534
        mov     edx, [edi+4]
1535
        add     eax, [edi+8]
1536
        adc     edx, [edi+12]
1537
 
1538
        DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
1539
                    [edi+4], [edi],\
1540
                    edx, eax, [edi+16]
1541
        add     edi, 20
1542
        dec     ecx
1543
        jnz     @b
1544
.done:
1545
        ret
1546
endp