Subversion Repositories Kolibri OS

Rev

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

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