Subversion Repositories Kolibri OS

Rev

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