Subversion Repositories Kolibri OS

Rev

Rev 9047 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
7967 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 9048 $
9
 
10
 
11
align 4
12
proc alloc_page
13
 
14
        pushfd
15
        cli
16
        push    ebx
8052 rgimad 17
 
2288 clevermous 18
        cmp     [pg_data.pages_free], 1
19
        jle     .out_of_memory
20
 
8052 rgimad 21
 
2288 clevermous 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:
8052 rgimad 35
 
2288 clevermous 36
        dec     [pg_data.pages_free]
37
        jz      .out_of_memory
8052 rgimad 38
 
2288 clevermous 39
        btr     [ebx], eax
40
        mov     [page_start], ebx
41
        sub     ebx, sys_pgmap
42
        lea     eax, [eax+ebx*8]
43
        shl     eax, 12
8052 rgimad 44
;       dec [pg_data.pages_free]
2288 clevermous 45
        pop     ebx
46
        popfd
47
        ret
8052 rgimad 48
 
2288 clevermous 49
.out_of_memory:
50
        mov     [pg_data.pages_free], 1
51
        xor     eax, eax
52
        pop     ebx
53
        popfd
54
        ret
8052 rgimad 55
 
2288 clevermous 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
8052 rgimad 68
 
2288 clevermous 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
8052 rgimad 75
 
2288 clevermous 76
        mov     ecx, [page_start]
77
        mov     ebx, [page_end]
78
.find:
79
        mov     edx, [count]
80
        mov     edi, ecx
7967 hidnplayr 81
  .match:
2288 clevermous 82
        cmp     byte [ecx], 0xFF
83
        jne     .next
84
        dec     edx
85
        jz      .ok
86
        inc     ecx
87
        cmp     ecx, ebx
88
        jb      .match
7967 hidnplayr 89
  .out_of_memory:
90
  .fail:
2288 clevermous 91
        xor     eax, eax
92
        pop     edi
93
        pop     ebx
94
        popfd
95
        ret
7967 hidnplayr 96
  .next:
2288 clevermous 97
        inc     ecx
98
        cmp     ecx, ebx
99
        jb      .find
100
        pop     edi
101
        pop     ebx
102
        popfd
103
        xor     eax, eax
104
        ret
7967 hidnplayr 105
  .ok:
2288 clevermous 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
4424 Serge 126
;proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
127
map_page:
2288 clevermous 128
        push    ebx
5357 serge 129
        mov     eax, [esp+12]              ; phis_addr
4424 Serge 130
        or      eax, [esp+16]              ; flags
5357 serge 131
        and     eax, [pte_valid_mask]
4424 Serge 132
        mov     ebx, [esp+8]               ; lin_addr
2288 clevermous 133
        shr     ebx, 12
134
        mov     [page_tabs+ebx*4], eax
4424 Serge 135
        mov     eax, [esp+8]               ; lin_addr
136
        pop     ebx
2288 clevermous 137
        invlpg  [eax]
4424 Serge 138
        ret     12
2288 clevermous 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
 
2414 Serge 169
align 4
2288 clevermous 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
        or      edx, [flags]
5357 serge 195
        and     edx, [pte_valid_mask]
2288 clevermous 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
 
5357 serge 232
        and     eax, [pte_valid_mask ]
2288 clevermous 233
        mov     edi, ebx
234
        shr     edi, 12
235
        lea     edi, [page_tabs+edi*4]
236
@@:
237
        stosd
238
        invlpg  [ebx]
239
        add     eax, 0x1000
240
        add     ebx, 0x1000
241
        loop    @B
242
 
243
        pop     edi
244
 
245
        mov     ecx, pg_data.mutex
246
        call    mutex_unlock
247
.fail:
248
        ret
249
 
250
 
251
; param
252
;  eax= base
253
;  ecx= count
254
 
255
align 4
256
release_pages:
257
 
258
        push    ebp
259
        push    esi
260
        push    edi
261
        push    ebx
262
 
263
        mov     esi, eax
264
        mov     edi, eax
265
 
266
        shr     esi, 12
267
        lea     esi, [page_tabs+esi*4]
268
 
269
        push    ecx
270
        mov     ecx, pg_data.mutex
271
        call    mutex_lock
272
        pop     ecx
273
 
274
        mov     ebp, [pg_data.pages_free]
275
        mov     ebx, [page_start]
276
        mov     edx, sys_pgmap
277
@@:
278
        xor     eax, eax
279
        xchg    eax, [esi]
280
        invlpg  [edi]
281
 
282
        test    eax, 1
283
        jz      .next
284
 
285
        shr     eax, 12
286
        bts     [edx], eax
287
        cmc
288
        adc     ebp, 0
289
        shr     eax, 3
290
        and     eax, -4
291
        add     eax, edx
292
        cmp     eax, ebx
293
        jae     .next
294
 
295
        mov     ebx, eax
296
.next:
297
        add     edi, 0x1000
298
        add     esi, 4
299
        loop    @B
300
 
301
        mov     [pg_data.pages_free], ebp
302
        mov     ecx, pg_data.mutex
303
        call    mutex_unlock
304
 
305
        pop     ebx
306
        pop     edi
307
        pop     esi
308
        pop     ebp
309
        ret
310
 
311
; param
312
;  eax= base
313
;  ecx= count
314
 
315
align 4
316
unmap_pages:
317
 
318
        push    edi
319
 
320
        mov     edi, eax
321
        mov     edx, eax
322
 
323
        shr     edi, 10
324
        add     edi, page_tabs
325
 
326
        xor     eax, eax
327
@@:
328
        stosd
329
        invlpg  [edx]
330
        add     edx, 0x1000
331
        loop    @b
332
 
333
        pop     edi
334
        ret
335
 
336
 
337
align 4
338
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
339
        push    ebx
340
        mov     ebx, [lin_addr]
341
        shr     ebx, 22
342
        mov     eax, [phis_addr]
343
        and     eax, not 0xFFF
5365 serge 344
        or      eax, PG_UWR
2288 clevermous 345
        mov     dword [master_tab+ebx*4], eax
346
        mov     eax, [lin_addr]
347
        shr     eax, 10
348
        add     eax, page_tabs
349
        invlpg  [eax]
350
        pop     ebx
351
        ret
352
endp
353
 
5057 clevermous 354
uglobal
355
sb16_buffer_allocated db 0
356
endg
357
 
358
; Allocates [.size] bytes so that the target memory block
359
; is inside one 64K page for 24-bit DMA controller,
360
; that is, somewhere between 00xx0000h and 00xxFFFFh.
361
proc alloc_dma24
362
; Implementation note.
363
; The only user of that function is SB16 driver,
364
; so just return a statically allocated buffer.
365
virtual at esp
366
                dd      ? ; return address
367
.size           dd      ?
368
end virtual
369
        cmp     [sb16_buffer_allocated], 0
370
        jnz     .fail
371
        inc     [sb16_buffer_allocated]
372
        mov     eax, SB16Buffer
373
        ret     4
374
.fail:
375
        xor     eax, eax
376
        ret     4
377
endp
378
 
5032 clevermous 379
; Allocates a physical page for master page table
380
; that duplicates first Mb of OS_BASE at address 0;
381
; used for starting APs and for shutting down,
382
; where it is important to execute code in trivial-mapped pages.
383
; Returns eax = allocated physical page.
384
proc create_trampoline_pgmap
385
; The only non-trivial moment:
386
; we need a linear address to fill information,
387
; but we don't need it outside of this function,
388
; so we're returning physical address.
389
; Therefore, allocate memory with kernel_alloc,
390
; this will allocate physical page and a linear address somewhere,
391
; and deallocate only linear address with free_kernel_space.
392
        stdcall kernel_alloc, 0x1000
393
        mov     edi, eax
394
        mov     esi, master_tab
395
        mov     ecx, 1024
396
        rep movsd
397
        mov     ecx, [master_tab+(OS_BASE shr 20)]
398
        mov     [eax], ecx
399
        mov     edi, eax
400
        call    get_pg_addr
401
        push    eax
402
        stdcall free_kernel_space, edi
403
        pop     eax
404
        ret
405
endp
406
 
2288 clevermous 407
align 4
408
proc new_mem_resize stdcall, new_size:dword
409
 
2594 Serge 410
        push    ebx
411
        push    esi
412
        push    edi
2288 clevermous 413
 
2594 Serge 414
        mov     edx, [current_slot]
5130 serge 415
        mov     ebx, [edx+APPDATA.process]
416
 
