Subversion Repositories Kolibri OS

Rev

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

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