Subversion Repositories Kolibri OS

Rev

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

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