00001  
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include <vmm/vmm.h>
00031 #include <lib/kprintf.h>
00032 #include <lib/kmalloc.h>
00033 #include <ubixos/types.h>
00034 #include <ubixos/kpanic.h>
00035 #include <ubixos/sched.h>
00036 #include <ubixos/spinlock.h>
00037 #include <string.h>
00038 #include <assert.h>
00039 
00040 uInt32         *kernelPageDirectory = 0x0;
00041 
00042 
00043 static spinLock_t fkpSpinLock = SPIN_LOCK_INITIALIZER;
00044 static spinLock_t rmpSpinLock = SPIN_LOCK_INITIALIZER;
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 int vmm_pagingInit(){
00060   uInt32          i = 0x0;
00061   uInt32         *pageTable = 0x0;
00062 
00063   
00064   kernelPageDirectory = (uInt32 *) vmmFindFreePage(sysID);
00065   if (kernelPageDirectory == 0x0) {
00066     K_PANIC("Error: vmmFindFreePage Failed");
00067     return (0x1);
00068     } 
00069     
00070   
00071   for (i = 0; i < pageEntries; i++) {
00072     (uInt32) kernelPageDirectory[i] = (uInt32) 0x0;
00073   } 
00074   
00075   
00076   if ((pageTable = (uInt32 *) vmmFindFreePage(sysID)) == 0x0)
00077     K_PANIC("Error: vmmFindFreePage Failed");
00078   kernelPageDirectory[0] = (uInt32) ((uInt32) (pageTable) | KERNEL_PAGE_DEFAULT);    
00079     
00080   
00081   memset(pageTable,0x0,0x1000);
00082     
00083   
00084 
00085 
00086 
00087 
00088   for (i = 0x1; i < (pageEntries / 0x4); i++) {
00089     pageTable[i] = (uInt32) ((i * 0x1000) | KERNEL_PAGE_DEFAULT);
00090     } 
00091 
00092   
00093 
00094 
00095 
00096   for (i = 768; i < pageEntries; i++) {
00097     if ((pageTable = (uInt32 *) vmmFindFreePage(sysID)) == 0x0)
00098       K_PANIC("Error: vmmFindFreePage Failed");
00099       
00100     
00101     memset(pageTable,0x0,0x1000);
00102 
00103     
00104     kernelPageDirectory[i] = (uInt32) ((uInt32) (pageTable) | KERNEL_PAGE_DEFAULT);
00105     } 
00106     
00107   
00108   if ((pageTable = (uInt32 *) vmmFindFreePage(sysID)) == 0x0)
00109     K_PANIC("Error: vmmFindFreePage Failed");
00110   
00111   
00112   memset(pageTable,0x0,0x1000);
00113   
00114   kernelPageDirectory[767] = ((uInt32) pageTable | KERNEL_PAGE_DEFAULT);
00115   for (i = 0; i < pageEntries; i++) {
00116     pageTable[i] = kernelPageDirectory[i];
00117     } 
00118   
00119   
00120   pageTable = (uInt32 *) (kernelPageDirectory[0] & 0xFFFFF000);
00121   pageTable[256] = (uInt32) ((uInt32) (kernelPageDirectory) | KERNEL_PAGE_DEFAULT);
00122 
00123   
00124   asm volatile(
00125     "movl %0,%%eax          \n"
00126     "movl %%eax,%%cr3       \n"
00127     "movl %%cr0,%%eax       \n"
00128     "orl  $0x80010000,%%eax \n" 
00129     "movl %%eax,%%cr0       \n"
00130     :
00131     :  "d"((uInt32 *) (kernelPageDirectory))
00132     );
00133 
00134   
00135   for (i = 0x101000; i <= (0x101000 + (numPages * sizeof(mMap))); i += 0x1000) {
00136     if ((vmm_remapPage(i, (vmmMemoryMapAddr + (i - 0x101000)),KERNEL_PAGE_DEFAULT)) == 0x0)
00137       K_PANIC("vmmRemapPage failed\n");
00138     }
00139   
00140   vmmMemoryMap = (mMap *) vmmMemoryMapAddr;
00141 
00142   
00143   kprintf("paging0 - Address: [0x%X], PagingISR Address: [0x%X]\n", kernelPageDirectory, &_vmm_pageFault);
00144 
00145   
00146   return (0x0);
00147   } 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 int vmm_remapPage(uInt32 source,uInt32 dest,uInt16 perms)
00161 {
00162   uInt16  destPageDirectoryIndex = 0x0, destPageTableIndex = 0x0;
00163   uInt32 *pageDir = 0x0, *pageTable = 0x0;
00164   short   i = 0x0;
00165 
00166   if (source == 0x0)
00167     K_PANIC("source == 0x0");
00168   if (dest == 0x0)
00169     K_PANIC("dest == 0x0");
00170 
00171   spinLock(&rmpSpinLock);
00172   if (perms == 0x0)
00173     perms = KERNEL_PAGE_DEFAULT;
00174 
00175   
00176 
00177 
00178 
00179   pageDir = (uInt32 *) parentPageDirAddr;
00180   
00181   if (dest == 0x0)
00182     return(0x0);
00183   
00184   
00185   destPageDirectoryIndex = (dest / 0x400000);
00186   
00187   if ((pageDir[destPageDirectoryIndex] & PAGE_PRESENT) != PAGE_PRESENT) {
00188     
00189     
00190     pageDir[destPageDirectoryIndex] = (uInt32) vmmFindFreePage(_current->id) | PAGE_DEFAULT;
00191     
00192     
00193     pageTable = (uInt32 *) (tablesBaseAddress + 0x2FF000);
00194     pageTable[destPageDirectoryIndex] = pageDir[destPageDirectoryIndex];
00195     
00196     asm volatile(
00197       "push %eax       \n"
00198       "mov  %cr3,%eax  \n"
00199       "mov  %eax,%cr3  \n"
00200       "pop  %eax       \n"
00201       );
00202     pageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * destPageDirectoryIndex));
00203     for (i = 0x0;i < pageEntries;i++)
00204       pageTable[i] = 0x0;
00205   }
00206   
00207   pageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * destPageDirectoryIndex));
00208 
00209   
00210   destPageTableIndex = ((dest - (destPageDirectoryIndex * 0x400000)) / 0x1000);
00211 
00212 
00213   
00214   if ((pageTable[destPageTableIndex] & PAGE_PRESENT) == PAGE_PRESENT) {
00215     if ((pageTable[destPageTableIndex] & PAGE_STACK) == PAGE_STACK)
00216       kprintf("Stack Page: [0x%X]\n",dest);
00217 
00218     if ((pageTable[destPageTableIndex] & PAGE_COW) != PAGE_COW) {
00219       kprintf("Page NOT COW\n");
00220       kprintf("Page Present: [0x%X][0x%X]",dest,pageTable[destPageTableIndex]);
00221       source = 0x0;
00222       goto rmDone;
00223       }
00224     
00225     freePage(((uInt32) pageTable[destPageTableIndex] & 0xFFFFF000));
00226   }
00227   
00228   pageTable[destPageTableIndex] = (uInt32) (source | perms);
00229   
00230   asm volatile(
00231       "push %eax     \n"
00232       "movl %cr3,%eax\n"
00233       "movl %eax,%cr3\n"
00234       "pop  %eax     \n"
00235     );
00236 
00237   rmDone:
00238   
00239   spinUnlock(&rmpSpinLock);
00240   return (source);
00241 }
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 void           *
00253 vmmGetFreeKernelPage(pidType pid, uInt16 count)
00254 {
00255   int             x = 0, y = 0, c = 0;
00256   uInt32         *pageTableSrc = 0x0;
00257 
00258   spinLock(&fkpSpinLock);
00259   
00260   for (x = 768; x < 1024; x++) {
00261     
00262     pageTableSrc = (uInt32 *) (tablesBaseAddress + (4096 * x));
00263     for (y = 0; y < 1024; y++) {
00264       
00265       if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) {
00266         if (count > 1) {
00267           for (c = 0; c < count; c++) {
00268             if (y + c < 1024) {
00269               if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) {
00270                 c = -1;
00271                 break;
00272                 }
00273               }
00274             }
00275           if (c != -1) {
00276             for (c = 0; c < count; c++) {
00277               if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),KERNEL_PAGE_DEFAULT)) == 0x0)
00278                 K_PANIC("vmmRemapPage failed: gfkp-1\n");
00279               vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096)));
00280             }
00281             spinUnlock(&fkpSpinLock);
00282             return ((void *)((x * (1024 * 4096)) + (y * 4096)));
00283           }
00284         } else {
00285           
00286 
00287           if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),KERNEL_PAGE_DEFAULT)) == 0x0)
00288             K_PANIC("vmmRemapPage failed: gfkp-2\n");
00289           
00290           vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096)));
00291           
00292           spinUnlock(&fkpSpinLock);
00293           return ((void *)((x * (1024 * 4096)) + (y * 4096)));
00294         }
00295       }
00296     }
00297   }
00298   
00299   spinUnlock(&fkpSpinLock);
00300   return (0x0);
00301 }
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 int 
00314 vmmClearVirtualPage(uInt32 pageAddr)
00315 {
00316   uInt32         *src = 0x0;
00317   int             counter = 0x0;
00318 
00319   
00320   src = (uInt32 *) pageAddr;
00321 
00322   
00323   for (counter = 0x0; counter < pageEntries; counter++) {
00324     (uInt32) src[counter] = (uInt32) 0x0;
00325   }
00326 
00327   
00328   return (0x0);
00329 }
00330 
00331 
00332 void *vmmMapFromTask(pidType pid,void *ptr,uInt32 size) {
00333   kTask_t *child = 0x0;
00334   uInt32 i = 0x0,x = 0x0,y = 0x0,count = ((size+4095)/0x1000),c = 0x0;
00335   uInt16 dI = 0x0,tI = 0x0;
00336   uInt32 baseAddr = 0x0,offset = 0x0;
00337   uInt32 *childPageDir   = (uInt32 *)0x5A00000;
00338   uInt32 *childPageTable = 0x0;
00339   uInt32 *pageTableSrc   = 0x0;
00340   offset = (uInt32)ptr & 0xFFF;
00341   baseAddr = (uInt32)ptr & 0xFFFFF000;
00342   child = schedFindTask(pid);
00343   
00344   dI = (baseAddr/(1024*4096));
00345   tI = ((baseAddr-(dI*(1024*4096)))/4096);
00346   if (vmm_remapPage(child->tss.cr3,0x5A00000,KERNEL_PAGE_DEFAULT) == 0x0)
00347     K_PANIC("vmmFailed");
00348 
00349   for (i=0;i<0x1000;i++) {
00350     if (vmm_remapPage(childPageDir[i],0x5A01000 + (i * 0x1000),KERNEL_PAGE_DEFAULT) == 0x0)
00351       K_PANIC("Returned NULL");
00352     }
00353   for (x=(_current->oInfo.vmStart/(1024*4096));x<1024;x++) {
00354     pageTableSrc = (uInt32 *)(tablesBaseAddress + (4096*x));
00355     for (y=0;y<1024;y++) {
00356       
00357       if ((uInt32)pageTableSrc[y] == (uInt32)0x0) {
00358         if (count > 1) {
00359           for (c=0;((c<count) && (y+c < 1024));c++) {
00360             if ((uInt32)pageTableSrc[y+c] != (uInt32)0x0) {
00361               c = -1;
00362               break;
00363               }
00364             }
00365           if (c != -1) {
00366             for (c=0;c<count;c++) {
00367               if ((tI + c) >= 0x1000) {
00368                 dI++;
00369                 tI = 0-c;
00370                 }
00371               childPageTable = (uInt32 *)(0x5A01000 + (0x1000 * dI));
00372               if (vmm_remapPage(childPageTable[tI+c],((x*(1024*4096))+((y+c)*4096)),KERNEL_PAGE_DEFAULT) == 0x0)
00373                 K_PANIC("remap == NULL");
00374               }
00375             vmmUnmapPage(0x5A00000,1);
00376             for (i=0;i<0x1000;i++) {
00377               vmmUnmapPage((0x5A01000 + (i*0x1000)),1);
00378               }
00379             return((void *)((x*(1024*4096))+(y*4096)+offset));
00380             }
00381           }
00382         else {
00383           
00384           childPageTable = (uInt32 *)(0x5A01000 + (0x1000 * dI));
00385           if (vmm_remapPage(childPageTable[tI],((x*(1024*4096))+(y*4096)),KERNEL_PAGE_DEFAULT) == 0x0)
00386             K_PANIC("remap Failed");
00387 
00388           
00389           vmmUnmapPage(0x5A00000,1);
00390           for (i=0;i<0x1000;i++) {
00391             vmmUnmapPage((0x5A01000 + (i*0x1000)),1);
00392             }
00393           return((void *)((x*(1024*4096))+(y*4096)+offset));
00394           }
00395         }
00396       }
00397     }
00398   return(0x0);
00399   }
00400 
00401 void *vmm_getFreeMallocPage(uInt16 count) {
00402   uInt16  x = 0x0, y = 0x0;
00403   int     c = 0x0;
00404   uInt32 *pageTableSrc = 0x0;
00405 
00406   spinLock(&fkpSpinLock);
00407   
00408   for (x = 960; x < 1024; x++) {
00409     
00410     pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x));
00411     for (y = 0; y < 1024; y++) {
00412       
00413       if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) {
00414         if (count > 1) {
00415           for (c = 0; c < count; c++) {
00416             if (y + c < 1024) {
00417               if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) {
00418                 c = -1;
00419                 break;
00420                 }
00421               }
00422             }
00423           if (c != -1) {
00424             for (c = 0; c < count; c++) {
00425               if (vmm_remapPage((uInt32) vmmFindFreePage(sysID), ((x * 0x400000) + ((y + c) * 0x1000)),KERNEL_PAGE_DEFAULT) == 0x0)
00426                 K_PANIC("remap Failed");
00427 
00428               vmmClearVirtualPage((uInt32) ((x * 0x400000) + ((y + c) * 0x1000)));
00429               }
00430             spinUnlock(&fkpSpinLock);
00431             return ((void *)((x * 0x400000) + (y * 0x1000)));
00432             }
00433           }
00434         else {
00435           
00436           if (vmm_remapPage((uInt32) vmmFindFreePage(sysID), ((x * 0x400000) + (y * 0x1000)),KERNEL_PAGE_DEFAULT) == 0x0)
00437             K_PANIC("Failed");
00438 
00439           
00440           vmmClearVirtualPage((uInt32) ((x * 0x400000) + (y * 0x1000)));
00441           
00442           spinUnlock(&fkpSpinLock);
00443           return ((void *)((x * 0x400000) + (y * 0x1000)));
00444           }
00445         }
00446       }
00447     }
00448   
00449   spinUnlock(&fkpSpinLock);
00450   return (0x0);
00451   }
00452   
00453 int mmap(struct thread *td,struct mmap_args *uap) {
00454   vm_offset_t addr = 0x0;
00455 
00456   addr = (vm_offset_t) uap->addr;
00457 
00458   if (uap->addr != 0x0) {
00459     kprintf("Address hints are not supported yet.\n");
00460     }
00461   
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470   if (uap->fd == -1)
00471     td->td_retval[0] = vmmGetFreeVirtualPage(_current->id,uap->len/0x1000,VM_TASK);
00472   else 
00473     td->td_retval[0] = 0x0;
00474   return(0x0);
00475   }
00476 
00477 int obreak(struct thread *td,struct obreak_args *uap) {
00478   u_int32_t   i    = 0x0;
00479   vm_offset_t old  = 0x0;
00480   vm_offset_t base = 0x0;
00481   vm_offset_t new  = 0x0;
00482   
00483   
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491   new  = round_page((vm_offset_t)uap->nsize);
00492 
00493   base = round_page((vm_offset_t)td->vm_daddr);
00494 
00495   old = base + ctob(td->vm_dsize);
00496   
00497   
00498 
00499   if (new < base) 
00500     K_PANIC("EINVAL");
00501 
00502   
00503   if (new > old) {
00504     for (i = old;i < new;i+= 0x1000) {
00505       if (vmm_remapPage(vmmFindFreePage(_current->id),i,PAGE_DEFAULT) == 0x0)
00506         K_PANIC("remap Failed");
00507       }
00508     td->vm_dsize += btoc(new - old);
00509     }
00510   else if (new < old) {
00511     
00512 
00513 
00514 
00515 
00516     K_PANIC("new < old"); 
00517     td->vm_dsize -= btoc(old - new);
00518     }
00519   return(0x0);
00520   }
00521 
00522 int munmap(struct thread *td,struct munmap_args *uap) {
00523   
00524   kprintf("munmap");
00525   return(0x0);
00526   }
00527 
00528 int vmm_cleanVirtualSpace(u_int32_t addr) {
00529   int         x            = 0x0;
00530   int         y            = 0x0;
00531   u_int32_t  *pageTableSrc = 0x0;
00532   u_int32_t  *pageDir      = 0x0;
00533 
00534   pageDir = (uInt32 *) parentPageDirAddr;
00535 
00536   kprintf("CVS: [0x%X]\n",addr);
00537 
00538   for (x = (addr / (1024 * 4096)); x < 770; x++) {
00539     if ((pageDir[x] & PAGE_PRESENT) == PAGE_PRESENT) {
00540       pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x));
00541       for (y = 0;y < 1024;y++) {
00542         if (pageTableSrc[y] != 0x0) { 
00543           if ((pageTableSrc[y] & PAGE_COW) == PAGE_COW) {
00544             
00545             pageTableSrc[y] = 0x0;
00546             }
00547           else if ((pageTableSrc[y] & PAGE_STACK) == PAGE_STACK) {
00548             
00549             
00550             }
00551           else {
00552             kprintf("+");
00553             }
00554           }
00555         }
00556       }
00557     }
00558 
00559   return(0x0);
00560   }
00561 
00562 
00563 
00564 
00565 
00566