Subversion Repositories Kolibri OS

Rev

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