/* translate virtual address to pysical address. handles tlbmiss, page faults, loads page to physical memory in case of page fault */ int translate(VirtualAddress address, PhysicalAddress &physicalAddress) { int rval = status_success; PageEntry pageEntry; /* the page entry from page table. We use this for lookup in page table, and get frame no from it */ Page page; /* in case we need to get page from backing store and add it to physical memory */ FrameNumber frameno; /* in case we need to add page to physical memory */ PageNumber pageno = -1; /* page number we will lookkup. get this from virtual address */ int offset = -1; /* offset we will lookkup. get this from virtual address */ bool pagehit = false; /* flags */ bool tlbhit = false; /* break address to page no offset */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- get page number and offset\n"); pageno = getPageNumberFromLogicalAddress(address); offset = getOffsetFromLogicalAddress(address); /* we are storing he required frame number in the frameno value, weather we get a hit from tlb, page table or page fault */ /* check in tlb */ tlb.lookup(pageno, frameno, tlbhit); if(true == tlbhit) { /* we are done here */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate - tlbhit !!\n"); tlbhits++; } else { /* check in page table tlb miss */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- get page entry for page no : %d\n", pageno); if(status_success != pageTable.lookup(pageno, pageEntry)) { rval = status_failure; zlog(ZLOG_LOC, "VirtualMemoryManager::translate- unable to get page table entry\n"); goto exit1; } /* check if this is a page fault */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- check for page fault\n"); if(true == pageEntry.isValid) { /* we are done */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- page hit! \n"); frameno = pageEntry.frameNumber; pagehit = true; /* update counter */ pagehits++; } /* page fault code */ if(false == pagehit) { /* update counter */ pagefaults++; /* get page from backing store */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- page fault on page : %d, reading block : %d from backing store\n", pageno, pageno); if(status_success != backingStore.getPage(page, pageno*PageSize, PageSize)) { zlog(ZLOG_LOC, "VirtualMemoryManager::translate- unable to get page form backing store\n"); rval = status_failure; goto exit2; } /* add to physical memory */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- putting the page in physical memory\n"); if(status_success != physicalMemory.addPage(page, frameno)) { zlog(ZLOG_LOC, "VirtualMemoryManager::translate- unable to add page to physical memory\n"); rval = status_failure; goto exit2; } /* update page entry */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- update page Entry \n"); pageEntry.frameNumber = frameno; pageEntry.isModified = false; pageEntry.isValid = true; /* add page entry to page table */ zlog(ZLOG_LOC, "VirtualMemoryManager::translate- update page table\n"); if(status_success != pageTable.updatePageEntry(pageEntry, pageno)) { zlog(ZLOG_LOC, "VirtualMemoryManager::translate- unable to add entry to page table\n"); rval = status_failure; goto exit2; } zlog(ZLOG_LOC, "VirtualMemoryManager::translate- lookup page table again\n"); frameno = pageEntry.frameNumber; pagehit = true; } /* by this time we have a valid page frame mapping if there was a tlb miss, update tlb table */ if(false == tlbhit) { TlbEntry tlbEntry; tlbEntry.pageNumber = pageno; tlbEntry.frameNumber = frameno; tlbEntry.valid = true; tlb.addEntry(tlbEntry); } } /* page entry contains the frame number required */ physicalAddress = (frameno << numBitsForFrameOffset) + offset; exit2: exit1: return rval; }
void *MMU::palloc(size_t numberOfPages) { size_t contiguousFoundPages = 0; size_t retpde = 0, retpte = 0; void *retval = nullptr; for (size_t pde = 0; pde < 1024 && contiguousFoundPages != numberOfPages; ++pde) { PageTable table = getOrCreateTable(pde); // look through page table for (size_t pte = 0; pte < 1024; ++pte) { PageEntry entry = table.entryAtIndex(pte); if (!entry.getFlag(kPresentBit)) { // found a page that isn't present (is available) if (contiguousFoundPages == 0) { // this is the first available page, set our return pointer to it retpde = pde; retpte = pte; } ++contiguousFoundPages; if (contiguousFoundPages == numberOfPages) { // done retval = (void *) ((retpde << 22) | (retpte << 12)); break; } } else if (contiguousFoundPages) { // current page is used, reset our contiguous page count retval = nullptr; contiguousFoundPages = 0; } } } if (retval) { // if we succeeded in finding space allocatePages(retval, numberOfPages); } return retval; }
int getPhysicalAddr(unsigned int x){ unsigned int pageNum = getPageNum(x) + 1; unsigned int offset = getPageOff(x); return ((ptable.getFrameNumber(pageNum)-1) * 256) + offset; }
int main(int argc, char* argv[]){ size_t pos = 0; int count = 0; string input; string fOutput; //get the input yo if(argc > 1){ input = argv[1]; } else { cerr << "Failed, usage is memTrans <InputFile> \n"; exit(EXIT_FAILURE); } ifstream fRead(input); while(!fRead.eof()){ getline(fRead,fOutput); istringstream r(fOutput); unsigned int fOut; r >> fOut; if(fOut != 0){ count++; signed int value = getValue(fOut); cout << "Virtual address: " << fOut << " "; cout << "Physical address: " << getPhysicalAddr(fOut) << " "; cout << "Value: " << value << std::endl; } fOut = 0; } //close the damn reader fRead.close(); //output needed statistics cout << "Number of Translated Addresses = " << count << std::endl; cout << "Page faults = " << ptable.getCounter() << std::endl; cout << "Page Fault Rate = " << ((double)ptable.getCounter()/(double)count) << std::endl; cout << "TLB hits = " << working_tlb.getHits() << std::endl; cout << "TLB Hit Rate = = " << ((double)working_tlb.getHits()/(double)count) << std::endl; //cout << "All Done <(^_^)^" << std::endl; return 0; }
int MMU::pfree(void *startOfMemoryRange, size_t numberOfPages) { uint32_t virtualAddress = (uint32_t) startOfMemoryRange; if (!numberOfPages) return -1; while (numberOfPages--) { uint32_t pdeIndex = virtualAddress >> 22; uint32_t pteIndex = virtualAddress >> 12 & 0x03FF; PageTable table = PageTableForDirectoryIndex(pdeIndex); PageEntry pte = table.entryAtIndex(pteIndex); _pageFrameAllocator.free(pte.address()); table.setEntry(pteIndex, PageEntry(0)); virtualAddress += 0x1000; } _flush(); return 0; }
void MMU::allocatePages(void *address, size_t numberOfPages) { uintptr_t virtualAddress = reinterpret_cast<uintptr_t>(address); uint32_t currpde = virtualAddress >> 22; uint32_t currpte = virtualAddress >> 12 & 0x03FF; size_t pagesLeft = numberOfPages; while (pagesLeft > 0) { // map the pages PageTable table = PageTableForDirectoryIndex(currpde); PageEntry entry = PageEntry(_pageFrameAllocator.alloc()); entry.setFlags(kPresentBit | kReadWriteBit); table.setEntry(currpte, entry); ++currpte; --pagesLeft; // move to next PDE if needed if (currpte > 1023) { ++currpde; currpte = 0; } } _flush(); }
int main() { GDT::init(); Console::init(); IDT::init(); ExceptionHandler::init_dispatcher(); IRQ::init(); InterruptHandler::init_dispatcher(); /* -- EXAMPLE OF AN EXCEPTION HANDLER -- */ class DBZ_Handler : public ExceptionHandler { public: virtual void handle_exception(REGS * _regs) { Console::puts("DIVISION BY ZERO!\n"); for(;;); } } dbz_handler; ExceptionHandler::register_handler(0, &dbz_handler); /* -- INITIALIZE FRAME POOLS -- */ FramePool kernel_mem_pool(KERNEL_POOL_START_FRAME, KERNEL_POOL_SIZE, 0); unsigned long process_mem_pool_info_frame = kernel_mem_pool.get_frame(); FramePool process_mem_pool(PROCESS_POOL_START_FRAME, PROCESS_POOL_SIZE, process_mem_pool_info_frame); process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE); /* -- INITIALIZE MEMORY (PAGING) -- */ /* ---- INSTALL PAGE FAULT HANDLER -- */ class PageFault_Handler : public ExceptionHandler { public: virtual void handle_exception(REGS * _regs) { PageTable::handle_fault(_regs); } } pagefault_handler; ExceptionHandler::register_handler(14, &pagefault_handler); /* ---- INITIALIZE THE PAGE TABLE -- */ PageTable::init_paging(&kernel_mem_pool, &process_mem_pool, 4 MB); PageTable pt; pt.load(); PageTable::enable_paging(); /* -- INITIALIZE THE TIMER (we use a very simple timer).-- */ SimpleTimer timer(100); /* timer ticks every 10ms. */ InterruptHandler::register_handler(0, &timer); /* NOTE: The timer chip starts periodically firing as soon as we enable interrupts. It is important to install a timer handler, as we would get a lot of uncaptured interrupts otherwise. */ /* -- ENABLE INTERRUPTS -- */ Machine::enable_interrupts(); /* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */ Console::puts("Hello World!\n"); /* -- GENERATE MEMORY REFERENCES */ int *foo = (int *) FAULT_ADDR; int i; for (i=0; i<NACCESS; i++) { foo[i] = i; } for (i=0; i<NACCESS; i++) { if(foo[i] != i) { Console::puts("TEST FAILED for access number:"); Console::putui(i); Console::puts("\n"); break; } } if(i == NACCESS) { Console::puts("TEST PASSED\n"); } /* -- NOW LOOP FOREVER */ for(;;); /* -- WE DO THE FOLLOWING TO KEEP THE COMPILER HAPPY. */ return 1; }
signed int getValue(unsigned int x){ unsigned int pageNum = getPageNum(x) + 1; unsigned int offset = getPageOff(x); //cout << pageNum; if(working_tlb.check(pageNum)){ //need more things here, like returning the actual physical address return (ptable.getValue(working_tlb.getFrameNumber(pageNum), offset)); } else if(ptable.checkPageTable(pageNum)){ //if in the page table, return the physical address working_tlb.addEntry(pageNum, ptable.getFrameNumber(pageNum)); return (ptable.getValue(ptable.getFrameNumber(pageNum), offset)); } else if((!(ptable.checkPageTable(pageNum)) && !(working_tlb.check(pageNum)))){ //up the page fault counter Frame f; f.setVal(getFrameDat(pageNum)); f.setPageNumber(pageNum); ptable.addEntry(f); ptable.incCounter(); working_tlb.addEntry(pageNum, ptable.getFrameNumber(pageNum)); return (ptable.getValue(ptable.getFrameNumber(pageNum), offset)); } }
int main(int argc, char **argv) { //cout<<argc<<endl; //srand((int)time(NULL)); /** * Configuration */ for(int i = 1; i < argc; i++) { if(i == 1) { if(strcmp(argv[i], "1") == 0) { debugMode = true; } else { debugMode = false; } } else if(i == 2) { sscanf(argv[i],"%d",&numberOfTLBEntries); numberOfTLBEntries = getNearestBiggerPowerOfTwo(numberOfTLBEntries); } else if(i == 3) { sscanf(argv[i],"%d",&numberOfPageFrames); numberOfPageFrames = getNearestBiggerPowerOfTwo(numberOfPageFrames); } else if(i == 4) { sscanf(argv[i],"%d",&numberOfInstructions); } else if(i == 5) { sscanf(argv[i],"%d",&pageChangeAfterInstructionCount); } } /** * Initial State */ cout<<"Debug Mode: "<<debugMode<<endl; cout<<"Total number of TLB Entries: "<<numberOfTLBEntries<<endl; cout<<"Total number of Page Frames: "<<numberOfPageFrames<<endl; cout<<"Total number of Instructions: "<<numberOfInstructions<<endl; cout<<"Total number of Virtual Pages: "<<numberOfVirtualPages<<endl; cout<<"On Average Virtual Address Page Changes after: "<<pageChangeAfterInstructionCount<<endl; /** * Operation starts... * Create a pageTable, a TLB */ PageTable pageTable; TranslationLookaheadBuffer tlb(numberOfTLBEntries); pageTable.setTranslationLookaheadBuffer(&tlb); for(int i = 0; i < numberOfInstructions; i++) { Instruction nextInstruction = getNextInstruction(); if(debugMode) { nextInstruction.print(); } LookupResult l = tlb.lookup(nextInstruction.msbAddress); if(l.isFound == true) { //do nothing } else { if(debugMode) { printf("Cache Miss for page %02x\n",nextInstruction.msbAddress); } totalNumberOfCacheMisses += 1; l = pageTable.lookup(nextInstruction.msbAddress); if(l.isFound == true) { //do nothing } else { if(debugMode) { printf("Page fault on page %02x\n",nextInstruction.msbAddress); } totalNumberOfPageFaults += 1; pageTable.insert(nextInstruction.msbAddress); l = pageTable.lookup(nextInstruction.msbAddress); } tlb.insert(nextInstruction.msbAddress, l.frameIndex); //pageTable.insert(nextInstruction.msbAddress); //l = pageTable.lookup(nextInstruction.msbAddress); } // if(debugMode) { printf("Virtual Address: %02x%02x, Physical Address: %02x%02x\n", nextInstruction.msbAddress, nextInstruction.lsbAddress, l.frameIndex, nextInstruction.lsbAddress); } } cout<<"Total number of Cache Misses: "<<totalNumberOfCacheMisses<<endl; cout<<"Total number of Page Faults: "<<totalNumberOfPageFaults<<endl; cout<<"Total number of Page Used: "<<pageTable.getUsedPageCount()<<endl; cout<<"Total number of Page Changed: "<<pageChangeCount<<endl; /*TranslationLookaheadBuffer tlb; unsigned char accessPattern[] = "ABACBDADEDAEBAC"; for(int i = 0; i < 15; i++) { cout<<i<<","<<accessPattern[i]<<endl; LookupResult result = tlb.lookup(accessPattern[i]); if(result.isFound) { tlb.print(); } else { cout<<"Cache Miss"<<endl; tlb.insert(accessPattern[i],accessPattern[i]); tlb.print(); } }*/ return 0; }