Subversion Repositories Kolibri OS

Rev

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

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