Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 5596 $
  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 init_LFB
  409.            locals
  410.              pg_count dd ?
  411.            endl
  412.  
  413.         cmp     dword [LFBAddress], -1
  414.         jne     @f
  415.         mov     [BOOT_VARS+BOOT_MTRR], byte 2
  416. ; max VGA=640*480*4=1228800 bytes
  417. ; + 32*640*4=81920 bytes for mouse pointer
  418.         stdcall alloc_pages, ((1228800+81920)/4096)
  419.  
  420.         push    eax
  421.         call    alloc_page
  422.         stdcall map_page_table, LFB_BASE, eax
  423.         pop     eax
  424.         or      eax, PG_UWR
  425.         mov     ebx, LFB_BASE
  426. ; max VGA=640*480*4=1228800 bytes
  427. ; + 32*640*4=81920 bytes for mouse pointer
  428.         mov     ecx, (1228800+81920)/4096
  429.         call    commit_pages
  430.         mov     [LFBAddress], dword LFB_BASE
  431.         ret
  432. @@:
  433.         test    [SCR_MODE], word 0100000000000000b
  434.         jnz     @f
  435.         mov     [BOOT_VARS+BOOT_MTRR], byte 2
  436.         ret
  437. @@:
  438.         call    init_mtrr
  439.  
  440.         mov     edx, LFB_BASE
  441.         mov     esi, [LFBAddress]
  442.         mov     edi, 0x00C00000
  443.         mov     dword [exp_lfb+4], edx
  444.  
  445.         shr     edi, 12
  446.         mov     [pg_count], edi
  447.         shr     edi, 10
  448.  
  449.         bt      [cpu_caps], CAPS_PSE
  450.         jnc     .map_page_tables
  451.         or      esi, PDE_LARGE+PG_UWR
  452.         mov     edx, sys_proc+PROC.pdt_0+(LFB_BASE shr 20)
  453. @@:
  454.         mov     [edx], esi
  455.         add     edx, 4
  456.         add     esi, 0x00400000
  457.         dec     edi
  458.         jnz     @B
  459.  
  460.         bt      [cpu_caps], CAPS_PGE
  461.         jnc     @F
  462.         or      dword [sys_proc+PROC.pdt_0+(LFB_BASE shr 20)], PG_GLOBAL
  463. @@:
  464.         mov     dword [LFBAddress], LFB_BASE
  465.         mov     eax, cr3      ;flush TLB
  466.         mov     cr3, eax
  467.         ret
  468.  
  469. .map_page_tables:
  470.  
  471. @@:
  472.         call    alloc_page
  473.         stdcall map_page_table, edx, eax
  474.         add     edx, 0x00400000
  475.         dec     edi
  476.         jnz     @B
  477.  
  478.         mov     eax, [LFBAddress]
  479.         mov     edi, page_tabs + (LFB_BASE shr 10)
  480.         or      eax, PG_GLOBAL+PG_UWR
  481.         and     eax, [pte_valid_mask]
  482.         mov     ecx, [pg_count]
  483.         cld
  484. @@:
  485.         stosd
  486.         add     eax, 0x1000
  487.         loop    @B
  488.  
  489.         mov     dword [LFBAddress], LFB_BASE
  490.         mov     eax, cr3      ;flush TLB
  491.         mov     cr3, eax
  492.  
  493.         ret
  494. endp
  495.  
  496. align 4
  497. proc new_mem_resize stdcall, new_size:dword
  498.  
  499.         push    ebx
  500.         push    esi
  501.         push    edi
  502.  
  503.         mov     edx, [current_slot]
  504.         mov     ebx, [edx+APPDATA.process]
  505.  
  506.         cmp     [ebx+PROC.heap_base], 0
  507.         jne     .exit
  508.  
  509.         mov     edi, [new_size]
  510.         add     edi, 4095
  511.         and     edi, not 4095
  512.         mov     [new_size], edi
  513.  
  514.         mov     esi, [ebx+PROC.mem_used]
  515.         add     esi, 4095
  516.         and     esi, not 4095
  517.  
  518.         cmp     edi, esi
  519.         ja      .expand
  520.         je      .exit
  521.  
  522.         mov     ebx, edi
  523.         shr     edi, 12
  524.         shr     esi, 12
  525.  
  526.         mov     ecx, pg_data.mutex
  527.         call    mutex_lock
  528. @@:
  529.         mov     eax, [app_page_tabs+edi*4]
  530.         test    eax, 1
  531.         jz      .next
  532.  
  533.         mov     dword [app_page_tabs+edi*4], 0
  534.         invlpg  [ebx]
  535.         call    free_page
  536.  
  537. .next:
  538.         inc     edi
  539.         add     ebx, 0x1000
  540.         cmp     edi, esi
  541.         jb      @B
  542.  
  543.         mov     ecx, pg_data.mutex
  544.         call    mutex_unlock
  545.  
  546. .update_size:
  547.         mov     edx, [current_slot]
  548.         mov     ebx, [new_size]
  549.         mov     edx, [edx+APPDATA.process]
  550.         mov     [edx+PROC.mem_used], ebx
  551. .exit:
  552.         pop     edi
  553.         pop     esi
  554.         pop     ebx
  555.         xor     eax, eax
  556.         ret
  557.  
  558. .expand:
  559.  
  560.         mov     ecx, pg_data.mutex
  561.         call    mutex_lock
  562.  
  563.         xchg    esi, edi
  564.  
  565.         push    esi                   ;new size
  566.         push    edi                   ;old size
  567.  
  568.         add     edi, 0x3FFFFF
  569.         and     edi, not(0x3FFFFF)
  570.         add     esi, 0x3FFFFF
  571.         and     esi, not(0x3FFFFF)
  572.  
  573.         cmp     edi, esi
  574.         jae     .grow
  575.  @@:
  576.         call    alloc_page
  577.         test    eax, eax
  578.         jz      .exit_fail
  579.  
  580.         stdcall map_page_table, edi, eax
  581.  
  582.         push    edi
  583.         shr     edi, 10
  584.         add     edi, page_tabs
  585.         mov     ecx, 1024
  586.         xor     eax, eax
  587.         cld
  588.         rep stosd
  589.         pop     edi
  590.  
  591.         add     edi, 0x00400000
  592.         cmp     edi, esi
  593.         jb      @B
  594. .grow:
  595.         pop     edi                   ;old size
  596.         pop     ecx                   ;new size
  597.  
  598.         shr     edi, 10
  599.         shr     ecx, 10
  600.         sub     ecx, edi
  601.         shr     ecx, 2                ;pages count
  602.         mov     eax, 2
  603.  
  604.         add     edi, app_page_tabs
  605.         rep stosd
  606.  
  607.         mov     ecx, pg_data.mutex
  608.         call    mutex_unlock
  609.  
  610.         jmp     .update_size
  611.  
  612. .exit_fail:
  613.         mov     ecx, pg_data.mutex
  614.         call    mutex_unlock
  615.  
  616.         add     esp, 8
  617.         pop     edi
  618.         pop     esi
  619.         pop     ebx
  620.         xor     eax, eax
  621.         inc     eax
  622.         ret
  623. endp
  624.  
  625.  
  626. ; param
  627. ;  eax= linear address
  628. ;
  629. ; retval
  630. ;  eax= phisical page address
  631.  
  632. align 4
  633. get_pg_addr:
  634.         sub     eax, OS_BASE
  635.         cmp     eax, 0x400000
  636.         jb      @f
  637.         shr     eax, 12
  638.         mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
  639. @@:
  640.         and     eax, 0xFFFFF000
  641.         ret
  642.  
  643.  
  644. align 4
  645. ; Now it is called from core/sys32::exc_c (see stack frame there)
  646. proc page_fault_handler
  647.  
  648.     .err_addr   equ ebp-4
  649.  
  650.         push    ebx               ;save exception number (#PF)
  651.         mov     ebp, esp
  652.         mov     ebx, cr2
  653.         push    ebx               ;that is locals: .err_addr = cr2
  654.         inc     [pg_data.pages_faults]
  655.  
  656.         mov     eax, [pf_err_code]
  657.  
  658.         cmp     ebx, OS_BASE      ;ebx == .err_addr
  659.         jb      .user_space       ;страница в памяти приложения ;
  660.  
  661.         cmp     ebx, page_tabs
  662.         jb      .kernel_space     ;страница в памяти ядра
  663.  
  664.         cmp     ebx, kernel_tabs
  665.         jb      .alloc;.app_tabs  ;таблицы страниц приложения ;
  666.                                   ;просто создадим одну
  667. if 0 ;пока это просто лишнее
  668.         cmp     ebx, LFB_BASE
  669.         jb      .core_tabs        ;таблицы страниц ядра
  670.                                   ;Ошибка
  671.   .lfb:
  672.                                   ;область LFB
  673.                                   ;Ошибка
  674.         jmp     .fail
  675. end if
  676. .core_tabs:
  677. .fail:  ;simply return to caller
  678.         mov     esp, ebp
  679.         pop     ebx               ;restore exception number (#PF)
  680.         ret
  681.  
  682. .user_space:
  683.         test    eax, PG_READ
  684.         jnz     .err_access       ;Страница присутствует
  685.                                   ;Ошибка доступа ?
  686.  
  687.         shr     ebx, 12
  688.         mov     ecx, ebx
  689.         shr     ecx, 10
  690.         mov     edx, [master_tab+ecx*4]
  691.         test    edx, PG_READ
  692.         jz      .fail             ;таблица страниц не создана
  693.                                   ;неверный адрес в программе
  694.  
  695.         mov     eax, [page_tabs+ebx*4]
  696.         test    eax, 2
  697.         jz      .fail             ;адрес не зарезервирован для ;
  698.                                   ;использования. Ошибка
  699. .alloc:
  700.         call    alloc_page
  701.         test    eax, eax
  702.         jz      .fail
  703.  
  704.         stdcall map_page, [.err_addr], eax, PG_UWR
  705.  
  706.         mov     edi, [.err_addr]
  707.         and     edi, 0xFFFFF000
  708.         mov     ecx, 1024
  709.         xor     eax, eax
  710.        ;cld     ;caller is duty for this
  711.         rep stosd
  712. .exit:  ;iret with repeat fault instruction
  713.         add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  714.         restore_ring3_context
  715.         iretd
  716.  
  717. .err_access:
  718. ; access denied? this may be a result of copy-on-write protection for DLL
  719. ; check list of HDLLs
  720.         and     ebx, not 0xFFF
  721.         mov     eax, [current_process]
  722.         mov     eax, [eax+PROC.dlls_list_ptr]
  723.         test    eax, eax
  724.         jz      .fail
  725.         mov     esi, [eax+HDLL.fd]
  726. .scan_hdll:
  727.         cmp     esi, eax
  728.         jz      .fail
  729.         mov     edx, ebx
  730.         sub     edx, [esi+HDLL.base]
  731.         cmp     edx, [esi+HDLL.size]
  732.         jb      .fault_in_hdll
  733. .scan_hdll.next:
  734.         mov     esi, [esi+HDLL.fd]
  735.         jmp     .scan_hdll
  736. .fault_in_hdll:
  737. ; allocate new page, map it as rw and copy data
  738.         call    alloc_page
  739.         test    eax, eax
  740.         jz      .fail
  741.         stdcall map_page, ebx, eax, PG_UWR
  742.         mov     edi, ebx
  743.         mov     ecx, 1024
  744.         sub     ebx, [esi+HDLL.base]
  745.         mov     esi, [esi+HDLL.parent]
  746.         mov     esi, [esi+DLLDESCR.data]
  747.         add     esi, ebx
  748.         rep movsd
  749.         jmp     .exit
  750.  
  751. .kernel_space:
  752.         test    eax, PG_READ
  753.         jz      .fail   ;страница не присутствует
  754.  
  755.         test    eax, 12 ;U/S (+below)
  756.         jnz     .fail   ;приложение обратилось к памяти
  757.                         ;ядра
  758.        ;test    eax, 8
  759.        ;jnz     .fail   ;установлен зарезервированный бит
  760.                         ;в таблицах страниц. добавлено в P4/Xeon
  761.  
  762. ;попытка записи в защищённую страницу ядра
  763.  
  764.         cmp     ebx, tss._io_map_0
  765.         jb      .fail
  766.  
  767.         cmp     ebx, tss._io_map_0+8192
  768.         jae     .fail
  769.  
  770. ; io permission map
  771. ; copy-on-write protection
  772.  
  773.         call    alloc_page
  774.         test    eax, eax
  775.         jz      .fail
  776.  
  777.         push    eax
  778.         stdcall map_page, [.err_addr], eax, dword PG_SWR
  779.         pop     eax
  780.         mov     edi, [.err_addr]
  781.         and     edi, -4096
  782.         lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
  783.  
  784.         mov     ebx, esi
  785.         shr     ebx, 12
  786.         mov     edx, [current_slot]
  787.         or      eax, PG_SWR
  788.         mov     [edx+APPDATA.io_map+ebx*4], eax
  789.  
  790.         add     esi, [default_io_map]
  791.         mov     ecx, 4096/4
  792.        ;cld     ;caller is duty for this
  793.         rep movsd
  794.         jmp     .exit
  795. endp
  796.  
  797. ; returns number of mapped bytes
  798. proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
  799.                       ofs:dword,buf_size:dword,req_access:dword
  800.         locals
  801.              count   dd ?
  802.              process dd ?
  803.         endl
  804.  
  805.         mov     [count], 0
  806.         cmp     [buf_size], 0
  807.         jz      .exit
  808.  
  809.         mov     eax, [slot]
  810.         shl     eax, 8
  811.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  812.         test    eax, eax
  813.         jz      .exit
  814.  
  815.         mov     [process], eax
  816.         mov     ebx, [ofs]
  817.         shr     ebx, 22
  818.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  819.         mov     esi, [ipc_ptab]
  820.         and     eax, 0xFFFFF000
  821.         jz      .exit
  822.         stdcall map_page, esi, eax, PG_SWR
  823. @@:
  824.         mov     edi, [lin_addr]
  825.         and     edi, 0xFFFFF000
  826.         mov     ecx, [buf_size]
  827.         add     ecx, 4095
  828.         shr     ecx, 12
  829.         inc     ecx                  ; ???????????
  830.  
  831.         mov     edx, [ofs]
  832.         shr     edx, 12
  833.         and     edx, 0x3FF
  834. .map:
  835.         stdcall safe_map_page, [slot], [req_access], [ofs]
  836.         jnc     .exit
  837.         add     [count], PAGE_SIZE
  838.         add     [ofs], PAGE_SIZE
  839.         dec     ecx
  840.         jz      .exit
  841.  
  842.         add     edi, PAGE_SIZE
  843.         inc     edx
  844.         cmp     edx, 1024
  845.         jnz     .map
  846.  
  847.         inc     ebx
  848.         mov     eax, [process]
  849.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  850.         and     eax, 0xFFFFF000
  851.         jz      .exit
  852.  
  853.         stdcall map_page, esi, eax, PG_SWR
  854.         xor     edx, edx
  855.         jmp     .map
  856. .exit:
  857.         mov     eax, [count]
  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.         locals
  864.              count   dd ?
  865.              process dd ?
  866.         endl
  867.  
  868.         mov     [count], 0
  869.         cmp     [buf_size], 0
  870.         jz      .exit
  871.  
  872.         mov     eax, [slot]
  873.         shl     eax, 8
  874.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  875.         test    eax, eax
  876.         jz      .exit
  877.  
  878.         mov     [process], eax
  879.         mov     ebx, [ofs]
  880.         shr     ebx, 22
  881.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  882.         mov     esi, [proc_mem_tab]
  883.         and     eax, 0xFFFFF000
  884.         jz      .exit
  885.         stdcall map_page, esi, eax, PG_SWR
  886. @@:
  887.         mov     edi, [lin_addr]
  888.         and     edi, 0xFFFFF000
  889.         mov     ecx, [buf_size]
  890.         add     ecx, 4095
  891.         shr     ecx, 12
  892.         inc     ecx                  ; ???????????
  893.  
  894.         mov     edx, [ofs]
  895.         shr     edx, 12
  896.         and     edx, 0x3FF
  897. .map:
  898.         stdcall safe_map_page, [slot], [req_access], [ofs]
  899.         jnc     .exit
  900.         add     [count], PAGE_SIZE
  901.         add     [ofs], PAGE_SIZE
  902.         dec     ecx
  903.         jz      .exit
  904.  
  905.         add     edi, PAGE_SIZE
  906.         inc     edx
  907.         cmp     edx, 1024
  908.         jnz     .map
  909.  
  910.         inc     ebx
  911.         mov     eax, [process]
  912.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  913.         and     eax, 0xFFFFF000
  914.         jz      .exit
  915.  
  916.         stdcall map_page, esi, eax, PG_SWR
  917.         xor     edx, edx
  918.         jmp     .map
  919. .exit:
  920.         mov     eax, [count]
  921.         ret
  922. endp
  923.  
  924. ; in: esi+edx*4 = pointer to page table entry
  925. ; in: [slot], [req_access], [ofs] on the stack
  926. ; in: edi = linear address to map
  927. ; out: CF cleared <=> failed
  928. ; destroys: only eax
  929. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  930.         mov     eax, [esi+edx*4]
  931.         test    al, PG_READ
  932.         jz      .not_present
  933.         test    al, PG_WRITE
  934.         jz      .resolve_readonly
  935. ; normal case: writable page, just map with requested access
  936. .map:
  937.         stdcall map_page, edi, eax, [req_access]
  938.         stc
  939. .fail:
  940.         ret
  941. .not_present:
  942. ; check for alloc-on-demand page
  943.         test    al, 2
  944.         jz      .fail
  945. ; allocate new page, save it to source page table
  946.         push    ecx
  947.         call    alloc_page
  948.         pop     ecx
  949.         test    eax, eax
  950.         jz      .fail
  951.         or      al, PG_UWR
  952.         mov     [esi+edx*4], eax
  953.         jmp     .map
  954. .resolve_readonly:
  955. ; readonly page, probably copy-on-write
  956. ; check: readonly request of readonly page is ok
  957.         test    [req_access], PG_WRITE
  958.         jz      .map
  959. ; find control structure for this page
  960.         pushf
  961.         cli
  962.         cld
  963.         push    ebx ecx
  964.         mov     eax, [slot]
  965.         shl     eax, 8
  966.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  967.         mov     eax, [eax+PROC.dlls_list_ptr]
  968.         test    eax, eax
  969.         jz      .no_hdll
  970.         mov     ecx, [eax+HDLL.fd]
  971. .scan_hdll:
  972.         cmp     ecx, eax
  973.         jz      .no_hdll
  974.         mov     ebx, [ofs]
  975.         and     ebx, not 0xFFF
  976.         sub     ebx, [ecx+HDLL.base]
  977.         cmp     ebx, [ecx+HDLL.size]
  978.         jb      .hdll_found
  979.         mov     ecx, [ecx+HDLL.fd]
  980.         jmp     .scan_hdll
  981. .no_hdll:
  982.         pop     ecx ebx
  983.         popf
  984.         clc
  985.         ret
  986. .hdll_found:
  987. ; allocate page, save it in page table, map it, copy contents from base
  988.         mov     eax, [ecx+HDLL.parent]
  989.         add     ebx, [eax+DLLDESCR.data]
  990.         call    alloc_page
  991.         test    eax, eax
  992.         jz      .no_hdll
  993.         or      al, PG_UWR
  994.         mov     [esi+edx*4], eax
  995.         stdcall map_page, edi, eax, [req_access]
  996.         push    esi edi
  997.         mov     esi, ebx
  998.         mov     ecx, 4096/4
  999.         rep movsd
  1000.         pop     edi esi
  1001.         pop     ecx ebx
  1002.         popf
  1003.         stc
  1004.         ret
  1005. endp
  1006.  
  1007. sys_IPC:
  1008. ;input:
  1009. ;  ebx=1 - set ipc buffer area
  1010. ;    ecx=address of buffer
  1011. ;    edx=size of buffer
  1012. ;  eax=2 - send message
  1013. ;    ebx=PID
  1014. ;    ecx=address of message
  1015. ;    edx=size of message
  1016.  
  1017.         dec     ebx
  1018.         jnz     @f
  1019.  
  1020.         mov     eax, [current_slot]
  1021.         pushf
  1022.         cli
  1023.         mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
  1024.         mov     [eax+APPDATA.ipc_size], edx
  1025.  
  1026.         add     edx, ecx
  1027.         add     edx, 4095
  1028.         and     edx, not 4095
  1029.  
  1030. .touch:
  1031.         mov     eax, [ecx]
  1032.         add     ecx, 0x1000
  1033.         cmp     ecx, edx
  1034.         jb      .touch
  1035.  
  1036.         popf
  1037.         mov     [esp+32], ebx   ;ebx=0
  1038.         ret
  1039.  
  1040. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1041. ;2
  1042. @@:
  1043.         dec     ebx
  1044.         jnz     @f
  1045.  
  1046.         stdcall sys_ipc_send, ecx, edx, esi
  1047.         mov     [esp+32], eax
  1048.         ret
  1049. @@:
  1050.         or      eax, -1
  1051.         mov     [esp+32], eax
  1052.         ret
  1053.  
  1054. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  1055.            locals
  1056.              dst_slot   dd ?
  1057.              dst_offset dd ?
  1058.              buf_size   dd ?
  1059.              used_buf   dd ?
  1060.            endl
  1061.  
  1062.         pushf
  1063.         cli
  1064.  
  1065.         mov     eax, [PID]
  1066.         call    pid_to_slot
  1067.         test    eax, eax
  1068.         jz      .no_pid
  1069.  
  1070.         mov     [dst_slot], eax
  1071.         shl     eax, 8
  1072.         mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
  1073.         test    edi, edi
  1074.         jz      .no_ipc_area
  1075.  
  1076.         mov     ebx, edi
  1077.         and     ebx, 0xFFF
  1078.         mov     [dst_offset], ebx
  1079.  
  1080.         mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
  1081.         mov     [buf_size], esi
  1082.  
  1083.         mov     ecx, [ipc_tmp]
  1084.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  1085.         jbe     @f
  1086.         push    esi edi
  1087.         add     esi, 0x1000
  1088.         stdcall alloc_kernel_space, esi
  1089.         mov     ecx, eax
  1090.         pop     edi esi
  1091. @@:
  1092.         mov     [used_buf], ecx
  1093.         stdcall map_mem_ipc, ecx, [dst_slot], \
  1094.                 edi, esi, PG_SWR
  1095.  
  1096.         mov     edi, [dst_offset]
  1097.         add     edi, [used_buf]
  1098.         cmp     dword [edi], 0
  1099.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1100.  
  1101.         mov     edx, dword [edi+4]
  1102.         lea     ebx, [edx+8]
  1103.         add     ebx, [msg_size]
  1104.         cmp     ebx, [buf_size]
  1105.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1106.  
  1107.         mov     dword [edi+4], ebx
  1108.         mov     eax, [TASK_BASE]
  1109.         mov     eax, [eax+0x04]        ;eax - our PID
  1110.         add     edi, edx
  1111.         mov     [edi], eax
  1112.         mov     ecx, [msg_size]
  1113.  
  1114.         mov     [edi+4], ecx
  1115.         add     edi, 8
  1116.         mov     esi, [msg_addr]
  1117.        ;    add esi, new_app_base
  1118.         cld
  1119.         rep movsb
  1120.  
  1121.         mov     ebx, [ipc_tmp]
  1122.         mov     edx, ebx
  1123.         shr     ebx, 12
  1124.         xor     eax, eax
  1125.         mov     [page_tabs+ebx*4], eax
  1126.         invlpg  [edx]
  1127.  
  1128.         mov     ebx, [ipc_pdir]
  1129.         mov     edx, ebx
  1130.         shr     ebx, 12
  1131.         xor     eax, eax
  1132.         mov     [page_tabs+ebx*4], eax
  1133.         invlpg  [edx]
  1134.  
  1135.         mov     ebx, [ipc_ptab]
  1136.         mov     edx, ebx
  1137.         shr     ebx, 12
  1138.         xor     eax, eax
  1139.         mov     [page_tabs+ebx*4], eax
  1140.         invlpg  [edx]
  1141.  
  1142.         mov     eax, [dst_slot]
  1143.         shl     eax, 8
  1144.         or      [eax+SLOT_BASE+0xA8], dword 0x40
  1145.         push    0
  1146.         jmp     .ret
  1147. .no_pid:
  1148.         popf
  1149.         mov     eax, 4
  1150.         ret
  1151. .no_ipc_area:
  1152.         popf
  1153.         xor     eax, eax
  1154.         inc     eax
  1155.         ret
  1156. .ipc_blocked:
  1157.         push    2
  1158.         jmp     .ret
  1159. .buffer_overflow:
  1160.         push    3
  1161. .ret:
  1162.         mov     eax, [used_buf]
  1163.         cmp     eax, [ipc_tmp]
  1164.         je      @f
  1165.         stdcall free_kernel_space, eax
  1166. @@:
  1167.         pop     eax
  1168.         popf
  1169.         ret
  1170. endp
  1171.  
  1172. align 4
  1173. sysfn_meminfo:
  1174.         cmp     ecx, OS_BASE
  1175.         jae     .fail
  1176.  
  1177.         mov     eax, [pg_data.pages_count]
  1178.         mov     [ecx], eax
  1179.         shl     eax, 12
  1180.         mov     [esp+32], eax
  1181.         mov     eax, [pg_data.pages_free]
  1182.         mov     [ecx+4], eax
  1183.         mov     eax, [pg_data.pages_faults]
  1184.         mov     [ecx+8], eax
  1185.         mov     eax, [heap_size]
  1186.         mov     [ecx+12], eax
  1187.         mov     eax, [heap_free]
  1188.         mov     [ecx+16], eax
  1189.         mov     eax, [heap_blocks]
  1190.         mov     [ecx+20], eax
  1191.         mov     eax, [free_blocks]
  1192.         mov     [ecx+24], eax
  1193.         ret
  1194. .fail:
  1195.         or      dword [esp+32], -1
  1196.         ret
  1197.  
  1198. align 4
  1199. f68:
  1200.         cmp     ebx, 4
  1201.         jbe     sys_sheduler
  1202.  
  1203.         cmp     ebx, 11
  1204.         jb      .fail
  1205.  
  1206.         cmp     ebx, 27
  1207.         ja      .fail
  1208.  
  1209.         jmp     dword [f68call+ebx*4-11*4]
  1210. .11:
  1211.         call    init_heap
  1212.         mov     [esp+32], eax
  1213.         ret
  1214. .12:
  1215.         stdcall user_alloc, ecx
  1216.         mov     [esp+32], eax
  1217.         ret
  1218. .13:
  1219.         stdcall user_free, ecx
  1220.         mov     [esp+32], eax
  1221.         ret
  1222. .14:
  1223.         cmp     ecx, OS_BASE
  1224.         jae     .fail
  1225.         mov     edi, ecx
  1226.         call    get_event_ex
  1227.         mov     [esp+32], eax
  1228.         ret
  1229. .16:
  1230.         test    ecx, ecx
  1231.         jz      .fail
  1232.         cmp     ecx, OS_BASE
  1233.         jae     .fail
  1234.         stdcall get_service, ecx
  1235.         mov     [esp+32], eax
  1236.         ret
  1237. .17:
  1238.         call    srv_handlerEx   ;ecx
  1239.         mov     [esp+32], eax
  1240.         ret
  1241. .19:
  1242.         cmp     ecx, OS_BASE
  1243.         jae     .fail
  1244.         stdcall load_library, ecx
  1245.         mov     [esp+32], eax
  1246.         ret
  1247. .20:
  1248.         mov     eax, edx
  1249.         mov     ebx, ecx
  1250.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1251.         mov     [esp+32], eax
  1252.         ret
  1253. .21:
  1254.         cmp     ecx, OS_BASE
  1255.         jae     .fail
  1256.  
  1257.         cmp     edx, OS_BASE
  1258.         jae     .fail
  1259.  
  1260.         stdcall load_pe_driver, ecx, edx
  1261.         mov     [esp+32], eax
  1262.         ret
  1263. .22:
  1264.         cmp     ecx, OS_BASE
  1265.         jae     .fail
  1266.  
  1267.         stdcall shmem_open, ecx, edx, esi
  1268.         mov     [esp+24], edx
  1269.         mov     [esp+32], eax
  1270.         ret
  1271.  
  1272. .23:
  1273.         cmp     ecx, OS_BASE
  1274.         jae     .fail
  1275.  
  1276.         stdcall shmem_close, ecx
  1277.         mov     [esp+32], eax
  1278.         ret
  1279. .24:
  1280.         mov     eax, [current_slot]
  1281.         xchg    ecx, [eax+APPDATA.exc_handler]
  1282.         xchg    edx, [eax+APPDATA.except_mask]
  1283.         mov     [esp+32], ecx ; reg_eax+8
  1284.         mov     [esp+20], edx ; reg_ebx+8
  1285.         ret
  1286. .25:
  1287.         cmp     ecx, 32
  1288.         jae     .fail
  1289.         mov     eax, [current_slot]
  1290.         btr     [eax+APPDATA.except_mask], ecx
  1291.         setc    byte[esp+32]
  1292.         jecxz   @f
  1293.         bts     [eax+APPDATA.except_mask], ecx
  1294. @@:
  1295.         ret
  1296.  
  1297. .26:
  1298.         stdcall user_unmap, ecx, edx, esi
  1299.         mov     [esp+32], eax
  1300.         ret
  1301.  
  1302. .27:
  1303.         cmp     ecx, OS_BASE
  1304.         jae     .fail
  1305.  
  1306.         stdcall load_file_umode, ecx
  1307.         mov     [esp+24], edx
  1308.         mov     [esp+32], eax
  1309.         ret
  1310.  
  1311. .fail:
  1312.         xor     eax, eax
  1313.         mov     [esp+32], eax
  1314.         ret
  1315.  
  1316.  
  1317. align 4
  1318. f68call:   ; keep this table closer to main code
  1319.  
  1320.            dd f68.11   ; init_heap
  1321.            dd f68.12   ; user_alloc
  1322.            dd f68.13   ; user_free
  1323.            dd f68.14   ; get_event_ex
  1324.            dd f68.fail ; moved to f68.24
  1325.            dd f68.16   ; get_service
  1326.            dd f68.17   ; call_service
  1327.            dd f68.fail ; moved to f68.25
  1328.            dd f68.19   ; load_dll
  1329.            dd f68.20   ; user_realloc
  1330.            dd f68.21   ; load_driver
  1331.            dd f68.22   ; shmem_open
  1332.            dd f68.23   ; shmem_close
  1333.            dd f68.24   ; set exception handler
  1334.            dd f68.25   ; unmask exception
  1335.            dd f68.26   ; user_unmap
  1336.            dd f68.27   ; load_file_umode
  1337.  
  1338.  
  1339. align 4
  1340. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1341.         push    esi
  1342.  
  1343.         stdcall load_PE, [file]
  1344.         test    eax, eax
  1345.         jz      .fail
  1346.  
  1347.         mov     esi, eax
  1348.         push    [cmdline]
  1349.         push    DRV_ENTRY
  1350.         call    eax
  1351.         pop     ecx
  1352.         pop     ecx
  1353.         test    eax, eax
  1354.         jz      .fail
  1355.  
  1356.         mov     [eax+SRV.entry], esi
  1357.         pop     esi
  1358.         ret
  1359.  
  1360. .fail:
  1361.         xor     eax, eax
  1362.         pop     esi
  1363.         ret
  1364. endp
  1365.  
  1366. align 4
  1367. proc create_ring_buffer stdcall, size:dword, flags:dword
  1368.            locals
  1369.              buf_ptr  dd ?
  1370.            endl
  1371.  
  1372.         mov     eax, [size]
  1373.         test    eax, eax
  1374.         jz      .fail
  1375.  
  1376.         add     eax, eax
  1377.         stdcall alloc_kernel_space, eax
  1378.         test    eax, eax
  1379.         jz      .fail
  1380.  
  1381.         push    ebx
  1382.  
  1383.         mov     [buf_ptr], eax
  1384.  
  1385.         mov     ebx, [size]
  1386.         shr     ebx, 12
  1387.         push    ebx
  1388.  
  1389.         stdcall alloc_pages, ebx
  1390.         pop     ecx
  1391.  
  1392.         test    eax, eax
  1393.         jz      .mm_fail
  1394.  
  1395.         push    edi
  1396.  
  1397.         or      eax, [flags]
  1398.         mov     edi, [buf_ptr]
  1399.         mov     ebx, [buf_ptr]
  1400.         mov     edx, ecx
  1401.         shl     edx, 2
  1402.         shr     edi, 10
  1403. @@:
  1404.         mov     [page_tabs+edi], eax
  1405.         mov     [page_tabs+edi+edx], eax
  1406.         invlpg  [ebx]
  1407.         invlpg  [ebx+0x10000]
  1408.         add     eax, 0x1000
  1409.         add     ebx, 0x1000
  1410.         add     edi, 4
  1411.         dec     ecx
  1412.         jnz     @B
  1413.  
  1414.         mov     eax, [buf_ptr]
  1415.         pop     edi
  1416.         pop     ebx
  1417.         ret
  1418. .mm_fail:
  1419.         stdcall free_kernel_space, [buf_ptr]
  1420.         xor     eax, eax
  1421.         pop     ebx
  1422. .fail:
  1423.         ret
  1424. endp
  1425.  
  1426.  
  1427. align 4
  1428. proc print_mem
  1429.         mov     edi, BOOT_VAR + 0x9104
  1430.         mov     ecx, [edi-4]
  1431.         test    ecx, ecx
  1432.         jz      .done
  1433.  
  1434. @@:
  1435.         mov     eax, [edi]
  1436.         mov     edx, [edi+4]
  1437.         add     eax, [edi+8]
  1438.         adc     edx, [edi+12]
  1439.  
  1440.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1441.                     [edi+4], [edi],\
  1442.                     edx, eax, [edi+16]
  1443.         add     edi, 20
  1444.         dec     ecx
  1445.         jnz     @b
  1446. .done:
  1447.         ret
  1448. endp
  1449.