Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // addrspace.cc
- // Routines to manage address spaces (executing user programs).
- //
- // In order to run a user program, you must:
- //
- // 1. link with the -N -T 0 option
- // 2. run coff2noff to convert the object file to Nachos format
- // (Nachos object code format is essentially just a simpler
- // version of the UNIX executable object code format)
- // 3. load the NOFF file into the Nachos file system
- // (if you haven't implemented the file system yet, you
- // don't need to do this last step)
- //
- // Copyright (c) 1992-1993 The Regents of the University of California.
- // All rights reserved. See copyright.h for copyright notice and limitation
- // of liability and disclaimer of warranty provisions.
- #include "copyright.h"
- #include "system.h"
- #include "addrspace.h"
- #include "noff.h"
- //Begin code changes by Hayden Presley
- struct IPTEntry{
- Thread* threadptr;
- int vPage;
- };
- IPTEntry* IPT = new IPTEntry[NumPhysPages];
- //End code changes by Hayden Presley
- //----------------------------------------------------------------------
- // SwapHeader
- // Do little endian to big endian conversion on the bytes in the
- // object file header, in case the file was generated on a little
- // endian machine, and we're now running on a big endian machine.
- //----------------------------------------------------------------------
- static void
- SwapHeader (NoffHeader *noffH)
- {
- noffH->noffMagic = WordToHost(noffH->noffMagic);
- noffH->code.size = WordToHost(noffH->code.size);
- noffH->code.virtualAddr = WordToHost(noffH->code.virtualAddr);
- noffH->code.inFileAddr = WordToHost(noffH->code.inFileAddr);
- noffH->initData.size = WordToHost(noffH->initData.size);
- noffH->initData.virtualAddr = WordToHost(noffH->initData.virtualAddr);
- noffH->initData.inFileAddr = WordToHost(noffH->initData.inFileAddr);
- noffH->uninitData.size = WordToHost(noffH->uninitData.size);
- noffH->uninitData.virtualAddr = WordToHost(noffH->uninitData.virtualAddr);
- noffH->uninitData.inFileAddr = WordToHost(noffH->uninitData.inFileAddr);
- }
- //----------------------------------------------------------------------
- // AddrSpace::AddrSpace
- // Create an address space to run a user program.
- // Load the program from a file "executable", and set everything
- // up so that we can start executing user instructions.
- //
- // Assumes that the object code file is in NOFF format.
- //
- // First, set up the translation from program memory to physical
- // memory. For now, this is really simple (1:1), since we are
- // only uniprogramming, and we have a single unsegmented page table
- //
- // "executable" is the file containing the object code to load into memory
- //----------------------------------------------------------------------
- AddrSpace::AddrSpace(OpenFile *executable)
- {
- unsigned int i, counter;
- space = false;
- executable->ReadAt((char *)&noffH, sizeof(noffH), 0);
- if ((noffH.noffMagic != NOFFMAGIC) &&
- (WordToHost(noffH.noffMagic) == NOFFMAGIC))
- SwapHeader(&noffH);
- ASSERT(noffH.noffMagic == NOFFMAGIC);
- // how big is address space?
- size = noffH.code.size + noffH.initData.size + noffH.uninitData.size
- + UserStackSize; // we need to increase the size
- // to leave room for the stack
- numPages = divRoundUp(size, PageSize);
- //printf("%d is numPages\n", numPages);
- size = numPages * PageSize;
- //Change this to reference the bitmap for free pages
- //instead of total amount of pages
- //This requires a global bitmap instance
- counter = 0;
- for(i = 0; i < NumPhysPages && counter < numPages; i++)
- {
- if(!memMap->Test(i))
- {
- if(counter == 0)
- startPage = i; //startPage is a class data member
- //Should it be public or private? (Currently private)
- counter++;
- }
- else
- counter = 0;
- }
- DEBUG('a', "%i contiguous blocks found for %i pages\n", counter, numPages);
- //If no memory available, terminate
- if(counter < numPages)
- {
- //printf("Not enough contiguous memory for new process; terminating!.\n");
- currentThread->killNewChild = true;
- //return;
- }
- //If we get past the if statement, then there was sufficient space
- space = true;
- //This safeguards against the loop terminating due to reaching
- //the end of the bitmap but no contiguous space being available
- DEBUG('a', "Initializing address space, numPages=%d, size=%d\n",
- numPages, size);
- // first, set up the translation
- //BEGIN CODE CHANGES BY THOMAS WRAY AND HAYDEN PRESLEY
- OPTSize = (numPages / 4) + (numPages%4);
- outerPageTable = new TranslationEntry*[4];
- for (i = 0; i < 4; i++){
- outerPageTable[i] = new TranslationEntry[OPTSize];
- for(int j = 0; j < OPTSize; j++){
- outerPageTable[i][j].valid = FALSE;
- outerPageTable[i][j].virtualPage = j;
- outerPageTable[i][j].use = FALSE;
- outerPageTable[i][j].dirty = FALSE;
- outerPageTable[i][j].readOnly = FALSE;
- }
- }
- //END CODE CHANGES BY THOMAS WRAY AND HAYDEN PRESLEY
- pageTable = new TranslationEntry[4];
- for (i = 0; i < numPages; i++) {
- pageTable[i].virtualPage = i; // for now, virtual page # = phys page #
- pageTable[i].physicalPage = i;
- //pageTable[i].physicalPage = i + startPage; NOW DONE IN PAGEFAULTEXCEPTION
- //Code Change by Thomas Wray
- pageTable[i].valid = FALSE; //set each valid bit to false so that a PageFaultException is thrown
- pageTable[i].use = FALSE;
- pageTable[i].dirty = FALSE;
- pageTable[i].readOnly = FALSE; // if the code segment was entirely on
- // a separate page, we could set its
- // pages to be read-only
- //Take the global bitmap and set the relevant chunks
- //to indicate that the memory is in use
- //memMap->Mark(i + startPage);
- }
- //memMap->Print(); // Useful!
- // zero out the entire address space, to zero the unitialized data segment
- // and the stack segment
- // bzero(machine->mainMemory, size); rm for Solaris
- //Edited version adds startPage * PageSize to the address. Hopefully this is proper.
- //Either way, it appears to zero out only however much memory is needed,
- //so zeroing out all memory doesn't seem to be an issue. - Devin
- pAddr = startPage * PageSize;
- //memset(machine->mainMemory + pAddr, 0, size);
- // then, copy in the code and data segments into memory
- //Change these too since they assume virtual page = physical page
- //Fix this by adding startPage times page size as an offset
- //exec = executable;
- //Code changes by Thomas Wray and Paul Smith
- fileName = new char[10];
- sprintf(fileName, "%d.swap", threadID); //come back to this later for thread 0
- printf("%s is being made\n", fileName);
- fileSystem->Create(fileName, size);
- OpenFile* swapFile = fileSystem->Open(fileName);
- char* buffer = new char[size];
- executable->Read(buffer, size);
- swapFile->Write(buffer, size);
- delete swapFile;
- delete buffer;
- //Code changes by Thomas wray and Paul smith
- }
- //----------------------------------------------------------------------
- // AddrSpace::~AddrSpace
- // Dealloate an address space. Nothing for now!
- //----------------------------------------------------------------------
- //Because the initialization already zeroes out the memory to be used,
- //is it even necessary to clear out any garbage data during deallocation?
- AddrSpace::~AddrSpace()
- {
- // Only clear the memory if it was set to begin with
- // which in turn only happens after space is set to true
- if(space)
- {
- /*for(int i = startPage; i < numPages + startPage; i++) // We need an offset of startPage + numPages for clearing.
- memMap->Clear(i);*/
- for(int i = 0; i < 4; i++){
- for(int j = 0; j < OPTSize; j++)
- if(outerPageTable[i][j].valid == TRUE)
- (memMap->Clear(outerPageTable[i][j].physicalPage));
- }
- for(int i = 0; i < 4; i++){
- delete outerPageTable[i];
- }
- printf("GOT HERE!\n");
- delete outerPageTable;
- printf("GOT HERE!\n");
- //delete pageTable;
- memMap->Print();
- }
- //printf("Filename is %s\n\n\n", fileName);
- fileSystem->Remove(fileName);
- delete fileName;
- }
- //----------------------------------------------------------------------
- // AddrSpace::InitRegisters
- // Set the initial values for the user-level register set.
- //
- // We write these directly into the "machine" registers, so
- // that we can immediately jump to user code. Note that these
- // will be saved/restored into the currentThread->userRegisters
- // when this thread is context switched out.
- //----------------------------------------------------------------------
- void
- AddrSpace::InitRegisters()
- {
- int i;
- for (i = 0; i < NumTotalRegs; i++)
- machine->WriteRegister(i, 0);
- // Initial program counter -- must be location of "Start"
- machine->WriteRegister(PCReg, 0);
- // Need to also tell MIPS where next instruction is, because
- // of branch delay possibility
- machine->WriteRegister(NextPCReg, 4);
- // Set the stack register to the end of the address space, where we
- // allocated the stack; but subtract off a bit, to make sure we don't
- // accidentally reference off the end!
- machine->WriteRegister(StackReg, numPages * PageSize - 16);
- DEBUG('a', "Initializing stack register to %d\n", numPages * PageSize - 16);
- }
- //----------------------------------------------------------------------
- // AddrSpace::SaveState
- // On a context switch, save any machine state, specific
- // to this address space, that needs saving.
- //
- // For now, nothing!
- //----------------------------------------------------------------------
- void AddrSpace::SaveState()
- {
- printf("STATE SAVED\n");
- }
- //----------------------------------------------------------------------
- // AddrSpace::RestoreState
- // On a context switch, restore the machine state so that
- // this address space can run.
- //
- // For now, tell the machine where to find the page table.
- //----------------------------------------------------------------------
- void AddrSpace::RestoreState()
- {
- machine->pageTable = pageTable;
- machine->pageTableSize = numPages; //size of inner page table for 2 level
- }
- //begin code changes by Thomas Wray and Hayden Presley
- void AddrSpace::InitPages(int VAddr, int PAddr, bool replaced){
- OpenFile * swapFile = fileSystem->Open(fileName);
- if (swapFile == NULL){
- printf("///////////////////////////////////////////////////////////NULL\n");
- }
- printf("%s is trying to be accessed\n", fileName);
- if(!swapFile){
- delete swapFile;
- return;
- }
- int outerIndex = pageTable[VAddr/OPTSize].physicalPage;
- outerPageTable[outerIndex][VAddr%OPTSize].valid = TRUE;
- //pageTable[VAddr].valid = TRUE;
- /*for (int i = 0; i < machine->pageTableSize; i++){
- if (machine->pageTable[i].valid == true){
- printf("1");
- }
- else printf("0");
- }
- printf("\n");*/
- if (replaced){
- Thread* threadToSwap = IPT[PAddr].threadptr;
- int replacing = IPT[PAddr].vPage;
- printf("Replacing is %d\n", replacing);
- int outerIndex_replacing = threadToSwap->space->pageTable[replacing/threadToSwap->space->OPTSize].physicalPage;
- threadToSwap->space->outerPageTable[outerIndex_replacing][replacing%threadToSwap->space->OPTSize].valid = FALSE;
- printf("OPENING SWAPFILE: %s\n", threadToSwap->space->fileName);
- OpenFile * swapping = fileSystem->Open(threadToSwap->space->fileName);
- swapping->WriteAt(&(machine->mainMemory[PAddr * PageSize]), PageSize, threadToSwap->space->noffH.code.inFileAddr + replacing * PageSize);
- printf("Location is %d\n",threadToSwap->space->noffH.code.inFileAddr + replacing * PageSize);
- delete swapping;
- //Begin code changes by Hunter Kliebert
- if (pageFlag == TRUE)
- printf("\nPAGE FAULT: PROCESS %i REQUESTED VIRTUAL PAGE %i\nSWAP OUT PHYSICAL PAGE %i FROM PROCESS %i\nVIRTUAL PAGE %i REMOVED\n\n",
- currentThread->getID(), VAddr, PAddr, threadToSwap->getID(), replacing);
- //End code changes by Hunter Kliebert
- }
- //Begin code changes by Hunter Kliebert
- else
- if (pageFlag == TRUE)
- printf("\nPAGE FAULT: PROCESS %i REQUESTED VIRTUAL PAGE %i\nASSIGNED PHYSICAL PAGE %i\n\n", currentThread->getID(), VAddr, PAddr);
- //End code changes by Hunter Kliebert
- memset(machine->mainMemory + PAddr * PageSize, 0, PageSize);
- outerPageTable[outerIndex][VAddr%OPTSize].physicalPage = PAddr;
- //pageTable[VAddr].physicalPage = PAddr;
- IPT[PAddr].threadptr = currentThread;
- IPT[PAddr].vPage = VAddr;
- printf("IPT[%d].vPage is %d\n", PAddr, IPT[PAddr].vPage);
- if (noffH.code.size > 0 && VAddr * PageSize >= 0
- && noffH.code.size + noffH.initData.size > VAddr * PageSize) {
- swapFile->ReadAt(&(machine->mainMemory[PAddr * PageSize]),
- PageSize, noffH.code.inFileAddr + VAddr * PageSize);
- }
- //printf("Init pages: address is %d and %d\n", VAddr, PAddr);
- delete swapFile;
- }
- //end code changes by Thomas Wray and Hayden Presley
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement