Subversion Repositories Kolibri OS

Rev

Rev 8052 | Rev 8876 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 8874 $
  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= physical 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       ;page in application memory
  571.  
  572.         cmp     ebx, page_tabs
  573.         jb      .kernel_space     ;page in kernel memory
  574.  
  575.         cmp     ebx, kernel_tabs
  576.         jb      .alloc;.app_tabs  ;page tables of application ;
  577.                                   ;simply create one
  578. .core_tabs:
  579. .fail:  ;simply return to caller
  580.         mov     esp, ebp
  581.         pop     ebx               ;restore exception number (#PF)
  582.         ret
  583.  
  584. .user_space:
  585.         test    eax, PG_READ
  586.         jnz     .err_access       ;Page presents
  587.                                   ;Access error ?
  588.  
  589.         shr     ebx, 12
  590.         mov     ecx, ebx
  591.         shr     ecx, 10
  592.         mov     edx, [master_tab+ecx*4]
  593.         test    edx, PG_READ
  594.         jz      .fail             ;page table is not created
  595.                                   ;incorrect address in program
  596.  
  597.         mov     eax, [page_tabs+ebx*4]
  598.         test    eax, 2
  599.         jz      .fail             ;address is not reserved for usage. Error
  600.                                  
  601. .alloc:
  602.         call    alloc_page
  603.         test    eax, eax
  604.         jz      .fail
  605.  
  606.         stdcall map_page, [.err_addr], eax, PG_UWR
  607.  
  608.         mov     edi, [.err_addr]
  609.         and     edi, 0xFFFFF000
  610.         mov     ecx, 1024
  611.         xor     eax, eax
  612.        ;cld     ;caller is duty for this
  613.         rep stosd
  614. .exit:  ;iret with repeat fault instruction
  615.         add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  616.         restore_ring3_context
  617.         iretd
  618.  
  619. .err_access:
  620. ; access denied? this may be a result of copy-on-write protection for DLL
  621. ; check list of HDLLs
  622.         and     ebx, not 0xFFF
  623.         mov     eax, [current_process]
  624.         mov     eax, [eax+PROC.dlls_list_ptr]
  625.         test    eax, eax
  626.         jz      .fail
  627.         mov     esi, [eax+HDLL.fd]
  628. .scan_hdll:
  629.         cmp     esi, eax
  630.         jz      .fail
  631.         mov     edx, ebx
  632.         sub     edx, [esi+HDLL.base]
  633.         cmp     edx, [esi+HDLL.size]
  634.         jb      .fault_in_hdll
  635. .scan_hdll.next:
  636.         mov     esi, [esi+HDLL.fd]
  637.         jmp     .scan_hdll
  638. .fault_in_hdll:
  639. ; allocate new page, map it as rw and copy data
  640.         call    alloc_page
  641.         test    eax, eax
  642.         jz      .fail
  643.         stdcall map_page, ebx, eax, PG_UWR
  644.         mov     edi, ebx
  645.         mov     ecx, 1024
  646.         sub     ebx, [esi+HDLL.base]
  647.         mov     esi, [esi+HDLL.parent]
  648.         mov     esi, [esi+DLLDESCR.data]
  649.         add     esi, ebx
  650.         rep movsd
  651.         jmp     .exit
  652.  
  653. .kernel_space:
  654.         test    eax, PG_READ
  655.         jz      .fail   ;page does not present
  656.  
  657.         test    eax, 12 ;U/S (+below)
  658.         jnz     .fail   ;application requested kernel memory
  659.                        
  660.        ;test    eax, 8
  661.        ;jnz     .fail   ;the reserved bit is set in page tables. Added in P4/Xeon
  662.                        
  663.  
  664. ;an attempt to write to a protected kernel page
  665.  
  666.         cmp     ebx, tss._io_map_0
  667.         jb      .fail
  668.  
  669.         cmp     ebx, tss._io_map_0+8192
  670.         jae     .fail
  671.  
  672. ; io permission map
  673. ; copy-on-write protection
  674.  
  675.         call    alloc_page
  676.         test    eax, eax
  677.         jz      .fail
  678.  
  679.         push    eax
  680.         stdcall map_page, [.err_addr], eax, dword PG_SWR
  681.         pop     eax
  682.         mov     edi, [.err_addr]
  683.         and     edi, -4096
  684.         lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
  685.  
  686.         mov     ebx, esi
  687.         shr     ebx, 12
  688.         mov     edx, [current_slot]
  689.         or      eax, PG_SWR
  690.         mov     [edx+APPDATA.io_map+ebx*4], eax
  691.  
  692.         add     esi, [default_io_map]
  693.         mov     ecx, 4096/4
  694.        ;cld     ;caller is duty for this
  695.         rep movsd
  696.         jmp     .exit
  697. endp
  698.  
  699. ; returns number of mapped bytes
  700. proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
  701.                       ofs:dword,buf_size:dword,req_access:dword
  702.         locals
  703.              count   dd ?
  704.              process dd ?
  705.         endl
  706.  
  707.         mov     [count], 0
  708.         cmp     [buf_size], 0
  709.         jz      .exit
  710.  
  711.         mov     eax, [slot]
  712.         shl     eax, 8
  713.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  714.         test    eax, eax
  715.         jz      .exit
  716.  
  717.         mov     [process], eax
  718.         mov     ebx, [ofs]
  719.         shr     ebx, 22
  720.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  721.         mov     esi, [ipc_ptab]
  722.         and     eax, 0xFFFFF000
  723.         jz      .exit
  724.         stdcall map_page, esi, eax, PG_SWR
  725. @@:
  726.         mov     edi, [lin_addr]
  727.         and     edi, 0xFFFFF000
  728.         mov     ecx, [buf_size]
  729.         add     ecx, 4095
  730.         shr     ecx, 12
  731.         inc     ecx                  ; ???????????
  732.  
  733.         mov     edx, [ofs]
  734.         shr     edx, 12
  735.         and     edx, 0x3FF
  736. .map:
  737.         stdcall safe_map_page, [slot], [req_access], [ofs]
  738.         jnc     .exit
  739.         add     [count], PAGE_SIZE
  740.         add     [ofs], PAGE_SIZE
  741.         dec     ecx
  742.         jz      .exit
  743.  
  744.         add     edi, PAGE_SIZE
  745.         inc     edx
  746.         cmp     edx, 1024
  747.         jnz     .map
  748.  
  749.         inc     ebx
  750.         mov     eax, [process]
  751.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  752.         and     eax, 0xFFFFF000
  753.         jz      .exit
  754.  
  755.         stdcall map_page, esi, eax, PG_SWR
  756.         xor     edx, edx
  757.         jmp     .map
  758. .exit:
  759.         mov     eax, [count]
  760.         ret
  761. endp
  762.  
  763. proc map_memEx stdcall, lin_addr:dword,slot:dword,\
  764.                         ofs:dword,buf_size:dword,req_access:dword
  765.         locals
  766.              count   dd ?
  767.              process dd ?
  768.         endl
  769.  
  770.         mov     [count], 0
  771.         cmp     [buf_size], 0
  772.         jz      .exit
  773.  
  774.         mov     eax, [slot]
  775.         shl     eax, 8
  776.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  777.         test    eax, eax
  778.         jz      .exit
  779.  
  780.         mov     [process], eax
  781.         mov     ebx, [ofs]
  782.         shr     ebx, 22
  783.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  784.         mov     esi, [proc_mem_tab]
  785.         and     eax, 0xFFFFF000
  786.         jz      .exit
  787.         stdcall map_page, esi, eax, PG_SWR
  788. @@:
  789.         mov     edi, [lin_addr]
  790.         and     edi, 0xFFFFF000
  791.         mov     ecx, [buf_size]
  792.         add     ecx, 4095
  793.         shr     ecx, 12
  794.         inc     ecx                  ; ???????????
  795.  
  796.         mov     edx, [ofs]
  797.         shr     edx, 12
  798.         and     edx, 0x3FF
  799. .map:
  800.         stdcall safe_map_page, [slot], [req_access], [ofs]
  801.         jnc     .exit
  802.         add     [count], PAGE_SIZE
  803.         add     [ofs], PAGE_SIZE
  804.         dec     ecx
  805.         jz      .exit
  806.  
  807.         add     edi, PAGE_SIZE
  808.         inc     edx
  809.         cmp     edx, 1024
  810.         jnz     .map
  811.  
  812.         inc     ebx
  813.         mov     eax, [process]
  814.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  815.         and     eax, 0xFFFFF000
  816.         jz      .exit
  817.  
  818.         stdcall map_page, esi, eax, PG_SWR
  819.         xor     edx, edx
  820.         jmp     .map
  821. .exit:
  822.         mov     eax, [count]
  823.         ret
  824. endp
  825.  
  826. ; in: esi+edx*4 = pointer to page table entry
  827. ; in: [slot], [req_access], [ofs] on the stack
  828. ; in: edi = linear address to map
  829. ; out: CF cleared <=> failed
  830. ; destroys: only eax
  831. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  832.         mov     eax, [esi+edx*4]
  833.         test    al, PG_READ
  834.         jz      .not_present
  835.         test    al, PG_WRITE
  836.         jz      .resolve_readonly
  837. ; normal case: writable page, just map with requested access
  838. .map:
  839.         stdcall map_page, edi, eax, [req_access]
  840.         stc
  841. .fail:
  842.         ret
  843. .not_present:
  844. ; check for alloc-on-demand page
  845.         test    al, 2
  846.         jz      .fail
  847. ; allocate new page, save it to source page table
  848.         push    ecx
  849.         call    alloc_page
  850.         pop     ecx
  851.         test    eax, eax
  852.         jz      .fail
  853.         or      al, PG_UWR
  854.         mov     [esi+edx*4], eax
  855.         jmp     .map
  856. .resolve_readonly:
  857. ; readonly page, probably copy-on-write
  858. ; check: readonly request of readonly page is ok
  859.         test    [req_access], PG_WRITE
  860.         jz      .map
  861. ; find control structure for this page
  862.         pushf
  863.         cli
  864.         cld
  865.         push    ebx ecx
  866.         mov     eax, [slot]
  867.         shl     eax, 8
  868.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  869.         mov     eax, [eax+PROC.dlls_list_ptr]
  870.         test    eax, eax
  871.         jz      .no_hdll
  872.         mov     ecx, [eax+HDLL.fd]
  873. .scan_hdll:
  874.         cmp     ecx, eax
  875.         jz      .no_hdll
  876.         mov     ebx, [ofs]
  877.         and     ebx, not 0xFFF
  878.         sub     ebx, [ecx+HDLL.base]
  879.         cmp     ebx, [ecx+HDLL.size]
  880.         jb      .hdll_found
  881.         mov     ecx, [ecx+HDLL.fd]
  882.         jmp     .scan_hdll
  883. .no_hdll:
  884.         pop     ecx ebx
  885.         popf
  886.         clc
  887.         ret
  888. .hdll_found:
  889. ; allocate page, save it in page table, map it, copy contents from base
  890.         mov     eax, [ecx+HDLL.parent]
  891.         add     ebx, [eax+DLLDESCR.data]
  892.         call    alloc_page
  893.         test    eax, eax
  894.         jz      .no_hdll
  895.         or      al, PG_UWR
  896.         mov     [esi+edx*4], eax
  897.         stdcall map_page, edi, eax, [req_access]
  898.         push    esi edi
  899.         mov     esi, ebx
  900.         mov     ecx, 4096/4
  901.         rep movsd
  902.         pop     edi esi
  903.         pop     ecx ebx
  904.         popf
  905.         stc
  906.         ret
  907. endp
  908.  
  909. sys_IPC:
  910. ;input:
  911. ;  ebx=1 - set ipc buffer area
  912. ;    ecx=address of buffer
  913. ;    edx=size of buffer
  914. ;  eax=2 - send message
  915. ;    ebx=PID
  916. ;    ecx=address of message
  917. ;    edx=size of message
  918.  
  919.         dec     ebx
  920.         jnz     @f
  921.  
  922.         mov     eax, [current_slot]
  923.         pushf
  924.         cli
  925.         mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
  926.         mov     [eax+APPDATA.ipc_size], edx
  927.  
  928.         add     edx, ecx
  929.         add     edx, 4095
  930.         and     edx, not 4095
  931.  
  932. .touch:
  933.         mov     eax, [ecx]
  934.         add     ecx, 0x1000
  935.         cmp     ecx, edx
  936.         jb      .touch
  937.  
  938.         popf
  939.         mov     [esp+32], ebx   ;ebx=0
  940.         ret
  941.  
  942. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  943. ;2
  944. @@:
  945.         dec     ebx
  946.         jnz     @f
  947.  
  948.         stdcall sys_ipc_send, ecx, edx, esi
  949.         mov     [esp+32], eax
  950.         ret
  951. @@:
  952.         or      eax, -1
  953.         mov     [esp+32], eax
  954.         ret
  955.  
  956. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  957.            locals
  958.              dst_slot   dd ?
  959.              dst_offset dd ?
  960.              buf_size   dd ?
  961.              used_buf   dd ?
  962.            endl
  963.  
  964.         pushf
  965.         cli
  966.  
  967.         mov     eax, [PID]
  968.         call    pid_to_slot
  969.         test    eax, eax
  970.         jz      .no_pid
  971.  
  972.         mov     [dst_slot], eax
  973.         shl     eax, 8
  974.         mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
  975.         test    edi, edi
  976.         jz      .no_ipc_area
  977.  
  978.         mov     ebx, edi
  979.         and     ebx, 0xFFF
  980.         mov     [dst_offset], ebx
  981.  
  982.         mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
  983.         mov     [buf_size], esi
  984.  
  985.         mov     ecx, [ipc_tmp]
  986.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  987.         jbe     @f
  988.         push    esi edi
  989.         add     esi, 0x1000
  990.         stdcall alloc_kernel_space, esi
  991.         mov     ecx, eax
  992.         pop     edi esi
  993. @@:
  994.         mov     [used_buf], ecx
  995.         stdcall map_mem_ipc, ecx, [dst_slot], \
  996.                 edi, esi, PG_SWR
  997.  
  998.         mov     edi, [dst_offset]
  999.         add     edi, [used_buf]
  1000.         cmp     dword [edi], 0
  1001.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1002.  
  1003.         mov     edx, dword [edi+4]
  1004.         lea     ebx, [edx+8]
  1005.         add     ebx, [msg_size]
  1006.         cmp     ebx, [buf_size]
  1007.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1008.  
  1009.         mov     dword [edi+4], ebx
  1010.         mov     eax, [TASK_BASE]
  1011.         mov     eax, [eax+TASKDATA.pid]        ;eax - our PID
  1012.         add     edi, edx
  1013.         mov     [edi], eax
  1014.         mov     ecx, [msg_size]
  1015.  
  1016.         mov     [edi+4], ecx
  1017.         add     edi, 8
  1018.         mov     esi, [msg_addr]
  1019.        ;    add esi, new_app_base
  1020.         cld
  1021.         rep movsb
  1022.  
  1023.         mov     ebx, [ipc_tmp]
  1024.         mov     edx, ebx
  1025.         shr     ebx, 12
  1026.         xor     eax, eax
  1027.         mov     [page_tabs+ebx*4], eax
  1028.         invlpg  [edx]
  1029.  
  1030.         mov     ebx, [ipc_pdir]
  1031.         mov     edx, ebx
  1032.         shr     ebx, 12
  1033.         xor     eax, eax
  1034.         mov     [page_tabs+ebx*4], eax
  1035.         invlpg  [edx]
  1036.  
  1037.         mov     ebx, [ipc_ptab]
  1038.         mov     edx, ebx
  1039.         shr     ebx, 12
  1040.         xor     eax, eax
  1041.         mov     [page_tabs+ebx*4], eax
  1042.         invlpg  [edx]
  1043.  
  1044.         mov     eax, [dst_slot]
  1045.         shl     eax, 8
  1046.         or      [eax+SLOT_BASE+0xA8], dword 0x40
  1047.         push    0
  1048.         jmp     .ret
  1049. .no_pid:
  1050.         popf
  1051.         mov     eax, 4
  1052.         ret
  1053. .no_ipc_area:
  1054.         popf
  1055.         xor     eax, eax
  1056.         inc     eax
  1057.         ret
  1058. .ipc_blocked:
  1059.         push    2
  1060.         jmp     .ret
  1061. .buffer_overflow:
  1062.         push    3
  1063. .ret:
  1064.         mov     eax, [used_buf]
  1065.         cmp     eax, [ipc_tmp]
  1066.         je      @f
  1067.         stdcall free_kernel_space, eax
  1068. @@:
  1069.         pop     eax
  1070.         popf
  1071.         ret
  1072. endp
  1073.  
  1074. align 4
  1075. sysfn_meminfo:
  1076.         cmp     ecx, OS_BASE
  1077.         jae     .fail
  1078.  
  1079.         mov     eax, [pg_data.pages_count]
  1080.         mov     [ecx], eax
  1081.         shl     eax, 12
  1082.         mov     [esp+32], eax
  1083.         mov     eax, [pg_data.pages_free]
  1084.         mov     [ecx+4], eax
  1085.         mov     eax, [pg_data.pages_faults]
  1086.         mov     [ecx+8], eax
  1087.         mov     eax, [heap_size]
  1088.         mov     [ecx+12], eax
  1089.         mov     eax, [heap_free]
  1090.         mov     [ecx+16], eax
  1091.         mov     eax, [heap_blocks]
  1092.         mov     [ecx+20], eax
  1093.         mov     eax, [free_blocks]
  1094.         mov     [ecx+24], eax
  1095.         ret
  1096. .fail:
  1097.         or      dword [esp+32], -1
  1098.         ret
  1099.  
  1100. align 4
  1101. f68:
  1102.         cmp     ebx, 4
  1103.         jbe     sys_sheduler
  1104.         cmp     ebx, 11
  1105.         jb      undefined_syscall
  1106.         cmp     ebx, 29
  1107.         ja      undefined_syscall
  1108.         xor     eax, eax
  1109.         jmp     dword [f68call+ebx*4-11*4]
  1110. .11:
  1111.         call    init_heap
  1112.         mov     [esp+SYSCALL_STACK._eax], eax
  1113.         ret
  1114. .12:
  1115.         stdcall user_alloc, ecx
  1116.         mov     [esp+SYSCALL_STACK._eax], eax
  1117.         ret
  1118. .13:
  1119.         stdcall user_free, ecx
  1120.         mov     [esp+SYSCALL_STACK._eax], eax
  1121.         ret
  1122. .14:
  1123.         cmp     ecx, OS_BASE
  1124.         jae     .fail
  1125.         mov     edi, ecx
  1126.         call    get_event_ex
  1127.         mov     [esp+SYSCALL_STACK._eax], eax
  1128.         ret
  1129. .16:
  1130.         test    ecx, ecx
  1131.         jz      .fail
  1132.         cmp     ecx, OS_BASE
  1133.         jae     .fail
  1134.         stdcall get_service, ecx
  1135.         mov     [esp+SYSCALL_STACK._eax], eax
  1136.         ret
  1137. .17:
  1138.         call    srv_handlerEx   ;ecx
  1139.         mov     [esp+SYSCALL_STACK._eax], eax
  1140.         ret
  1141. .18:
  1142.         mov     eax, edx
  1143. .19:
  1144.         cmp     ecx, OS_BASE
  1145.         jae     .fail
  1146.         stdcall load_library, ecx, eax
  1147.         mov     [esp+SYSCALL_STACK._eax], eax
  1148.         ret
  1149. .20:
  1150.         mov     eax, edx
  1151.         mov     ebx, ecx
  1152.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1153.         mov     [esp+SYSCALL_STACK._eax], eax
  1154.         ret
  1155. .21:
  1156.         cmp     ecx, OS_BASE
  1157.         jae     .fail
  1158.         cmp     edx, OS_BASE
  1159.         jae     .fail
  1160.         stdcall load_pe_driver, ecx, edx
  1161.         mov     [esp+SYSCALL_STACK._eax], eax
  1162.         ret
  1163. .22:
  1164.         cmp     ecx, OS_BASE
  1165.         jae     .fail
  1166.         stdcall shmem_open, ecx, edx, esi
  1167.         mov     [esp+SYSCALL_STACK._edx], edx
  1168.         mov     [esp+SYSCALL_STACK._eax], eax
  1169.         ret
  1170. .23:
  1171.         cmp     ecx, OS_BASE
  1172.         jae     .fail
  1173.         stdcall shmem_close, ecx
  1174.         mov     [esp+SYSCALL_STACK._eax], eax
  1175.         ret
  1176. .24:
  1177.         mov     eax, [current_slot]
  1178.         xchg    ecx, [eax+APPDATA.exc_handler]
  1179.         xchg    edx, [eax+APPDATA.except_mask]
  1180.         mov     [esp+SYSCALL_STACK._ebx], edx
  1181.         mov     [esp+SYSCALL_STACK._eax], ecx
  1182.         ret
  1183. .25:
  1184.         cmp     ecx, 32
  1185.         jae     .fail
  1186.         mov     eax, [current_slot]
  1187.         btr     [eax+APPDATA.except_mask], ecx
  1188.         setc    byte[esp+SYSCALL_STACK._eax]
  1189.         jecxz   @f
  1190.         bts     [eax+APPDATA.except_mask], ecx
  1191. @@:
  1192.         ret
  1193. .26:
  1194.         stdcall user_unmap, ecx, edx, esi
  1195.         mov     [esp+SYSCALL_STACK._eax], eax
  1196.         ret
  1197. .27:
  1198.         cmp     ecx, OS_BASE
  1199.         jae     .fail
  1200.         stdcall load_file_umode, ecx
  1201.         mov     [esp+SYSCALL_STACK._edx], edx
  1202.         mov     [esp+SYSCALL_STACK._eax], eax
  1203.         ret
  1204. .28:
  1205.         cmp     ecx, OS_BASE
  1206.         jae     .fail
  1207.         push    ecx edx
  1208.         stdcall kernel_alloc, maxPathLength
  1209.         mov     edi, eax
  1210.         pop     eax esi
  1211.         push    edi
  1212.         call    getFullPath
  1213.         pop     ebp
  1214.         test    eax, eax
  1215.         jz      @f
  1216.         stdcall load_file_umode, ebp
  1217.         mov     [esp+SYSCALL_STACK._edx], edx
  1218. @@:
  1219.         mov     [esp+SYSCALL_STACK._eax], eax
  1220.         stdcall kernel_free, ebp
  1221.         ret
  1222.  
  1223. .29:
  1224.         stdcall user_ring, ecx
  1225.         mov     [esp+SYSCALL_STACK._eax], eax
  1226.         ret
  1227.  
  1228. .fail:
  1229.         mov     [esp+SYSCALL_STACK._eax], eax
  1230.         ret
  1231.  
  1232. align 4
  1233. f68call:   ; keep this table closer to main code
  1234.  
  1235.            dd f68.11   ; init_heap
  1236.            dd f68.12   ; user_alloc
  1237.            dd f68.13   ; user_free
  1238.            dd f68.14   ; get_event_ex
  1239.            dd f68.fail ; moved to f68.24
  1240.            dd f68.16   ; get_service
  1241.            dd f68.17   ; call_service
  1242.            dd f68.18   ; loadLibUnicode
  1243.            dd f68.19   ; load_dll
  1244.            dd f68.20   ; user_realloc
  1245.            dd f68.21   ; load_driver
  1246.            dd f68.22   ; shmem_open
  1247.            dd f68.23   ; shmem_close
  1248.            dd f68.24   ; set exception handler
  1249.            dd f68.25   ; unmask exception
  1250.            dd f68.26   ; user_unmap
  1251.            dd f68.27   ; load_file_umode
  1252.            dd f68.28   ; loadFileUnicode
  1253.            dd f68.29   ; user_ring
  1254.  
  1255. align 4
  1256. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1257.         push    esi
  1258.  
  1259.         stdcall load_PE, [file]
  1260.         test    eax, eax
  1261.         jz      .fail
  1262.  
  1263.         mov     esi, eax
  1264.         push    [cmdline]
  1265.         push    DRV_ENTRY
  1266.         call    eax
  1267.         pop     ecx
  1268.         pop     ecx
  1269.         test    eax, eax
  1270.         jz      .fail
  1271.  
  1272.         mov     [eax+SRV.entry], esi
  1273.         pop     esi
  1274.         ret
  1275.  
  1276. .fail:
  1277.         xor     eax, eax
  1278.         pop     esi
  1279.         ret
  1280. endp
  1281.  
  1282. align 4
  1283. proc create_ring_buffer stdcall, size:dword, flags:dword
  1284.            locals
  1285.              buf_ptr  dd ?
  1286.            endl
  1287.  
  1288.         mov     eax, [size]
  1289.         test    eax, eax
  1290.         jz      .fail
  1291.  
  1292.         add     eax, eax
  1293.         stdcall alloc_kernel_space, eax
  1294.         test    eax, eax
  1295.         jz      .fail
  1296.  
  1297.         push    ebx
  1298.  
  1299.         mov     [buf_ptr], eax
  1300.  
  1301.         mov     ebx, [size]
  1302.         shr     ebx, 12
  1303.         push    ebx
  1304.  
  1305.         stdcall alloc_pages, ebx
  1306.         pop     ecx
  1307.  
  1308.         test    eax, eax
  1309.         jz      .mm_fail
  1310.  
  1311.         push    edi
  1312.  
  1313.         or      eax, [flags]
  1314.         mov     edi, [buf_ptr]
  1315.         mov     ebx, [buf_ptr]
  1316.         mov     edx, ecx
  1317.         shl     edx, 2
  1318.         shr     edi, 10
  1319. @@:
  1320.         mov     [page_tabs+edi], eax
  1321.         mov     [page_tabs+edi+edx], eax
  1322.         invlpg  [ebx]
  1323.         invlpg  [ebx+0x10000]
  1324.         add     eax, 0x1000
  1325.         add     ebx, 0x1000
  1326.         add     edi, 4
  1327.         dec     ecx
  1328.         jnz     @B
  1329.  
  1330.         mov     eax, [buf_ptr]
  1331.         pop     edi
  1332.         pop     ebx
  1333.         ret
  1334. .mm_fail:
  1335.         stdcall free_kernel_space, [buf_ptr]
  1336.         xor     eax, eax
  1337.         pop     ebx
  1338. .fail:
  1339.         ret
  1340. endp
  1341.  
  1342.  
  1343. align 4
  1344. proc print_mem
  1345.         mov     edi, BOOT.memmap_blocks
  1346.         mov     ecx, [edi-4]
  1347.         test    ecx, ecx
  1348.         jz      .done
  1349.  
  1350. @@:
  1351.         mov     eax, [edi]
  1352.         mov     edx, [edi+4]
  1353.         add     eax, [edi+8]
  1354.         adc     edx, [edi+12]
  1355.  
  1356.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1357.                     [edi+4], [edi],\
  1358.                     edx, eax, [edi+16]
  1359.         add     edi, 20
  1360.         dec     ecx
  1361.         jnz     @b
  1362. .done:
  1363.         ret
  1364. endp
  1365.