Subversion Repositories Kolibri OS

Rev

Rev 3908 | Rev 4423 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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