Subversion Repositories Kolibri OS

Rev

Rev 2398 | Rev 2414 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 2400 $
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
        push    ebx
128
        mov     eax, [phis_addr]
129
        and     eax, not 0xFFF
130
        or      eax, [flags]
131
        mov     ebx, [lin_addr]
132
        shr     ebx, 12
133
        mov     [page_tabs+ebx*4], eax
134
        mov     eax, [lin_addr]
135
        invlpg  [eax]
136
        pop     ebx
137
        ret
138
endp
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
proc map_io_mem stdcall, base:dword, size:dword, flags:dword
170
 
171
        push    ebx
172
        push    edi
173
        mov     eax, [size]
174
        add     eax, [base]
175
        add     eax, 4095
176
        and     eax, -4096
177
        mov     ecx, [base]
178
        and     ecx, -4096
179
        sub     eax, ecx
180
        mov     [size], eax
181
 
182
        stdcall alloc_kernel_space, eax
183
        test    eax, eax
184
        jz      .fail
185
        push    eax
186
 
187
        mov     edi, 0x1000
188
        mov     ebx, eax
189
        mov     ecx, [size]
190
        mov     edx, [base]
191
        shr     eax, 12
192
        shr     ecx, 12
193
        and     edx, -4096
194
        or      edx, [flags]
195
@@:
196
        mov     [page_tabs+eax*4], edx
197
        invlpg  [ebx]
198
        inc     eax
199
        add     ebx, edi
200
        add     edx, edi
201
        loop    @B
202
 
203
        pop     eax
204
        mov     edx, [base]
205
        and     edx, 4095
206
        add     eax, edx
207
.fail:
208
        pop     edi
209
        pop     ebx
210
        ret
211
endp
212
 
213
; param
214
;  eax= page base + page flags
215
;  ebx= linear address
216
;  ecx= count
217
 
218
align 4
219
commit_pages:
220
        test    ecx, ecx
221
        jz      .fail
222
 
223
        push    edi
224
        push    eax
225
        push    ecx
226
        mov     ecx, pg_data.mutex
227
        call    mutex_lock
228
        pop     ecx
229
        pop     eax
230
 
231
        mov     edi, ebx
232
        shr     edi, 12
233
        lea     edi, [page_tabs+edi*4]
234
@@:
235
        stosd
236
        invlpg  [ebx]
237
        add     eax, 0x1000
238
        add     ebx, 0x1000
239
        loop    @B
240
 
241
        pop     edi
242
 
243
        mov     ecx, pg_data.mutex
244
        call    mutex_unlock
245
.fail:
246
        ret
247
 
248
 
249
; param
250
;  eax= base
251
;  ecx= count
252
 
253
align 4
254
release_pages:
255
 
256
        push    ebp
257
        push    esi
258
        push    edi
259
        push    ebx
260
 
261
        mov     esi, eax
262
        mov     edi, eax
263
 
264
        shr     esi, 12
265
        lea     esi, [page_tabs+esi*4]
266
 
267
        push    ecx
268
        mov     ecx, pg_data.mutex
269
        call    mutex_lock
270
        pop     ecx
271
 
272
        mov     ebp, [pg_data.pages_free]
273
        mov     ebx, [page_start]
274
        mov     edx, sys_pgmap
275
@@:
276
        xor     eax, eax
277
        xchg    eax, [esi]
278
        invlpg  [edi]
279
 
280
        test    eax, 1
281
        jz      .next
282
 
283
        shr     eax, 12
284
        bts     [edx], eax
285
        cmc
286
        adc     ebp, 0
287
        shr     eax, 3
288
        and     eax, -4
289
        add     eax, edx
290
        cmp     eax, ebx
291
        jae     .next
292
 
293
        mov     ebx, eax
294
.next:
295
        add     edi, 0x1000
296
        add     esi, 4
297
        loop    @B
298
 
299
        mov     [pg_data.pages_free], ebp
300
        mov     ecx, pg_data.mutex
301
        call    mutex_unlock
302
 
303
        pop     ebx
304
        pop     edi
305
        pop     esi
306
        pop     ebp
307
        ret
308
 
309
; param
310
;  eax= base
311
;  ecx= count
312
 
313
align 4
314
unmap_pages:
315
 
316
        push    edi
317
 
318
        mov     edi, eax
319
        mov     edx, eax
320
 
321
        shr     edi, 10
322
        add     edi, page_tabs
323
 
324
        xor     eax, eax
325
@@:
326
        stosd
327
        invlpg  [edx]
328
        add     edx, 0x1000
329
        loop    @b
330
 
331
        pop     edi
332
        ret
333
 
334
 
335
align 4
336
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
337
        push    ebx
338
        mov     ebx, [lin_addr]
339
        shr     ebx, 22
340
        mov     eax, [phis_addr]
341
        and     eax, not 0xFFF
342
        or      eax, PG_UW        ;+PG_NOCACHE
343
        mov     dword [master_tab+ebx*4], eax
344
        mov     eax, [lin_addr]
345
        shr     eax, 10
346
        add     eax, page_tabs
347
        invlpg  [eax]
348
        pop     ebx
349
        ret
350
endp
351
 
352
align 4
353
proc init_LFB
354
           locals
355
             pg_count dd ?
356
           endl
357
 
358
        cmp     dword [LFBAddress], -1
359
        jne     @f
360
        mov     [BOOT_VAR+0x901c], byte 2
