Main Page   Compound List   File List   Compound Members   File Members  

addrspace.cc

Go to the documentation of this file.
00001 // addrspace.cc 
00002 //      Routines to manage address spaces (executing user programs).
00003 //
00004 //      In order to run a user program, you must:
00005 //
00006 //      1. link with the -N -T 0 option 
00007 //      2. run coff2noff to convert the object file to Nachos format
00008 //              (Nachos object code format is essentially just a simpler
00009 //              version of the UNIX executable object code format)
00010 //      3. load the NOFF file into the Nachos file system
00011 //              (if you haven't implemented the file system yet, you
00012 //              don't need to do this last step)
00013 //
00014 // Copyright (c) 1992-1993 The Regents of the University of California.
00015 // All rights reserved.  See copyright.h for copyright notice and limitation 
00016 // of liability and disclaimer of warranty provisions.
00017 
00018 #include "copyright.h"
00019 #include "system.h"
00020 #include "addrspace.h"
00021 #include "noff.h"
00022 
00023 extern "C" {
00024         int bzero(char *, int);
00025 };
00026 
00027 //----------------------------------------------------------------------
00028 // SwapHeader
00029 //      Do little endian to big endian conversion on the bytes in the 
00030 //      object file header, in case the file was generated on a little
00031 //      endian machine, and we're now running on a big endian machine.
00032 //----------------------------------------------------------------------
00033 
00034 static void 
00035 SwapHeader (NoffHeader *noffH)
00036 {
00037         noffH->noffMagic = WordToHost(noffH->noffMagic);
00038         noffH->code.size = WordToHost(noffH->code.size);
00039         noffH->code.virtualAddr = WordToHost(noffH->code.virtualAddr);
00040         noffH->code.inFileAddr = WordToHost(noffH->code.inFileAddr);
00041         noffH->initData.size = WordToHost(noffH->initData.size);
00042         noffH->initData.virtualAddr = WordToHost(noffH->initData.virtualAddr);
00043         noffH->initData.inFileAddr = WordToHost(noffH->initData.inFileAddr);
00044         noffH->uninitData.size = WordToHost(noffH->uninitData.size);
00045         noffH->uninitData.virtualAddr = WordToHost(noffH->uninitData.virtualAddr);
00046         noffH->uninitData.inFileAddr = WordToHost(noffH->uninitData.inFileAddr);
00047 }
00048 
00049 //----------------------------------------------------------------------
00050 // AddrSpace::AddrSpace
00051 //      Create an address space to run a user program.
00052 //      Load the program from a file "executable", and set everything
00053 //      up so that we can start executing user instructions.
00054 //
00055 //      Assumes that the object code file is in NOFF format.
00056 //
00057 //      First, set up the translation from program memory to physical 
00058 //      memory.  For now, this is really simple (1:1), since we are
00059 //      only uniprogramming, and we have a single unsegmented page table
00060 //
00061 //      "executable" is the file containing the object code to load into memory
00062 //----------------------------------------------------------------------
00063 
00064 AddrSpace::AddrSpace(OpenFile *executable)
00065 {
00066     NoffHeader noffH;
00067     unsigned int i, size;
00068 
00069     executable->ReadAt((char *)&noffH, sizeof(noffH), 0);
00070     if ((noffH.noffMagic != NOFFMAGIC) && 
00071                 (WordToHost(noffH.noffMagic) == NOFFMAGIC))
00072         SwapHeader(&noffH);
00073     ASSERT(noffH.noffMagic == NOFFMAGIC);
00074 
00075 // how big is address space?
00076     size = noffH.code.size + noffH.initData.size + noffH.uninitData.size 
00077                         + UserStackSize;        // we need to increase the size
00078                                                 // to leave room for the stack
00079     numPages = divRoundUp(size, PageSize);
00080     size = numPages * PageSize;
00081 
00082     ASSERT(numPages <= NumPhysPages);           // check we're not trying
00083                                                 // to run anything too big --
00084                                                 // at least until we have
00085                                                 // virtual memory
00086 
00087     DEBUG('a', "Initializing address space, num pages %d, size %d\n", 
00088                                         numPages, size);
00089 // first, set up the translation 
00090     pageTable = new TranslationEntry[numPages];
00091     for (i = 0; i < numPages; i++) {
00092         pageTable[i].virtualPage = i;   // for now, virtual page # = phys page #
00093         pageTable[i].physicalPage = i;
00094         pageTable[i].valid = TRUE;
00095         pageTable[i].use = FALSE;
00096         pageTable[i].dirty = FALSE;
00097         pageTable[i].readOnly = FALSE;  // if the code segment was entirely on 
00098                                         // a separate page, we could set its 
00099                                         // pages to be read-only
00100     }
00101     
00102 // zero out the entire address space, to zero the unitialized data segment 
00103 // and the stack segment
00104     bzero(machine->mainMemory, size);
00105 
00106 // then, copy in the code and data segments into memory
00107     if (noffH.code.size > 0) {
00108         DEBUG('a', "Initializing code segment, at 0x%x, size %d\n", 
00109                         noffH.code.virtualAddr, noffH.code.size);
00110         executable->ReadAt(&(machine->mainMemory[noffH.code.virtualAddr]),
00111                         noffH.code.size, noffH.code.inFileAddr);
00112     }
00113     if (noffH.initData.size > 0) {
00114         DEBUG('a', "Initializing data segment, at 0x%x, size %d\n", 
00115                         noffH.initData.virtualAddr, noffH.initData.size);
00116         executable->ReadAt(&(machine->mainMemory[noffH.initData.virtualAddr]),
00117                         noffH.initData.size, noffH.initData.inFileAddr);
00118     }
00119 
00120 }
00121 
00122 //----------------------------------------------------------------------
00123 // AddrSpace::~AddrSpace
00124 //      Dealloate an address space.  Nothing for now!
00125 //----------------------------------------------------------------------
00126 
00127 AddrSpace::~AddrSpace()
00128 {
00129    delete pageTable;
00130 }
00131 
00132 //----------------------------------------------------------------------
00133 // AddrSpace::InitRegisters
00134 //      Set the initial values for the user-level register set.
00135 //
00136 //      We write these directly into the "machine" registers, so
00137 //      that we can immediately jump to user code.  Note that these
00138 //      will be saved/restored into the currentThread->userRegisters
00139 //      when this thread is context switched out.
00140 //----------------------------------------------------------------------
00141 
00142 void
00143 AddrSpace::InitRegisters()
00144 {
00145     int i;
00146 
00147     for (i = 0; i < NumTotalRegs; i++)
00148         machine->WriteRegister(i, 0);
00149 
00150     // Initial program counter -- must be location of "Start"
00151     machine->WriteRegister(PCReg, 0);   
00152 
00153     // Need to also tell MIPS where next instruction is, because
00154     // of branch delay possibility
00155     machine->WriteRegister(NextPCReg, 4);
00156 
00157    // Set the stack register to the end of the address space, where we
00158    // allocated the stack; but subtract off a bit, to make sure we don't
00159    // accidentally reference off the end!
00160     machine->WriteRegister(StackReg, numPages * PageSize - 16);
00161     DEBUG('a', "Initializing stack register to %d\n", numPages * PageSize - 16);
00162 }
00163 
00164 //----------------------------------------------------------------------
00165 // AddrSpace::SaveState
00166 //      On a context switch, save any machine state, specific
00167 //      to this address space, that needs saving.
00168 //
00169 //      For now, nothing!
00170 //----------------------------------------------------------------------
00171 
00172 void AddrSpace::SaveState() 
00173 {}
00174 
00175 //----------------------------------------------------------------------
00176 // AddrSpace::RestoreState
00177 //      On a context switch, restore the machine state so that
00178 //      this address space can run.
00179 //
00180 //      For now, tell the machine where to find the page table.
00181 //----------------------------------------------------------------------
00182 
00183 void AddrSpace::RestoreState() 
00184 {
00185     machine->pageTable = pageTable;
00186     machine->pageTableSize = numPages;
00187 }

Generated on Mon Feb 10 09:54:44 2003 for nachos by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002
The University of Southern California does not screen or control the content on this website and thus does not guarantee the accuracy, integrity, or quality of such content. All content on this website is provided by and is the sole responsibility of the person from which such content originated, and such content does not necessarily reflect the opinions of the University administration or the Board of Trustees