Subversion Repositories Kolibri OS

Rev

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