Subversion Repositories Kolibri OS

Rev

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