Subversion Repositories Kolibri OS

Rev

Rev 21 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ha 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
21 poddubny 241
    cmp   byte [second_base_address+0x3000+ecx+0xa],9 ;if process running?
242
    jz    .next                  ;skip empty slots
1 ha 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
25 halyavin 254
    cmp   edx,1
255
    jg    .threadsexists
1 ha 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