Subversion Repositories Kolibri OS

Rev

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