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