Subversion Repositories Kolibri OS

Rev

Rev 103 | Blame | Last modification | View Log | Download | RSS feed

  1. if ~defined mem_inc
  2. mem_inc_fix:
  3. mem_inc fix mem_inc_fix
  4. ;include "memmanag.inc"
  5. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  6. ;;High-level memory management in MenuetOS.
  7. ;;It uses memory manager in memmanager.inc
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9. second_base_address=0xC0000000
  10. std_application_base_address=0x10000000
  11. general_page_table_ dd 0
  12. general_page_table=general_page_table_+second_base_address
  13. ;-----------------------------------------------------------------------------
  14. create_general_page_table:
  15. ;input
  16. ;  none
  17. ;output
  18. ;  none
  19. ;Procedure create general page directory and write
  20. ;it address to [general_page_table].
  21.     pushad
  22.     mov   eax,1                  ;alloc 1 page
  23.     mov   ebx,general_page_table ;write address to [general_page_table]
  24.     call  MEM_Alloc_Pages        ;allocate page directory
  25.     mov   eax,[general_page_table]
  26.     call  MEM_Get_Linear_Address ;eax - linear address of page directory
  27.     mov   edi,eax
  28.     mov   ebx,eax                ;copy address of page directory to safe place
  29.     xor   eax,eax
  30.     mov   ecx,4096/4
  31.     cld
  32.     rep   stosd                  ;clear page directory
  33.    
  34.     mov   eax,4
  35.     mov   edx,eax
  36.     call  MEM_Alloc_Pages        ;alloc page tables for 0x0-0x1000000 region
  37.     cmp   eax,edx
  38.     jnz   $                      ;hang if not enough memory
  39.    
  40. ;fill page tables
  41.     xor   esi,esi  
  42.     mov   ebp,7
  43.    
  44. .loop:
  45. ;esi - number of page in page directory
  46. ;ebp - current page address
  47. ;ebx - linear address of page directory
  48.     mov   eax,[ebx+4*esi]
  49.     add   dword [ebx+4*esi],7    ;add flags to address of page table
  50.     call  MEM_Get_Linear_Address
  51. ;eax - linear address of page table    
  52.     mov   ecx,4096/4
  53. ;ecx (counter) - number of pages in page table
  54. ;current address=4Mb*esi    
  55.    
  56. .loop1:
  57.     mov   [eax],ebp              ;write page address (with flags) in page table
  58.     add   eax,4
  59.     add   ebp,4096               ;size of page=4096 bytes
  60.     loop  .loop1
  61.    
  62.     inc   esi                    ;next page directory entry
  63.     cmp   esi,edx
  64.     jnz   .loop
  65.    
  66. ;map region 0x80000000-0x807fffff to LFB
  67.     mov   eax,2                  ;size of the region is 4Mb so only 1 page table needed
  68.     mov   edx,ebx                ;ebx still contains linear address of the page directory
  69.     add   ebx,0x800
  70.     call  MEM_Alloc_Pages        ;alloc page table for the region
  71.     mov   eax,[ebx]
  72.     add   dword [ebx],7          ;add flags
  73.     call  MEM_Get_Linear_Address ;get linear address of the page table
  74.     mov   ecx,4096/4             ;number of pages in page table
  75.     mov   edi,[0xfe80]
  76.     add   edi,7
  77. .loop3:
  78. ;eax - linear address of page table
  79. ;edi - current linear address with flags
  80.     mov   [eax],edi
  81.     add   eax,4
  82.     add   edi,4096
  83.     loop  .loop3
  84.     mov   eax,[ebx+4]
  85.     call  MEM_Get_Linear_Address
  86.     add   dword [ebx+4],7
  87.     mov   ecx,4096/4
  88. .loop31:
  89.     mov   [eax],edi
  90.     add   eax,4
  91.     add   edi,4096
  92.     loop  .loop31
  93.    
  94. ;map region 0xC0000000-* to 0x0-*
  95.     mov   esi,edx                ;esi=linear address of the page directory
  96.     lea   edi,[esi+(second_base_address shr 20)];add offset of entry (0xC00)
  97.     mov   ecx,4
  98.     rep   movsd                  ;first 16Mb of the region mapped as 0x0-0x1000000 block
  99.     mov   eax,[0xfe8c]           ;eax=memory size
  100.     add   eax,0x3fffff
  101.     shr   eax,22                
  102.     mov   esi,eax         ;calculate number of entries in page directory
  103.     sub   esi,4                  ;subtract entries for first 16Mb.
  104.     mov   ebp,0x1000000+7        ;start physical address with flags
  105.    
  106. ;mapping memory higher than 16Mb    
  107. .loop4:
  108. ;esi (counter) - number of entries in page directory
  109. ;edi - address of entry
  110.     test  esi,esi
  111.     jle   .loop4end
  112.     call  MEM_Alloc_Page         ;alloc page table for entry in page directory
  113.     mov   [edi],eax
  114.     add   dword [edi],7          ;write physical address of page table in page directory
  115.     add   edi,4                  ;move entry pointer
  116.     call  MEM_Get_Linear_Address
  117.     mov   ecx,eax
  118.     xor   edx,edx
  119.    
  120. .loop5:
  121. ;ecx - linear address of page table
  122. ;edx - index of page in page table
  123. ;ebp - current mapped physical address with flags
  124.     mov   [ecx+4*edx],ebp        ;write address of page in page table
  125.     add   ebp,0x1000             ;move to next page
  126.     inc   edx
  127.     cmp   edx,4096/4
  128.     jl    .loop5
  129.    
  130.     dec   esi
  131.     jmp   .loop4
  132. .loop4end:    
  133.    
  134. .set_cr3:
  135. ;set value of cr3 register to the address of page directory
  136.     mov   eax,[general_page_table]
  137.     add   eax,8+16               ;add flags
  138.     mov   cr3,eax                ;now we have full access paging
  139.    
  140.     popad
  141.     ret
  142. ;-----------------------------------------------------------------------------
  143. simple_clone_cr3_table:
  144. ;Parameters:
  145. ;  eax - physical address of cr3 table (page directory)
  146. ;result:
  147. ;  eax - physical address of clone of cr3 table.
  148. ;Function copy only page directory.
  149.     push  ecx
  150.     push  edx
  151.     push  esi
  152.     push  edi
  153.     call  MEM_Get_Linear_Address
  154. ;eax - linear address of cr3 table    
  155.     mov   esi,eax                
  156.     call  MEM_Alloc_Page
  157.     test  eax,eax
  158.     jz    .failed
  159. ;eax - physical address of new page diretory
  160.     mov   edx,eax                
  161.     call  MEM_Get_Linear_Address    
  162.     mov   edi,eax
  163.     mov   ecx,4096/4
  164.     cld
  165. ;esi - address of old page directory
  166. ;edi - address of new page directory    
  167.     rep   movsd                  ;copy page directory
  168.     mov   eax,edx
  169. .failed:                    
  170.     pop   edi
  171.     pop   esi
  172.     pop   edx
  173.     pop   ecx
  174.     ret
  175.        
  176. ;-----------------------------------------------------------------------------    
  177. create_app_cr3_table:
  178. ;Parameters:
  179. ;  eax - slot of process (index in 0x3000 table)
  180. ;result:
  181. ;  eax - physical address of table.
  182. ;This function create page directory for new process and
  183. ;write it physical address to offset 0xB8 of extended
  184. ;process information.
  185.     push  ebx
  186.  
  187.     mov   ebx,eax
  188.     mov   eax,[general_page_table]
  189.     call  simple_clone_cr3_table ;clone general page table
  190.     shl   ebx,8
  191.     mov   [second_base_address+0x80000+ebx+APPDATA.dir_table],eax ;save address of page directory
  192.    
  193.     pop   ebx
  194.     ret
  195. ;-----------------------------------------------------------------------------
  196. get_cr3_table:
  197. ;Input:
  198. ;  eax - slot of process    
  199. ;result:
  200. ;  eax - physical address of page directory
  201.    shl    eax,8                  ;size of process extended information=256 bytes
  202.    mov    eax,[second_base_address+0x80000+eax+APPDATA.dir_table]
  203.    ret
  204. ;-----------------------------------------------------------------------------    
  205. dispose_app_cr3_table:
  206. ;Input:
  207. ;  eax - slot of process
  208. ;result:
  209. ;  none
  210. ;This procedure frees page directory,
  211. ;page tables and all memory of process.
  212.     pushad
  213.     mov   ebp,eax
  214. ;ebp = process slot in the procedure.
  215.     shl   eax,8
  216.     mov   eax,[second_base_address+0x80000+eax+APPDATA.dir_table]
  217.     mov   ebx,eax
  218. ;ebx = physical address of page directory    
  219.     call  MEM_Get_Linear_Address
  220.     mov   edi,eax
  221. ;edi = linear address of page directory    
  222.     mov   eax,[edi+(std_application_base_address shr 20)]
  223.     and   eax,not (4096-1)
  224.     call  MEM_Get_Linear_Address
  225.     mov   esi,eax
  226. ;esi = linear address of first page table
  227.  
  228. ;search threads
  229. ;    mov   ecx,0x200
  230.     xor   edx,edx
  231.     mov   eax,0x2
  232.  
  233. .loop:
  234. ;eax = current slot of process  
  235.     mov   ecx,eax
  236.     shl   ecx,5
  237.     cmp   byte [second_base_address+0x3000+ecx+TASKDATA.state],9 ;if process running?
  238.     jz    .next                  ;skip empty slots
  239.     shl   ecx,3
  240.     cmp   [second_base_address+0x80000+ecx+APPDATA.dir_table],ebx  ;compare page directory addresses
  241.     jnz   .next
  242.     inc   edx                    ;thread found
  243. .next:
  244.     inc   eax
  245.     cmp   eax,[0x3004]           ;exit loop if we look through all processes
  246.     jle   .loop
  247.            
  248. ;edx = number of threads
  249. ;our process is zombi so it isn't counted
  250.     cmp   edx,1
  251.     jg    .threadsexists
  252. ;if there isn't threads then clear memory.
  253.     add   edi,std_application_base_address shr 20
  254.    
  255. .loop1:    
  256. ;edi = linear address of current directory entry
  257. ;esi = linear address of current page table
  258.     test  esi,esi
  259.     jz    .loop1end
  260.     xor   ecx,ecx
  261.    
  262. .loop2:
  263. ;ecx = index of page
  264.     mov   eax,[esi+4*ecx]
  265.     test  eax,eax
  266.     jz    .loopend               ;skip empty entries
  267.     and   eax,not (4096-1)       ;clear flags
  268.     push  ecx
  269.     call  MEM_Free_Page          ;free page
  270.     pop   ecx
  271. .loopend:    
  272.     inc   ecx
  273.     cmp   ecx,1024               ;there are 1024 pages in page table
  274.     jl    .loop2
  275.    
  276.     mov   eax,esi
  277.     call  MEM_Free_Page_Linear   ;free page table
  278. .loop1end:    
  279.     add   edi,4                  ;move to next directory entry
  280.     mov   eax,[edi]
  281.     and   eax,not (4096-1)
  282.     call  MEM_Get_Linear_Address
  283.     mov   esi,eax                ;calculate linear address of new page table
  284.     test  edi,0x800
  285.     jz    .loop1                 ;test if we at 0x80000000 address?
  286.    
  287.     and   edi,not (4096-1)       ;clear offset of page directory entry
  288.     mov   eax,edi
  289.     call  MEM_Free_Page_Linear   ;free page directory
  290.     popad
  291.     ret
  292.    
  293. .threadsexists:                  ;do nothing  
  294.     popad                        ;last thread will free memory
  295.     ret    
  296. ;-----------------------------------------------------------------------------
  297. mem_alloc_specified_region:
  298. ;eax - linear directory address
  299. ;ebx - start address (aligned to 4096 bytes)
  300. ;ecx - size in pages
  301. ;result:
  302. ; eax=1 - ok
  303. ; eax=0 - failed
  304. ;Try to alloc and map ecx pages to [ebx;ebx+4096*ecx) interval.
  305.     pushad
  306.     mov   ebp,ebx                ;save start address for recoil
  307.     mov   esi,eax
  308. .gen_loop:    
  309. ;esi = linear directory address
  310. ;ebx = current address
  311. ;ecx = remaining size in pages
  312.     mov   edx,ebx
  313.     shr   edx,22
  314.     mov   edi,[esi+4*edx]        ;find directory entry for current address
  315.     test  edi,edi
  316.     jnz   .table_exists          ;check if page table allocated
  317.     call  MEM_Alloc_Page         ;alloc page table
  318.     test  eax,eax
  319.     jz    .failed
  320.     mov   [esi+4*edx],eax
  321.     add   dword [esi+4*edx],7    ;write it address with flags
  322.     call  MEM_Get_Linear_Address
  323.     call  mem_fill_page          ;clear page table
  324.     jmp   .table_linear        
  325. .table_exists:
  326. ;calculate linear address of page table
  327.     mov   eax,edi
  328.     and   eax,not (4096-1)       ;clear flags
  329.     call  MEM_Get_Linear_Address
  330. .table_linear:
  331. ;eax = linear address of page table
  332.     mov   edx,ebx
  333.     shr   edx,12
  334.     and   edx,(1024-1)           ;calculate index in page table
  335.     mov   edi,eax
  336.    
  337. .loop:
  338. ;edi = linear address of page table
  339. ;edx = current page table index
  340. ;ecx = remaining size in pages
  341. ;ebx = current address
  342.     test  ecx,ecx
  343.     jle   .endloop1              ;all requested pages allocated
  344.    
  345.     call  MEM_Alloc_Page         ;alloc new page
  346.     test  eax,eax
  347.     jz    .failed
  348.     mov   [edi+4*edx],eax
  349.     add   dword [edi+4*edx],7    ;write it address with flags
  350.     call  MEM_Get_Linear_Address
  351.     call  mem_fill_page          ;clear new page
  352. ;go to next page table entry    
  353.     dec   ecx
  354.     add   ebx,4096
  355.     inc   edx
  356.     test  edx,(1024-1)
  357.     jnz   .loop
  358.    
  359.     jmp   .gen_loop
  360.      
  361. .endloop1:                          
  362.     popad
  363.     mov   eax,1                  ;ok
  364.     ret
  365.    
  366. .failed:
  367. ;calculate data for recoil
  368.     sub   ebx,ebp
  369.     shr   ebx,12
  370.     mov   ecx,ebx                ;calculate number of allocated pages
  371.     mov   eax,esi                ;restore linear address of page directory
  372.     mov   ebx,ebp                ;restore initial address
  373.     call  mem_free_specified_region ;free all allocated pages
  374.     popad
  375.     xor   eax,eax                ;fail
  376.     ret
  377. ;-----------------------------------------------------------------------------    
  378. mem_fill_page:
  379. ;Input:
  380. ;  eax - address
  381. ;result:
  382. ;  none
  383. ;set to zero 4096 bytes at eax address.
  384.     push  ecx
  385.     push  edi
  386.     mov   edi,eax
  387.     mov   ecx,4096/4
  388.     xor   eax,eax
  389.     rep   stosd
  390.     lea   eax,[edi-4096]
  391.     pop   edi
  392.     pop   ecx
  393.     ret
  394. ;-----------------------------------------------------------------------------    
  395. mem_free_specified_region:
  396. ;eax - linear page directory address
  397. ;ebx - start address (aligned to 4096 bytes)
  398. ;ecx - size in pages
  399. ;result - none
  400. ;Free pages in [ebx;ebx+4096*ecx) region.
  401.     pushad
  402.     mov   esi,eax
  403.     xor   ebp,ebp
  404.    
  405. .gen_loop:    
  406. ;esi = linear page directory address
  407. ;ebx = current address
  408. ;ecx = remaining pages
  409. ;ebp = 0 for first page table
  410. ;      1 otherwise
  411.     mov   edx,ebx
  412.     shr   edx,22
  413.     mov   eax,[esi+4*edx]        ;find directory entry for current address
  414.     and   eax,not (4096-1)
  415.     test  eax,eax
  416.     jnz   .table_exists          
  417. ;skip absent page tables    
  418.     mov   edx,ebx
  419.     shr   edx,12
  420.     and   edx,(1024-1)           ;edx - index of current page
  421.     add   ebx,1 shl 22
  422.     add   ecx,edx
  423.     and   ebx,not ((1 shl 22)-1)
  424.     mov   ebp,1                  ;set flag
  425.     sub   ecx,1024               ;ecx=ecx-(1024-edx)
  426.     jg    .gen_loop
  427.     popad
  428.     ret
  429. .table_exists:
  430.     call  MEM_Get_Linear_Address
  431. ;eax - linear address of table
  432.     mov   edx,ebx
  433.     shr   edx,12
  434.     and   edx,(1024-1)           ;edx - index of current page
  435.     mov   edi,eax
  436.    
  437. .loop:
  438. ;edi = linear address of page table entry
  439. ;edx = index of page table entry
  440. ;ecx = remaining pages
  441.     test  ecx,ecx
  442.     jle   .endloop1
  443.    
  444.     mov   eax,[edi+4*edx]
  445.     and   eax,not (4096-1)
  446.     call  MEM_Free_Page          ;free page
  447.     mov   dword [edi+4*edx],0    ;and clear page table entry
  448.     dec   ecx
  449.     inc   edx
  450.     cmp   edx,1024
  451.     jl    .loop
  452.    
  453.     test  ebp,ebp
  454.     jz    .first_page
  455.     mov   eax,edi                
  456.     call  MEM_Free_Page_Linear   ;free page table
  457.     mov   edx,ebx
  458.     shr   edx,22
  459.     mov   dword [esi+4*edx],0    ;and clear page directory entry
  460. .first_page:
  461.     add   ebx,1 shl 22
  462.     and   ebx,not ((1 shl 22)-1) ;calculate new current address
  463.     mov   ebp,1                  ;set flag
  464.     jmp   .gen_loop
  465.    
  466. .endloop1:  
  467.     popad
  468.     ret
  469. end if
  470.