2398 mario79 361
; max VGA=640*480*4=1228800 bytes
362
; + 32*640*4=81920 bytes for mouse pointer
363
        stdcall alloc_pages, ((1228800+81920)/4096)
2288 clevermous 364
 
365
        push    eax
366
        call    alloc_page
367
        stdcall map_page_table, LFB_BASE, eax
368
        pop     eax
369
        or      eax, PG_UW
370
        mov     ebx, LFB_BASE
2398 mario79 371
; max VGA=640*480*4=1228800 bytes
372
; + 32*640*4=81920 bytes for mouse pointer
373
        mov     ecx, (1228800+81920)/4096
2288 clevermous 374
        call    commit_pages
375
        mov     [LFBAddress], dword LFB_BASE
376
        ret
377
@@:
378
        test    [SCR_MODE], word 0100000000000000b
379
        jnz     @f
380
        mov     [BOOT_VAR+0x901c], byte 2
381
        ret
382
@@:
383
        call    init_mtrr
384
 
385
        mov     edx, LFB_BASE
386
        mov     esi, [LFBAddress]
387
        mov     edi, 0x00C00000
388
        mov     dword [exp_lfb+4], edx
389
 
390
        shr     edi, 12
391
        mov     [pg_count], edi
392
        shr     edi, 10
393
 
394
        bt      [cpu_caps], CAPS_PSE
395
        jnc     .map_page_tables
396
        or      esi, PG_LARGE+PG_UW
397
        mov     edx, sys_pgdir+(LFB_BASE shr 20)
398
@@:
399
        mov     [edx], esi
400
        add     edx, 4
401
        add     esi, 0x00400000
402
        dec     edi
403
        jnz     @B
404
 
405
        bt      [cpu_caps], CAPS_PGE
406
        jnc     @F
407
        or      dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL
408
@@:
409
        mov     dword [LFBAddress], LFB_BASE
410
        mov     eax, cr3      ;flush TLB
411
        mov     cr3, eax
412
        ret
413
 
414
.map_page_tables:
415
 
416
@@:
417
        call    alloc_page
418
        stdcall map_page_table, edx, eax
419
        add     edx, 0x00400000
420
        dec     edi
421
        jnz     @B
422
 
423
        mov     eax, [LFBAddress]
424
        mov     edi, page_tabs + (LFB_BASE shr 10)
425
        or      eax, PG_UW
426
        mov     ecx, [pg_count]
427
        cld
428
@@:
429
        stosd
430
        add     eax, 0x1000
431
        dec     ecx
432
        jnz     @B
433
 
434
        mov     dword [LFBAddress], LFB_BASE
435
        mov     eax, cr3      ;flush TLB
436
        mov     cr3, eax
437
 
438
        ret
439
endp
440
 
441
align 4
442
proc new_mem_resize stdcall, new_size:dword
443
 
444
        mov     ecx, pg_data.mutex
445
        call    mutex_lock
446
 
447
        mov     edi, [new_size]
448
        add     edi, 4095
449
        and     edi, not 4095
450
        mov     [new_size], edi
451
 
452
        mov     edx, [current_slot]
453
        cmp     [edx+APPDATA.heap_base], 0
454
        jne     .exit
455
 
456
        mov     esi, [edx+APPDATA.mem_size]
457
        add     esi, 4095
458
        and     esi, not 4095
459
 
460
        cmp     edi, esi
461
        jae     .expand
462
 
463
        shr     edi, 12
464
        shr     esi, 12
465
@@:
466
        mov     eax, [app_page_tabs+edi*4]
467
        test    eax, 1
468
        jz      .next
469
        mov     dword [app_page_tabs+edi*4], 2
470
        mov     ebx, edi
471
        shl     ebx, 12
472
        push    eax
473
        invlpg  [ebx]
474
        pop     eax
475
        call    free_page
476
 
477
.next:
478
        add     edi, 1
479
        cmp     edi, esi
480
        jb      @B
481
 
482
.update_size:
483
        mov     ebx, [new_size]
484
        call    update_mem_size
485
 
486
        mov     ecx, pg_data.mutex
487
        call    mutex_unlock
488
 
489
        xor     eax, eax
490
        ret
491
.expand:
492
 
493
        push    esi
494
        push    edi
495
 
496
        add     edi, 0x3FFFFF
497
        and     edi, not(0x3FFFFF)
498
        add     esi, 0x3FFFFF
499
        and     esi, not(0x3FFFFF)
500
 
501
        cmp     esi, edi
502
        jae     .grow
503
 
504
        xchg    esi, edi
505
 
506
@@:
507
        call    alloc_page
508
        test    eax, eax
509
        jz      .exit_pop
510
 
511
        stdcall map_page_table, edi, eax
512
 
513
        push    edi
514
        shr     edi, 10
515
        add     edi, page_tabs
516
        mov     ecx, 1024
517
        xor     eax, eax
518
        cld
519
        rep stosd
520
        pop     edi
521
 
522
        add     edi, 0x00400000
523
        cmp     edi, esi
524
        jb      @B
525
.grow:
526
;//-
527
        pop     edi
528
        push    edi
529
        mov     esi, [pg_data.pages_free]
530
        sub     esi, 1
531
        shr     edi, 12
532
        cmp     esi, edi
533
        jle     .out_of_memory
534
;//-
535
        pop     edi
536
        pop     esi
537
@@:
538
        call    alloc_page
539
        test    eax, eax
540
        jz      .exit
541
        stdcall map_page, esi, eax, dword PG_UW
542
 
543
        push    edi
544
        mov     edi, esi
