Subversion Repositories Kolibri OS

Rev

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