417
        cmp     [ebx+PROC.heap_base], 0
2594 Serge 418
        jne     .exit
419
 
2288 clevermous 420
        mov     edi, [new_size]
421
        add     edi, 4095
422
        and     edi, not 4095
423
        mov     [new_size], edi
424
 
5130 serge 425
        mov     esi, [ebx+PROC.mem_used]
2288 clevermous 426
        add     esi, 4095
427
        and     esi, not 4095
428
 
429
        cmp     edi, esi
2594 Serge 430
        ja      .expand
431
        je      .exit
2288 clevermous 432
 
2594 Serge 433
        mov     ebx, edi
2288 clevermous 434
        shr     edi, 12
435
        shr     esi, 12
2594 Serge 436
 
437
        mov     ecx, pg_data.mutex
438
        call    mutex_lock
2288 clevermous 439
@@:
440
        mov     eax, [app_page_tabs+edi*4]
441
        test    eax, 1
442
        jz      .next
2594 Serge 443
 
444
        mov     dword [app_page_tabs+edi*4], 0
2288 clevermous 445
        invlpg  [ebx]
446
        call    free_page
447
 
448
.next:
2594 Serge 449
        inc     edi
2595 Serge 450
        add     ebx, 0x1000
2288 clevermous 451
        cmp     edi, esi
452
        jb      @B
453
 
2594 Serge 454
        mov     ecx, pg_data.mutex
455
        call    mutex_unlock
456
 
2288 clevermous 457
.update_size:
2594 Serge 458
        mov     edx, [current_slot]
2288 clevermous 459
        mov     ebx, [new_size]
5130 serge 460
        mov     edx, [edx+APPDATA.process]
461
        mov     [edx+PROC.mem_used], ebx
2594 Serge 462
.exit:
463
        pop     edi
464
        pop     esi
465
        pop     ebx
2288 clevermous 466
        xor     eax, eax
467
        ret
2594 Serge 468
 
2288 clevermous 469
.expand:
470
 
2594 Serge 471
        mov     ecx, pg_data.mutex
472
        call    mutex_lock
2288 clevermous 473
 
2594 Serge 474
        xchg    esi, edi
475
 
476
        push    esi                   ;new size
477
        push    edi                   ;old size
478
 
2288 clevermous 479
        add     edi, 0x3FFFFF
480
        and     edi, not(0x3FFFFF)
481
        add     esi, 0x3FFFFF
482
        and     esi, not(0x3FFFFF)
483
 
2594 Serge 484
        cmp     edi, esi
2288 clevermous 485
        jae     .grow
2594 Serge 486
 @@:
2288 clevermous 487
        call    alloc_page
488
        test    eax, eax
2594 Serge 489
        jz      .exit_fail
2288 clevermous 490
 
491
        stdcall map_page_table, edi, eax
492
 
493
        push    edi
494
        shr     edi, 10
495
        add     edi, page_tabs
496
        mov     ecx, 1024
497
        xor     eax, eax
498
        cld
499
        rep stosd
500
        pop     edi
501
 
502
        add     edi, 0x00400000
503
        cmp     edi, esi
504
        jb      @B
505
.grow:
2594 Serge 506
        pop     edi                   ;old size
507
        pop     ecx                   ;new size
2288 clevermous 508
 
2594 Serge 509
        shr     edi, 10
510
        shr     ecx, 10
511
        sub     ecx, edi
512
        shr     ecx, 2                ;pages count
513
        mov     eax, 2
514
 
515
        add     edi, app_page_tabs
2288 clevermous 516
        rep stosd
517
 
2594 Serge 518
        mov     ecx, pg_data.mutex
519
        call    mutex_unlock
2288 clevermous 520
 
521
        jmp     .update_size
2594 Serge 522
 
523
.exit_fail:
2288 clevermous 524
        mov     ecx, pg_data.mutex
525
        call    mutex_unlock
526
 
2594 Serge 527
        add     esp, 8
528
        pop     edi
529
        pop     esi
530
        pop     ebx
2288 clevermous 531
        xor     eax, eax
532
        inc     eax
533
        ret
534
endp
535
 
2594 Serge 536
 
2288 clevermous 537
; param
538
;  eax= linear address
539
;
540
; retval
8052 rgimad 541
;  eax= physical page address
2288 clevermous 542
 
543
align 4
544
get_pg_addr:
3166 clevermous 545
        sub     eax, OS_BASE
546
        cmp     eax, 0x400000
547
        jb      @f
2288 clevermous 548
        shr     eax, 12
3166 clevermous 549
        mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
550
@@:
2288 clevermous 551
        and     eax, 0xFFFFF000
552
        ret
553
 
554
 
555
align 4
556
; Now it is called from core/sys32::exc_c (see stack frame there)
557
proc page_fault_handler
558
 
559
    .err_addr   equ ebp-4
560
 
