Subversion Repositories Kolibri OS

Rev

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