00001 // machine.h 00002 // Data structures for simulating the execution of user programs 00003 // running on top of Nachos. 00004 // 00005 // User programs are loaded into "mainMemory"; to Nachos, 00006 // this looks just like an array of bytes. Of course, the Nachos 00007 // kernel is in memory too -- but as in most machines these days, 00008 // the kernel is loaded into a separate memory region from user 00009 // programs, and accesses to kernel memory are not translated or paged. 00010 // 00011 // In Nachos, user programs are executed one instruction at a time, 00012 // by the simulator. Each memory reference is translated, checked 00013 // for errors, etc. 00014 // 00015 // DO NOT CHANGE EXCEPT AS NOTED BELOW -- part of the machine emulation 00016 // 00017 // Copyright (c) 1992-1996 The Regents of the University of California. 00018 // All rights reserved. See copyright.h for copyright notice and limitation 00019 // of liability and disclaimer of warranty provisions. 00020 00021 #ifndef MACHINE_H 00022 #define MACHINE_H 00023 00024 #include "copyright.h" 00025 #include "utility.h" 00026 #include "translate.h" 00027 00028 // Definitions related to the size, and format of user memory 00029 00030 const int PageSize = 128; // set the page size equal to 00031 // the disk sector size, for simplicity 00032 00033 // 00034 // You are allowed to change this value. 00035 // Doing so will change the number of pages of physical memory 00036 // available on the simulated machine. 00037 // 00038 const int NumPhysPages = 128; 00039 00040 const int MemorySize = (NumPhysPages * PageSize); 00041 const int TLBSize = 4; // if there is a TLB, make it small 00042 00043 enum ExceptionType { NoException, // Everything ok! 00044 SyscallException, // A program executed a system call. 00045 PageFaultException, // No valid translation found 00046 ReadOnlyException, // Write attempted to page marked 00047 // "read-only" 00048 BusErrorException, // Translation resulted in an 00049 // invalid physical address 00050 AddressErrorException, // Unaligned reference or one that 00051 // was beyond the end of the 00052 // address space 00053 OverflowException, // Integer overflow in add or sub. 00054 IllegalInstrException, // Unimplemented or reserved instr. 00055 00056 NumExceptionTypes 00057 }; 00058 00059 // User program CPU state. The full set of MIPS registers, plus a few 00060 // more because we need to be able to start/stop a user program between 00061 // any two instructions (thus we need to keep track of things like load 00062 // delay slots, etc.) 00063 00064 #define StackReg 29 // User's stack pointer 00065 #define RetAddrReg 31 // Holds return address for procedure calls 00066 #define NumGPRegs 32 // 32 general purpose registers on MIPS 00067 #define HiReg 32 // Double register to hold multiply result 00068 #define LoReg 33 00069 #define PCReg 34 // Current program counter 00070 #define NextPCReg 35 // Next program counter (for branch delay) 00071 #define PrevPCReg 36 // Previous program counter (for debugging) 00072 #define LoadReg 37 // The register target of a delayed load. 00073 #define LoadValueReg 38 // The value to be loaded by a delayed load. 00074 #define BadVAddrReg 39 // The failing virtual address on an exception 00075 00076 #define NumTotalRegs 40 00077 00078 // The following class defines the simulated host workstation hardware, as 00079 // seen by user programs -- the CPU registers, main memory, etc. 00080 // User programs shouldn't be able to tell that they are running on our 00081 // simulator or on the real hardware, except 00082 // we don't support floating point instructions 00083 // the system call interface to Nachos is not the same as UNIX 00084 // (10 system calls in Nachos vs. 200 in UNIX!) 00085 // If we were to implement more of the UNIX system calls, we ought to be 00086 // able to run Nachos on top of Nachos! 00087 // 00088 // The procedures in this class are defined in machine.cc, mipssim.cc, and 00089 // translate.cc. 00090 00091 class Instruction; 00092 class Interrupt; 00093 00094 class Machine { 00095 public: 00096 Machine(bool debug); // Initialize the simulation of the hardware 00097 // for running user programs 00098 ~Machine(); // De-allocate the data structures 00099 00100 // Routines callable by the Nachos kernel 00101 void Run(); // Run a user program 00102 00103 int ReadRegister(int num); // read the contents of a CPU register 00104 00105 void WriteRegister(int num, int value); 00106 // store a value into a CPU register 00107 00108 // Data structures accessible to the Nachos kernel -- main memory and the 00109 // page table/TLB. 00110 // 00111 // Note that *all* communication between the user program and the kernel 00112 // are in terms of these data structures (plus the CPU registers). 00113 00114 char *mainMemory; // physical memory to store user program, 00115 // code and data, while executing 00116 00117 // NOTE: the hardware translation of virtual addresses in the user program 00118 // to physical addresses (relative to the beginning of "mainMemory") 00119 // can be controlled by one of: 00120 // a traditional linear page table 00121 // a software-loaded translation lookaside buffer (tlb) -- a cache of 00122 // mappings of virtual page #'s to physical page #'s 00123 // 00124 // If "tlb" is NULL, the linear page table is used 00125 // If "tlb" is non-NULL, the Nachos kernel is responsible for managing 00126 // the contents of the TLB. But the kernel can use any data structure 00127 // it wants (eg, segmented paging) for handling TLB cache misses. 00128 // 00129 // For simplicity, both the page table pointer and the TLB pointer are 00130 // public. However, while there can be multiple page tables (one per address 00131 // space, stored in memory), there is only one TLB (implemented in hardware). 00132 // Thus the TLB pointer should be considered as *read-only*, although 00133 // the contents of the TLB are free to be modified by the kernel software. 00134 00135 TranslationEntry *tlb; // this pointer should be considered 00136 // "read-only" to Nachos kernel code 00137 00138 TranslationEntry *pageTable; 00139 unsigned int pageTableSize; 00140 00141 bool ReadMem(int addr, int size, int* value); 00142 bool WriteMem(int addr, int size, int value); 00143 // Read or write 1, 2, or 4 bytes of virtual 00144 // memory (at addr). Return FALSE if a 00145 // correct translation couldn't be found. 00146 private: 00147 00148 // Routines internal to the machine simulation -- DO NOT call these directly 00149 void DelayedLoad(int nextReg, int nextVal); 00150 // Do a pending delayed load (modifying a reg) 00151 00152 void OneInstruction(Instruction *instr); 00153 // Run one instruction of a user program. 00154 00155 00156 00157 ExceptionType Translate(int virtAddr, int* physAddr, int size,bool writing); 00158 // Translate an address, and check for 00159 // alignment. Set the use and dirty bits in 00160 // the translation entry appropriately, 00161 // and return an exception code if the 00162 // translation couldn't be completed. 00163 00164 void RaiseException(ExceptionType which, int badVAddr); 00165 // Trap to the Nachos kernel, because of a 00166 // system call or other exception. 00167 00168 void Debugger(); // invoke the user program debugger 00169 void DumpState(); // print the user CPU and memory state 00170 00171 00172 // Internal data structures 00173 00174 int registers[NumTotalRegs]; // CPU registers, for executing user programs 00175 00176 bool singleStep; // drop back into the debugger after each 00177 // simulated instruction 00178 int runUntilTime; // drop back into the debugger when simulated 00179 // time reaches this value 00180 00181 friend class Interrupt; // calls DelayedLoad() 00182 }; 00183 00184 extern void ExceptionHandler(ExceptionType which); 00185 // Entry point into Nachos for handling 00186 // user system calls and exceptions 00187 // Defined in exception.cc 00188 00189 00190 // Routines for converting Words and Short Words to and from the 00191 // simulated machine's format of little endian. If the host machine 00192 // is little endian (DEC and Intel), these end up being NOPs. 00193 // 00194 // What is stored in each format: 00195 // host byte ordering: 00196 // kernel data structures 00197 // user registers 00198 // simulated machine byte ordering: 00199 // contents of main memory 00200 00201 unsigned int WordToHost(unsigned int word); 00202 unsigned short ShortToHost(unsigned short shortword); 00203 unsigned int WordToMachine(unsigned int word); 00204 unsigned short ShortToMachine(unsigned short shortword); 00205 00206 #endif // MACHINE_H