Subversion Repositories Kolibri OS

Rev

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