Subversion Repositories Kolibri OS

Rev

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