Subversion Repositories Kolibri OS

Rev

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