Subversion Repositories Kolibri OS

Rev

Rev 6317 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 6339 $
  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.         or      eax, [esp+16]              ; flags
  131.         and     eax, [pte_valid_mask]
  132.         mov     ebx, [esp+8]               ; lin_addr
  133.         shr     ebx, 12
  134.         mov     [page_tabs+ebx*8], 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.         or      edx, [flags]
  195.         and     edx, [pte_valid_mask]
  196. @@:
  197.         mov     [page_tabs+eax*8], edx
  198.         mov     [page_tabs+eax*8+4], dword 0
  199.         invlpg  [ebx]
  200.         inc     eax
  201.         add     ebx, edi
  202.         add     edx, edi
  203.         loop    @B
  204.  
  205.         pop     eax
  206.         mov     edx, [base]
  207.         and     edx, 4095
  208.         add     eax, edx
  209. .fail:
  210.         pop     edi
  211.         pop     ebx
  212.         ret
  213. endp
  214.  
  215. ; param
  216. ;  eax= page base + page flags
  217. ;  ebx= linear address
  218. ;  ecx= count
  219.  
  220. align 4
  221. commit_pages:
  222.         test    ecx, ecx
  223.         jz      .fail
  224.  
  225.         push    edi
  226.         push    eax
  227.         push    ecx
  228.         mov     ecx, pg_data.mutex
  229.         call    mutex_lock
  230.         pop     ecx
  231.         pop     eax
  232.  
  233.         and     eax, [pte_valid_mask ]
  234.         mov     edi, ebx
  235.         shr     edi, 12
  236.         lea     edi, [page_tabs+edi*8]
  237. @@:
  238.         mov     [edi], eax
  239.         mov     [edi+4], dword 0
  240.         invlpg  [ebx]
  241.         add     eax, 0x1000
  242.         add     ebx, 0x1000
  243.         add     edi, 8
  244.         loop    @B
  245.  
  246.         pop     edi
  247.  
  248.         mov     ecx, pg_data.mutex
  249.         call    mutex_unlock
  250. .fail:
  251.         ret
  252.  
  253.  
  254. ; param
  255. ;  eax= base
  256. ;  ecx= count
  257.  
  258. align 4
  259. release_pages:
  260.  
  261.         push    ebp
  262.         push    esi
  263.         push    edi
  264.         push    ebx
  265.  
  266.         mov     esi, eax
  267.         mov     edi, eax
  268.  
  269.         shr     esi, 12
  270.         lea     esi, [page_tabs+esi*8]
  271.  
  272.         push    ecx
  273.         mov     ecx, pg_data.mutex
  274.         call    mutex_lock
  275.         pop     ecx
  276.  
  277.         mov     ebp, [pg_data.pages_free]
  278.         mov     ebx, [page_start]
  279.         mov     edx, sys_pgmap
  280. @@:
  281.         xor     eax, eax
  282.         xchg    eax, [esi]
  283.         invlpg  [edi]
  284.  
  285.         test    eax, 1
  286.         jz      .next
  287.  
  288.         shr     eax, 12
  289.         bts     [edx], eax
  290.         cmc
  291.         adc     ebp, 0
  292.         shr     eax, 3
  293.         and     eax, -4
  294.         add     eax, edx
  295.         cmp     eax, ebx
  296.         jae     .next
  297.  
  298.         mov     ebx, eax
  299. .next:
  300.         add     edi, 0x1000
  301.         add     esi, 8
  302.         loop    @B
  303.  
  304.         mov     [pg_data.pages_free], ebp
  305.         mov     ecx, pg_data.mutex
  306.         call    mutex_unlock
  307.  
  308.         pop     ebx
  309.         pop     edi
  310.         pop     esi
  311.         pop     ebp
  312.         ret
  313.  
  314. ; param
  315. ;  eax= base
  316. ;  ecx= count
  317.  
  318. align 4
  319. unmap_pages:
  320.  
  321.         push    edi
  322.  
  323.         mov     edi, eax
  324.         mov     edx, eax
  325.  
  326.         shr     edi, 9
  327.         add     edi, page_tabs
  328.  
  329.         xor     eax, eax
  330. @@:
  331.         stosd
  332.         stosd
  333.         invlpg  [edx]
  334.         add     edx, 0x1000
  335.         loop    @b
  336.  
  337.         pop     edi
  338.         ret
  339.  
  340.  
  341. align 4
  342. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  343.         push    ebx
  344.         mov     ebx, [lin_addr]
  345.         shr     ebx, 21
  346.         mov     eax, [phis_addr]
  347.         and     eax, not 0xFFF
  348.         or      eax, PG_UWR
  349.         mov     [master_tab+ebx*8], eax
  350.         mov     [master_tab+ebx*8+4], dword 0
  351.         mov     eax, [lin_addr]
  352.         shr     eax, 9
  353.         add     eax, page_tabs
  354.         invlpg  [eax]
  355.         pop     ebx
  356.         ret
  357. endp
  358.  
  359. uglobal
  360. sb16_buffer_allocated db 0
  361. endg
  362.  
  363. ; Allocates [.size] bytes so that the target memory block
  364. ; is inside one 64K page for 24-bit DMA controller,
  365. ; that is, somewhere between 00xx0000h and 00xxFFFFh.
  366. proc alloc_dma24
  367. ; Implementation note.
  368. ; The only user of that function is SB16 driver,
  369. ; so just return a statically allocated buffer.
  370. virtual at esp
  371.                 dd      ? ; return address
  372. .size           dd      ?
  373. end virtual
  374.         cmp     [sb16_buffer_allocated], 0
  375.         jnz     .fail
  376.         inc     [sb16_buffer_allocated]
  377.         mov     eax, SB16Buffer
  378.         ret     4
  379. .fail:
  380.         xor     eax, eax
  381.         ret     4
  382. endp
  383.  
  384. ; Allocates a physical page for master page table
  385. ; that duplicates first Mb of OS_BASE at address 0;
  386. ; used for starting APs and for shutting down,
  387. ; where it is important to execute code in trivial-mapped pages.
  388. ; Returns eax = allocated physical page.
  389. proc create_trampoline_pgmap
  390. ; The only non-trivial moment:
  391. ; we need a linear address to fill information,
  392. ; but we don't need it outside of this function,
  393. ; so we're returning physical address.
  394. ; Therefore, allocate memory with kernel_alloc,
  395. ; this will allocate physical page and a linear address somewhere,
  396. ; and deallocate only linear address with free_kernel_space.
  397.         stdcall kernel_alloc, 0x1000
  398.         mov     edi, eax
  399.         mov     esi, master_tab
  400.         mov     ecx, 1024
  401.         rep movsd
  402.         mov     ecx, [master_tab+(OS_BASE shr 20)]
  403.         mov     [eax], ecx
  404.         mov     edi, eax
  405.         call    get_pg_addr
  406.         push    eax
  407.         stdcall free_kernel_space, edi
  408.         pop     eax
  409.         ret
  410. endp
  411.  
  412. align 4
  413. proc new_mem_resize stdcall, new_size:dword
  414.  
  415.         push    ebx
  416.         push    esi
  417.         push    edi
  418.  
  419.         mov     edx, [current_slot]
  420.         mov     ebx, [edx+APPDATA.process]
  421.  
  422.         cmp     [ebx+PROC.heap_base], 0
  423.         jne     .exit
  424.  
  425.         mov     edi, [new_size]
  426.         add     edi, 4095
  427.         and     edi, not 4095
  428.         mov     [new_size], edi
  429.  
  430.         mov     esi, [ebx+PROC.mem_used]
  431.         add     esi, 4095
  432.         and     esi, not 4095
  433.  
  434.         cmp     edi, esi
  435.         ja      .expand
  436.         je      .exit
  437.  
  438.         mov     ebx, edi
  439.         shr     edi, 12
  440.         shr     esi, 12
  441.  
  442.         mov     ecx, pg_data.mutex
  443.         call    mutex_lock
  444. @@:
  445.         mov     eax, [app_page_tabs+edi*8]
  446.         test    eax, 1
  447.         jz      .next
  448.  
  449.         mov     dword [app_page_tabs+edi*8], 0
  450.         invlpg  [ebx]
  451.         call    free_page
  452.  
  453. .next:
  454.         inc     edi
  455.         add     ebx, 0x1000
  456.         cmp     edi, esi
  457.         jb      @B
  458.  
  459.         mov     ecx, pg_data.mutex
  460.         call    mutex_unlock
  461.  
  462. .update_size:
  463.         mov     edx, [current_slot]
  464.         mov     ebx, [new_size]
  465.         mov     edx, [edx+APPDATA.process]
  466.         mov     [edx+PROC.mem_used], ebx
  467. .exit:
  468.         pop     edi
  469.         pop     esi
  470.         pop     ebx
  471.         xor     eax, eax
  472.         ret
  473.  
  474. .expand:
  475.  
  476.         mov     ecx, pg_data.mutex
  477.         call    mutex_lock
  478.  
  479.         xchg    esi, edi
  480.  
  481.         push    esi                   ;new size
  482.         push    edi                   ;old size
  483.  
  484.         add     edi, 0x1FFFFF
  485.         and     edi, not(0x1FFFFF)
  486.         add     esi, 0x1FFFFF
  487.         and     esi, not(0x1FFFFF)
  488.  
  489.         cmp     edi, esi
  490.         jae     .grow
  491.  @@:
  492.         call    alloc_page
  493.         test    eax, eax
  494.         jz      .exit_fail
  495.  
  496.         stdcall map_page_table, edi, eax
  497.  
  498.         push    edi
  499.         shr     edi, 9
  500.         add     edi, page_tabs
  501.         mov     ecx, 1024
  502.         xor     eax, eax
  503.         cld
  504.         rep stosd
  505.         pop     edi
  506.  
  507.         add     edi, 0x00200000
  508.         cmp     edi, esi
  509.         jb      @B
  510. .grow:
  511.         pop     edi                   ;old size
  512.         pop     ecx                   ;new size
  513.  
  514.         shr     edi, 10
  515.         shr     ecx, 10
  516.         sub     ecx, edi
  517.         shr     ecx, 2                ;pages count
  518.         mov     eax, 2
  519.  
  520.         add     edi, app_page_tabs
  521.         rep stosd
  522.  
  523.         mov     ecx, pg_data.mutex
  524.         call    mutex_unlock
  525.  
  526.         jmp     .update_size
  527.  
  528. .exit_fail:
  529.         mov     ecx, pg_data.mutex
  530.         call    mutex_unlock
  531.  
  532.         add     esp, 8
  533.         pop     edi
  534.         pop     esi
  535.         pop     ebx
  536.         xor     eax, eax
  537.         inc     eax
  538.         ret
  539. endp
  540.  
  541.  
  542. ; param
  543. ;  eax= linear address
  544. ;
  545. ; retval
  546. ;  eax= phisical page address
  547.  
  548. align 4
  549. get_pg_addr:
  550.         sub     eax, OS_BASE
  551.         cmp     eax, 0x400000
  552.         jb      @f
  553.         shr     eax, 12
  554.         mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*8]
  555. @@:
  556.         and     eax, 0xFFFFF000
  557.         ret
  558.  
  559.  
  560. align 4
  561. ; Now it is called from core/sys32::exc_c (see stack frame there)
  562. proc page_fault_handler
  563.  
  564.     .err_addr   equ ebp-4
  565.  
  566.         push    ebx               ;save exception number (#PF)
  567.         mov     ebp, esp
  568.         mov     ebx, cr2
  569.         push    ebx               ;that is locals: .err_addr = cr2
  570.         inc     [pg_data.pages_faults]
  571.  
  572.         mov     eax, [pf_err_code]
  573.  
  574.         cmp     ebx, OS_BASE      ;ebx == .err_addr
  575.         jb      .user_space       ;страница в памяти приложения ;
  576.  
  577.         cmp     ebx, page_tabs
  578.         jb      .kernel_space     ;страница в памяти ядра
  579.  
  580.         cmp     ebx, kernel_tabs
  581.         jb      .alloc;.app_tabs  ;таблицы страниц приложения ;
  582.                                   ;просто создадим одну
  583. .core_tabs:
  584. .fail:  ;simply return to caller
  585.         mov     esp, ebp
  586.         pop     ebx               ;restore exception number (#PF)
  587.         ret
  588.  
  589. .user_space:
  590.         test    eax, PG_READ
  591.         jnz     .err_access       ;Страница присутствует
  592.                                   ;Ошибка доступа ?
  593.  
  594.         shr     ebx, 12
  595.         mov     ecx, ebx
  596.         shr     ecx, 9
  597.         mov     edx, [master_tab+ecx*8]
  598.         test    edx, PG_READ
  599.         jz      .fail             ;таблица страниц не создана
  600.                                   ;неверный адрес в программе
  601.  
  602.         mov     eax, [page_tabs+ebx*8]
  603.         test    eax, 2
  604.         jz      .fail             ;адрес не зарезервирован для ;
  605.                                   ;использования. Ошибка
  606. .alloc:
  607.         call    alloc_page
  608.         test    eax, eax
  609.         jz      .fail
  610.  
  611.         stdcall map_page, [.err_addr], eax, PG_UWR
  612.  
  613.         mov     edi, [.err_addr]
  614.         and     edi, 0xFFFFF000
  615.         mov     ecx, 1024
  616.         xor     eax, eax
  617.        ;cld     ;caller is duty for this
  618.         rep stosd
  619. .exit:  ;iret with repeat fault instruction
  620.         add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  621.         restore_ring3_context
  622.         iretd
  623.  
  624. .err_access:
  625. ; access denied? this may be a result of copy-on-write protection for DLL
  626. ; check list of HDLLs
  627.         and     ebx, not 0xFFF
  628.         mov     eax, [current_process]
  629.         mov     eax, [eax+PROC.dlls_list_ptr]
  630.         test    eax, eax
  631.         jz      .fail
  632.         mov     esi, [eax+HDLL.fd]
  633. .scan_hdll:
  634.         cmp     esi, eax
  635.         jz      .fail
  636.         mov     edx, ebx
  637.         sub     edx, [esi+HDLL.base]
  638.         cmp     edx, [esi+HDLL.size]
  639.         jb      .fault_in_hdll
  640. .scan_hdll.next:
  641.         mov     esi, [esi+HDLL.fd]
  642.         jmp     .scan_hdll
  643. .fault_in_hdll:
  644. ; allocate new page, map it as rw and copy data
  645.         call    alloc_page
  646.         test    eax, eax
  647.         jz      .fail
  648.         stdcall map_page, ebx, eax, PG_UWR
  649.         mov     edi, ebx
  650.         mov     ecx, 1024
  651.         sub     ebx, [esi+HDLL.base]
  652.         mov     esi, [esi+HDLL.parent]
  653.         mov     esi, [esi+DLLDESCR.data]
  654.         add     esi, ebx
  655.         rep movsd
  656.         jmp     .exit
  657.  
  658. .kernel_space:
  659.         test    eax, PG_READ
  660.         jz      .fail   ;страница не присутствует
  661.  
  662.         test    eax, 12 ;U/S (+below)
  663.         jnz     .fail   ;приложение обратилось к памяти
  664.                         ;ядра
  665.        ;test    eax, 8
  666.        ;jnz     .fail   ;установлен зарезервированный бит
  667.                         ;в таблицах страниц. добавлено в P4/Xeon
  668.  
  669. ;попытка записи в защищённую страницу ядра
  670.  
  671.         cmp     ebx, tss._io_map_0
  672.         jb      .fail
  673.  
  674.         cmp     ebx, tss._io_map_0+8192
  675.         jae     .fail
  676.  
  677. ; io permission map
  678. ; copy-on-write protection
  679.  
  680.         call    alloc_page
  681.         test    eax, eax
  682.         jz      .fail
  683.  
  684.         push    eax
  685.         stdcall map_page, [.err_addr], eax, dword PG_SWR
  686.         pop     eax
  687.         mov     edi, [.err_addr]
  688.         and     edi, -4096
  689.         lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
  690.  
  691.         mov     ebx, esi
  692.         shr     ebx, 12
  693.         mov     edx, [current_slot]
  694.         or      eax, PG_SWR
  695.         mov     [edx+APPDATA.io_map+ebx*4], eax
  696.  
  697.         add     esi, [default_io_map]
  698.         mov     ecx, 4096/4
  699.        ;cld     ;caller is duty for this
  700.         rep movsd
  701.         jmp     .exit
  702. endp
  703.  
  704. ; returns number of mapped bytes
  705. proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
  706.                       ofs:dword,buf_size:dword,req_access:dword
  707.         locals
  708.              count   dd ?
  709.              process dd ?
  710.         endl
  711. xchg bx, bx
  712.         mov     [count], 0
  713.         cmp     [buf_size], 0
  714.         jz      .exit
  715.  
  716.         mov     eax, [slot]
  717.         shl     eax, 8
  718.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  719.         test    eax, eax
  720.         jz      .exit
  721.  
  722.         mov     [process], eax
  723.         mov     ebx, [ofs]
  724.         shr     ebx, 22
  725.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  726.         mov     esi, [ipc_ptab]
  727.         and     eax, 0xFFFFF000
  728.         jz      .exit
  729.         stdcall map_page, esi, eax, PG_SWR
  730. @@:
  731.         mov     edi, [lin_addr]
  732.         and     edi, 0xFFFFF000
  733.         mov     ecx, [buf_size]
  734.         add     ecx, 4095
  735.         shr     ecx, 12
  736.         inc     ecx                  ; ???????????
  737.  
  738.         mov     edx, [ofs]
  739.         shr     edx, 12
  740.         and     edx, 0x3FF
  741. .map:
  742.         stdcall safe_map_page, [slot], [req_access], [ofs]
  743.         jnc     .exit
  744.         add     [count], PAGE_SIZE
  745.         add     [ofs], PAGE_SIZE
  746.         dec     ecx
  747.         jz      .exit
  748.  
  749.         add     edi, PAGE_SIZE
  750.         inc     edx
  751.         cmp     edx, 1024
  752.         jnz     .map
  753.  
  754.         inc     ebx
  755.         mov     eax, [process]
  756.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  757.         and     eax, 0xFFFFF000
  758.         jz      .exit
  759.  
  760.         stdcall map_page, esi, eax, PG_SWR
  761.         xor     edx, edx
  762.         jmp     .map
  763. .exit:
  764.         mov     eax, [count]
  765.         ret
  766. endp
  767.  
  768. proc map_memEx stdcall, lin_addr:dword,slot:dword,\
  769.                         ofs:dword,buf_size:dword,req_access:dword
  770.         locals
  771.              count   dd ?
  772.              process dd ?
  773.         endl
  774.  
  775.         mov     [count], 0
  776.         cmp     [buf_size], 0
  777.         jz      .exit
  778.  
  779.         mov     eax, [slot]
  780.         shl     eax, 8
  781.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  782.         test    eax, eax
  783.         jz      .exit
  784.  
  785.         mov     [process], eax
  786.         mov     ebx, [ofs]
  787.         shr     ebx, 22
  788.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  789.         mov     esi, [proc_mem_tab]
  790.         and     eax, 0xFFFFF000
  791.         jz      .exit
  792.         stdcall map_page, esi, eax, PG_SWR
  793. @@:
  794.         mov     edi, [lin_addr]
  795.         and     edi, 0xFFFFF000
  796.         mov     ecx, [buf_size]
  797.         add     ecx, 4095
  798.         shr     ecx, 12
  799.         inc     ecx                  ; ???????????
  800.  
  801.         mov     edx, [ofs]
  802.         shr     edx, 12
  803.         and     edx, 0x3FF
  804. .map:
  805.         stdcall safe_map_page, [slot], [req_access], [ofs]
  806.         jnc     .exit
  807.         add     [count], PAGE_SIZE
  808.         add     [ofs], PAGE_SIZE
  809.         dec     ecx
  810.         jz      .exit
  811.  
  812.         add     edi, PAGE_SIZE
  813.         inc     edx
  814.         cmp     edx, 1024
  815.         jnz     .map
  816.  
  817.         inc     ebx
  818.         mov     eax, [process]
  819.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  820.         and     eax, 0xFFFFF000
  821.         jz      .exit
  822.  
  823.         stdcall map_page, esi, eax, PG_SWR
  824.         xor     edx, edx
  825.         jmp     .map
  826. .exit:
  827.         mov     eax, [count]
  828.         ret
  829. endp
  830.  
  831. ; in: esi+edx*4 = pointer to page table entry
  832. ; in: [slot], [req_access], [ofs] on the stack
  833. ; in: edi = linear address to map
  834. ; out: CF cleared <=> failed
  835. ; destroys: only eax
  836. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  837.         mov     eax, [esi+edx*8]
  838.         test    al, PG_READ
  839.         jz      .not_present
  840.         test    al, PG_WRITE
  841.         jz      .resolve_readonly
  842. ; normal case: writable page, just map with requested access
  843. .map:
  844.         stdcall map_page, edi, eax, [req_access]
  845.         stc
  846. .fail:
  847.         ret
  848. .not_present:
  849. ; check for alloc-on-demand page
  850.         test    al, 2
  851.         jz      .fail
  852. ; allocate new page, save it to source page table
  853.         push    ecx
  854.         call    alloc_page
  855.         pop     ecx
  856.         test    eax, eax
  857.         jz      .fail
  858.         or      al, PG_UWR
  859.         mov     [esi+edx*8], eax
  860.         jmp     .map
  861. .resolve_readonly:
  862. ; readonly page, probably copy-on-write
  863. ; check: readonly request of readonly page is ok
  864.         test    [req_access], PG_WRITE
  865.         jz      .map
  866. ; find control structure for this page
  867.         pushf
  868.         cli
  869.         cld
  870.         push    ebx ecx
  871.         mov     eax, [slot]
  872.         shl     eax, 8
  873.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  874.         mov     eax, [eax+PROC.dlls_list_ptr]
  875.         test    eax, eax
  876.         jz      .no_hdll
  877.         mov     ecx, [eax+HDLL.fd]
  878. .scan_hdll:
  879.         cmp     ecx, eax
  880.         jz      .no_hdll
  881.         mov     ebx, [ofs]
  882.         and     ebx, not 0xFFF
  883.         sub     ebx, [ecx+HDLL.base]
  884.         cmp     ebx, [ecx+HDLL.size]
  885.         jb      .hdll_found
  886.         mov     ecx, [ecx+HDLL.fd]
  887.         jmp     .scan_hdll
  888. .no_hdll:
  889.         pop     ecx ebx
  890.         popf
  891.         clc
  892.         ret
  893. .hdll_found:
  894. ; allocate page, save it in page table, map it, copy contents from base
  895.         mov     eax, [ecx+HDLL.parent]
  896.         add     ebx, [eax+DLLDESCR.data]
  897.         call    alloc_page
  898.         test    eax, eax
  899.         jz      .no_hdll
  900.         or      al, PG_UWR
  901.         mov     [esi+edx*8], eax
  902.         stdcall map_page, edi, eax, [req_access]
  903.         push    esi edi
  904.         mov     esi, ebx
  905.         mov     ecx, 4096/4
  906.         rep movsd
  907.         pop     edi esi
  908.         pop     ecx ebx
  909.         popf
  910.         stc
  911.         ret
  912. endp
  913.  
  914. sys_IPC:
  915. ;input:
  916. ;  ebx=1 - set ipc buffer area
  917. ;    ecx=address of buffer
  918. ;    edx=size of buffer
  919. ;  eax=2 - send message
  920. ;    ebx=PID
  921. ;    ecx=address of message
  922. ;    edx=size of message
  923.  
  924.         dec     ebx
  925.         jnz     @f
  926.  
  927.         mov     eax, [current_slot]
  928.         pushf
  929.         cli
  930.         mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
  931.         mov     [eax+APPDATA.ipc_size], edx
  932.  
  933.         add     edx, ecx
  934.         add     edx, 4095
  935.         and     edx, not 4095
  936.  
  937. .touch:
  938.         mov     eax, [ecx]
  939.         add     ecx, 0x1000
  940.         cmp     ecx, edx
  941.         jb      .touch
  942.  
  943.         popf
  944.         mov     [esp+32], ebx   ;ebx=0
  945.         ret
  946.  
  947. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  948. ;2
  949. @@:
  950.         dec     ebx
  951.         jnz     @f
  952.  
  953.         stdcall sys_ipc_send, ecx, edx, esi
  954.         mov     [esp+32], eax
  955.         ret
  956. @@:
  957.         or      eax, -1
  958.         mov     [esp+32], eax
  959.         ret
  960.  
  961. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  962.            locals
  963.              dst_slot   dd ?
  964.              dst_offset dd ?
  965.              buf_size   dd ?
  966.              used_buf   dd ?
  967.            endl
  968.  
  969.         pushf
  970.         cli
  971.  
  972.         mov     eax, [PID]
  973.         call    pid_to_slot
  974.         test    eax, eax
  975.         jz      .no_pid
  976.  
  977.         mov     [dst_slot], eax
  978.         shl     eax, 8
  979.         mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
  980.         test    edi, edi
  981.         jz      .no_ipc_area
  982.  
  983.         mov     ebx, edi
  984.         and     ebx, 0xFFF
  985.         mov     [dst_offset], ebx
  986.  
  987.         mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
  988.         mov     [buf_size], esi
  989.  
  990.         mov     ecx, [ipc_tmp]
  991.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  992.         jbe     @f
  993.         push    esi edi
  994.         add     esi, 0x1000
  995.         stdcall alloc_kernel_space, esi
  996.         mov     ecx, eax
  997.         pop     edi esi
  998. @@:
  999.         mov     [used_buf], ecx
  1000.         stdcall map_mem_ipc, ecx, [dst_slot], \
  1001.                 edi, esi, PG_SWR
  1002.  
  1003.         mov     edi, [dst_offset]
  1004.         add     edi, [used_buf]
  1005.         cmp     dword [edi], 0
  1006.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1007.  
  1008.         mov     edx, dword [edi+4]
  1009.         lea     ebx, [edx+8]
  1010.         add     ebx, [msg_size]
  1011.         cmp     ebx, [buf_size]
  1012.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1013.  
  1014.         mov     dword [edi+4], ebx
  1015.         mov     eax, [TASK_BASE]
  1016.         mov     eax, [eax+0x04]        ;eax - our PID
  1017.         add     edi, edx
  1018.         mov     [edi], eax
  1019.         mov     ecx, [msg_size]
  1020.  
  1021.         mov     [edi+4], ecx
  1022.         add     edi, 8
  1023.         mov     esi, [msg_addr]
  1024.        ;    add esi, new_app_base
  1025.         cld
  1026.         rep movsb
  1027.  
  1028.         mov     ebx, [ipc_tmp]
  1029.         mov     edx, ebx
  1030.         shr     ebx, 12
  1031.         xor     eax, eax
  1032.         mov     [page_tabs+ebx*8], eax
  1033.         mov     [page_tabs+ebx*8+4], eax
  1034.         invlpg  [edx]
  1035.  
  1036.         mov     ebx, [ipc_pdir]
  1037.         mov     edx, ebx
  1038.         shr     ebx, 12
  1039.         xor     eax, eax
  1040.         mov     [page_tabs+ebx*8], eax
  1041.         mov     [page_tabs+ebx*8+4], eax
  1042.         invlpg  [edx]
  1043.  
  1044.         mov     ebx, [ipc_ptab]
  1045.         mov     edx, ebx
  1046.         shr     ebx, 12
  1047.         xor     eax, eax
  1048.         mov     [page_tabs+ebx*8], eax
  1049.         mov     [page_tabs+ebx*8+4], eax
  1050.         invlpg  [edx]
  1051.  
  1052.         mov     eax, [dst_slot]
  1053.         shl     eax, 8
  1054.         or      [eax+SLOT_BASE+0xA8], dword 0x40
  1055.         push    0
  1056.         jmp     .ret
  1057. .no_pid:
  1058.         popf
  1059.         mov     eax, 4
  1060.         ret
  1061. .no_ipc_area:
  1062.         popf
  1063.         xor     eax, eax
  1064.         inc     eax
  1065.         ret
  1066. .ipc_blocked:
  1067.         push    2
  1068.         jmp     .ret
  1069. .buffer_overflow:
  1070.         push    3
  1071. .ret:
  1072.         mov     eax, [used_buf]
  1073.         cmp     eax, [ipc_tmp]
  1074.         je      @f
  1075.         stdcall free_kernel_space, eax
  1076. @@:
  1077.         pop     eax
  1078.         popf
  1079.         ret
  1080. endp
  1081.  
  1082. align 4
  1083. sysfn_meminfo:
  1084.         cmp     ecx, OS_BASE
  1085.         jae     .fail
  1086.  
  1087.         mov     eax, [pg_data.pages_count]
  1088.         mov     [ecx], eax
  1089.         shl     eax, 12
  1090.         mov     [esp+32], eax
  1091.         mov     eax, [pg_data.pages_free]
  1092.         mov     [ecx+4], eax
  1093.         mov     eax, [pg_data.pages_faults]
  1094.         mov     [ecx+8], eax
  1095.         mov     eax, [heap_size]
  1096.         mov     [ecx+12], eax
  1097.         mov     eax, [heap_free]
  1098.         mov     [ecx+16], eax
  1099.         mov     eax, [heap_blocks]
  1100.         mov     [ecx+20], eax
  1101.         mov     eax, [free_blocks]
  1102.         mov     [ecx+24], eax
  1103.         ret
  1104. .fail:
  1105.         or      dword [esp+32], -1
  1106.         ret
  1107.  
  1108. align 4
  1109. f68:
  1110.         cmp     ebx, 4
  1111.         jbe     sys_sheduler
  1112.  
  1113.         cmp     ebx, 11
  1114.         jb      .fail
  1115.  
  1116.         cmp     ebx, 27
  1117.         ja      .fail
  1118.  
  1119.         jmp     dword [f68call+ebx*4-11*4]
  1120. .11:
  1121.         call    init_heap
  1122.         mov     [esp+32], eax
  1123.         ret
  1124. .12:
  1125.         stdcall user_alloc, ecx
  1126.         mov     [esp+32], eax
  1127.         ret
  1128. .13:
  1129.         stdcall user_free, ecx
  1130.         mov     [esp+32], eax
  1131.         ret
  1132. .14:
  1133.         cmp     ecx, OS_BASE
  1134.         jae     .fail
  1135.         mov     edi, ecx
  1136.         call    get_event_ex
  1137.         mov     [esp+32], eax
  1138.         ret
  1139. .16:
  1140.         test    ecx, ecx
  1141.         jz      .fail
  1142.         cmp     ecx, OS_BASE
  1143.         jae     .fail
  1144.         stdcall get_service, ecx
  1145.         mov     [esp+32], eax
  1146.         ret
  1147. .17:
  1148.         call    srv_handlerEx   ;ecx
  1149.         mov     [esp+32], eax
  1150.         ret
  1151. .19:
  1152.         cmp     ecx, OS_BASE
  1153.         jae     .fail
  1154.         stdcall load_library, ecx
  1155.         mov     [esp+32], eax
  1156.         ret
  1157. .20:
  1158.         mov     eax, edx
  1159.         mov     ebx, ecx
  1160.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1161.         mov     [esp+32], eax
  1162.         ret
  1163. .21:
  1164.         cmp     ecx, OS_BASE
  1165.         jae     .fail
  1166.  
  1167.         cmp     edx, OS_BASE
  1168.         jae     .fail
  1169.  
  1170.         stdcall load_pe_driver, ecx, edx
  1171.         mov     [esp+32], eax
  1172.         ret
  1173. .22:
  1174.         cmp     ecx, OS_BASE
  1175.         jae     .fail
  1176.  
  1177.         stdcall shmem_open, ecx, edx, esi
  1178.         mov     [esp+24], edx
  1179.         mov     [esp+32], eax
  1180.         ret
  1181.  
  1182. .23:
  1183.         cmp     ecx, OS_BASE
  1184.         jae     .fail
  1185.  
  1186.         stdcall shmem_close, ecx
  1187.         mov     [esp+32], eax
  1188.         ret
  1189. .24:
  1190.         mov     eax, [current_slot]
  1191.         xchg    ecx, [eax+APPDATA.exc_handler]
  1192.         xchg    edx, [eax+APPDATA.except_mask]
  1193.         mov     [esp+32], ecx ; reg_eax+8
  1194.         mov     [esp+20], edx ; reg_ebx+8
  1195.         ret
  1196. .25:
  1197.         cmp     ecx, 32
  1198.         jae     .fail
  1199.         mov     eax, [current_slot]
  1200.         btr     [eax+APPDATA.except_mask], ecx
  1201.         setc    byte[esp+32]
  1202.         jecxz   @f
  1203.         bts     [eax+APPDATA.except_mask], ecx
  1204. @@:
  1205.         ret
  1206.  
  1207. .26:
  1208.         stdcall user_unmap, ecx, edx, esi
  1209.         mov     [esp+32], eax
  1210.         ret
  1211.  
  1212. .27:
  1213.         cmp     ecx, OS_BASE
  1214.         jae     .fail
  1215.  
  1216.         stdcall load_file_umode, ecx
  1217.         mov     [esp+24], edx
  1218.         mov     [esp+32], eax
  1219.         ret
  1220.  
  1221. .fail:
  1222.         xor     eax, eax
  1223.         mov     [esp+32], eax
  1224.         ret
  1225.  
  1226.  
  1227. align 4
  1228. f68call:   ; keep this table closer to main code
  1229.  
  1230.            dd f68.11   ; init_heap
  1231.            dd f68.12   ; user_alloc
  1232.            dd f68.13   ; user_free
  1233.            dd f68.14   ; get_event_ex
  1234.            dd f68.fail ; moved to f68.24
  1235.            dd f68.16   ; get_service
  1236.            dd f68.17   ; call_service
  1237.            dd f68.fail ; moved to f68.25
  1238.            dd f68.19   ; load_dll
  1239.            dd f68.20   ; user_realloc
  1240.            dd f68.21   ; load_driver
  1241.            dd f68.22   ; shmem_open
  1242.            dd f68.23   ; shmem_close
  1243.            dd f68.24   ; set exception handler
  1244.            dd f68.25   ; unmask exception
  1245.            dd f68.26   ; user_unmap
  1246.            dd f68.27   ; load_file_umode
  1247.  
  1248.  
  1249. align 4
  1250. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1251.         push    esi
  1252.  
  1253.         stdcall load_PE, [file]
  1254.         test    eax, eax
  1255.         jz      .fail
  1256.  
  1257.         mov     esi, eax
  1258.         push    [cmdline]
  1259.         push    DRV_ENTRY
  1260.         call    eax
  1261.         pop     ecx
  1262.         pop     ecx
  1263.         test    eax, eax
  1264.         jz      .fail
  1265.  
  1266.         mov     [eax+SRV.entry], esi
  1267.         pop     esi
  1268.         ret
  1269.  
  1270. .fail:
  1271.         xor     eax, eax
  1272.         pop     esi
  1273.         ret
  1274. endp
  1275.  
  1276. align 4
  1277. proc create_ring_buffer stdcall, size:dword, flags:dword
  1278.            locals
  1279.              buf_ptr  dd ?
  1280.            endl
  1281.  
  1282.         mov     eax, [size]
  1283.         test    eax, eax
  1284.         jz      .fail
  1285.  
  1286.         add     eax, eax
  1287.         stdcall alloc_kernel_space, eax
  1288.         test    eax, eax
  1289.         jz      .fail
  1290.  
  1291.         push    ebx
  1292.  
  1293.         mov     [buf_ptr], eax
  1294.  
  1295.         mov     ebx, [size]
  1296.         shr     ebx, 12
  1297.         push    ebx
  1298.  
  1299.         stdcall alloc_pages, ebx
  1300.         pop     ecx
  1301.  
  1302.         test    eax, eax
  1303.         jz      .mm_fail
  1304.  
  1305.         push    edi
  1306.  
  1307.         or      eax, [flags]
  1308.         mov     edi, [buf_ptr]
  1309.         mov     ebx, [buf_ptr]
  1310.         mov     edx, ecx
  1311.         shl     edx, 2
  1312.         shr     edi, 10
  1313. @@:
  1314.         mov     [page_tabs+edi], eax
  1315.         mov     [page_tabs+edi+edx], eax
  1316.         invlpg  [ebx]
  1317.         invlpg  [ebx+0x10000]
  1318.         add     eax, 0x1000
  1319.         add     ebx, 0x1000
  1320.         add     edi, 4
  1321.         dec     ecx
  1322.         jnz     @B
  1323.  
  1324.         mov     eax, [buf_ptr]
  1325.         pop     edi
  1326.         pop     ebx
  1327.         ret
  1328. .mm_fail:
  1329.         stdcall free_kernel_space, [buf_ptr]
  1330.         xor     eax, eax
  1331.         pop     ebx
  1332. .fail:
  1333.         ret
  1334. endp
  1335.  
  1336.  
  1337. align 4
  1338. proc print_mem
  1339.         mov     edi, BOOT_VAR + 0x9104
  1340.         mov     ecx, [edi-4]
  1341.         test    ecx, ecx
  1342.         jz      .done
  1343.  
  1344. @@:
  1345.         mov     eax, [edi]
  1346.         mov     edx, [edi+4]
  1347.         add     eax, [edi+8]
  1348.         adc     edx, [edi+12]
  1349.  
  1350.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1351.                     [edi+4], [edi],\
  1352.                     edx, eax, [edi+16]
  1353.         add     edi, 20
  1354.         dec     ecx
  1355.         jnz     @b
  1356. .done:
  1357.         ret
  1358. endp
  1359.