Subversion Repositories Kolibri OS

Rev

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