545
        xor     eax, eax
546
        mov     ecx, 1024
547
        cld
548
        rep stosd
549
        pop     edi
550
 
551
        add     esi, 0x1000
552
        cmp     esi, edi
553
        jb      @B
554
 
555
        jmp     .update_size
556
;//-
557
.exit_pop:
558
.out_of_memory:
559
;//-
560
        pop     edi
561
        pop     esi
562
.exit:
563
        mov     ecx, pg_data.mutex
564
        call    mutex_unlock
565
 
566
        xor     eax, eax
567
        inc     eax
568
        ret
569
endp
570
 
571
update_mem_size:
572
; in: edx = slot base
573
;     ebx = new memory size
574
; destroys eax,ecx,edx
575
 
576
        mov     [APPDATA.mem_size+edx], ebx
577
;search threads and update
578
;application memory size infomation
579
        mov     ecx, [APPDATA.dir_table+edx]
580
        mov     eax, 2
581
 
582
.search_threads:
583
;eax = current slot
584
;ebx = new memory size
585
;ecx = page directory
586
        cmp     eax, [TASK_COUNT]
587
        jg      .search_threads_end
588
        mov     edx, eax
589
        shl     edx, 5
590
        cmp     word [CURRENT_TASK+edx+TASKDATA.state], 9  ;if slot empty?
591
        jz      .search_threads_next
592
        shl     edx, 3
593
        cmp     [SLOT_BASE+edx+APPDATA.dir_table], ecx      ;if it is our thread?
594
        jnz     .search_threads_next
595
        mov     [SLOT_BASE+edx+APPDATA.mem_size], ebx      ;update memory size
596
.search_threads_next:
597
        inc     eax
598
        jmp     .search_threads
599
.search_threads_end:
600
        ret
601
 
602
; param
603
;  eax= linear address
604
;
605
; retval
606
;  eax= phisical page address
607
 
608
align 4
609
get_pg_addr:
610
        shr     eax, 12
611
        mov     eax, [page_tabs+eax*4]
612
        and     eax, 0xFFFFF000
613
        ret
614
 
615
 
616
align 4
617
; Now it is called from core/sys32::exc_c (see stack frame there)
618
proc page_fault_handler
619
 
620
    .err_addr   equ ebp-4
621
 