561
        push    ebx               ;save exception number (#PF)
562
        mov     ebp, esp
563
        mov     ebx, cr2
564
        push    ebx               ;that is locals: .err_addr = cr2
565
        inc     [pg_data.pages_faults]
566
 
9048 Boppan 567
        mov     esi, [pf_err_code]
2288 clevermous 568
 
569
        cmp     ebx, OS_BASE      ;ebx == .err_addr
8052 rgimad 570
        jb      .user_space       ;page in application memory
2288 clevermous 571
 
572
        cmp     ebx, page_tabs
8052 rgimad 573
        jb      .kernel_space     ;page in kernel memory
2288 clevermous 574
 
9048 Boppan 575
        xor     eax, eax
2288 clevermous 576
        cmp     ebx, kernel_tabs
8052 rgimad 577
        jb      .alloc;.app_tabs  ;page tables of application ;
578
                                  ;simply create one
2288 clevermous 579
.core_tabs:
580
.fail:  ;simply return to caller
581
        mov     esp, ebp
582
        pop     ebx               ;restore exception number (#PF)
583
        ret
9048 Boppan 584
.fail_maybe_unlock:
585
        test    esi, esi
586
        jz      .fail
587
.fail_unlock:
588
        mov     ecx, [current_process]
589
        add     ecx, PROC.heap_lock
590
        call    mutex_unlock
591
        jmp     .fail
2288 clevermous 592
 
593
.user_space:
9048 Boppan 594
; PF entry in IDT is interrupt gate, so up to this moment
595
; atomicity was guaranteed by cleared IF.
596
; It is inpractical to guard all modifications in the page table by cli/sti,
597
; so enable interrupts and acquire the address space lock.
598
; Unfortunately, that enables the scenario when the fault of current thread
599
; is resolved by another thread when the current thread waits in mutex_lock,
600
; so watch out: in lock-protected section we can find out that
601
; there is no error already.
602
        sti
603
        mov     ecx, [current_process]
604
        add     ecx, PROC.heap_lock
605
        call    mutex_lock
606
        test    esi, PG_READ
607
        jnz     .err_access       ;Page is present
8052 rgimad 608
                                  ;Access error ?
2288 clevermous 609
 
610
        shr     ebx, 12
611
        mov     ecx, ebx
612
        shr     ecx, 10
9048 Boppan 613
        test    dword [master_tab+ecx*4], PG_READ
614
        jz      .fail_unlock      ;page table is not created
8052 rgimad 615
                                  ;incorrect address in program
2288 clevermous 616
 
617
        mov     eax, [page_tabs+ebx*4]
9048 Boppan 618
        test    eax, PG_READ
619
        jnz     .exit_unlock      ; already resolved by a parallel thread
620
        test    eax, LAZY_ALLOC_PAGE
621
        jz      .fail_unlock      ;address is not reserved for use, error
622
        test    eax, LAZY_ALLOC_UNREADABLE
623
        jnz     .fail_unlock
2288 clevermous 624
.alloc:
9048 Boppan 625
        mov     esi, eax
626
        call    alloc_zero_page
2288 clevermous 627
        test    eax, eax
9048 Boppan 628
        jz      .fail_maybe_unlock
2288 clevermous 629
 
9048 Boppan 630
        mov     edx, PG_UWR
631
        test    esi, LAZY_ALLOC_UNWRITABLE
632
        jz      @f
633
        mov     edx, PG_UR
634
@@:
635
        stdcall map_page, [.err_addr], eax, edx
636
        mov     ecx, [current_process]
637
        add     [ecx+PROC.mem_used], 0x1000
638
.exit_unlock:
639
        mov     ecx, [current_process]
640
        add     ecx, PROC.heap_lock
641
        call    mutex_unlock
2288 clevermous 642
.exit:  ;iret with repeat fault instruction
643
        add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
644
        restore_ring3_context
645
        iretd
646
 
647
.err_access:
9048 Boppan 648
; access denied? this may be a result of copy-on-write protection
649
; Check whether the problem has already been resolved
650
; while we were waiting in mutex_lock.
651
        mov     eax, ebx
652
        shr     eax, 12
653
        mov     eax, [page_tabs+eax*4]
654
        test    eax, PG_READ
655
        jz      .fail_unlock ; someone has free'd the page
656
        test    eax, PG_USER
657
        jz      .fail_unlock ; page is mprotect'ed without PROT_READ
658
        test    eax, PG_WRITE
659
        jnz     .exit_unlock ; someone has enabled write
660
        test    eax, PG_SHARED
661
        jz      .fail_unlock ; only shared pages can be copy-on-write
662
; check list of mapped data
2288 clevermous 663
        and     ebx, not 0xFFF
9048 Boppan 664
        call    find_smap_by_address
665
        test    esi, esi
666
        jz      .fail_unlock
667
; ignore children of SMEM, only children of PEDESCR can have copy-on-write data
668
        cmp     [esi+SMAP.type], SMAP_TYPE_PE
669
        jnz     .fail_unlock
670
        shr     edi, 12
671
; lock page array in PEDESCR
672
        mov     esi, [esi+SMAP.parent]
673
        lea     ecx, [esi+PEDESCR.page_array_lock]
674
        push    eax
675
        call    mutex_lock
676
        pop     eax
677
; check whether the page is shared
678
; PG_SHARED flag could be set by lock_and_map_page
679
        xor     eax, [esi+sizeof.PEDESCR+edi*4]
680
        test    eax, not 0xFFF
681
        jnz     .fail_unlock2
682
; check whether write is allowed by section attributes
683
        mov     eax, [esi+sizeof.PEDESCR+edi*4]
684
        test    eax, IMAGE_SCN_MEM_WRITE shr 20
685
        jz      .fail_unlock2
686
; if we're faulting on the page which was originally shareable writable,
687
; it means that someone has disabled writing with mprotect; fail
688
        test    eax, IMAGE_SCN_MEM_SHARED shr 20
689
        jnz     .fail_unlock2
690
        stdcall pe_copy_on_write, PG_UWR
691
        jc	.fail_unlock2
692
.exit_unlock2:
693
        lea     ecx, [esi+PEDESCR.page_array_lock]
694
        call    mutex_unlock
695
        jmp     .exit_unlock
696
.fail_unlock2:
697
        lea     ecx, [esi+PEDESCR.page_array_lock]
698
        call    mutex_unlock
699
        jmp     .fail_unlock
2288 clevermous 700
 
701
.kernel_space:
9048 Boppan 702
        test    esi, PG_READ
8052 rgimad 703
        jz      .fail   ;page does not present
2288 clevermous 704
 
9048 Boppan 705
        test    esi, 12 ;U/S (+below)
8052 rgimad 706
        jnz     .fail   ;application requested kernel memory
707
 
9048 Boppan 708
       ;test    esi, 8
709
       ;jnz     .fail   ;the reserved bit is set in page tables
710
			;added in P4/Xeon
2288 clevermous 711
 
8052 rgimad 712
;an attempt to write to a protected kernel page
2288 clevermous 713
 
714
        cmp     ebx, tss._io_map_0
715
        jb      .fail
716
 
717
        cmp     ebx, tss._io_map_0+8192
718
        jae     .fail
719
 
720
; io permission map
721
; copy-on-write protection
722
 
723
        call    alloc_page
724
        test    eax, eax
725
        jz      .fail
726
 
727
        push    eax
9048 Boppan 728
        stdcall map_page, [.err_addr], eax, PG_SWR
2288 clevermous 729
        pop     eax
730
        mov     edi, [.err_addr]
731
        and     edi, -4096
732
        lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
733
 
734
        mov     ebx, esi
735
        shr     ebx, 12
736
        mov     edx, [current_slot]
5356 serge 737
        or      eax, PG_SWR
2288 clevermous 738
        mov     [edx+APPDATA.io_map+ebx*4], eax
739
 
740
        add     esi, [default_io_map]
741
        mov     ecx, 4096/4
742
       ;cld     ;caller is duty for this
743
        rep movsd
744
        jmp     .exit
745
endp
746
 
9048 Boppan 747
; Sometimes we can just allocate a page and let the caller fill it.
748
; Sometimes we need a zero-filled page, but we can zero it at the target.
749
; Sometimes we need a zero-filled page before mapping to the target.
750
; This function is for the last case.
751
; out: eax = physical page
752
; destroys: nothing
753
proc alloc_zero_page
754
	call	alloc_page
755
	test	eax, eax
756
	jz	.nothing
757
	spin_lock_irqsave zero_page_spinlock
758
	push	ecx edx edi eax
759
	mov	edi, [zero_page_tab]
760
	stdcall	map_page, edi, [esp+4], PG_SWR
761
	pushd	0 [esp+4] edi ; for map_page
762
	mov	ecx, 0x1000/4
763
	xor	eax, eax
764
	rep stosd
765
	call	map_page
766
	pop	eax edi edx ecx
767
	spin_unlock_irqrestore zero_page_spinlock
768
.nothing:
769
	ret
770
endp
771
 
772
; in: ebx = address
773
; out if SMAP exists for this address: esi -> SMAP, edi = ebx - SMAP.base
774
; out if SMAP does not exist: esi = 0
775
proc find_smap_by_address
776
        mov     edx, [current_process]
777
        add     edx, PROC.smap_list
778
        mov     esi, [edx+SMAP.fd]
779
.scan:
780
        cmp     esi, edx
781
        jz      .fail
782
        mov     edi, ebx
783
        sub     edi, [esi+SMAP.base]
784
        cmp     edi, [esi+SMAP.size]
785
        jb      .exit
786
        mov     esi, [esi+SMAP.fd]
787
        jmp     .scan
788
.fail:
789
        xor     esi, esi
790
.exit:
791
        ret
792
endp
793
 
794
; Someone is about to write to copy-on-write page inside mapped PE.
795
; Provide a page that can be written to.
796
; in: esi -> PEDESCR
797
; in: edi = page number inside PE
798
; in: eax = [esi+sizeof.PEDESCR+edi*4]
799
; in: ebx = address in process, must be page-aligned
800
; in: [esp+4] = access rights for the new page
801
; out: CF=0 - ok, CF=1 - error, no memory
802
proc pe_copy_on_write
803
; 1. Decrement reference counter unless it is 0xFF.
804
        mov     edx, eax
805
        and     edx, 0xFF
806
        cmp     edx, 0xFF
807
        jz      @f
808
        dec     eax
809
@@:
810
; 2. If reference counter is zero now, transfer ownership from PEDESCR to the process.
811
        test    eax, 0xFF
812
        jnz     .alloc_copy
813
        mov     dword [esi+sizeof.PEDESCR+edi*4], 0
814
        and     eax, not 0xFFF
815
.remap:
816
        stdcall map_page, ebx, eax, [esp+4]
817
        clc
818
        ret     4
819
.alloc_copy:
820
; 3. Otherwise, store updated reference counter to PEDESCR,
821
; allocate new page, map it as rw and copy data.
822
        mov     [esi+sizeof.PEDESCR+edi*4], eax
823
        stdcall kernel_alloc, 0x1000
824
        test    eax, eax
825
        jz      .error
826
        push    esi
827
        mov     esi, ebx
828
        mov     edi, eax
829
        mov     ecx, 0x1000/4
830
        rep movsd
831
        mov     esi, eax
832
        call    get_pg_addr
833
        push    eax
834
        stdcall free_kernel_space, esi
835
        pop     eax
836
        pop     esi
837
        jmp     .remap
838
.error:
839
        stc
840
        ret     4
841
endp
842
 
843
PROT_READ = 1
844
PROT_WRITE = 2
845
PROT_EXEC = 4
846
proc mprotect stdcall uses ebx esi edi, address:dword, size:dword, access:dword
847
locals
848
retval		dd	-1
849
smap_ptr	dd	0
850
endl
851
	mov	ecx, [current_process]
852
	add	ecx, PROC.heap_lock
853
	call	mutex_lock
854
	test	[access], not (PROT_READ+PROT_WRITE+PROT_EXEC)
855
	jnz	.error
856
	cmp	[size], 0
857
	jz	.error
858
	mov	eax, [address]
859
	add	[size], eax
860
	and	eax, not 0xFFF
861
.addrloop:
862
	mov	[address], eax
863
	mov	ecx, eax
864
	cmp	eax, OS_BASE
865
	jae	.error
866
	shr     eax, 22
867
	test    byte [master_tab+eax*4], PG_READ
868
	jz      .error
869
	shr	ecx, 12
870
	mov	eax, [page_tabs+ecx*4]
871
	test	al, PG_READ
872
	jnz	.page_present
873
	test	al, LAZY_ALLOC_PAGE
874
	jz	.error
875
	cmp	[retval], -1
876
	jnz	.skip_query
877
	inc	[retval]
878
	test	al, LAZY_ALLOC_UNREADABLE
879
	jnz	@f
880
	or	[retval], PROT_READ+PROT_EXEC
881
@@:
882
	test	al, LAZY_ALLOC_UNWRITABLE
883
	jnz	@f
884
	or	[retval], PROT_WRITE
885
@@:
886
.skip_query:
887
	and	al, not (LAZY_ALLOC_UNREADABLE+LAZY_ALLOC_UNWRITABLE)
888
	test	[access], PROT_READ
889
	jnz	@f
890
	or	al, LAZY_ALLOC_UNREADABLE
891
@@:
892
	test	[access], PROT_WRITE
893
	jnz	@f
894
	or	al, LAZY_ALLOC_UNWRITABLE
895
@@:
896
	mov	[page_tabs+ecx*4], eax
897
	jmp	.nextpage
898
.page_present:
899
	test	eax, PG_SHARED
900
	jnz	.page_shared
901
.normal_page:
902
	cmp	[retval], -1
903
	jnz	.skip_query2
904
	inc	[retval]
905
	test	al, PG_USER
906
	jz	@f
907
	or	[retval], PROT_READ+PROT_EXEC
908
@@:
909
	test	al, PG_WRITE
910
	jz	@f
911
	or	[retval], PROT_WRITE
912
@@:
913
.skip_query2:
914
	and	al, not (PG_USER+PG_WRITE)
915
	test	[access], PROT_READ
916
	jz	@f
917
	or	al, PG_USER
918
@@:
919
	test	[access], PROT_WRITE
920
	jz	@f
921
	or	al, PG_WRITE
922
@@:
923
	mov	[page_tabs+ecx*4], eax
924
	mov	eax, [address]
925
	invlpg	[eax]
926
	jmp	.nextpage
927
.page_shared:
928
	mov	esi, [smap_ptr]
929
	test	esi, esi
930
	jz	.find_smap
931
	mov	edx, [address]
932
	sub	edx, [esi+SMAP.base]
933
	cmp	edx, [esi+SMAP.size]
934
	jb	.found_smap
935
.find_smap:
936
	mov	ebx, [address]
937
	call	find_smap_by_address
938
	mov	[smap_ptr], esi
939
	test	esi, esi
940
	jz	.normal_page
941
.found_smap:
942
	cmp	[esi+SMAP.type], SMAP_TYPE_PE
943
	jnz	.error
944
	shr	edi, 12
945
	mov	esi, [esi+SMAP.parent]
946
	lea	ecx, [esi+PEDESCR.page_array_lock]
947
	push	eax
948
	call	mutex_lock
949
	pop	eax
950
	xor	eax, [esi+sizeof.PEDESCR+edi*4]
951
	test	eax, not 0xFFF
952
	jnz	.normal_page_unlock
953
	mov	eax, [esi+sizeof.PEDESCR+edi*4]
954
	test	eax, IMAGE_SCN_MEM_SHARED shr 20
955
	jnz	.normal_page_unlock
956
	cmp	[retval], -1
957
	jnz	.skip_query3
958
	mov	edx, [address]
959
	shr	edx, 12
960
	inc	[retval]
961
	test	byte [page_tabs+edx*4], PG_USER
962
	jz	@f
963
	or	[retval], PROT_READ+PROT_EXEC
964
@@:
965
	test	eax, IMAGE_SCN_MEM_WRITE shr 20
966
	jz	@f
967
	or	[retval], PROT_WRITE
968
@@:
969
.skip_query3:
970
	test	[access], PROT_WRITE
971
	jz	.no_write
972
	push	PG_SWR
973
	test	[access], PROT_READ
974
	jz	@f
975
	pop	edx
976
	push	PG_UWR
977
@@:
978
	call	pe_copy_on_write
979
	lea	ecx, [esi+PEDESCR.page_array_lock]
980
	call	mutex_unlock
981
	jmp	.nextpage
982
.normal_page_unlock:
983
	lea	ecx, [esi+PEDESCR.page_array_lock]
984
	call	mutex_unlock
985
	mov	ecx, [address]
986
	shr	ecx, 12
987
	mov	eax, [page_tabs+ecx*4]
988
	jmp	.normal_page
989
.no_write:
990
	lea	ecx, [esi+PEDESCR.page_array_lock]
991
	call	mutex_unlock
992
	mov	ecx, [address]
993
	shr	ecx, 12
994
	mov	eax, [page_tabs+ecx*4]
995
	jmp	.skip_query2
996
.nextpage:
997
	mov	eax, [address]
998
	add	eax, 0x1000
999
	cmp	eax, [size]
1000
	jb	.addrloop
1001
.exit:
1002
	mov	ecx, [current_process]
1003
	add	ecx, PROC.heap_lock
1004
	call	mutex_unlock
1005
	mov	eax, [retval]
1006
	ret
1007
.error:
1008
	or	[retval], -1
1009
	jmp	.exit
1010
endp
1011
 
2288 clevermous 1012
; returns number of mapped bytes
9048 Boppan 1013
proc map_memEx stdcall uses ebx esi edi, lin_addr:dword,slot:dword,\
1014
                      ofs:dword,buf_size:dword,req_access:dword,where:dword
5130 serge 1015
        locals
1016
             count   dd ?
1017
             process dd ?
1018
        endl
2288 clevermous 1019
 
5130 serge 1020
        mov     [count], 0
2288 clevermous 1021
        cmp     [buf_size], 0
1022
        jz      .exit
1023
 
1024
        mov     eax, [slot]
1025
        shl     eax, 8
9048 Boppan 1026
        mov     ecx, [SLOT_BASE+eax+APPDATA.process]
1027
        test    ecx, ecx
5130 serge 1028
        jz      .exit
2288 clevermous 1029
 
9048 Boppan 1030
        mov     [process], ecx
1031
        add     ecx, PROC.heap_lock
1032
        call    mutex_lock
1033
        mov     eax, [process]
2288 clevermous 1034
        mov     ebx, [ofs]
1035
        shr     ebx, 22
5130 serge 1036
        mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
9048 Boppan 1037
        mov     esi, [where]
2288 clevermous 1038
        and     eax, 0xFFFFF000
9048 Boppan 1039
        jz      .unlock_exit
5356 serge 1040
        stdcall map_page, esi, eax, PG_SWR
2288 clevermous 1041
@@:
1042
        mov     edi, [lin_addr]
1043
        and     edi, 0xFFFFF000
1044
        mov     ecx, [buf_size]
1045
        add     ecx, 4095
1046
        shr     ecx, 12
1047
 
1048
        mov     edx, [ofs]
1049
        shr     edx, 12
1050
        and     edx, 0x3FF
1051
.map:
9048 Boppan 1052
        stdcall lock_and_map_page, [slot], [req_access], [ofs]
1053
        jnc     .unlock_exit
5130 serge 1054
        add     [count], PAGE_SIZE
1055
        add     [ofs], PAGE_SIZE
2288 clevermous 1056
        dec     ecx
9048 Boppan 1057
        jz      .unlock_exit
5130 serge 1058
 
1059
        add     edi, PAGE_SIZE
2288 clevermous 1060
        inc     edx
5130 serge 1061
        cmp     edx, 1024
2288 clevermous 1062
        jnz     .map
5130 serge 1063
 
2288 clevermous 1064
        inc     ebx
5130 serge 1065
        mov     eax, [process]
1066
        mov     eax, [eax+PROC.pdt_0+ebx*4]
2288 clevermous 1067
        and     eax, 0xFFFFF000
9048 Boppan 1068
        jz      .unlock_exit
5130 serge 1069
 
5356 serge 1070
        stdcall map_page, esi, eax, PG_SWR
2288 clevermous 1071
        xor     edx, edx
1072
        jmp     .map
9048 Boppan 1073
.unlock_exit:
1074
        mov     ecx, [process]
1075
        add     ecx, PROC.heap_lock
1076
        call    mutex_unlock
2288 clevermous 1077
.exit:
5130 serge 1078
        mov     eax, [count]
2288 clevermous 1079
        ret
1080
endp
1081
 
9048 Boppan 1082
proc unmap_memEx stdcall uses ebx esi edi, lin_addr:dword,slot:dword,\
1083
                      ofs:dword,mapped_size:dword,pagedir:dword
5130 serge 1084
        locals
1085
             process dd ?
1086
        endl
2288 clevermous 1087
 
9048 Boppan 1088
        cmp     [mapped_size], 0
2288 clevermous 1089
        jz      .exit
1090
 
1091
        mov     eax, [slot]
1092
        shl     eax, 8
9048 Boppan 1093
        mov     ecx, [SLOT_BASE+eax+APPDATA.process]
1094
        mov     [process], ecx
1095
        xor     eax, eax
1096
        test    ecx, ecx
1097
        jz      @f
1098
        add     ecx, PROC.heap_lock
1099
        call    mutex_lock
2288 clevermous 1100
        mov     ebx, [ofs]
1101
        shr     ebx, 22
9048 Boppan 1102
        mov     eax, [process]
5130 serge 1103
        mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
9048 Boppan 1104
@@:
1105
        xor     esi, esi
2288 clevermous 1106
        and     eax, 0xFFFFF000
9048 Boppan 1107
        jz      @f
1108
        mov     esi, [pagedir]
5356 serge 1109
        stdcall map_page, esi, eax, PG_SWR
2288 clevermous 1110
@@:
9048 Boppan 1111
        mov     ecx, shared_locked_mutex
1112
        call    mutex_lock
2288 clevermous 1113
        mov     edi, [lin_addr]
9048 Boppan 1114
        shr     edi, 12
1115
        mov     ecx, [mapped_size]
2288 clevermous 1116
        add     ecx, 4095
1117
        shr     ecx, 12
9048 Boppan 1118
        mov     [mapped_size], ecx
2288 clevermous 1119
 
1120
        mov     edx, [ofs]
1121
        shr     edx, 12
1122
        and     edx, 0x3FF
9048 Boppan 1123
        lea     esi, [esi+edx*4]
2288 clevermous 1124
.map:
9048 Boppan 1125
        call    unlock_and_unmap_page
1126
        dec     [mapped_size]
1127
        jz      .done
5130 serge 1128
 
9048 Boppan 1129
        inc     edi
1130
        add     esi, 4
1131
        test    esi, 0xFFF
2288 clevermous 1132
        jnz     .map
5130 serge 1133
 
1134
        inc     ebx
9048 Boppan 1135
        xor     esi, esi
1136
        cmp     [process], 0
1137
        jz      .map
5130 serge 1138
        mov     eax, [process]
1139
        mov     eax, [eax+PROC.pdt_0+ebx*4]
1140
        and     eax, 0xFFFFF000
9048 Boppan 1141
        jz      .map
5130 serge 1142
 
9048 Boppan 1143
        mov     esi, [pagedir]
5356 serge 1144
        stdcall map_page, esi, eax, PG_SWR
5130 serge 1145
        jmp     .map
9048 Boppan 1146
.done:
1147
        mov     ecx, shared_locked_mutex
1148
        call    mutex_unlock
1149
        cmp     [process], 0
1150
        jz      .exit
1151
        mov     ecx, [process]
1152
        add     ecx, PROC.heap_lock
1153
        call    mutex_unlock
2288 clevermous 1154
.exit:
9048 Boppan 1155
        mov     eax, [pagedir]
1156
        mov     ecx, eax
1157
        shr     ecx, 12
1158
        mov     dword [page_tabs+ecx*4], 0
1159
        invlpg  [eax]
2288 clevermous 1160
        ret
1161
endp
1162
 
1163
; in: esi+edx*4 = pointer to page table entry
1164
; in: [slot], [req_access], [ofs] on the stack
1165
; in: edi = linear address to map
9048 Boppan 1166
; in: address space lock must be held
2288 clevermous 1167
; out: CF cleared <=> failed
1168
; destroys: only eax
9048 Boppan 1169
proc lock_and_map_page stdcall, slot:dword, req_access:dword, ofs:dword
1170
    locals
1171
        locked_descr dd ?
1172
    endl
1173
 
2288 clevermous 1174
        mov     eax, [esi+edx*4]
9048 Boppan 1175
        test    eax, PG_READ
2288 clevermous 1176
        jz      .not_present
9048 Boppan 1177
        test    eax, PG_SHARED
1178
        jnz     .resolve_shared
1179
; normal case: not shared allocated page, mark as shared and map with requested access
1180
        or      dword [esi+edx*4], PG_SHARED
2288 clevermous 1181
.map:
9048 Boppan 1182
        and     eax, not 0xFFF
2288 clevermous 1183
        stdcall map_page, edi, eax, [req_access]
1184
        stc
1185
.fail:
1186
        ret
1187
.not_present:
1188
; check for alloc-on-demand page
9048 Boppan 1189
        test    eax, LAZY_ALLOC_PAGE
2288 clevermous 1190
        jz      .fail
1191
; allocate new page, save it to source page table
1192
        push    ecx
9048 Boppan 1193
        call    alloc_zero_page
2288 clevermous 1194
        pop     ecx
1195
        test    eax, eax
1196
        jz      .fail
9048 Boppan 1197
        or      eax, PG_READ+PG_SHARED
1198
        test    dword [esi+edx*4], LAZY_ALLOC_UNREADABLE
1199
        jnz     @f
1200
        or      eax, PG_USER
1201
@@:
1202
        test    dword [esi+edx*4], LAZY_ALLOC_UNWRITABLE
1203
        jnz     @f
1204
        or      eax, PG_WRITE
1205
@@:
2288 clevermous 1206
        mov     [esi+edx*4], eax
1207
        jmp     .map
9048 Boppan 1208
.resolve_shared:
1209
        push    ecx edx eax
1210
        mov     eax, sizeof.SHARED_LOCKED_PAGE
1211
        call    malloc
1212
        mov     [locked_descr], eax
1213
        test    eax, eax
1214
        jz      .fail_pop
1215
        mov     edx, [esp]
1216
        and     edx, not 0xFFF
1217
        mov     [eax+SHARED_LOCKED_PAGE.address], edx
2288 clevermous 1218
        mov     eax, [slot]
1219
        shl     eax, 8
5130 serge 1220
        mov     eax, [SLOT_BASE+eax+APPDATA.process]
9048 Boppan 1221
        mov     ecx, [eax+PROC.smap_list]
1222
        add     eax, PROC.smap_list
1223
.find_shared_parent:
2288 clevermous 1224
        cmp     ecx, eax
9048 Boppan 1225
        jz      .shared_orphan
1226
        mov     edx, [ofs]
1227
        sub     edx, [ecx+SMAP.base]
1228
        cmp     edx, [ecx+SMAP.size]
1229
        jb      .found_shared_parent
1230
        mov     ecx, [ecx+SMAP.fd]
1231
        jmp     .find_shared_parent
1232
.shared_abandoned:
1233
        call    mutex_unlock
1234
.shared_orphan:
1235
; no copy-on-write for orphans
1236
        test    dword [esp], PG_WRITE
1237
        jnz     @f
1238
        test    [req_access], PG_WRITE
1239
        jnz     .shared_forbidden
1240
@@:
1241
; locking the same normal page for second time:
1242
; the first lock_and_map_page has set PG_SHARED,
1243
; now we must cooperate with that other thread.
1244
        mov     ecx, shared_locked_mutex
1245
        call    mutex_lock
1246
        mov     eax, [locked_descr]
1247
        mov     [eax+SHARED_LOCKED_PAGE.parent], 0
1248
.shared_common:
1249
        mov     edx, [shared_locked_list+SHARED_LOCKED_PAGE.bk]
1250
        mov     [eax+SHARED_LOCKED_PAGE.fd], shared_locked_list
1251
        mov     [eax+SHARED_LOCKED_PAGE.bk], edx
1252
        mov     [edx+SHARED_LOCKED_PAGE.fd], eax
1253
        mov     [shared_locked_list+SHARED_LOCKED_PAGE.bk], edx
1254
        call    mutex_unlock
1255
        pop     eax edx ecx
1256
        jmp     .map
1257
.shared_forbidden_unlock:
1258
        call    mutex_unlock
1259
.shared_forbidden:
1260
        mov     eax, [locked_descr]
1261
        call    free
1262
.fail_pop:
1263
        pop     eax edx ecx
2288 clevermous 1264
        clc
1265
        ret
9048 Boppan 1266
.found_shared_parent:
1267
        shr     edx, 12
1268
        mov     eax, [locked_descr]
1269
        mov     [eax+SHARED_LOCKED_PAGE.offs], edx
1270
        cmp     [ecx+SMAP.type], SMAP_TYPE_PE
1271
        jnz     .parent_smap
1272
        push    edx
1273
        mov     ecx, [ecx+SMAP.parent]
1274
        add     ecx, PEDESCR.page_array_lock
1275
        call    mutex_lock
1276
        pop     edx
1277
        mov     eax, [esp]
1278
        xor     eax, [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4]
1279
        test    eax, not 0xFFF
1280
        jnz     .shared_abandoned
1281
        test    dword [esp], PG_WRITE
1282
        jnz     @f
1283
        test    [req_access], PG_WRITE
1284
        jnz     .pedescr_try_cow
1285
@@:
1286
        mov     eax, [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4]
1287
        inc     eax
1288
        test    eax, 0xFF
1289
        jnz     @f
1290
        dec     eax
1291
@@:
1292
        mov     [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4], eax
1293
        push    ecx
1294
        mov     ecx, pe_list_mutex
1295
        call    mutex_lock
1296
        mov     eax, [esp]
1297
        inc     dword [eax+PEDESCR.refcount-PEDESCR.page_array_lock]
1298
        call    mutex_unlock
1299
        pop     ecx
1300
        call    mutex_unlock
1301
        sub     ecx, PEDESCR.page_array_lock
1302
        push    ecx
1303
.shared_common2:
1304
        mov     ecx, shared_locked_mutex
1305
        call    mutex_lock
1306
        mov     eax, [locked_descr]
1307
        pop     [eax+SHARED_LOCKED_PAGE.parent]
1308
        jmp     .shared_common
1309
.pedescr_try_cow:
1310
        mov     eax, [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4]
1311
        test	eax, IMAGE_SCN_MEM_WRITE shr 20
1312
        jz	@f
1313
        or      dword [esp], PG_WRITE
1314
@@:
1315
        dec     eax
1316
        test    eax, 0xFF
1317
        jnz     .pedescr_alloc_copy
1318
        mov     dword [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4], 0
1319
        call    mutex_unlock
1320
        mov     eax, [locked_descr]
1321
        call    free
1322
        pop     eax edx ecx
1323
        or      eax, PG_SHARED
1324
        mov     [esi+edx*4], eax
1325
        jmp     .map
1326
.pedescr_alloc_copy:
1327
        push    ecx edx
1328
        stdcall kernel_alloc, 0x1000
1329
        pop     edx ecx
2288 clevermous 1330
        test    eax, eax
9048 Boppan 1331
        jz      .shared_forbidden_unlock
1332
        dec     dword [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4]
1333
        push    ecx esi edi
1334
        mov     esi, edi
1335
        mov     edi, eax
1336
        stdcall map_page, esi, [ecx+sizeof.PEDESCR-PEDESCR.page_array_lock+edx*4], PG_READ
1337
        mov     ecx, 0x1000/4
1338
        rep movsd
1339
        sub     esi, 0x1000
1340
        sub     edi, 0x1000
1341
        mov     eax, edi
1342
        call    get_pg_addr
1343
        and     dword [esp+12], 0xFFF
1344
        or      dword [esp+12], eax
1345
        stdcall map_page, esi, eax, [req_access]
1346
        stdcall free_kernel_space, edi
1347
        pop     edi esi ecx
1348
        call    mutex_unlock
1349
        mov     eax, [locked_descr]
1350
        call    free
1351
        pop     eax edx ecx
1352
        or      eax, PG_SHARED
2288 clevermous 1353
        mov     [esi+edx*4], eax
1354
        stc
1355
        ret
9048 Boppan 1356
.parent_smap:
1357
        test    dword [esp], PG_WRITE
1358
        jnz     @f
1359
        test    [req_access], PG_WRITE
1360
        jz      .shared_forbidden
1361
@@:
1362
        push    [ecx+SMAP.parent]
1363
        mov     ecx, shmem_list_mutex
1364
        call    mutex_lock
1365
        mov     eax, [esp]
1366
        inc     dword [esp]
1367
        inc     [eax+SMEM.refcount]
1368
        call    mutex_unlock
1369
        jmp     .shared_common2
2288 clevermous 1370
endp
1371
 
9048 Boppan 1372
; in: esi -> process page table entry or esi < 0x1000 if no page table entry
1373
; in: edi = page number for mapped copy
1374
; in: shared_locked_mutex is held
1375
; destroys eax, ecx, edx
1376
proc unlock_and_unmap_page
1377
        mov     edx, [page_tabs+edi*4]
1378
        and     edx, not 0xFFF
1379
        mov     dword [page_tabs+edi*4], 0
1380
        mov     eax, edi
1381
        shl     eax, 12
1382
        invlpg  [eax]
1383
        mov     eax, [shared_locked_list+SHARED_LOCKED_PAGE.fd]
1384
.check_list:
1385
        cmp     eax, shared_locked_list
1386
        jz      .not_in_list
1387
        cmp     edx, [eax+SHARED_LOCKED_PAGE.address]
1388
        jz      .found_in_list
1389
        mov     eax, [eax+SHARED_LOCKED_PAGE.fd]
1390
        jmp     .check_list
1391
.found_in_list:
1392
        push    esi
1393
        mov     esi, [eax+SHARED_LOCKED_PAGE.parent]
1394
        mov     edx, [eax+SHARED_LOCKED_PAGE.fd]
1395
        mov     ecx, [eax+SHARED_LOCKED_PAGE.bk]
1396
        mov     [edx+SHARED_LOCKED_PAGE.bk], ecx
1397
        mov     [ecx+SHARED_LOCKED_PAGE.fd], edx
1398
        test    esi, esi
1399
        jz      .orphan
1400
        btr     esi, 0
1401
        jc      .parent_smap
1402
        push    eax
1403
        lea     ecx, [esi+PEDESCR.page_array_lock]
1404
        call    mutex_lock
1405
        mov     edx, [esp]
1406
        mov     edx, [edx+SHARED_LOCKED_PAGE.offs]
1407
        mov     eax, [esi+sizeof.PEDESCR+edx*4]
1408
        and     eax, 0xFF
1409
        cmp     eax, 0xFF
1410
        jz      .no_deref
1411
        mov     eax, [esi+sizeof.PEDESCR+edx*4]
1412
        dec     eax
1413
        test    eax, 0xFF
1414
        jnz     @f
1415
        call    free_page
1416
        xor     eax, eax
1417
@@:
1418
        mov     [esi+sizeof.PEDESCR+edx*4], eax
1419
.no_deref:
1420
        lea     ecx, [esi+PEDESCR.page_array_lock]
1421
        call    mutex_unlock
1422
        call    dereference_pe
1423
        pop     eax
1424
        call    free
1425
        pop     esi
1426
        ret
1427
.parent_smap:
1428
        call    free
1429
        call    dereference_smem
1430
        pop     esi
1431
        ret
1432
.orphan:
1433
        call    free
1434
        pop     esi
1435
        ret
1436
.not_in_list:
1437
        cmp     esi, 0x1000
1438
        jb      .just_free
1439
        mov     eax, [esi]
1440
        and     eax, not 0xFFF
1441
        cmp     eax, edx
1442
        jnz     .just_free
1443
        and     dword [esi], not PG_SHARED
1444
        ret
1445
.just_free:
1446
        mov     eax, edx
1447
        call    free_page
1448
        ret
1449
endp
1450
 
2288 clevermous 1451
sys_IPC:
1452
;input:
1453
;  ebx=1 - set ipc buffer area
1454
;    ecx=address of buffer
1455
;    edx=size of buffer
1456
;  eax=2 - send message
1457
;    ebx=PID
1458
;    ecx=address of message
1459
;    edx=size of message
1460
 
1461
        dec     ebx
1462
        jnz     @f
1463
 
1464
        mov     eax, [current_slot]
1465
        pushf
1466
        cli
1467
        mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
1468
        mov     [eax+APPDATA.ipc_size], edx
1469
 
1470
        add     edx, ecx
1471
        add     edx, 4095
1472
        and     edx, not 4095
1473
 
1474
.touch:
1475
        mov     eax, [ecx]
1476
        add     ecx, 0x1000
1477
        cmp     ecx, edx
1478
        jb      .touch
1479
 
1480
        popf
1481
        mov     [esp+32], ebx   ;ebx=0
1482
        ret
1483
 
1484
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1485
;2
1486
@@:
1487
        dec     ebx
1488
        jnz     @f
1489
 
1490
        stdcall sys_ipc_send, ecx, edx, esi
1491
        mov     [esp+32], eax
1492
        ret
1493
@@:
1494
        or      eax, -1
1495
        mov     [esp+32], eax
1496
        ret
1497
 
1498
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
1499
           locals
1500
             dst_slot   dd ?
1501
             dst_offset dd ?
9048 Boppan 1502
             dst_ptr    dd ?
2288 clevermous 1503
             buf_size   dd ?
1504
             used_buf   dd ?
9048 Boppan 1505
             mapped_size dd ?
1506
             result     dd ?
2288 clevermous 1507
           endl
1508
 
9048 Boppan 1509
        mov     ecx, ipc_mutex
1510
        call    mutex_lock
2288 clevermous 1511
 
1512
        mov     eax, [PID]
1513
        call    pid_to_slot
1514
        test    eax, eax
1515
        jz      .no_pid
1516
 
1517
        mov     [dst_slot], eax
1518
        shl     eax, 8
5130 serge 1519
        mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
2288 clevermous 1520
        test    edi, edi
1521
        jz      .no_ipc_area
9048 Boppan 1522
        mov     [dst_ptr], edi
2288 clevermous 1523
 
1524
        mov     ebx, edi
1525
        and     ebx, 0xFFF
1526
        mov     [dst_offset], ebx
1527
 
5130 serge 1528
        mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
2288 clevermous 1529
        mov     [buf_size], esi
1530
 
1531
        mov     ecx, [ipc_tmp]
1532
        cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
1533
        jbe     @f
1534
        push    esi edi
1535
        add     esi, 0x1000
1536
        stdcall alloc_kernel_space, esi
1537
        mov     ecx, eax
1538
        pop     edi esi
1539
@@:
1540
        mov     [used_buf], ecx
9048 Boppan 1541
        stdcall map_memEx, ecx, [dst_slot], \
1542
                edi, esi, PG_SWR, [ipc_ptab]
1543
        mov     [mapped_size], eax
1544
        mov     [result], 3 ; buffer overflow
1545
        sub     eax, [dst_offset]
1546
        jc      .no_copy_data
1547
        cmp     [buf_size], eax
1548
        jb      @f
1549
        mov     [buf_size], eax
1550
@@:
1551
        cmp     [buf_size], 8
1552
        jb      .no_copy_data
2288 clevermous 1553
 
9048 Boppan 1554
        mov     [result], 2 ; ipc blocked
2288 clevermous 1555
        mov     edi, [dst_offset]
1556
        add     edi, [used_buf]
1557
        cmp     dword [edi], 0
9048 Boppan 1558
        jnz     .no_copy_data         ;if dword [buffer]<>0 - ipc blocked now
2288 clevermous 1559
 
9048 Boppan 1560
        mov     [result], 3 ; buffer overflow
2288 clevermous 1561
        mov     edx, dword [edi+4]
1562
        lea     ebx, [edx+8]
1563
        add     ebx, [msg_size]
1564
        cmp     ebx, [buf_size]
9048 Boppan 1565
        ja      .no_copy_data          ;esi<0 - not enough memory in buffer
2288 clevermous 1566
 
9048 Boppan 1567
        mov     [result], 0
2288 clevermous 1568
        mov     dword [edi+4], ebx
1569
        mov     eax, [TASK_BASE]
8874 rgimad 1570
        mov     eax, [eax+TASKDATA.pid]        ;eax - our PID
2288 clevermous 1571
        add     edi, edx
1572
        mov     [edi], eax
1573
        mov     ecx, [msg_size]
1574
 
1575
        mov     [edi+4], ecx
1576
        add     edi, 8
1577
        mov     esi, [msg_addr]
1578
       ;    add esi, new_app_base
1579
        cld
1580
        rep movsb
9048 Boppan 1581
.no_copy_data:
1582
        stdcall unmap_memEx, [used_buf], [dst_slot], [dst_ptr], [mapped_size], [ipc_ptab]
2288 clevermous 1583
 
9048 Boppan 1584
        cmp     [result], 0
1585
        jnz     @f
2288 clevermous 1586
        mov     eax, [dst_slot]
8876 rgimad 1587
        shl     eax, BSF sizeof.APPDATA
1588
        or      [eax+SLOT_BASE+APPDATA.occurred_events], EVENT_IPC
9048 Boppan 1589
@@:
1590
        mov     eax, [used_buf]
1591
        cmp     eax, [ipc_tmp]
1592
        je      @f
1593
        stdcall free_kernel_space, eax
1594
@@:
1595
        mov     ecx, ipc_mutex
1596
        call    mutex_unlock
1597
        mov     eax, [result]
1598
        ret
2288 clevermous 1599
.no_pid:
9048 Boppan 1600
        mov     ecx, ipc_mutex
1601
        call    mutex_unlock
2288 clevermous 1602
        mov     eax, 4
1603
        ret
1604
.no_ipc_area:
9048 Boppan 1605
        mov     ecx, ipc_mutex
1606
        call    mutex_unlock
2288 clevermous 1607
        xor     eax, eax
1608
        inc     eax
1609
        ret
1610
endp
1611
 
1612
align 4
1613
sysfn_meminfo:
1614
        cmp     ecx, OS_BASE
1615
        jae     .fail
1616
 
1617
        mov     eax, [pg_data.pages_count]
1618
        mov     [ecx], eax
1619
        shl     eax, 12
1620
        mov     [esp+32], eax
1621
        mov     eax, [pg_data.pages_free]
1622
        mov     [ecx+4], eax
1623
        mov     eax, [pg_data.pages_faults]
1624
        mov     [ecx+8], eax
1625
        mov     eax, [heap_size]
1626
        mov     [ecx+12], eax
1627
        mov     eax, [heap_free]
1628
        mov     [ecx+16], eax
1629
        mov     eax, [heap_blocks]
1630
        mov     [ecx+20], eax
1631
        mov     eax, [free_blocks]
1632
        mov     [ecx+24], eax
1633
        ret
1634
.fail:
1635
        or      dword [esp+32], -1
1636
        ret
1637
 
1638
align 4
1639
f68:
1640
        cmp     ebx, 4
1641
        jbe     sys_sheduler
1642
        cmp     ebx, 11
6599 serge 1643
        jb      undefined_syscall
9048 Boppan 1644
        cmp     ebx, 32
6599 serge 1645
        ja      undefined_syscall
6792 pathoswith 1646
        xor     eax, eax
2288 clevermous 1647
        jmp     dword [f68call+ebx*4-11*4]
1648
.11:
1649
        call    init_heap
6599 serge 1650
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1651
        ret
1652
.12:
1653
        stdcall user_alloc, ecx
6599 serge 1654
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1655
        ret
1656
.13:
1657
        stdcall user_free, ecx
6599 serge 1658
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1659
        ret
1660
.14:
1661
        cmp     ecx, OS_BASE
1662
        jae     .fail
1663
        mov     edi, ecx
1664
        call    get_event_ex
6599 serge 1665
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1666
        ret
1667
.16:
1668
        test    ecx, ecx
1669
        jz      .fail
1670
        cmp     ecx, OS_BASE
1671
        jae     .fail
1672
        stdcall get_service, ecx
6599 serge 1673
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1674
        ret
1675
.17:
1676
        call    srv_handlerEx   ;ecx
6599 serge 1677
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1678
        ret
6798 pathoswith 1679
.18:
1680
        mov     eax, edx
2288 clevermous 1681
.19:
1682
        cmp     ecx, OS_BASE
1683
        jae     .fail
6792 pathoswith 1684
        stdcall load_library, ecx, eax
6599 serge 1685
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1686
        ret
1687
.20:
1688
        mov     eax, edx
1689
        mov     ebx, ecx
1690
        call    user_realloc            ;in: eax = pointer, ebx = new size
6599 serge 1691
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1692
        ret
1693
.21:
1694
        cmp     ecx, OS_BASE
1695
        jae     .fail
2647 mario79 1696
        cmp     edx, OS_BASE
2288 clevermous 1697
        jae     .fail
4418 clevermous 1698
        stdcall load_pe_driver, ecx, edx
6599 serge 1699
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1700
        ret
1701
.22:
1702
        cmp     ecx, OS_BASE
1703
        jae     .fail
1704
        stdcall shmem_open, ecx, edx, esi
6599 serge 1705
        mov     [esp+SYSCALL_STACK._edx], edx
1706
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1707
        ret
1708
.23:
1709
        cmp     ecx, OS_BASE
1710
        jae     .fail
1711
        stdcall shmem_close, ecx
6599 serge 1712
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1713
        ret
1714
.24:
1715
        mov     eax, [current_slot]
1716
        xchg    ecx, [eax+APPDATA.exc_handler]
1717
        xchg    edx, [eax+APPDATA.except_mask]
6599 serge 1718
        mov     [esp+SYSCALL_STACK._ebx], edx
1719
        mov     [esp+SYSCALL_STACK._eax], ecx
2288 clevermous 1720
        ret
1721
.25:
1722
        cmp     ecx, 32
1723
        jae     .fail
1724
        mov     eax, [current_slot]
1725
        btr     [eax+APPDATA.except_mask], ecx
6599 serge 1726
        setc    byte[esp+SYSCALL_STACK._eax]
2288 clevermous 1727
        jecxz   @f
1728
        bts     [eax+APPDATA.except_mask], ecx
1729
@@:
1730
        ret
2400 Serge 1731
.26:
1732
        stdcall user_unmap, ecx, edx, esi
6599 serge 1733
        mov     [esp+SYSCALL_STACK._eax], eax
2400 Serge 1734
        ret
3786 Serge 1735
.27:
1736
        cmp     ecx, OS_BASE
1737
        jae     .fail
1738
        stdcall load_file_umode, ecx
6599 serge 1739
        mov     [esp+SYSCALL_STACK._edx], edx
1740
        mov     [esp+SYSCALL_STACK._eax], eax
3786 Serge 1741
        ret
6798 pathoswith 1742
.28:
1743
        cmp     ecx, OS_BASE
1744
        jae     .fail
1745
        push    ecx edx
1746
        stdcall kernel_alloc, maxPathLength
1747
        mov     edi, eax
1748
        pop     eax esi
1749
        push    edi
1750
        call    getFullPath
1751
        pop     ebp
1752
        test    eax, eax
1753
        jz      @f
1754
        stdcall load_file_umode, ebp
1755
        mov     [esp+SYSCALL_STACK._edx], edx
1756
@@:
1757
        mov     [esp+SYSCALL_STACK._eax], eax
1758
        stdcall kernel_free, ebp
1759
        ret
3786 Serge 1760
 
7967 hidnplayr 1761
.29:
1762
        stdcall user_ring, ecx
1763
        mov     [esp+SYSCALL_STACK._eax], eax
9048 Boppan 1764
	ret
1765
.30:
1766
        cmp     ecx, OS_BASE
1767
        jae     .fail
1768
        stdcall load_file_maybe_pe, ecx
1769
        test    esi, esi
1770
        jz      .30.not_pe
1771
        stdcall map_pe_usermode, esi, eax, ebx
1772
        mov     [esp+32], eax
7967 hidnplayr 1773
        ret
9048 Boppan 1774
.30.resolve_fail:
1775
        movi    eax, -5
1776
        jmp     .30.error
1777
.30.not_pe:
1778
        cmp     eax, -0x1000
1779
        ja      .30.error
1780
        stdcall kernel_free, eax
1781
        movi    eax, -31
1782
.30.error:
1783
        mov     [esp+32], eax
1784
        ret
7967 hidnplayr 1785
 
9048 Boppan 1786
.31:
1787
        stdcall unmap_pe_usermode, ecx
1788
        mov     [esp+32], eax
1789
        ret
1790
 
1791
.32:
1792
        stdcall mprotect, edx, esi, ecx
1793
        mov     [esp+32], eax
1794
        ret
1795
 
2288 clevermous 1796
.fail:
6599 serge 1797
        mov     [esp+SYSCALL_STACK._eax], eax
2288 clevermous 1798
        ret
1799
 
1800
align 4
1801
f68call:   ; keep this table closer to main code
1802
 
1803
           dd f68.11   ; init_heap
1804
           dd f68.12   ; user_alloc
1805
           dd f68.13   ; user_free
1806
           dd f68.14   ; get_event_ex
1807
           dd f68.fail ; moved to f68.24
1808
           dd f68.16   ; get_service
1809
           dd f68.17   ; call_service
6798 pathoswith 1810
           dd f68.18   ; loadLibUnicode
2288 clevermous 1811
           dd f68.19   ; load_dll
1812
           dd f68.20   ; user_realloc
1813
           dd f68.21   ; load_driver
1814
           dd f68.22   ; shmem_open
1815
           dd f68.23   ; shmem_close
2400 Serge 1816
           dd f68.24   ; set exception handler
1817
           dd f68.25   ; unmask exception
1818
           dd f68.26   ; user_unmap
3786 Serge 1819
           dd f68.27   ; load_file_umode
6798 pathoswith 1820
           dd f68.28   ; loadFileUnicode
7967 hidnplayr 1821
           dd f68.29   ; user_ring
9048 Boppan 1822
           dd f68.30   ; map_pe_usermode
1823
           dd f68.31   ; unmap_pe_usermode
1824
           dd f68.32   ; mprotect
2288 clevermous 1825
 
1826
align 4
4418 clevermous 1827
proc load_pe_driver stdcall, file:dword, cmdline:dword
1828
        push    esi
2288 clevermous 1829
 
1830
        stdcall load_PE, [file]
1831
        test    eax, eax
1832
        jz      .fail
1833
 
1834
        mov     esi, eax
4418 clevermous 1835
        push    [cmdline]
1836
        push    DRV_ENTRY
1837
        call    eax
1838
        pop     ecx
1839
        pop     ecx
2288 clevermous 1840
        test    eax, eax
1841
        jz      .fail
1842
 
1843
        mov     [eax+SRV.entry], esi
4418 clevermous 1844
        pop     esi
2288 clevermous 1845
        ret
1846
 
1847
.fail:
1848
        xor     eax, eax
4418 clevermous 1849
        pop     esi
2288 clevermous 1850
        ret
1851
endp
1852
 
1853
align 4
1854
proc create_ring_buffer stdcall, size:dword, flags:dword
1855
           locals
1856
             buf_ptr  dd ?
1857
           endl
1858
 
1859
        mov     eax, [size]
1860
        test    eax, eax
1861
        jz      .fail
1862
 
1863
        add     eax, eax
1864
        stdcall alloc_kernel_space, eax
1865
        test    eax, eax
1866
        jz      .fail
1867
 
1868
        push    ebx
1869
 
1870
        mov     [buf_ptr], eax
1871
 
1872
        mov     ebx, [size]
1873
        shr     ebx, 12
1874
        push    ebx
1875
 
1876
        stdcall alloc_pages, ebx
1877
        pop     ecx
1878
 
1879
        test    eax, eax
1880
        jz      .mm_fail
1881
 
1882
        push    edi
1883
 
1884
        or      eax, [flags]
1885
        mov     edi, [buf_ptr]
1886
        mov     ebx, [buf_ptr]
1887
        mov     edx, ecx
1888
        shl     edx, 2
1889
        shr     edi, 10
1890
@@:
1891
        mov     [page_tabs+edi], eax
1892
        mov     [page_tabs+edi+edx], eax
1893
        invlpg  [ebx]
1894
        invlpg  [ebx+0x10000]
1895
        add     eax, 0x1000
1896
        add     ebx, 0x1000
1897
        add     edi, 4
1898
        dec     ecx
1899
        jnz     @B
1900
 
1901
        mov     eax, [buf_ptr]
1902
        pop     edi
1903
        pop     ebx
1904
        ret
1905
.mm_fail:
1906
        stdcall free_kernel_space, [buf_ptr]
1907
        xor     eax, eax
1908
        pop     ebx
1909
.fail:
1910
        ret
1911
endp
2466 Serge 1912
 
1913
 
1914
align 4
1915
proc print_mem
7132 dunkaist 1916
        mov     edi, BOOT.memmap_blocks
2466 Serge 1917
        mov     ecx, [edi-4]
1918
        test    ecx, ecx
1919
        jz      .done
1920
 
1921
@@:
1922
        mov     eax, [edi]
1923
        mov     edx, [edi+4]
1924
        add     eax, [edi+8]
1925
        adc     edx, [edi+12]
1926
 
1927
        DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
1928
                    [edi+4], [edi],\
1929
                    edx, eax, [edi+16]
1930
        add     edi, 20
1931
        dec     ecx
1932
        jnz     @b
1933
.done:
1934
        ret
1935
endp