Subversion Repositories Kolibri OS

Rev

Rev 4923 | Go to most recent revision | Blame | 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: 4424 $
  9.  
  10.  
  11. align 4
  12. proc alloc_page
  13.  
  14.         pushfd
  15.         cli
  16.         push    ebx
  17. ;//-
  18.         cmp     [pg_data.pages_free], 1
  19.         jle     .out_of_memory
  20. ;//-
  21.  
  22.         mov     ebx, [page_start]
  23.         mov     ecx, [page_end]
  24. .l1:
  25.         bsf     eax, [ebx];
  26.         jnz     .found
  27.         add     ebx, 4
  28.         cmp     ebx, ecx
  29.         jb      .l1
  30.         pop     ebx
  31.         popfd
  32.         xor     eax, eax
  33.         ret
  34. .found:
  35. ;//-
  36.         dec     [pg_data.pages_free]
  37.         jz      .out_of_memory
  38. ;//-
  39.         btr     [ebx], eax
  40.         mov     [page_start], ebx
  41.         sub     ebx, sys_pgmap
  42.         lea     eax, [eax+ebx*8]
  43.         shl     eax, 12
  44. ;//-       dec [pg_data.pages_free]
  45.         pop     ebx
  46.         popfd
  47.         ret
  48. ;//-
  49. .out_of_memory:
  50.         mov     [pg_data.pages_free], 1
  51.         xor     eax, eax
  52.         pop     ebx
  53.         popfd
  54.         ret
  55. ;//-
  56. endp
  57.  
  58. align 4
  59. proc alloc_pages stdcall, count:dword
  60.         pushfd
  61.         push    ebx
  62.         push    edi
  63.         cli
  64.         mov     eax, [count]
  65.         add     eax, 7
  66.         shr     eax, 3
  67.         mov     [count], eax
  68. ;//-
  69.         mov     ebx, [pg_data.pages_free]
  70.         sub     ebx, 9
  71.         js      .out_of_memory
  72.         shr     ebx, 3
  73.         cmp     eax, ebx
  74.         jg      .out_of_memory
  75. ;//-
  76.         mov     ecx, [page_start]
  77.         mov     ebx, [page_end]
  78. .find:
  79.         mov     edx, [count]
  80.         mov     edi, ecx
  81. .match:
  82.         cmp     byte [ecx], 0xFF
  83.         jne     .next
  84.         dec     edx
  85.         jz      .ok
  86.         inc     ecx
  87.         cmp     ecx, ebx
  88.         jb      .match
  89. .out_of_memory:
  90. .fail:
  91.         xor     eax, eax
  92.         pop     edi
  93.         pop     ebx
  94.         popfd
  95.         ret
  96. .next:
  97.         inc     ecx
  98.         cmp     ecx, ebx
  99.         jb      .find
  100.         pop     edi
  101.         pop     ebx
  102.         popfd
  103.         xor     eax, eax
  104.         ret
  105. .ok:
  106.         sub     ecx, edi
  107.         inc     ecx
  108.         push    esi
  109.         mov     esi, edi
  110.         xor     eax, eax
  111.         rep stosb
  112.         sub     esi, sys_pgmap
  113.         shl     esi, 3+12
  114.         mov     eax, esi
  115.         mov     ebx, [count]
  116.         shl     ebx, 3
  117.         sub     [pg_data.pages_free], ebx
  118.         pop     esi
  119.         pop     edi
  120.         pop     ebx
  121.         popfd
  122.         ret
  123. endp
  124.  
  125. align 4
  126. ;proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
  127. map_page:
  128.         push    ebx
  129.         mov     eax, [esp+12]               ; phis_addr
  130.         and     eax, not 0xFFF
  131.         or      eax, [esp+16]              ; flags
  132.         mov     ebx, [esp+8]               ; lin_addr
  133.         shr     ebx, 12
  134.         mov     [page_tabs+ebx*4], eax
  135.         mov     eax, [esp+8]               ; lin_addr
  136.         pop     ebx
  137.         invlpg  [eax]
  138.         ret     12
  139.  
  140. align 4
  141. map_space:    ;not implemented
  142.  
  143.  
  144.         ret
  145.  
  146.  
  147. align 4
  148. proc free_page
  149. ;arg:  eax  page address
  150.         pushfd
  151.         cli
  152.         shr     eax, 12                       ;page index
  153.         bts     dword [sys_pgmap], eax        ;that's all!
  154.         cmc
  155.         adc     [pg_data.pages_free], 0
  156.         shr     eax, 3
  157.         and     eax, not 3                    ;dword offset from page_map
  158.         add     eax, sys_pgmap
  159.         cmp     [page_start], eax
  160.         ja      @f
  161.         popfd
  162.         ret
  163. @@:
  164.         mov     [page_start], eax
  165.         popfd
  166.         ret
  167. endp
  168.  
  169. align 4
  170. proc map_io_mem stdcall, base:dword, size:dword, flags:dword
  171.  
  172.         push    ebx
  173.         push    edi
  174.         mov     eax, [size]
  175.         add     eax, [base]
  176.         add     eax, 4095
  177.         and     eax, -4096
  178.         mov     ecx, [base]
  179.         and     ecx, -4096
  180.         sub     eax, ecx
  181.         mov     [size], eax
  182.  
  183.         stdcall alloc_kernel_space, eax
  184.         test    eax, eax
  185.         jz      .fail
  186.         push    eax
  187.  
  188.         mov     edi, 0x1000
  189.         mov     ebx, eax
  190.         mov     ecx, [size]
  191.         mov     edx, [base]
  192.         shr     eax, 12
  193.         shr     ecx, 12
  194.         and     edx, -4096
  195.         or      edx, [flags]
  196. @@:
  197.         mov     [page_tabs+eax*4], edx
  198.         invlpg  [ebx]
  199.         inc     eax
  200.         add     ebx, edi
  201.         add     edx, edi
  202.         loop    @B
  203.  
  204.         pop     eax
  205.         mov     edx, [base]
  206.         and     edx, 4095
  207.         add     eax, edx
  208. .fail:
  209.         pop     edi
  210.         pop     ebx
  211.         ret
  212. endp
  213.  
  214. ; param
  215. ;  eax= page base + page flags
  216. ;  ebx= linear address
  217. ;  ecx= count
  218.  
  219. align 4
  220. commit_pages:
  221.         test    ecx, ecx
  222.         jz      .fail
  223.  
  224.         push    edi
  225.         push    eax
  226.         push    ecx
  227.         mov     ecx, pg_data.mutex
  228.         call    mutex_lock
  229.         pop     ecx
  230.         pop     eax
  231.  
  232.         mov     edi, ebx
  233.         shr     edi, 12
  234.         lea     edi, [page_tabs+edi*4]
  235. @@:
  236.         stosd
  237.         invlpg  [ebx]
  238.         add     eax, 0x1000
  239.         add     ebx, 0x1000
  240.         loop    @B
  241.  
  242.         pop     edi
  243.  
  244.         mov     ecx, pg_data.mutex
  245.         call    mutex_unlock
  246. .fail:
  247.         ret
  248.  
  249.  
  250. ; param
  251. ;  eax= base
  252. ;  ecx= count
  253.  
  254. align 4
  255. release_pages:
  256.  
  257.         push    ebp
  258.         push    esi
  259.         push    edi
  260.         push    ebx
  261.  
  262.         mov     esi, eax
  263.         mov     edi, eax
  264.  
  265.         shr     esi, 12
  266.         lea     esi, [page_tabs+esi*4]
  267.  
  268.         push    ecx
  269.         mov     ecx, pg_data.mutex
  270.         call    mutex_lock
  271.         pop     ecx
  272.  
  273.         mov     ebp, [pg_data.pages_free]
  274.         mov     ebx, [page_start]
  275.         mov     edx, sys_pgmap
  276. @@:
  277.         xor     eax, eax
  278.         xchg    eax, [esi]
  279.         invlpg  [edi]
  280.  
  281.         test    eax, 1
  282.         jz      .next
  283.  
  284.         shr     eax, 12
  285.         bts     [edx], eax
  286.         cmc
  287.         adc     ebp, 0
  288.         shr     eax, 3
  289.         and     eax, -4
  290.         add     eax, edx
  291.         cmp     eax, ebx
  292.         jae     .next
  293.  
  294.         mov     ebx, eax
  295. .next:
  296.         add     edi, 0x1000
  297.         add     esi, 4
  298.         loop    @B
  299.  
  300.         mov     [pg_data.pages_free], ebp
  301.         mov     ecx, pg_data.mutex
  302.         call    mutex_unlock
  303.  
  304.         pop     ebx
  305.         pop     edi
  306.         pop     esi
  307.         pop     ebp
  308.         ret
  309.  
  310. ; param
  311. ;  eax= base
  312. ;  ecx= count
  313.  
  314. align 4
  315. unmap_pages:
  316.  
  317.         push    edi
  318.  
  319.         mov     edi, eax
  320.         mov     edx, eax
  321.  
  322.         shr     edi, 10
  323.         add     edi, page_tabs
  324.  
  325.         xor     eax, eax
  326. @@:
  327.         stosd
  328.         invlpg  [edx]
  329.         add     edx, 0x1000
  330.         loop    @b
  331.  
  332.         pop     edi
  333.         ret
  334.  
  335.  
  336. align 4
  337. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  338.         push    ebx
  339.         mov     ebx, [lin_addr]
  340.         shr     ebx, 22
  341.         mov     eax, [phis_addr]
  342.         and     eax, not 0xFFF
  343.         or      eax, PG_UW        ;+PG_NOCACHE
  344.         mov     dword [master_tab+ebx*4], eax
  345.         mov     eax, [lin_addr]
  346.         shr     eax, 10
  347.         add     eax, page_tabs
  348.         invlpg  [eax]
  349.         pop     ebx
  350.         ret
  351. endp
  352.  
  353. 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_UW
  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, PG_LARGE+PG_UW
  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_UW
  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_MAP
  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_MAP
  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_UW
  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_UW
  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_MAP
  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_SW
  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_SW
  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_SW
  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     dword [ebp-4], 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_SW
  853.         xor     edx, edx
  854.         jmp     .map
  855.  
  856. .exit:
  857.         pop     eax
  858.         ret
  859. endp
  860.  
  861. proc map_memEx stdcall, lin_addr:dword,slot:dword,\
  862.                         ofs:dword,buf_size:dword,req_access:dword
  863.         push    0 ; initialize number of mapped bytes
  864.  
  865.         cmp     [buf_size], 0
  866.         jz      .exit
  867.  
  868.         mov     eax, [slot]
  869.         shl     eax, 8
  870.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  871.         mov     eax, [eax+PROC.pdt_0_phys]
  872.         and     eax, 0xFFFFF000
  873.  
  874.         stdcall map_page, [proc_mem_pdir], eax, PG_UW
  875.         mov     ebx, [ofs]
  876.         shr     ebx, 22
  877.         mov     esi, [proc_mem_pdir]
  878.         mov     edi, [proc_mem_tab]
  879.         mov     eax, [esi+ebx*4]
  880.         and     eax, 0xFFFFF000
  881.         test    eax, eax
  882.         jz      .exit
  883.         stdcall map_page, edi, eax, PG_UW
  884.  
  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.         mov     esi, [proc_mem_tab]
  897.  
  898. .map:
  899.         stdcall safe_map_page, [slot], [req_access], [ofs]
  900.         jnc     .exit
  901.         add     dword [ebp-4], 0x1000
  902.         add     edi, 0x1000
  903.         add     [ofs], 0x1000
  904.         inc     edx
  905.         dec     ecx
  906.         jnz     .map
  907. .exit:
  908.         pop     eax
  909.         ret
  910. endp
  911.  
  912. ; in: esi+edx*4 = pointer to page table entry
  913. ; in: [slot], [req_access], [ofs] on the stack
  914. ; in: edi = linear address to map
  915. ; out: CF cleared <=> failed
  916. ; destroys: only eax
  917. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  918.         mov     eax, [esi+edx*4]
  919.         test    al, PG_MAP
  920.         jz      .not_present
  921.         test    al, PG_WRITE
  922.         jz      .resolve_readonly
  923. ; normal case: writable page, just map with requested access
  924. .map:
  925.         stdcall map_page, edi, eax, [req_access]
  926.         stc
  927. .fail:
  928.         ret
  929. .not_present:
  930. ; check for alloc-on-demand page
  931.         test    al, 2
  932.         jz      .fail
  933. ; allocate new page, save it to source page table
  934.         push    ecx
  935.         call    alloc_page
  936.         pop     ecx
  937.         test    eax, eax
  938.         jz      .fail
  939.         or      al, PG_UW
  940.         mov     [esi+edx*4], eax
  941.         jmp     .map
  942. .resolve_readonly:
  943. ; readonly page, probably copy-on-write
  944. ; check: readonly request of readonly page is ok
  945.         test    [req_access], PG_WRITE
  946.         jz      .map
  947. ; find control structure for this page
  948.         pushf
  949.         cli
  950.         cld
  951.         push    ebx ecx
  952.         mov     eax, [slot]
  953.         shl     eax, 8
  954.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  955.         mov     eax, [eax+PROC.dlls_list_ptr]
  956.         test    eax, eax
  957.         jz      .no_hdll
  958.         mov     ecx, [eax+HDLL.fd]
  959. .scan_hdll:
  960.         cmp     ecx, eax
  961.         jz      .no_hdll
  962.         mov     ebx, [ofs]
  963.         and     ebx, not 0xFFF
  964.         sub     ebx, [ecx+HDLL.base]
  965.         cmp     ebx, [ecx+HDLL.size]
  966.         jb      .hdll_found
  967.         mov     ecx, [ecx+HDLL.fd]
  968.         jmp     .scan_hdll
  969. .no_hdll:
  970.         pop     ecx ebx
  971.         popf
  972.         clc
  973.         ret
  974. .hdll_found:
  975. ; allocate page, save it in page table, map it, copy contents from base
  976.         mov     eax, [ecx+HDLL.parent]
  977.         add     ebx, [eax+DLLDESCR.data]
  978.         call    alloc_page
  979.         test    eax, eax
  980.         jz      .no_hdll
  981.         or      al, PG_UW
  982.         mov     [esi+edx*4], eax
  983.         stdcall map_page, edi, eax, [req_access]
  984.         push    esi edi
  985.         mov     esi, ebx
  986.         mov     ecx, 4096/4
  987.         rep movsd
  988.         pop     edi esi
  989.         pop     ecx ebx
  990.         popf
  991.         stc
  992.         ret
  993. endp
  994.  
  995. sys_IPC:
  996. ;input:
  997. ;  ebx=1 - set ipc buffer area
  998. ;    ecx=address of buffer
  999. ;    edx=size of buffer
  1000. ;  eax=2 - send message
  1001. ;    ebx=PID
  1002. ;    ecx=address of message
  1003. ;    edx=size of message
  1004.  
  1005.         dec     ebx
  1006.         jnz     @f
  1007.  
  1008.         mov     eax, [current_slot]
  1009.         pushf
  1010.         cli
  1011.         mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
  1012.         mov     [eax+APPDATA.ipc_size], edx
  1013.  
  1014.         add     edx, ecx
  1015.         add     edx, 4095
  1016.         and     edx, not 4095
  1017.  
  1018. .touch:
  1019.         mov     eax, [ecx]
  1020.         add     ecx, 0x1000
  1021.         cmp     ecx, edx
  1022.         jb      .touch
  1023.  
  1024.         popf
  1025.         mov     [esp+32], ebx   ;ebx=0
  1026.         ret
  1027.  
  1028. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1029. ;2
  1030. @@:
  1031.         dec     ebx
  1032.         jnz     @f
  1033.  
  1034.         stdcall sys_ipc_send, ecx, edx, esi
  1035.         mov     [esp+32], eax
  1036.         ret
  1037. @@:
  1038.         or      eax, -1
  1039.         mov     [esp+32], eax
  1040.         ret
  1041.  
  1042. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  1043.            locals
  1044.              dst_slot   dd ?
  1045.              dst_offset dd ?
  1046.              buf_size   dd ?
  1047.              used_buf   dd ?
  1048.            endl
  1049.  
  1050.         pushf
  1051.         cli
  1052.  
  1053.         mov     eax, [PID]
  1054.         call    pid_to_slot
  1055.         test    eax, eax
  1056.         jz      .no_pid
  1057.  
  1058.         mov     [dst_slot], eax
  1059.         shl     eax, 8
  1060.         mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
  1061.         test    edi, edi
  1062.         jz      .no_ipc_area
  1063.  
  1064.         mov     ebx, edi
  1065.         and     ebx, 0xFFF
  1066.         mov     [dst_offset], ebx
  1067.  
  1068.         mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
  1069.         mov     [buf_size], esi
  1070.  
  1071.         mov     ecx, [ipc_tmp]
  1072.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  1073.         jbe     @f
  1074.         push    esi edi
  1075.         add     esi, 0x1000
  1076.         stdcall alloc_kernel_space, esi
  1077.         mov     ecx, eax
  1078.         pop     edi esi
  1079. @@:
  1080.         mov     [used_buf], ecx
  1081.         stdcall map_mem_ipc, ecx, [dst_slot], \
  1082.                 edi, esi, PG_SW
  1083.  
  1084.         mov     edi, [dst_offset]
  1085.         add     edi, [used_buf]
  1086.         cmp     dword [edi], 0
  1087.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1088.  
  1089.         mov     edx, dword [edi+4]
  1090.         lea     ebx, [edx+8]
  1091.         add     ebx, [msg_size]
  1092.         cmp     ebx, [buf_size]
  1093.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1094.  
  1095.         mov     dword [edi+4], ebx
  1096.         mov     eax, [TASK_BASE]
  1097.         mov     eax, [eax+0x04]        ;eax - our PID
  1098.         add     edi, edx
  1099.         mov     [edi], eax
  1100.         mov     ecx, [msg_size]
  1101.  
  1102.         mov     [edi+4], ecx
  1103.         add     edi, 8
  1104.         mov     esi, [msg_addr]
  1105.        ;    add esi, new_app_base
  1106.         cld
  1107.         rep movsb
  1108.  
  1109.         mov     ebx, [ipc_tmp]
  1110.         mov     edx, ebx
  1111.         shr     ebx, 12
  1112.         xor     eax, eax
  1113.         mov     [page_tabs+ebx*4], eax
  1114.         invlpg  [edx]
  1115.  
  1116.         mov     ebx, [ipc_pdir]
  1117.         mov     edx, ebx
  1118.         shr     ebx, 12
  1119.         xor     eax, eax
  1120.         mov     [page_tabs+ebx*4], eax
  1121.         invlpg  [edx]
  1122.  
  1123.         mov     ebx, [ipc_ptab]
  1124.         mov     edx, ebx
  1125.         shr     ebx, 12
  1126.         xor     eax, eax
  1127.         mov     [page_tabs+ebx*4], eax
  1128.         invlpg  [edx]
  1129.  
  1130.         mov     eax, [dst_slot]
  1131.         shl     eax, 8
  1132.         or      [eax+SLOT_BASE+0xA8], dword 0x40
  1133.         push    0
  1134.         jmp     .ret
  1135. .no_pid:
  1136.         popf
  1137.         mov     eax, 4
  1138.         ret
  1139. .no_ipc_area:
  1140.         popf
  1141.         xor     eax, eax
  1142.         inc     eax
  1143.         ret
  1144. .ipc_blocked:
  1145.         push    2
  1146.         jmp     .ret
  1147. .buffer_overflow:
  1148.         push    3
  1149. .ret:
  1150.         mov     eax, [used_buf]
  1151.         cmp     eax, [ipc_tmp]
  1152.         je      @f
  1153.         stdcall free_kernel_space, eax
  1154. @@:
  1155.         pop     eax
  1156.         popf
  1157.         ret
  1158. endp
  1159.  
  1160. align 4
  1161. sysfn_meminfo:
  1162.  
  1163.         ;   add ecx, new_app_base
  1164.         cmp     ecx, OS_BASE
  1165.         jae     .fail
  1166.  
  1167.         mov     eax, [pg_data.pages_count]
  1168.         mov     [ecx], eax
  1169.         shl     eax, 12
  1170.         mov     [esp+32], eax
  1171.         mov     eax, [pg_data.pages_free]
  1172.         mov     [ecx+4], eax
  1173.         mov     eax, [pg_data.pages_faults]
  1174.         mov     [ecx+8], eax
  1175.         mov     eax, [heap_size]
  1176.         mov     [ecx+12], eax
  1177.         mov     eax, [heap_free]
  1178.         mov     [ecx+16], eax
  1179.         mov     eax, [heap_blocks]
  1180.         mov     [ecx+20], eax
  1181.         mov     eax, [free_blocks]
  1182.         mov     [ecx+24], eax
  1183.         ret
  1184. .fail:
  1185.         or      dword [esp+32], -1
  1186.         ret
  1187.  
  1188. align 4
  1189. f68:
  1190.         cmp     ebx, 4
  1191.         jbe     sys_sheduler
  1192.  
  1193.         cmp     ebx, 11
  1194.         jb      .fail
  1195.  
  1196.         cmp     ebx, 27
  1197.         ja      .fail
  1198.  
  1199.         jmp     dword [f68call+ebx*4-11*4]
  1200. .11:
  1201.         call    init_heap
  1202.         mov     [esp+32], eax
  1203.         ret
  1204. .12:
  1205.         stdcall user_alloc, ecx
  1206.         mov     [esp+32], eax
  1207.         ret
  1208. .13:
  1209.         stdcall user_free, ecx
  1210.         mov     [esp+32], eax
  1211.         ret
  1212. .14:
  1213.         cmp     ecx, OS_BASE
  1214.         jae     .fail
  1215.         mov     edi, ecx
  1216.         call    get_event_ex
  1217.         mov     [esp+32], eax
  1218.         ret
  1219. .16:
  1220.         test    ecx, ecx
  1221.         jz      .fail
  1222.         cmp     ecx, OS_BASE
  1223.         jae     .fail
  1224.         stdcall get_service, ecx
  1225.         mov     [esp+32], eax
  1226.         ret
  1227. .17:
  1228.         call    srv_handlerEx   ;ecx
  1229.         mov     [esp+32], eax
  1230.         ret
  1231. .19:
  1232.         cmp     ecx, OS_BASE
  1233.         jae     .fail
  1234.         stdcall load_library, ecx
  1235.         mov     [esp+32], eax
  1236.         ret
  1237. .20:
  1238.         mov     eax, edx
  1239.         mov     ebx, ecx
  1240.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1241.         mov     [esp+32], eax
  1242.         ret
  1243. .21:
  1244.         cmp     ecx, OS_BASE
  1245.         jae     .fail
  1246.  
  1247.         cmp     edx, OS_BASE
  1248.         jae     .fail
  1249.  
  1250.         stdcall load_pe_driver, ecx, edx
  1251.         mov     [esp+32], eax
  1252.         ret
  1253. .22:
  1254.         cmp     ecx, OS_BASE
  1255.         jae     .fail
  1256.  
  1257.         stdcall shmem_open, ecx, edx, esi
  1258.         mov     [esp+24], edx
  1259.         mov     [esp+32], eax
  1260.         ret
  1261.  
  1262. .23:
  1263.         cmp     ecx, OS_BASE
  1264.         jae     .fail
  1265.  
  1266.         stdcall shmem_close, ecx
  1267.         mov     [esp+32], eax
  1268.         ret
  1269. .24:
  1270.         mov     eax, [current_slot]
  1271.         xchg    ecx, [eax+APPDATA.exc_handler]
  1272.         xchg    edx, [eax+APPDATA.except_mask]
  1273.         mov     [esp+32], ecx ; reg_eax+8
  1274.         mov     [esp+20], edx ; reg_ebx+8
  1275.         ret
  1276. .25:
  1277.         cmp     ecx, 32
  1278.         jae     .fail
  1279.         mov     eax, [current_slot]
  1280.         btr     [eax+APPDATA.except_mask], ecx
  1281.         setc    byte[esp+32]
  1282.         jecxz   @f
  1283.         bts     [eax+APPDATA.except_mask], ecx
  1284. @@:
  1285.         ret
  1286.  
  1287. .26:
  1288.         stdcall user_unmap, ecx, edx, esi
  1289.         mov     [esp+32], eax
  1290.         ret
  1291.  
  1292. .27:
  1293.         cmp     ecx, OS_BASE
  1294.         jae     .fail
  1295.  
  1296.         stdcall load_file_umode, ecx
  1297.         mov     [esp+24], edx
  1298.         mov     [esp+32], eax
  1299.         ret
  1300.  
  1301. .fail:
  1302.         xor     eax, eax
  1303.         mov     [esp+32], eax
  1304.         ret
  1305.  
  1306.  
  1307. align 4
  1308. f68call:   ; keep this table closer to main code
  1309.  
  1310.            dd f68.11   ; init_heap
  1311.            dd f68.12   ; user_alloc
  1312.            dd f68.13   ; user_free
  1313.            dd f68.14   ; get_event_ex
  1314.            dd f68.fail ; moved to f68.24
  1315.            dd f68.16   ; get_service
  1316.            dd f68.17   ; call_service
  1317.            dd f68.fail ; moved to f68.25
  1318.            dd f68.19   ; load_dll
  1319.            dd f68.20   ; user_realloc
  1320.            dd f68.21   ; load_driver
  1321.            dd f68.22   ; shmem_open
  1322.            dd f68.23   ; shmem_close
  1323.            dd f68.24   ; set exception handler
  1324.            dd f68.25   ; unmask exception
  1325.            dd f68.26   ; user_unmap
  1326.            dd f68.27   ; load_file_umode
  1327.  
  1328.  
  1329. align 4
  1330. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1331.         push    esi
  1332.  
  1333.         stdcall load_PE, [file]
  1334.         test    eax, eax
  1335.         jz      .fail
  1336.  
  1337.         mov     esi, eax
  1338.         push    [cmdline]
  1339.         push    DRV_ENTRY
  1340.         call    eax
  1341.         pop     ecx
  1342.         pop     ecx
  1343.         test    eax, eax
  1344.         jz      .fail
  1345.  
  1346.         mov     [eax+SRV.entry], esi
  1347.         pop     esi
  1348.         ret
  1349.  
  1350. .fail:
  1351.         xor     eax, eax
  1352.         pop     esi
  1353.         ret
  1354. endp
  1355.  
  1356. align 4
  1357. proc create_ring_buffer stdcall, size:dword, flags:dword
  1358.            locals
  1359.              buf_ptr  dd ?
  1360.            endl
  1361.  
  1362.         mov     eax, [size]
  1363.         test    eax, eax
  1364.         jz      .fail
  1365.  
  1366.         add     eax, eax
  1367.         stdcall alloc_kernel_space, eax
  1368.         test    eax, eax
  1369.         jz      .fail
  1370.  
  1371.         push    ebx
  1372.  
  1373.         mov     [buf_ptr], eax
  1374.  
  1375.         mov     ebx, [size]
  1376.         shr     ebx, 12
  1377.         push    ebx
  1378.  
  1379.         stdcall alloc_pages, ebx
  1380.         pop     ecx
  1381.  
  1382.         test    eax, eax
  1383.         jz      .mm_fail
  1384.  
  1385.         push    edi
  1386.  
  1387.         or      eax, [flags]
  1388.         mov     edi, [buf_ptr]
  1389.         mov     ebx, [buf_ptr]
  1390.         mov     edx, ecx
  1391.         shl     edx, 2
  1392.         shr     edi, 10
  1393. @@:
  1394.         mov     [page_tabs+edi], eax
  1395.         mov     [page_tabs+edi+edx], eax
  1396.         invlpg  [ebx]
  1397.         invlpg  [ebx+0x10000]
  1398.         add     eax, 0x1000
  1399.         add     ebx, 0x1000
  1400.         add     edi, 4
  1401.         dec     ecx
  1402.         jnz     @B
  1403.  
  1404.         mov     eax, [buf_ptr]
  1405.         pop     edi
  1406.         pop     ebx
  1407.         ret
  1408. .mm_fail:
  1409.         stdcall free_kernel_space, [buf_ptr]
  1410.         xor     eax, eax
  1411.         pop     ebx
  1412. .fail:
  1413.         ret
  1414. endp
  1415.  
  1416.  
  1417. align 4
  1418. proc print_mem
  1419.         mov     edi, BOOT_VAR + 0x9104
  1420.         mov     ecx, [edi-4]
  1421.         test    ecx, ecx
  1422.         jz      .done
  1423.  
  1424. @@:
  1425.         mov     eax, [edi]
  1426.         mov     edx, [edi+4]
  1427.         add     eax, [edi+8]
  1428.         adc     edx, [edi+12]
  1429.  
  1430.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1431.                     [edi+4], [edi],\
  1432.                     edx, eax, [edi+16]
  1433.         add     edi, 20
  1434.         dec     ecx
  1435.         jnz     @b
  1436. .done:
  1437.         ret
  1438. endp
  1439.