Subversion Repositories Kolibri OS

Rev

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