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
00034 indice = get_page_index ( (addr_t) dir_logica );
00035
00036 pd_t *dir= (pd_t *) cr3;
00037
00038 pt_t *tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);
00039
00040 dir_fisica = (void *) (tabla->entry[indice.tabla_index] & 0xfffff000);
00041
00042
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
00073
00074
00075
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
00119 for (i=0; i < PAGINAS_POR_TABLA ; i++)
00120 tabla->entry[i]=(pte_t) make_pte (0, 0);
00121 }
00122
00123 else {
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 ) {
00162 if ( getvar("pagedebug")==1 )
00163 kprintf("Debug Mode - KunmapMem: la tabla esta vacia\n");
00164 return ERR_DIR_EMPTY;
00165 }
00166
00167
00168 tabla->entry[indice.tabla_index] = 0;
00169
00170
00171
00172
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