Functions | |||||||
| void | init_paging () | ||||||
Initialize the paging mechanism.
| |||||||
| dword | pop_frame () | ||||||
Pop a free frame from the free frames stack.
| |||||||
| void | push_frame (dword p_addr) | ||||||
Push a free frame into the free frames stack.
| |||||||
| bool | map_page (dword vir_addr, dword phys_addr, word attribs) | ||||||
Map a physical address into a virtual address for the current address space.
| |||||||
| void | unmap_page (dword vir_addr) | ||||||
Unmap a page, but doesn't destroy the physical frame.
| |||||||
| void | delete_page (dword vir_addr) | ||||||
Unmap a page and destroy the physical frame where the address is mapped.
| |||||||
| void * | get_temp_page () | ||||||
Get a free virtual page from the temporary memory area.
| |||||||
| void | free_temp_page (void *p, bool do_delete) | ||||||
Free a virtual temporary page allocated by get_temp_page().
| |||||||
| dword | vir_to_phys (dword vir_addr) | ||||||
Translate a virtual address into the physical address.
| |||||||
| int | page_fault_handler (dword err_code, dword cr2) | ||||||
This is the page-fault handler. Every time a page-fault occurs, this routine must be invoked.
| |||||||
| void | dump_dirty_pages () | ||||||
| Dump the dirty pages to stdout. | |||||||
| void | dump_free_frames () | ||||||
| Dump the free frames to stdout. | |||||||
| void | check_free_frames_integrity () | ||||||
This process checks the free frames stack integrity.
| |||||||
|
|
This process checks the free frames stack integrity.
Definition at line 545 of file paging.c.
00546 {
00547 dword flag, i;
00548 dword *j;
00549
00550 kprintf("\n\rChecking free frames integrity (%s)...\n\r", get_pname());
00551 for (i=P_ADDR_16MB; i<ADDR_TO_PAGE(PHYS_MEM_DIM); i++)
00552 {
00553 flag=0;
00554 for (j=free_frames; j<K_VIR_END; j++)
00555 {
00556 if (*j == i) flag++;
00557 }
00558 if (flag>1) kprintf("\n\rError! frame:%#010x", i);
00559 }
00560 beep();
00561 kprintf("\n\rCheck done.\n\r");
00562 _exit( 0 );
00563 }
|
|
|
Unmap a page and destroy the physical frame where the address is mapped.
Definition at line 224 of file paging.c.
00225 {
00226 dword temp;
00227 dword IF = GET_IF();
00228
00229 // Align address to the page boundary //
00230 vir_addr = PAGE_ALIGN(vir_addr);
00231
00232 if (*ADDR_TO_PDE(vir_addr) == NULL) return;
00233 if (*ADDR_TO_PTE(vir_addr) == NULL) return;
00234
00235 disable();
00236
00237 // Push the physical frame into the free frames stack //
00238 if (
00239 (vir_to_phys(vir_addr) >= DMA_MEMORY_END) &&
00240 (vir_to_phys(vir_addr) < PHYS_MEM_DIM)
00241 )
00242 push_frame(vir_to_phys(vir_addr)/PAGE_SIZE);
00243
00244 // Unmap the page //
00245 *ADDR_TO_PTE(vir_addr) = NULL;
00246
00247 // Invalidate the page in the TLB cache //
00248 flush_tlb_single(vir_addr);
00249
00250 // Check if it is possible to deallocate the frame
00251 // of the page table used to map the address
00252 // So let's examine all entries in the page table
00253 // where the address is mapped.
00254
00255 for( temp = PAGE_DIR_ALIGN(vir_addr);
00256 temp < PAGE_DIR_ALIGN_UP(vir_addr);
00257 temp += PAGE_SIZE )
00258
00259 if (*ADDR_TO_PTE(temp) != NULL)
00260 {
00261 SET_IF(IF);
00262 return;
00263 }
00264
00265 // No PTEs found... deallocate the page table! //
00266 push_frame(*ADDR_TO_PDE(vir_addr)/PAGE_SIZE);
00267 *ADDR_TO_PDE(vir_addr) = NULL;
00268
00269 // Ivalidate the whole TLB cache //
00270 flush_tlb_all();
00271
00272 // ...and update the master page directory! //
00273 if (vir_addr >= K_VIR_START)
00274 K_PDBR[vir_addr/(PAGE_SIZE*1024)] = NULL;
00275
00276 SET_IF(IF);
00277 }
|
|
|
Dump the dirty pages to stdout.
Definition at line 493 of file paging.c.
00494 {
00495 // Show all the dirty pages //
00496
00497 dword vir_addr;
00498 dword display=1;
00499
00500 // Print all the dirty pages //
00501 kprintf("\n\rDirty pages:\n\r");
00502 for (vir_addr = 0; vir_addr<PAGE_TABLE_MAP; vir_addr += PAGE_SIZE)
00503 if (*ADDR_TO_PDE(vir_addr) != NULL)
00504 if ((*ADDR_TO_PTE(vir_addr) & P_DIRTY) == P_DIRTY)
00505 {
00506 if (!(display = display++ % 24))
00507 if (kgetchar() == CTRL_C)
00508 {
00509 kprintf("\n\r");
00510 return;
00511 }
00512 kprintf("\n\rvir_addr = %#010x\tpage_entry = %#010x",
00513 vir_addr, *(ADDR_TO_PTE(vir_addr)));
00514 }
00515 kprintf("\n\r");
00516 }
|
|
|
Dump the free frames to stdout.
Definition at line 520 of file paging.c.
00521 {
00522 dword *f = free_frames;
00523 dword display=1;
00524
00525 kprintf("\n\rFree frames list: (KERNEL_TOP=%#010x)\n\r", (dword)&KERNEL_TOP);
00526 for(;;)
00527 {
00528 if (*f == NULL) break;
00529 if (!(display = display++ % 24))
00530 if (kgetchar() == CTRL_C)
00531 {
00532 kprintf("\n\r");
00533 return;
00534 }
00535 kprintf("\n\rframe=%#010x &frame=%#010x", *f, (dword)f);
00536 f++;
00537 }
00538 kprintf("\n\r");
00539 }
|
|
||||||||||||
|
Free a virtual temporary page allocated by get_temp_page().
Definition at line 333 of file paging.c.
00334 {
00335 // Is the page into the temporary memory range?! //
00336 if ( (((dword)p >= (K_MEM_TEMP_START))) && ((dword)p < K_MEM_TEMP_END) )
00337 {
00338 if ( do_delete )
00339 delete_page( (dword)p );
00340 else
00341 unmap_page( (dword)p );
00342 }
00343 }
|
|
|
Get a free virtual page from the temporary memory area.
Definition at line 285 of file paging.c.
00286 {
00287 byte *p = (byte *)K_MEM_TEMP_START;
00288 size_t frame;
00289 dword IF = GET_IF();
00290
00291 disable();
00292
00293 while(TRUE)
00294 {
00295 if ( *ADDR_TO_PDE((size_t)p) )
00296 {
00297 if ( *ADDR_TO_PTE((size_t)p) )
00298 {
00299 p += PAGE_SIZE;
00300 if (p >= (byte *)K_MEM_TEMP_END)
00301 {
00302 // Out of temporary memory! //
00303 SET_IF(IF);
00304 return( NULL );
00305 }
00306 continue;
00307 }
00308 }
00309 // OK! A free temporary page has been found! //
00310 // Now map this page to a free frame and return the //
00311 // virtual address of this page, or NULL if there is //
00312 // no free frame.
00313 frame = ( pop_frame()*PAGE_SIZE );
00314 if ( frame==NULL )
00315 {
00316 p = NULL;
00317 }
00318 else if ( !map_page((dword)p, frame, P_PRESENT | P_WRITE) )
00319 {
00320 p = NULL;
00321 }
00322 SET_IF(IF);
00323 return( (void *)p );
00324 }
00325 }
|
|
|
Initialize the paging mechanism.
Definition at line 456 of file paging.c.
00457 {
00458 extern multiboot_info_t *boot_info;
00459 size_t addr;
00460
00461 if (boot_info->flags & 0x02)
00462 {
00463 PHYS_MEM_DIM = (boot_info->mem_upper)*1024;
00464 }
00465 else
00466 {
00467 // Error reading multiboot informations... halting!.
00468 halt();
00469 }
00470
00471 // Initialize free frames stack //
00472 init_free_frames();
00473
00474 // Unmap first 4MB identical-map pages.
00475 *ADDR_TO_PDE(0) = NULL;
00476
00477 // Flush the whole TLB cache.
00478 flush_tlb_all();
00479
00480 // Map part of physical memory into the kernel address space //
00481 for (addr=PHYS_MEM_START; addr<PHYS_MEM_END; addr+=PAGE_SIZE)
00482 map_page(addr, addr-PHYS_MEM_START, P_PRESENT | P_WRITE);
00483
00484 // Initialize master page directory //
00485 for (addr=0; addr<1024; addr++)
00486 K_PDBR[addr] = ((dword *)PAGE_DIR_MAP)[addr];
00487 }
|
|
||||||||||||||||
|
Map a physical address into a virtual address for the current address space.
Definition at line 115 of file paging.c.
00116 {
00117 dword *PTE;
00118 dword i;
00119 dword IF = GET_IF();
00120
00121 // Round virtual & physical address to the page boundary //
00122 vir_addr = PAGE_ALIGN(vir_addr);
00123 phys_addr = PAGE_ALIGN(phys_addr);
00124
00125 // Get only valid attribs //
00126 attribs &= (PAGE_SIZE-1);
00127
00128 disable();
00129
00130 // If the page directory entry is NULL must be created //
00131 if (*ADDR_TO_PDE(vir_addr) == NULL)
00132 {
00133 // Create a new page table //
00134 PTE = (dword *)(pop_frame() * PAGE_SIZE);
00135 if (PTE == NULL)
00136 {
00137 // Out of memory!!! //
00138 SET_IF(IF);
00139 return(FALSE);
00140 }
00141
00142 // Set the PDE as present, user level, read-write //
00143 *ADDR_TO_PDE(vir_addr) = (dword)PTE | P_PRESENT | P_USER | P_WRITE;
00144
00145 // Flush the whole TLB cache //
00146 flush_tlb_all();
00147
00148 // NULL every PTE entry //
00149 for (i=PAGE_DIR_ALIGN(vir_addr); i<PAGE_DIR_ALIGN_UP(vir_addr); i+=PAGE_SIZE)
00150 {
00151 *ADDR_TO_PTE(i) = NULL;
00152 }
00153
00154 // Update master page directory //
00155 if (vir_addr >= K_VIR_START)
00156 K_PDBR[vir_addr/(PAGE_SIZE*1024)] = *ADDR_TO_PDE(vir_addr);
00157 }
00158
00159 // Store the physical address into the page table entry //
00160 *ADDR_TO_PTE(vir_addr) = (dword)phys_addr | attribs;
00161
00162 // Invalidate the page in the TLB cache //
00163 flush_tlb_single(vir_addr);
00164
00165 SET_IF(IF);
00166 return(TRUE);
00167 }
|
|
||||||||||||
|
This is the page-fault handler. Every time a page-fault occurs, this routine must be invoked.
Definition at line 367 of file paging.c.
00368 {
00369 dword phys_addr;
00370
00371 #ifdef PAGE_DEBUG
00372 kprintf("\n\rPAGE_FAULT : %#010x", cr2);
00373 #endif
00374 if( cr2==NULL )
00375 {
00376 // Cannot map the NULL pointer.
00377 return( -1 );
00378 }
00379
00380 // Get a physical free frame.
00381 phys_addr = pop_frame()*PAGE_SIZE;
00382
00383 // If out of memory => return!
00384 if (phys_addr == NULL)
00385 {
00386 set_color(LIGHT_RED);
00387 kprintf("\n\rPage fault handler panic: Out of memory!!!");
00388 set_color(DEFAULT_COLOR);
00389 return(-1);
00390 }
00391
00392 // Get only valid err_code //
00393 err_code &= (P_PRESENT | P_WRITE | P_USER);
00394
00395 // Map page with correct attributes //
00396 if (cr2 >= K_VIR_START)
00397 {
00398 if (!(map_page(cr2, phys_addr, P_PRESENT | P_WRITE)))
00399 {
00400 // Out of memory!!! //
00401 set_color(LIGHT_RED);
00402 kprintf("\n\rPage fault handler panic: Out of memory!!!");
00403 set_color(DEFAULT_COLOR);
00404 return( -1 );
00405 }
00406 }
00407 else
00408 {
00409 if (!(map_page(cr2, phys_addr, P_PRESENT | P_WRITE | P_USER)))
00410 {
00411 // Out of memory!!! //
00412 set_color(LIGHT_RED);
00413 kprintf("\n\rPage fault handler panic: Out of memory!!!");
00414 set_color(DEFAULT_COLOR);
00415 return( -1 );
00416 }
00417 }
00418 // Null the new page.
00419 // memsetl((void *)PAGE_ALIGN(cr2), 0, PAGE_SIZE/sizeof(uint32_t));
00420 fast_clear_page((void *)PAGE_ALIGN(cr2));
00421 return( 0 );
00422 }
|
|
|
Pop a free frame from the free frames stack.
Definition at line 61 of file paging.c.
00062 {
00063 dword ret;
00064 dword IF = GET_IF();
00065
00066 disable();
00067
00068 if (*free_frames != NULL)
00069 {
00070 ret = *free_frames++;
00071
00072 SET_IF(IF);
00073 return(ret);
00074 }
00075
00076 // Out of memory!!! //
00077 SET_IF(IF);
00078 return(NULL);
00079 }
|
|
|
Push a free frame into the free frames stack.
Definition at line 88 of file paging.c.
00089 {
00090 dword IF = GET_IF();
00091
00092 disable();
00093
00094 // Push the frame into free frames stack //
00095 if ((dword)free_frames > ((dword)&KERNEL_TOP))
00096 {
00097 *(--free_frames)=p_addr;
00098 }
00099
00100 SET_IF(IF);
00101 }
|
|
|
Unmap a page, but doesn't destroy the physical frame.
Definition at line 172 of file paging.c.
00173 {
00174 dword temp;
00175 dword IF = GET_IF();
00176
00177 // Align address to the page boundary //
00178 vir_addr = PAGE_ALIGN(vir_addr);
00179
00180 if (*ADDR_TO_PDE(vir_addr) == NULL) return;
00181 if (*ADDR_TO_PTE(vir_addr) == NULL) return;
00182
00183 disable();
00184
00185 // Unmap the page //
00186 *ADDR_TO_PTE(vir_addr) = NULL;
00187
00188 // Invalidate the page in the TLB cache //
00189 flush_tlb_single(vir_addr);
00190
00191 // Check if it is possible to deallocate the frame
00192 // of the page table used to map the address
00193 // So let's examine all entries in the page table
00194 // where the address is mapped.
00195
00196 for( temp = PAGE_DIR_ALIGN(vir_addr);
00197 temp < PAGE_DIR_ALIGN_UP(vir_addr);
00198 temp += PAGE_SIZE)
00199
00200 if (*ADDR_TO_PTE(temp) != NULL)
00201 {
00202 SET_IF(IF);
00203 return;
00204 }
00205
00206 // No PTEs found... deallocate the page table! //
00207 push_frame(*ADDR_TO_PDE(vir_addr)/PAGE_SIZE);
00208 *ADDR_TO_PDE(vir_addr) = NULL;
00209
00210 // Invalidate the whole TLB cache //
00211 flush_tlb_all();
00212
00213 // ...and update the master page directory! //
00214 if (vir_addr >= K_VIR_START)
00215 K_PDBR[vir_addr/(PAGE_SIZE*1024)] = NULL;
00216
00217 SET_IF(IF);
00218 }
|
|
|
Translate a virtual address into the physical address.
Definition at line 350 of file paging.c.
00351 {
00352 if (*ADDR_TO_PDE(vir_addr) == NULL) return(NULL);
00353 return ((*ADDR_TO_PTE(vir_addr) & -PAGE_SIZE) + (vir_addr % PAGE_SIZE));
00354 }
|
1.2.18