622
        push    ebx               ;save exception number (#PF)
623
        mov     ebp, esp
624
        mov     ebx, cr2
625
        push    ebx               ;that is locals: .err_addr = cr2
626
        inc     [pg_data.pages_faults]
627
 
628
        mov     eax, [pf_err_code]
629
 
630
        cmp     ebx, OS_BASE      ;ebx == .err_addr
631
        jb      .user_space       ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ;
632
 
633
        cmp     ebx, page_tabs
634
        jb      .kernel_space     ;ñòðàíèöà â ïàìÿòè ÿäðà
635
 
636
        cmp     ebx, kernel_tabs
637
        jb      .alloc;.app_tabs  ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ;
638
                                  ;ïðîñòî ñîçäàäèì îäíó
639
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå
640
        cmp     ebx, LFB_BASE
641
        jb      .core_tabs        ;òàáëèöû ñòðàíèö ÿäðà
642
                                  ;Îøèáêà
643
  .lfb:
644
                                  ;îáëàñòü LFB
645
                                  ;Îøèáêà
646
        jmp     .fail
647
end if
648
.core_tabs:
649
.fail:  ;simply return to caller
650
        mov     esp, ebp
651
        pop     ebx               ;restore exception number (#PF)
652
        ret
653
 
654
;        xchg bx, bx
655
;        add     esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller
656
;        restore_ring3_context
657
;        iretd
658
 
659
.user_space:
660
        test    eax, PG_MAP
661
        jnz     .err_access       ;Ñòðàíèöà ïðèñóòñòâóåò
662
                                  ;Îøèáêà äîñòóïà ?
663
 
664
        shr     ebx, 12
665
        mov     ecx, ebx
666
        shr     ecx, 10
667
        mov     edx, [master_tab+ecx*4]
668
        test    edx, PG_MAP
669
        jz      .fail             ;òàáëèöà ñòðàíèö íå ñîçäàíà
670
                                  ;íåâåðíûé àäðåñ â ïðîãðàììå
671
 
672
        mov     eax, [page_tabs+ebx*4]
673
        test    eax, 2
674
        jz      .fail             ;àäðåñ íå çàðåçåðâèðîâàí äëÿ ;
675
                                  ;èñïîëüçîâàíèÿ. Îøèáêà
676
.alloc:
677
        call    alloc_page
678
        test    eax, eax
679
        jz      .fail
680
 
681
        stdcall map_page, [.err_addr], eax, PG_UW
682
 
683
        mov     edi, [.err_addr]
684
        and     edi, 0xFFFFF000
685
        mov     ecx, 1024
686
        xor     eax, eax
687
       ;cld     ;caller is duty for this
688
        rep stosd
689
.exit:  ;iret with repeat fault instruction
690
        add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
691
        restore_ring3_context
692
        iretd
693
 
694
.err_access:
695
; access denied? this may be a result of copy-on-write protection for DLL
696
; check list of HDLLs
697
        and     ebx, not 0xFFF
698
        mov     eax, [CURRENT_TASK]
699
        shl     eax, 8
700
        mov     eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
701
        test    eax, eax
702
        jz      .fail
703
        mov     esi, [eax+HDLL.fd]
704
.scan_hdll:
705
        cmp     esi, eax
706
        jz      .fail
707
        mov     edx, ebx
708
        sub     edx, [esi+HDLL.base]
709
        cmp     edx, [esi+HDLL.size]
710
        jb      .fault_in_hdll
711
.scan_hdll.next:
712
        mov     esi, [esi+HDLL.fd]
713
        jmp     .scan_hdll
714
.fault_in_hdll:
715
; allocate new page, map it as rw and copy data
716
        call    alloc_page
717
        test    eax, eax
718
        jz      .fail
719
        stdcall map_page, ebx, eax, PG_UW
720
        mov     edi, ebx
721
        mov     ecx, 1024
722
        sub     ebx, [esi+HDLL.base]
723
        mov     esi, [esi+HDLL.parent]
724
        mov     esi, [esi+DLLDESCR.data]
725
        add     esi, ebx
726
        rep movsd
727
        jmp     .exit
728
 
729
.kernel_space:
730
        test    eax, PG_MAP
731
        jz      .fail   ;ñòðàíèöà íå ïðèñóòñòâóåò
732
 
733
        test    eax, 12 ;U/S (+below)
734
        jnz     .fail   ;ïðèëîæåíèå îáðàòèëîñü ê ïàìÿòè
735
                        ;ÿäðà
736
       ;test    eax, 8
737
       ;jnz     .fail   ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò
738
                        ;â òàáëèöàõ ñòðàíèö. äîáàâëåíî â P4/Xeon
739
 
740
;ïîïûòêà çàïèñè â çàùèù¸ííóþ ñòðàíèöó ÿäðà
741
 
742
        cmp     ebx, tss._io_map_0
743
        jb      .fail
744
 
745
        cmp     ebx, tss._io_map_0+8192
746
        jae     .fail
747
 
748
; io permission map
749
; copy-on-write protection
750
 
751
        call    alloc_page
752
        test    eax, eax
753
        jz      .fail
754
 
755
        push    eax
756
        stdcall map_page, [.err_addr], eax, dword PG_SW
757
        pop     eax
758
        mov     edi, [.err_addr]
759
        and     edi, -4096
760
        lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
761
 
762
        mov     ebx, esi
763
        shr     ebx, 12
764
        mov     edx, [current_slot]
765
        or      eax, PG_SW
766
        mov     [edx+APPDATA.io_map+ebx*4], eax
767
 
768
        add     esi, [default_io_map]
769
        mov     ecx, 4096/4
770
       ;cld     ;caller is duty for this
771
        rep movsd
772
        jmp     .exit
773
endp
774
 
775
; returns number of mapped bytes
776
proc map_mem stdcall, lin_addr:dword,slot:dword,\
777
                      ofs:dword,buf_size:dword,req_access:dword
778
        push    0 ; initialize number of mapped bytes
779
 
780
        cmp     [buf_size], 0
781
        jz      .exit
782
 
783
        mov     eax, [slot]
784
        shl     eax, 8
785
        mov     eax, [SLOT_BASE+eax+APPDATA.dir_table]
786
        and     eax, 0xFFFFF000
787
 
788
        stdcall map_page, [ipc_pdir], eax, PG_UW
789
        mov     ebx, [ofs]
790
        shr     ebx, 22
791
        mov     esi, [ipc_pdir]
792
        mov     edi, [ipc_ptab]
793
        mov     eax, [esi+ebx*4]
794
        and     eax, 0xFFFFF000
795
        jz      .exit
796
        stdcall map_page, edi, eax, PG_UW
797
;           inc ebx
798
;           add edi, 0x1000
799
;           mov eax, [esi+ebx*4]
800
;           test eax, eax
801
;           jz @f
802
;          and eax, 0xFFFFF000
803
;           stdcall map_page, edi, eax
804
 
805
@@:
806
        mov     edi, [lin_addr]
807
        and     edi, 0xFFFFF000
808
        mov     ecx, [buf_size]
809
        add     ecx, 4095
810
        shr     ecx, 12
811
        inc     ecx
812
 
813
        mov     edx, [ofs]
814
        shr     edx, 12
815
        and     edx, 0x3FF
816
        mov     esi, [ipc_ptab]
817
 
818
.map:
819
        stdcall safe_map_page, [slot], [req_access], [ofs]
820
        jnc     .exit
821
        add     dword [ebp-4], 4096
822
        add     [ofs], 4096
823
        dec     ecx
824
        jz      .exit
825
        add     edi, 0x1000
826
        inc     edx
827
        cmp     edx, 0x400
828
        jnz     .map
829
        inc     ebx
830
        mov     eax, [ipc_pdir]
831
        mov     eax, [eax+ebx*4]
832
        and     eax, 0xFFFFF000
833
        jz      .exit
834
        stdcall map_page, esi, eax, PG_UW
835
        xor     edx, edx
836
        jmp     .map
837
 
838
.exit:
839
        pop     eax
840
        ret
841
endp
842
 
843
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
844
                        ofs:dword,buf_size:dword,req_access:dword
845
        push    0 ; initialize number of mapped bytes
846
 
847
        cmp     [buf_size], 0
848
        jz      .exit
849
 
850
        mov     eax, [slot]
851
        shl     eax, 8
852
        mov     eax, [SLOT_BASE+eax+APPDATA.dir_table]
853
        and     eax, 0xFFFFF000
854
 
855
        stdcall map_page, [proc_mem_pdir], eax, PG_UW
856
        mov     ebx, [ofs]
857
        shr     ebx, 22
858
        mov     esi, [proc_mem_pdir]
859
        mov     edi, [proc_mem_tab]
860
        mov     eax, [esi+ebx*4]
861
        and     eax, 0xFFFFF000
862
        test    eax, eax
863
        jz      .exit
864
        stdcall map_page, edi, eax, PG_UW
865
 
866
@@:
867
        mov     edi, [lin_addr]
868
        and     edi, 0xFFFFF000
869
        mov     ecx, [buf_size]
870
        add     ecx, 4095
871
        shr     ecx, 12
872
        inc     ecx
873
 
874
        mov     edx, [ofs]
875
        shr     edx, 12
876
        and     edx, 0x3FF
877
        mov     esi, [proc_mem_tab]
878
 
879
.map:
880
        stdcall safe_map_page, [slot], [req_access], [ofs]
881
        jnc     .exit
882
        add     dword [ebp-4], 0x1000
883
        add     edi, 0x1000
884
        add     [ofs], 0x1000
885
        inc     edx
886
        dec     ecx
887
        jnz     .map
888
.exit:
889
        pop     eax
890
        ret
891
endp
892
 
893
; in: esi+edx*4 = pointer to page table entry
894
; in: [slot], [req_access], [ofs] on the stack
895
; in: edi = linear address to map
896
; out: CF cleared <=> failed
897
; destroys: only eax
898
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
899
        mov     eax, [esi+edx*4]
900
        test    al, PG_MAP
901
        jz      .not_present
902
        test    al, PG_WRITE
903
        jz      .resolve_readonly
904
; normal case: writable page, just map with requested access
905
.map:
906
        stdcall map_page, edi, eax, [req_access]
907
        stc
908
.fail:
909
        ret
910
.not_present:
911
; check for alloc-on-demand page
912
        test    al, 2
913
        jz      .fail
914
; allocate new page, save it to source page table
915
        push    ecx
916
        call    alloc_page
917
        pop     ecx
918
        test    eax, eax
919
        jz      .fail
920
        or      al, PG_UW
921
        mov     [esi+edx*4], eax
922
        jmp     .map
923
.resolve_readonly:
924
; readonly page, probably copy-on-write
925
; check: readonly request of readonly page is ok
926
        test    [req_access], PG_WRITE
927
        jz      .map
928
; find control structure for this page
929
        pushf
930
        cli
931
        cld
932
        push    ebx ecx
933
        mov     eax, [slot]
934
        shl     eax, 8
935
        mov     eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
936
        test    eax, eax
937
        jz      .no_hdll
938
        mov     ecx, [eax+HDLL.fd]
939
.scan_hdll:
940
        cmp     ecx, eax
941
        jz      .no_hdll
942
        mov     ebx, [ofs]
943
        and     ebx, not 0xFFF
944
        sub     ebx, [ecx+HDLL.base]
945
        cmp     ebx, [ecx+HDLL.size]
946
        jb      .hdll_found
947
        mov     ecx, [ecx+HDLL.fd]
948
        jmp     .scan_hdll
949
.no_hdll:
950
        pop     ecx ebx
951
        popf
952
        clc
953
        ret
954
.hdll_found:
955
; allocate page, save it in page table, map it, copy contents from base
956
        mov     eax, [ecx+HDLL.parent]
957
        add     ebx, [eax+DLLDESCR.data]
958
        call    alloc_page
959
        test    eax, eax
960
        jz      .no_hdll
961
        or      al, PG_UW
962
        mov     [esi+edx*4], eax
963
        stdcall map_page, edi, eax, [req_access]
964
        push    esi edi
965
        mov     esi, ebx
966
        mov     ecx, 4096/4
967
        rep movsd
968
        pop     edi esi
969
        pop     ecx ebx
970
        popf
971
        stc
972
        ret
973
endp
974
 
975
sys_IPC:
976
;input:
977
;  ebx=1 - set ipc buffer area
978
;    ecx=address of buffer
979
;    edx=size of buffer
980
;  eax=2 - send message
981
;    ebx=PID
982
;    ecx=address of message
983
;    edx=size of message
984
 
985
        dec     ebx
986
        jnz     @f
987
 
988
        mov     eax, [current_slot]
989
        pushf
990
        cli
991
        mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
992
        mov     [eax+APPDATA.ipc_size], edx
993
 
994
        add     edx, ecx
995
        add     edx, 4095
996
        and     edx, not 4095
997
 
998
.touch:
999
        mov     eax, [ecx]
1000
        add     ecx, 0x1000
1001
        cmp     ecx, edx
1002
        jb      .touch
1003
 
1004
        popf
1005
        mov     [esp+32], ebx   ;ebx=0
1006
        ret
1007
 
1008
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1009
;2
1010
@@:
1011
        dec     ebx
1012
        jnz     @f
1013
 
1014
        stdcall sys_ipc_send, ecx, edx, esi
1015
        mov     [esp+32], eax
1016
        ret
1017
@@:
1018
        or      eax, -1
1019
        mov     [esp+32], eax
1020
        ret
1021
 
1022
;align 4
1023
;proc set_ipc_buff
1024
 
1025
;           mov  eax,[current_slot]
1026
;           pushf
1027
;           cli
1028
;           mov  [eax+APPDATA.ipc_start],ebx     ;set fields in extended information area
1029
;           mov  [eax+APPDATA.ipc_size],ecx
1030
;
1031
;           add ecx, ebx
1032
;           add ecx, 4095
1033
;           and ecx, not 4095
1034
;
1035
;.touch:    mov eax, [ebx]
1036
;           add ebx, 0x1000
1037
;           cmp ebx, ecx
1038
;           jb  .touch
1039
;
1040
;           popf
1041
;           xor eax, eax
1042
;           ret
1043
;endp
1044
 
1045
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
1046
           locals
1047
             dst_slot   dd ?
1048
             dst_offset dd ?
1049
             buf_size   dd ?
1050
             used_buf   dd ?
1051
           endl
1052
 
1053
        pushf
1054
        cli
1055
 
1056
        mov     eax, [PID]
1057
        call    pid_to_slot
1058
        test    eax, eax
1059
        jz      .no_pid
1060
 
1061
        mov     [dst_slot], eax
1062
        shl     eax, 8
1063
        mov     edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined?
1064
        test    edi, edi
1065
        jz      .no_ipc_area
1066
 
1067
        mov     ebx, edi
1068
        and     ebx, 0xFFF
1069
        mov     [dst_offset], ebx
1070
 
1071
        mov     esi, [eax+SLOT_BASE+0xa4]
1072
        mov     [buf_size], esi
1073
 
1074
        mov     ecx, [ipc_tmp]
1075
        cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
1076
        jbe     @f
1077
        push    esi edi
1078
        add     esi, 0x1000
1079
        stdcall alloc_kernel_space, esi
1080
        mov     ecx, eax
1081
        pop     edi esi
1082
@@:
1083
        mov     [used_buf], ecx
1084
        stdcall map_mem, ecx, [dst_slot], \
1085
                edi, esi, PG_SW
1086
 
1087
        mov     edi, [dst_offset]
1088
        add     edi, [used_buf]
1089
        cmp     dword [edi], 0
1090
        jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
1091
 
1092
        mov     edx, dword [edi+4]
1093
        lea     ebx, [edx+8]
1094
        add     ebx, [msg_size]
1095
        cmp     ebx, [buf_size]
1096
        ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
1097
 
1098
        mov     dword [edi+4], ebx
1099
        mov     eax, [TASK_BASE]
1100
        mov     eax, [eax+0x04]        ;eax - our PID
1101
        add     edi, edx
1102
        mov     [edi], eax
1103
        mov     ecx, [msg_size]
1104
 
1105
        mov     [edi+4], ecx
1106
        add     edi, 8
1107
        mov     esi, [msg_addr]
1108
       ;    add esi, new_app_base
1109
        cld
1110
        rep movsb
1111
 
1112
        mov     ebx, [ipc_tmp]
1113
        mov     edx, ebx
1114
        shr     ebx, 12
1115
        xor     eax, eax
1116
        mov     [page_tabs+ebx*4], eax
1117
        invlpg  [edx]
1118
 
1119
        mov     ebx, [ipc_pdir]
1120
        mov     edx, ebx
1121
        shr     ebx, 12
1122
        xor     eax, eax
1123
        mov     [page_tabs+ebx*4], eax
1124
        invlpg  [edx]
1125
 
1126
        mov     ebx, [ipc_ptab]
1127
        mov     edx, ebx
1128
        shr     ebx, 12
1129
        xor     eax, eax
1130
        mov     [page_tabs+ebx*4], eax
1131
        invlpg  [edx]
1132
 
1133
        mov     eax, [dst_slot]
1134
        shl     eax, 8
1135
        or      [eax+SLOT_BASE+0xA8], dword 0x40
1136
        cmp     dword [check_idle_semaphore], 20
1137
        jge     .ipc_no_cis
1138
 
1139
        mov     dword [check_idle_semaphore], 5
1140
.ipc_no_cis:
1141
        push    0
1142
        jmp     .ret
1143
.no_pid:
1144
        popf
1145
        mov     eax, 4
1146
        ret
1147
.no_ipc_area:
1148
        popf
1149
        xor     eax, eax
1150
        inc     eax
1151
        ret
1152
.ipc_blocked:
1153
        push    2
1154
        jmp     .ret
1155
.buffer_overflow:
1156
        push    3
1157
.ret:
1158
        mov     eax, [used_buf]
1159
        cmp     eax, [ipc_tmp]
1160
        jz      @f
1161
        stdcall free_kernel_space, eax
1162
@@:
1163
        pop     eax
1164
        popf
1165
        ret
1166
endp
1167
 
1168
align 4
1169
sysfn_meminfo:
1170
 
1171
        ;   add ecx, new_app_base
1172
        cmp     ecx, OS_BASE
1173
        jae     .fail
1174
 
1175
        mov     eax, [pg_data.pages_count]
1176
        mov     [ecx], eax
1177
        shl     eax, 12
1178
        mov     [esp+32], eax
1179
        mov     eax, [pg_data.pages_free]
1180
        mov     [ecx+4], eax
1181
        mov     eax, [pg_data.pages_faults]
1182
        mov     [ecx+8], eax
1183
        mov     eax, [heap_size]
1184
        mov     [ecx+12], eax
1185
        mov     eax, [heap_free]
1186
        mov     [ecx+16], eax
1187
        mov     eax, [heap_blocks]
1188
        mov     [ecx+20], eax
1189
        mov     eax, [free_blocks]
1190
        mov     [ecx+24], eax
1191
        ret
1192
.fail:
1193
        or      dword [esp+32], -1
1194
        ret
1195
 
1196
align 4
1197
f68:
1198
        cmp     ebx, 4
1199
        jbe     sys_sheduler
1200
 
1201
        cmp     ebx, 11
1202
        jb      .fail
1203
 
1204
        cmp     ebx, 25
1205
        ja      .fail
1206
 
1207
        jmp     dword [f68call+ebx*4-11*4]
1208
.11:
1209
        call    init_heap
1210
        mov     [esp+32], eax
1211
        ret
1212
.12:
1213
        stdcall user_alloc, ecx
1214
        mov     [esp+32], eax
1215
        ret
1216
.13:
1217
        stdcall user_free, ecx
1218
        mov     [esp+32], eax
1219
        ret
1220
.14:
1221
        cmp     ecx, OS_BASE
1222
        jae     .fail
1223
        mov     edi, ecx
1224
        call    get_event_ex
1225
        mov     [esp+32], eax
1226
        ret
1227
.16:
1228
        test    ecx, ecx
1229
        jz      .fail
1230
        cmp     ecx, OS_BASE
1231
        jae     .fail
1232
        stdcall get_service, ecx
1233
        mov     [esp+32], eax
1234
        ret
1235
.17:
1236
        call    srv_handlerEx   ;ecx
1237
        mov     [esp+32], eax
1238
        ret
1239
.19:
1240
        cmp     ecx, OS_BASE
1241
        jae     .fail
1242
        stdcall load_library, ecx
1243
        mov     [esp+32], eax
1244
        ret
1245
.20:
1246
        mov     eax, edx
1247
        mov     ebx, ecx
1248
        call    user_realloc            ;in: eax = pointer, ebx = new size
1249
        mov     [esp+32], eax
1250
        ret
1251
.21:
1252
        cmp     ecx, OS_BASE
1253
        jae     .fail
1254
 
1255
        cmp     ebx, OS_BASE
1256
        jae     .fail
1257
 
1258
        mov     edi, edx
1259
        stdcall load_PE, ecx
1260
        mov     esi, eax
1261
        test    eax, eax
1262
        jz      @F
1263
 
1264
        push    edi
1265
        push    DRV_ENTRY
1266
        call    eax
1267
        add     esp, 8
1268
        test    eax, eax
1269
        jz      @F
1270
 
1271
        mov     [eax+SRV.entry], esi
1272
 
1273
@@:
1274
        mov     [esp+32], eax
1275
        ret
1276
.22:
1277
        cmp     ecx, OS_BASE
1278
        jae     .fail
1279
 
1280
        stdcall shmem_open, ecx, edx, esi
1281
        mov     [esp+24], edx
1282
        mov     [esp+32], eax
1283
        ret
1284
 
1285
.23:
1286
        cmp     ecx, OS_BASE
1287
        jae     .fail
1288
 
1289
        stdcall shmem_close, ecx
1290
        mov     [esp+32], eax
1291
        ret
1292
.24:
1293
        mov     eax, [current_slot]
1294
        xchg    ecx, [eax+APPDATA.exc_handler]
1295
        xchg    edx, [eax+APPDATA.except_mask]
1296
        mov     [esp+32], ecx ; reg_eax+8
1297
        mov     [esp+20], edx ; reg_ebx+8
1298
        ret
1299
.25:
1300
        cmp     ecx, 32
1301
        jae     .fail
1302
        mov     eax, [current_slot]
1303
        btr     [eax+APPDATA.except_mask], ecx
1304
        setc    byte[esp+32]
1305
        jecxz   @f
1306
        bts     [eax+APPDATA.except_mask], ecx
1307
@@:
1308
        ret
1309
 
2400 Serge 1310
.26:
1311
        stdcall user_unmap, ecx, edx, esi
1312
        mov     [esp+32], eax
1313
        ret
1314
 
2288 clevermous 1315
.fail:
1316
        xor     eax, eax
1317
        mov     [esp+32], eax
1318
        ret
1319
 
1320
 
1321
align 4
1322
f68call:   ; keep this table closer to main code
1323
 
1324
           dd f68.11   ; init_heap
1325
           dd f68.12   ; user_alloc
1326
           dd f68.13   ; user_free
1327
           dd f68.14   ; get_event_ex
1328
           dd f68.fail ; moved to f68.24
1329
           dd f68.16   ; get_service
1330
           dd f68.17   ; call_service
1331
           dd f68.fail ; moved to f68.25
1332
           dd f68.19   ; load_dll
1333
           dd f68.20   ; user_realloc
1334
           dd f68.21   ; load_driver
1335
           dd f68.22   ; shmem_open
1336
           dd f68.23   ; shmem_close
2400 Serge 1337
           dd f68.24   ; set exception handler
1338
           dd f68.25   ; unmask exception
1339
           dd f68.26   ; user_unmap
2288 clevermous 1340
 
1341
 
1342
align 4
1343
proc load_pe_driver stdcall, file:dword
1344
 
1345
        stdcall load_PE, [file]
1346
        test    eax, eax
1347
        jz      .fail
1348
 
1349
        mov     esi, eax
1350
        stdcall eax, DRV_ENTRY
1351
        test    eax, eax
1352
        jz      .fail
1353
 
1354
        mov     [eax+SRV.entry], esi
1355
        ret
1356
 
1357
.fail:
1358
        xor     eax, eax
1359
        ret
1360
endp
1361
 
1362
 
1363
align 4
1364
proc init_mtrr
1365
 
1366
        cmp     [BOOT_VAR+0x901c], byte 2
1367
        je      .exit
1368
 
1369
        bt      [cpu_caps], CAPS_MTRR
1370
        jnc     .exit
1371
 
1372
        mov     eax, cr0
1373
        or      eax, 0x60000000 ;disable caching
1374
        mov     cr0, eax
1375
        wbinvd                  ;invalidate cache
1376
 
1377
        mov     ecx, 0x2FF
1378
        rdmsr                   ;
1379
; has BIOS already initialized MTRRs?
1380
        test    ah, 8
1381
        jnz     .skip_init
1382
; rarely needed, so mainly placeholder
1383
; main memory - cached
1384
        push    eax
1385
 
1386
        mov     eax, [MEM_AMOUNT]
1387
; round eax up to next power of 2
1388
        dec     eax
1389
        bsr     ecx, eax
1390
        mov     ebx, 2
1391
        shl     ebx, cl
1392
        dec     ebx
1393
; base of memory range = 0, type of memory range = MEM_WB
1394
        xor     edx, edx
1395
        mov     eax, MEM_WB
1396
        mov     ecx, 0x200
1397
        wrmsr
1398
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
1399
        mov     eax, 0xFFFFFFFF
1400
        mov     edx, 0x0000000F
1401
        sub     eax, ebx
1402
        sbb     edx, 0
1403
        or      eax, 0x800
1404
        inc     ecx
1405
        wrmsr
1406
; clear unused MTRRs
1407
        xor     eax, eax
1408
        xor     edx, edx
1409
@@:
1410
        wrmsr
1411
        inc     ecx
1412
        cmp     ecx, 0x210
1413
        jb      @b
1414
; enable MTRRs
1415
        pop     eax
1416
        or      ah, 8
1417
        and     al, 0xF0; default memtype = UC
1418
        mov     ecx, 0x2FF
1419
        wrmsr
1420
.skip_init:
1421
        stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC
1422
 
1423
        wbinvd                  ;again invalidate
1424
 
1425
        mov     eax, cr0
1426
        and     eax, not 0x60000000
1427
        mov     cr0, eax        ; enable caching
1428
.exit:
1429
        ret
1430
endp
1431
 
1432
align 4
1433
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
1434
; find unused register
1435
        mov     ecx, 0x201
1436
@@:
1437
        rdmsr
1438
        dec     ecx
1439
        test    ah, 8
1440
        jz      .found
1441
        rdmsr
1442
        mov     al, 0; clear memory type field
1443
        cmp     eax, [base]
1444
        jz      .ret
1445
        add     ecx, 3
1446
        cmp     ecx, 0x210
1447
        jb      @b
1448
; no free registers, ignore the call
1449
.ret:
1450
        ret
1451
.found:
1452
; found, write values
1453
        xor     edx, edx
1454
        mov     eax, [base]
1455
        or      eax, [mem_type]
1456
        wrmsr
1457
 
1458
        mov     ebx, [size]
1459
        dec     ebx
1460
        mov     eax, 0xFFFFFFFF
1461
        mov     edx, 0x00000000
1462
        sub     eax, ebx
1463
        sbb     edx, 0
1464
        or      eax, 0x800
1465
        inc     ecx
1466
        wrmsr
1467
        ret
1468
endp
1469
 
1470
align 4
1471
proc stall stdcall, delay:dword
1472
        push    ecx
1473
        push    edx
1474
        push    ebx
1475
        push    eax
1476
 
1477
        mov     eax, [delay]
1478
        mul     [stall_mcs]
1479
        mov     ebx, eax      ;low
1480
        mov     ecx, edx      ;high
1481
        rdtsc
1482
        add     ebx, eax
1483
        adc     ecx, edx
1484
@@:
1485
        rdtsc
1486
        sub     eax, ebx
1487
        sbb     edx, ecx
1488
        jb      @B
1489
 
1490
        pop     eax
1491
        pop     ebx
1492
        pop     edx
1493
        pop     ecx
1494
        ret
1495
endp
1496
 
1497
align 4
1498
proc create_ring_buffer stdcall, size:dword, flags:dword
1499
           locals
1500
             buf_ptr  dd ?
1501
           endl
1502
 
1503
        mov     eax, [size]
1504
        test    eax, eax
1505
        jz      .fail
1506
 
1507
        add     eax, eax
1508
        stdcall alloc_kernel_space, eax
1509
        test    eax, eax
1510
        jz      .fail
1511
 
1512
        push    ebx
1513
 
1514
        mov     [buf_ptr], eax
1515
 
1516
        mov     ebx, [size]
1517
        shr     ebx, 12
1518
        push    ebx
1519
 
1520
        stdcall alloc_pages, ebx
1521
        pop     ecx
1522
 
1523
        test    eax, eax
1524
        jz      .mm_fail
1525
 
1526
        push    edi
1527
 
1528
        or      eax, [flags]
1529
        mov     edi, [buf_ptr]
1530
        mov     ebx, [buf_ptr]
1531
        mov     edx, ecx
1532
        shl     edx, 2
1533
        shr     edi, 10
1534
@@:
1535
        mov     [page_tabs+edi], eax
1536
        mov     [page_tabs+edi+edx], eax
1537
        invlpg  [ebx]
1538
        invlpg  [ebx+0x10000]
1539
        add     eax, 0x1000
1540
        add     ebx, 0x1000
1541
        add     edi, 4
1542
        dec     ecx
1543
        jnz     @B
1544
 
1545
        mov     eax, [buf_ptr]
1546
        pop     edi
1547
        pop     ebx
1548
        ret
1549
.mm_fail:
1550
        stdcall free_kernel_space, [buf_ptr]
1551
        xor     eax, eax
1552
        pop     ebx
1553
.fail:
1554
        ret
1555
endp