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 <sys/io.h>
00032 #include <ubixos/kpanic.h>
00033 #include <lib/kprintf.h>
00034 #include <lib/kmalloc.h>
00035 #include <sys/kern_sysctl.h>
00036 #include <ubixos/spinlock.h>
00037 #include <assert.h>
00038
00042 static uInt32 freePages = 0;
00043 static spinLock_t vmmSpinLock = SPIN_LOCK_INITIALIZER;
00044 static spinLock_t vmmCowSpinLock = SPIN_LOCK_INITIALIZER;
00045
00046
00047 int numPages = 0x0;
00048 mMap *vmmMemoryMap = (mMap *) 0x101000;
00049
00050
00060 int vmmMemMapInit() {
00061 int i = 0x0;
00062 int memStart = 0x0;
00063
00064
00065 numPages = countMemory();
00066
00067
00068 vmmMemoryMap = (mMap *) 0x101000;
00069
00070
00071 for (i = 0x0; i < numPages; i++) {
00072 vmmMemoryMap[i].cowCounter = 0x0;
00073 vmmMemoryMap[i].status = memNotavail;
00074 vmmMemoryMap[i].pid = vmmID;
00075 vmmMemoryMap[i].pageAddr = i * 4096;
00076 }
00077
00078
00079 memStart = (0x101000 / 0x1000);
00080 memStart += (((sizeof(mMap) * numPages) + (sizeof(mMap) - 1)) / 0x1000);
00081
00082
00083 vmmMemoryMap[(0x100000 / 0x1000)].status = memAvail;
00084 freePages++;
00085 for (i = memStart; i < numPages; i++) {
00086 vmmMemoryMap[i].status = memAvail;
00087 freePages++;
00088 }
00089
00090
00091 kprintf("Real Memory: %iKB\n", numPages * 4);
00092 kprintf("Available Memory: %iKB\n", freePages * 4);
00093
00094
00095 return (0);
00096 }
00097
00107 int countMemory() {
00108 register uInt32 *mem = 0x0;
00109 unsigned long memCount = -1, tempMemory = 0x0;
00110 unsigned short memKb = 0;
00111 unsigned char irq1State, irq2State;
00112 unsigned long cr0 = 0x0;
00113
00114
00115
00116
00117
00118 irq1State = inportByte(0x21);
00119 irq2State = inportByte(0xA1);
00120
00121
00122 outportByte(0x21, 0xFF);
00123 outportByte(0xA1, 0xFF);
00124
00125
00126 asm volatile (
00127 "movl %%cr0, %%ebx\n"
00128 : "=a" (cr0)
00129 :
00130 : "ebx"
00131 );
00132
00133 asm volatile ("wbinvd");
00134 asm volatile (
00135 "movl %%ebx, %%cr0\n"
00136 :
00137 : "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000)
00138 : "ebx"
00139 );
00140
00141 while (memKb < 4096 && memCount != 0) {
00142 memKb++;
00143 if (memCount == -1)
00144 memCount = 0;
00145 memCount += 1024 * 1024;
00146 mem = (uInt32 *)memCount;
00147 tempMemory = *mem;
00148 *mem = 0x55AA55AA;
00149 asm("": : :"memory");
00150 if (*mem != 0x55AA55AA) {
00151 memCount = 0;
00152 }
00153 else {
00154 *mem = 0xAA55AA55;
00155 asm("": : :"memory");
00156 if (*mem != 0xAA55AA55) {
00157 memCount = 0;
00158 }
00159 }
00160 asm("": : :"memory");
00161 *mem = tempMemory;
00162 }
00163
00164 asm volatile (
00165 "movl %%ebx, %%cr0\n"
00166 :
00167 : "a" (cr0)
00168 : "ebx"
00169 );
00170
00171
00172 outportByte(0x21, irq1State);
00173 outportByte(0xA1, irq2State);
00174
00175
00176 return ((memKb * 1024 * 1024) / 4096);
00177 }
00178
00189 uInt32 vmmFindFreePage(pidType pid) {
00190 int i = 0x0;
00191
00192
00193 if (pid < sysID)
00194 kpanic("Error: invalid PID %i\n",pid);
00195
00196 spinLock(&vmmSpinLock);
00197
00198 for (i = 0; i <= numPages; i++) {
00199
00200
00201
00202
00203
00204 if ((vmmMemoryMap[i].status == memAvail) && (vmmMemoryMap[i].cowCounter == 0)) {
00205 vmmMemoryMap[i].status = memNotavail;
00206 vmmMemoryMap[i].pid = pid;
00207 freePages--;
00208 if (sysctl_enabled == TRUE) {
00209 systemVitals->freePages = freePages;
00210 }
00211
00212 spinUnlock(&vmmSpinLock);
00213 return (vmmMemoryMap[i].pageAddr);
00214 }
00215 }
00216
00217
00218 kpanic("Out Of Memory!!!!");
00219 return (0x0);
00220 }
00221
00222
00232 int freePage(uInt32 pageAddr) {
00233 int pageIndex = 0x0;
00234 assert((pageAddr & 0xFFF) == 0x0);
00235 spinLock(&vmmSpinLock);
00236
00237
00238 pageIndex = (pageAddr / 4096);
00239
00240
00241 if (vmmMemoryMap[pageIndex].cowCounter == 0) {
00242
00243 vmmMemoryMap[pageIndex].status = memAvail;
00244 vmmMemoryMap[pageIndex].cowCounter = 0x0;
00245 vmmMemoryMap[pageIndex].pid = -2;
00246 freePages++;
00247 systemVitals->freePages = freePages;
00248 }
00249 else {
00250
00251 adjustCowCounter(((uInt32) vmmMemoryMap[pageIndex].pageAddr), -1);
00252 }
00253 spinUnlock(&vmmSpinLock);
00254
00255 return (0);
00256 }
00257
00270 int adjustCowCounter(uInt32 baseAddr, int adjustment) {
00271 int vmmMemoryMapIndex = (baseAddr / 4096);
00272 assert((baseAddr & 0xFFF) == 0x0);
00273 spinLock(&vmmCowSpinLock);
00274
00275 vmmMemoryMap[vmmMemoryMapIndex].cowCounter += adjustment;
00276
00277 if (vmmMemoryMap[vmmMemoryMapIndex].cowCounter == 0) {
00278 vmmMemoryMap[vmmMemoryMapIndex].cowCounter = 0x0;
00279 vmmMemoryMap[vmmMemoryMapIndex].pid = vmmID;
00280 vmmMemoryMap[vmmMemoryMapIndex].status = memAvail;
00281 freePages++;
00282 systemVitals->freePages = freePages;
00283 }
00284 spinUnlock(&vmmCowSpinLock);
00285
00286 return (0);
00287 }
00288
00300 void vmmFreeProcessPages(pidType pid) {
00301 int i=0,x=0;
00302 uInt32 *tmpPageTable = 0x0;
00303 uInt32 *tmpPageDir = (uInt32 *)parentPageDirAddr;
00304 spinLock(&vmmSpinLock);
00305
00306 for (i=0;i<=0x300;i++) {
00307 if (tmpPageDir[i] != 0) {
00308
00309 tmpPageTable = (uInt32 *)(tablesBaseAddress + (i * 0x1000));
00310
00311 for (x=0;x<pageEntries;x++) {
00312
00313 if (((uInt32)tmpPageTable[x] & PAGE_COW) == PAGE_COW) {
00314 adjustCowCounter(((uInt32)tmpPageTable[x] & 0xFFFFF000),-1);
00315 }
00316 }
00317 }
00318 }
00319
00320
00321 for (i=0;i<numPages;i++) {
00322 if (vmmMemoryMap[i].pid == pid) {
00323
00324 if (vmmMemoryMap[i].cowCounter == 0) {
00325 vmmMemoryMap[i].status = memAvail;
00326 vmmMemoryMap[i].cowCounter = 0x0;
00327 vmmMemoryMap[i].pid = vmmID;
00328 freePages++;
00329 systemVitals->freePages = freePages;
00330 }
00331 }
00332 }
00333
00334 spinUnlock(&vmmSpinLock);
00335 return;
00336 }
00337
00338
00339
00340
00341