Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

Paging
[Memory Manager]


Functions

void init_paging ()
 Initialize the paging mechanism.
Note:
This routine must be called once, when the system is initializing.
Warning:
This routine must be the first routine of the kernel initialization process!!!


dword pop_frame ()
 Pop a free frame from the free frames stack.
Exceptions:
NULL  Out-of-memory.
Note:
The function returns the address expressed in the page number format. This value will be multiplied by PAGE_SIZE to obtain the real physical address of the frame.


void push_frame (dword p_addr)
 Push a free frame into the free frames stack.
Parameters:
p_addr  The page number you want to push.
Note:
The value p_addr must be the page number!
If you know the physical address you have to divide this value to PAGE_SIZE.


bool map_page (dword vir_addr, dword phys_addr, word attribs)
 Map a physical address into a virtual address for the current address space.
Parameters:
vir_addr  The virtual address.
phys_addr  The physical address.
attribs  The attributes mask for this page.
Returns:


void unmap_page (dword vir_addr)
 Unmap a page, but doesn't destroy the physical frame.
Parameters:
vir_addr  The virtual address you want to unmap.


void delete_page (dword vir_addr)
 Unmap a page and destroy the physical frame where the address is mapped.
Parameters:
vir_addr  The virtual address you want to delete.


void * get_temp_page ()
 Get a free virtual page from the temporary memory area.
Returns:
The address of the temporary page or NULL if out of memory.


void free_temp_page (void *p, bool do_delete)
 Free a virtual temporary page allocated by get_temp_page().
Parameters:
p  The temporary page virtual address.
do_delete 
  • TRUE free the page and also the physical frame;
  • FALSE unmap the page only, do not free the physical frame.


dword vir_to_phys (dword vir_addr)
 Translate a virtual address into the physical address.
Parameters:
vir_addr  The virtual address to be translated.


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.
Parameters:
err_code  The error code from the CPU.
cr2  The address that caused the fault.
Returns:
  • 0 success;
  • < 0 otherwise.


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.
Warning:
This is a process so it must end with auto_kill();.



Detailed Description

The page manager module.

Function Documentation

void check_free_frames_integrity  
 

This process checks the free frames stack integrity.

Warning:
This is a process so it must end with auto_kill();.

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 }

void delete_page dword    vir_addr
 

Unmap a page and destroy the physical frame where the address is mapped.

Parameters:
vir_addr  The virtual address you want to delete.

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 }

void dump_dirty_pages  
 

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 }

void dump_free_frames  
 

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 }

void free_temp_page void *    p,
bool    do_delete
 

Free a virtual temporary page allocated by get_temp_page().

Parameters:
p  The temporary page virtual address.
do_delete 
  • TRUE free the page and also the physical frame;
  • FALSE unmap the page only, do not free the physical frame.

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 }

void* get_temp_page  
 

Get a free virtual page from the temporary memory area.

Returns:
The address of the temporary page or NULL if out of memory.

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 }

void init_paging  
 

Initialize the paging mechanism.

Note:
This routine must be called once, when the system is initializing.
Warning:
This routine must be the first routine of the kernel initialization process!!!

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 }

bool map_page dword    vir_addr,
dword    phys_addr,
word    attribs
 

Map a physical address into a virtual address for the current address space.

Parameters:
vir_addr  The virtual address.
phys_addr  The physical address.
attribs  The attributes mask for this page.
Returns:

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 }

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.

Parameters:
err_code  The error code from the CPU.
cr2  The address that caused the fault.
Returns:
  • 0 success;
  • < 0 otherwise.

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 }

dword pop_frame  
 

Pop a free frame from the free frames stack.

Exceptions:
NULL  Out-of-memory.
Note:
The function returns the address expressed in the page number format. This value will be multiplied by PAGE_SIZE to obtain the real physical address of the frame.

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 }

void push_frame dword    p_addr
 

Push a free frame into the free frames stack.

Parameters:
p_addr  The page number you want to push.
Note:
The value p_addr must be the page number!
If you know the physical address you have to divide this value to PAGE_SIZE.

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 }

void unmap_page dword    vir_addr
 

Unmap a page, but doesn't destroy the physical frame.

Parameters:
vir_addr  The virtual address you want to unmap.

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 }

dword vir_to_phys dword    vir_addr
 

Translate a virtual address into the physical address.

Parameters:
vir_addr  The virtual address to be translated.

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 }


Generated on Fri Feb 20 15:32:22 2004 for Minirighi by doxygen1.2.18