Subversion Repositories Kolibri OS

Rev

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