Subversion Repositories Kolibri OS

Rev

Rev 1599 | Rev 1689 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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