00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 #include "copyright.h"
00019 #include "main.h"
00020 #include "addrspace.h"
00021 #include "machine.h"
00022 #include "noff.h"
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 static void 
00032 SwapHeader (NoffHeader *noffH)
00033 {
00034     noffH->noffMagic = WordToHost(noffH->noffMagic);
00035     noffH->code.size = WordToHost(noffH->code.size);
00036     noffH->code.virtualAddr = WordToHost(noffH->code.virtualAddr);
00037     noffH->code.inFileAddr = WordToHost(noffH->code.inFileAddr);
00038 #ifdef RDATA
00039     noffH->readonlyData.size = WordToHost(noffH->readonlyData.size);
00040     noffH->readonlyData.virtualAddr = 
00041            WordToHost(noffH->readonlyData.virtualAddr);
00042     noffH->readonlyData.inFileAddr = 
00043            WordToHost(noffH->readonlyData.inFileAddr);
00044 #endif 
00045     noffH->initData.size = WordToHost(noffH->initData.size);
00046     noffH->initData.virtualAddr = WordToHost(noffH->initData.virtualAddr);
00047     noffH->initData.inFileAddr = WordToHost(noffH->initData.inFileAddr);
00048     noffH->uninitData.size = WordToHost(noffH->uninitData.size);
00049     noffH->uninitData.virtualAddr = WordToHost(noffH->uninitData.virtualAddr);
00050     noffH->uninitData.inFileAddr = WordToHost(noffH->uninitData.inFileAddr);
00051 
00052 #ifdef RDATA
00053     DEBUG(dbgAddr, "code = " << noffH->code.size <<  
00054                    " readonly = " << noffH->readonlyData.size <<
00055                    " init = " << noffH->initData.size <<
00056                    " uninit = " << noffH->uninitData.size << "\n");
00057 #endif
00058 }
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 AddrSpace::AddrSpace()
00069 {
00070     pageTable = new TranslationEntry[NumPhysPages];
00071     for (int i = 0; i < NumPhysPages; i++) {
00072         pageTable[i].virtualPage = i;   
00073         pageTable[i].physicalPage = i;
00074         pageTable[i].valid = TRUE;
00075         pageTable[i].use = FALSE;
00076         pageTable[i].dirty = FALSE;
00077         pageTable[i].readOnly = FALSE;  
00078     }
00079     
00080     
00081     bzero(kernel->machine->mainMemory, MemorySize);
00082 }
00083 
00084 
00085 
00086 
00087 
00088 
00089 AddrSpace::~AddrSpace()
00090 {
00091    delete pageTable;
00092 }
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 bool 
00106 AddrSpace::Load(char *fileName) 
00107 {
00108     OpenFile *executable = kernel->fileSystem->Open(fileName);
00109     NoffHeader noffH;
00110     unsigned int size;
00111 
00112     if (executable == NULL) {
00113         cerr << "Unable to open file " << fileName << "\n";
00114         return FALSE;
00115     }
00116 
00117     executable->ReadAt((char *)&noffH, sizeof(noffH), 0);
00118     if ((noffH.noffMagic != NOFFMAGIC) && 
00119                 (WordToHost(noffH.noffMagic) == NOFFMAGIC))
00120         SwapHeader(&noffH);
00121     ASSERT(noffH.noffMagic == NOFFMAGIC);
00122 
00123 #ifdef RDATA
00124 
00125     size = noffH.code.size + noffH.readonlyData.size + noffH.initData.size +
00126            noffH.uninitData.size + UserStackSize;       
00127                                                 
00128                                                 
00129 #else
00130 
00131     size = noffH.code.size + noffH.initData.size + noffH.uninitData.size 
00132                         + UserStackSize;        
00133                                                 
00134 #endif
00135     numPages = divRoundUp(size, PageSize);
00136     size = numPages * PageSize;
00137 
00138     ASSERT(numPages <= NumPhysPages);           
00139                                                 
00140                                                 
00141                                                 
00142 
00143     DEBUG(dbgAddr, "Initializing address space: " << numPages << ", " << size);
00144 
00145 
00146 
00147     if (noffH.code.size > 0) {
00148         DEBUG(dbgAddr, "Initializing code segment.");
00149         DEBUG(dbgAddr, noffH.code.virtualAddr << ", " << noffH.code.size);
00150         executable->ReadAt(
00151                 &(kernel->machine->mainMemory[noffH.code.virtualAddr]), 
00152                         noffH.code.size, noffH.code.inFileAddr);
00153     }
00154     if (noffH.initData.size > 0) {
00155         DEBUG(dbgAddr, "Initializing data segment.");
00156         DEBUG(dbgAddr, noffH.initData.virtualAddr << ", " << noffH.initData.size);
00157         executable->ReadAt(
00158                 &(kernel->machine->mainMemory[noffH.initData.virtualAddr]),
00159                         noffH.initData.size, noffH.initData.inFileAddr);
00160     }
00161 
00162 #ifdef RDATA
00163     if (noffH.readonlyData.size > 0) {
00164         DEBUG(dbgAddr, "Initializing read only data segment.");
00165         DEBUG(dbgAddr, noffH.readonlyData.virtualAddr << ", " << noffH.readonlyData.size);
00166         executable->ReadAt(
00167                 &(kernel->machine->mainMemory[noffH.readonlyData.virtualAddr]),
00168                         noffH.readonlyData.size, noffH.readonlyData.inFileAddr);
00169     }
00170 #endif
00171 
00172     delete executable;                  
00173     return TRUE;                        
00174 }
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 void 
00186 AddrSpace::Execute() 
00187 {
00188 
00189    
00190 
00191     this->InitRegisters();              
00192     this->RestoreState();               
00193 
00194     kernel->machine->Run();             
00195 
00196     ASSERTNOTREACHED();                 
00197                                         
00198                                         
00199 }
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 void
00213 AddrSpace::InitRegisters()
00214 {
00215     Machine *machine = kernel->machine;
00216     int i;
00217 
00218     for (i = 0; i < NumTotalRegs; i++)
00219         machine->WriteRegister(i, 0);
00220 
00221     
00222     
00223     machine->WriteRegister(PCReg, 0);   
00224 
00225     
00226     
00227     
00228     
00229     machine->WriteRegister(NextPCReg, 4);
00230 
00231    
00232    
00233    
00234     machine->WriteRegister(StackReg, numPages * PageSize - 16);
00235     DEBUG(dbgAddr, "Initializing stack pointer: " << numPages * PageSize - 16);
00236 }
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 void AddrSpace::SaveState() 
00247 {}
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 void AddrSpace::RestoreState() 
00258 {
00259     kernel->machine->pageTable = pageTable;
00260     kernel->machine->pageTableSize = numPages;
00261 }
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 ExceptionType
00273 AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
00274 {
00275     TranslationEntry *pte;
00276     int               pfn;
00277     unsigned int      vpn    = vaddr / PageSize;
00278     unsigned int      offset = vaddr % PageSize;
00279 
00280     if(vpn >= numPages) {
00281         return AddressErrorException;
00282     }
00283 
00284     pte = &pageTable[vpn];
00285 
00286     if(isReadWrite && pte->readOnly) {
00287         return ReadOnlyException;
00288     }
00289 
00290     pfn = pte->physicalPage;
00291 
00292     
00293     
00294     if (pfn >= NumPhysPages) {
00295         DEBUG(dbgAddr, "Illegal physical page " << pfn);
00296         return BusErrorException;
00297     }
00298 
00299     pte->use = TRUE;          
00300 
00301     if(isReadWrite)
00302         pte->dirty = TRUE;
00303 
00304     *paddr = pfn*PageSize + offset;
00305 
00306     ASSERT((*paddr < MemorySize));
00307 
00308     
00309     
00310 
00311     return NoException;
00312 }
00313 
00314 
00315 
00316