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 #ifdef DEBUG
00459 if (uap->addr != 0x0) {
00460 kprintf("Address hints are not supported yet.\n");
00461 }
00462 kprintf("uap->flags: [0x%X]\n",uap->flags);
00463 kprintf("uap->addr: [0x%X]\n",uap->addr);
00464 kprintf("uap->len: [0x%X]\n",uap->len);
00465 kprintf("uap->prot: [0x%X]\n",uap->prot);
00466 kprintf("uap->fd: [%i]\n",uap->fd);
00467 kprintf("uap->pad: [0x%X]\n",uap->pad);
00468 kprintf("uap->pos: [0x%X]\n",uap->pos);
00469 #endif
00470
00471 if (uap->fd == -1)
00472 td->td_retval[0] = vmmGetFreeVirtualPage(_current->id,uap->len/0x1000,VM_TASK);
00473 else
00474 td->td_retval[0] = 0x0;
00475 return(0x0);
00476 }
00477
00478 int obreak(struct thread *td,struct obreak_args *uap) {
00479 uint32_t i = 0x0;
00480 vm_offset_t old = 0x0;
00481 vm_offset_t base = 0x0;
00482 vm_offset_t new = 0x0;
00483
00484 #ifdef DEBUG
00485 kprintf("vm_offset_t: [%i]\n",sizeof(vm_offset_t));
00486 kprintf("nsize: [0x%X]\n",uap->nsize);
00487 kprintf("vm_daddr: [0x%X]\n",td->vm_daddr);
00488 kprintf("vm_dsize: [0x%X]\n",td->vm_dsize);
00489 kprintf("total: [0x%X]\n",td->vm_daddr + td->vm_dsize);
00490 #endif
00491
00492 new = round_page((vm_offset_t)uap->nsize);
00493
00494 base = round_page((vm_offset_t)td->vm_daddr);
00495
00496 old = base + ctob(td->vm_dsize);
00497
00498 if (new < base)
00499 K_PANIC("EINVAL");
00500
00501 if (new > old) {
00502 for (i = old;i < new;i+= 0x1000) {
00503 if (vmm_remapPage(vmmFindFreePage(_current->id),i,PAGE_DEFAULT) == 0x0)
00504 K_PANIC("remap Failed");
00505 }
00506 td->vm_dsize += btoc(new - old);
00507 }
00508 else if (new < old) {
00509 K_PANIC("new < old");
00510 td->vm_dsize -= btoc(old - new);
00511 }
00512
00513 return(0x0);
00514 }
00515
00516 int munmap(struct thread *td,struct munmap_args *uap) {
00517
00518 kprintf("munmap");
00519 return(0x0);
00520 }
00521
00522 int vmm_cleanVirtualSpace(uint32_t addr) {
00523 int x = 0x0;
00524 int y = 0x0;
00525 uint32_t *pageTableSrc = 0x0;
00526 uint32_t *pageDir = 0x0;
00527
00528 pageDir = (uInt32 *) parentPageDirAddr;
00529
00530 #ifdef DEBUG
00531 kprintf("CVS: [0x%X]\n",addr);
00532 #endif
00533
00534 for (x = (addr / (1024 * 4096)); x < 770; x++) {
00535 if ((pageDir[x] & PAGE_PRESENT) == PAGE_PRESENT) {
00536 pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x));
00537 for (y = 0;y < 1024;y++) {
00538 if (pageTableSrc[y] != 0x0) {
00539 if ((pageTableSrc[y] & PAGE_COW) == PAGE_COW) {
00540
00541 pageTableSrc[y] = 0x0;
00542 }
00543 else if ((pageTableSrc[y] & PAGE_STACK) == PAGE_STACK) {
00544
00545
00546 }
00547 else {
00548
00549 }
00550 }
00551 }
00552 }
00553 }
00554 asm(
00555 "movl %cr3,%eax\n"
00556 "movl %eax,%cr3\n"
00557 );
00558 return(0x0);
00559 }
00560
00561
00562
00563
00564