paging.c

Go to the documentation of this file.
00001 
00007 #include "routix/system.h"
00008 #include "routix/paging.h"
00009 #include "routix/debug.h"
00010 #include <routix/kstdio.h>
00011 #include "routix/kalloc.h"
00012 
00013 
00014 
00016 page_index_t get_page_index (addr_t p)
00017 {       
00018         page_index_t indice;
00019 
00020         indice.dir_index = p / ( PAGINA_SIZE * TABLAS_POR_DIR);
00021         indice.tabla_index = (p % ( PAGINA_SIZE * TABLAS_POR_DIR)) / PAGINA_SIZE;
00022         return indice;
00023 }
00024 
00025 
00027 void *convertir_direccion ( void *dir_logica, addr_t cr3 )
00028 {
00029     void *dir_fisica;
00030     
00031     page_index_t indice;
00032 
00033     // Obtener los indices del directorio y de la tabla de paginas para la direccion logica
00034     indice = get_page_index ( (addr_t) dir_logica );
00035 
00036     pd_t *dir= (pd_t *) cr3;
00037     // Obtener la direccion de la tabla correspondiente y enmascarar los 12 bits de atributos
00038     pt_t *tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);
00039     // Obtener la direccion fisica y enmascarar los 12 bits de atributos
00040     dir_fisica = (void *) (tabla->entry[indice.tabla_index] & 0xfffff000);
00041 
00042     // Sumarle a la pagina obtenida de la tabla el offset de la direccion logica
00043     dir_fisica = dir_fisica + ((dword) dir_logica & 0xfff);
00044 
00045     return dir_fisica;
00046 }       
00047 
00048 
00050 pde_t make_pde (addr_t direccion, word atributos)
00051 {       
00052         pde_t entrada;
00053         entrada= atributos & 0xfff;
00054         entrada= entrada | direccion;
00055 
00056         return entrada;
00057 }
00058 
00060 pte_t make_pte (addr_t direccion, word atributos)
00061 {       
00062         pte_t entrada;
00063         entrada= atributos & 0xfff;
00064         entrada= entrada | direccion;
00065 
00066         return entrada;
00067 }
00068 
00069 
00070 
00072 /* ej.:
00073  *      mem = kmalloc_page();
00074  *      if ( ! kmapmem( fisica, mem, 0xe0000000, PAGE_PRES ) )
00075  *              kfree_page(mem);
00076  */
00077 #define ERR_DIR_BUSY    -1
00078 #define ERR_NO_ALIGN    -2
00079 
00080 #define ERR_DIR_EMPTY   -5
00081 
00089 int kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo)
00090 {
00091         page_index_t indice;
00092         indice = get_page_index ( logica );
00093         pd_t *dir;
00094         pt_t *tabla;
00095         word i;
00096         
00097         atributo = atributo & 0xfff;
00098 
00099         if ( (fisica & 0xfff) || (logica & 0xfff) ) {
00100             if ( getvar("pagedebug")==1 )
00101                         kprintf("Debug Mode - Fis2log: las direcciones deben estar alineadas a 4KB\n");
00102             return ERR_NO_ALIGN;
00103         }
00104 
00105     if ( getvar("pagedebug")==1 )       {
00106                  kprintf("Kmapmem: Mapeando 0x%x en 0x%x\n", fisica, logica);
00107                  kprintf("Kmapmem: Indice DIR: %d  Indice Tabla: %d\n", indice.dir_index, indice.tabla_index);
00108         }
00109 
00110         dir= (pd_t *) directorio;
00111 
00112         if (dir->entry[indice.dir_index] ==  0 )        {
00113             if ( getvar("pagedebug")==1 )
00114                         kprintf("Kmapmem: Debe alocarse una nueva tabla de paginas\n");
00115         
00116                 dir->entry[indice.dir_index]= (pde_t) make_pde ( kmalloc_page(), PAGE_PRES | PAGE_SUPER | PAGE_RW);
00117                 tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);
00118                 /* Poner todas las pte en 0 */
00119                 for (i=0; i < PAGINAS_POR_TABLA ; i++)
00120                         tabla->entry[i]=(pte_t) make_pte (0, 0);
00121         }
00122         
00123         else    {       // Si la entrada existe, esa pagina puede ya estar asignada
00124 
00125                 tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);
00126                 if (tabla->entry[indice.tabla_index]) {
00127                     if ( getvar("pagedebug")==1 )
00128                         kprintf("Kmapmem: Pagina ya en uso\n");
00129                         return ERR_DIR_BUSY;
00130                 }
00131         }
00132 
00133         tabla->entry[indice.tabla_index]= (pte_t) make_pte ( fisica , atributo);
00134 
00135     return OK;
00136 }
00137 
00144 int kunmapmem (addr_t logica, addr_t directorio)
00145 {
00146     if ( logica & 0xfff)  {
00147             if ( getvar("pagedebug")==1 )
00148                     kprintf("KunmapMem: la direccion debe estar alineada a 4KB\n");
00149                 return ERR_NO_ALIGN;
00150     }
00151 
00152     
00153     page_index_t indice;
00154     indice = get_page_index ( logica );
00155 
00156     pd_t *dir = (pd_t *) directorio;
00157 
00158     pt_t *tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);
00159 
00160     
00161     if ( !tabla ) {     //Si la entrada correspondiente a "logica" esta vacia
00162         if ( getvar("pagedebug")==1 )
00163                         kprintf("Debug Mode - KunmapMem: la tabla esta vacia\n");
00164             return ERR_DIR_EMPTY;
00165     }
00166 
00167     //Liberar la entrada correspondiente
00168     tabla->entry[indice.tabla_index] = 0;
00169 
00170 
00171     //Ahora verifico si todas las entradas de la tabla estan vacias. Si es asi la libero. Con que haya una
00172     //ocupada, no puedo hacerlo
00173     word i;
00174     for ( i=0 ; i < PAGINAS_POR_TABLA ; i++)
00175                 if ( tabla->entry[i] )
00176                         return OK;
00177 
00178         if (getvar("pagedebug")==1)
00179                 kprintf("Kunmapmem: liberando tabla en: 0x%x\n", dir->entry[indice.dir_index] & 0xfffff000);
00180     kfree_page( (addr_t) (dir->entry[indice.dir_index] & 0xfffff000) );    
00181     dir->entry[indice.dir_index] = 0;
00182     return OK;
00183 
00184 }       
00185 
00187 void *make_pdt (void)
00188 {
00189     addr_t nuevo_directorio = kmalloc_page();
00190     if ( nuevo_directorio == 0) {
00191                 return NULL;
00192     }
00193 
00194     copy_page( (void *) nuevo_directorio, (void *) USER_PDT);
00195         return (void *) nuevo_directorio;
00196 }       
00197 
00200 void *copy_page( void *dest, const void *src)
00201 {
00202     __asm__("push %%ecx; push %%edi ; push %%esi ;cld ; rep ; movsl ; pop %%esi ; pop %%edi ; pop %%ecx" \
00203                     :  : "c" ((word) (PAGINA_SIZE / (sizeof(dword)))), "S" (src), "D" (dest));
00204     
00205     return dest;
00206 }
00207 

Generated on Sun May 30 18:38:35 2004 for Routix OS by doxygen 1.3.6