Main Page | Alphabetical List | Class List | File List | Class Members | File Members

translate.cc

Go to the documentation of this file.
00001 // translate.cc 00002 // Routines to translate virtual addresses to physical addresses. 00003 // Software sets up a table of legal translations. We look up 00004 // in the table on every memory reference to find the true physical 00005 // memory location. 00006 // 00007 // Two types of translation are supported here. 00008 // 00009 // Linear page table -- the virtual page # is used as an index 00010 // into the table, to find the physical page #. 00011 // 00012 // Translation lookaside buffer -- associative lookup in the table 00013 // to find an entry with the same virtual page #. If found, 00014 // this entry is used for the translation. 00015 // If not, it traps to software with an exception. 00016 // 00017 // In practice, the TLB is much smaller than the amount of physical 00018 // memory (16 entries is common on a machine that has 1000's of 00019 // pages). Thus, there must also be a backup translation scheme 00020 // (such as page tables), but the hardware doesn't need to know 00021 // anything at all about that. 00022 // 00023 // Note that the contents of the TLB are specific to an address space. 00024 // If the address space changes, so does the contents of the TLB! 00025 // 00026 // DO NOT CHANGE -- part of the machine emulation 00027 // 00028 // Copyright (c) 1992-1993 The Regents of the University of California. 00029 // All rights reserved. See copyright.h for copyright notice and limitation 00030 // of liability and disclaimer of warranty provisions. 00031 00032 #include "copyright.h" 00033 #include "machine.h" 00034 #include "addrspace.h" 00035 #include "system.h" 00036 00037 // Routines for converting Words and Short Words to and from the 00038 // simulated machine's format of little endian. These end up 00039 // being NOPs when the host machine is also little endian (DEC and Intel). 00040 00041 unsigned int 00042 WordToHost(unsigned int word) { 00043 #ifdef HOST_IS_BIG_ENDIAN 00044 register unsigned long result; 00045 result = (word >> 24) & 0x000000ff; 00046 result |= (word >> 8) & 0x0000ff00; 00047 result |= (word << 8) & 0x00ff0000; 00048 result |= (word << 24) & 0xff000000; 00049 return result; 00050 #else 00051 return word; 00052 #endif /* HOST_IS_BIG_ENDIAN */ 00053 } 00054 00055 unsigned short 00056 ShortToHost(unsigned short shortword) { 00057 #ifdef HOST_IS_BIG_ENDIAN 00058 register unsigned short result; 00059 result = (shortword << 8) & 0xff00; 00060 result |= (shortword >> 8) & 0x00ff; 00061 return result; 00062 #else 00063 return shortword; 00064 #endif /* HOST_IS_BIG_ENDIAN */ 00065 } 00066 00067 unsigned int 00068 WordToMachine(unsigned int word) { return WordToHost(word); } 00069 00070 unsigned short 00071 ShortToMachine(unsigned short shortword) { return ShortToHost(shortword); } 00072 00073 00074 //---------------------------------------------------------------------- 00075 // Machine::ReadMem 00076 // Read "size" (1, 2, or 4) bytes of virtual memory at "addr" into 00077 // the location pointed to by "value". 00078 // 00079 // Returns FALSE if the translation step from virtual to physical memory 00080 // failed. 00081 // 00082 // "addr" -- the virtual address to read from 00083 // "size" -- the number of bytes to read (1, 2, or 4) 00084 // "value" -- the place to write the result 00085 //---------------------------------------------------------------------- 00086 00087 bool 00088 Machine::ReadMem(int addr, int size, int *value) 00089 { 00090 int data; 00091 ExceptionType exception; 00092 int physicalAddress; 00093 00094 DEBUG('a', "Reading VA 0x%x, size %d\n", addr, size); 00095 00096 exception = Translate(addr, &physicalAddress, size, FALSE); 00097 if (exception != NoException) { 00098 machine->RaiseException(exception, addr); 00099 return FALSE; 00100 } 00101 switch (size) { 00102 case 1: 00103 data = machine->mainMemory[physicalAddress]; 00104 *value = data; 00105 break; 00106 00107 case 2: 00108 data = *(unsigned short *) &machine->mainMemory[physicalAddress]; 00109 *value = ShortToHost(data); 00110 break; 00111 00112 case 4: 00113 data = *(unsigned int *) &machine->mainMemory[physicalAddress]; 00114 *value = WordToHost(data); 00115 break; 00116 00117 default: ASSERT(FALSE); 00118 } 00119 00120 DEBUG('a', "\tvalue read = %8.8x\n", *value); 00121 return (TRUE); 00122 } 00123 00124 //---------------------------------------------------------------------- 00125 // Machine::WriteMem 00126 // Write "size" (1, 2, or 4) bytes of the contents of "value" into 00127 // virtual memory at location "addr". 00128 // 00129 // Returns FALSE if the translation step from virtual to physical memory 00130 // failed. 00131 // 00132 // "addr" -- the virtual address to write to 00133 // "size" -- the number of bytes to be written (1, 2, or 4) 00134 // "value" -- the data to be written 00135 //---------------------------------------------------------------------- 00136 00137 bool 00138 Machine::WriteMem(int addr, int size, int value) 00139 { 00140 ExceptionType exception; 00141 int physicalAddress; 00142 00143 DEBUG('a', "Writing VA 0x%x, size %d, value 0x%x\n", addr, size, value); 00144 00145 exception = Translate(addr, &physicalAddress, size, TRUE); 00146 if (exception != NoException) { 00147 machine->RaiseException(exception, addr); 00148 return FALSE; 00149 } 00150 switch (size) { 00151 case 1: 00152 machine->mainMemory[physicalAddress] = (unsigned char) (value & 0xff); 00153 break; 00154 00155 case 2: 00156 *(unsigned short *) &machine->mainMemory[physicalAddress] 00157 = ShortToMachine((unsigned short) (value & 0xffff)); 00158 break; 00159 00160 case 4: 00161 *(unsigned int *) &machine->mainMemory[physicalAddress] 00162 = WordToMachine((unsigned int) value); 00163 break; 00164 00165 default: ASSERT(FALSE); 00166 } 00167 00168 return TRUE; 00169 } 00170 00171 //---------------------------------------------------------------------- 00172 // Machine::Translate 00173 // Translate a virtual address into a physical address, using 00174 // either a page table or a TLB. Check for alignment and all sorts 00175 // of other errors, and if everything is ok, set the use/dirty bits in 00176 // the translation table entry, and store the translated physical 00177 // address in "physAddr". If there was an error, returns the type 00178 // of the exception. 00179 // 00180 // "virtAddr" -- the virtual address to translate 00181 // "physAddr" -- the place to store the physical address 00182 // "size" -- the amount of memory being read or written 00183 // "writing" -- if TRUE, check the "read-only" bit in the TLB 00184 //---------------------------------------------------------------------- 00185 00186 ExceptionType 00187 Machine::Translate(int virtAddr, int* physAddr, int size, bool writing) 00188 { 00189 int i; 00190 unsigned int vpn, offset; 00191 TranslationEntry *entry; 00192 unsigned int pageFrame; 00193 00194 DEBUG('a', "\tTranslate 0x%x, %s: ", virtAddr, writing ? "write" : "read"); 00195 00196 // check for alignment errors 00197 if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){ 00198 DEBUG('a', "alignment problem at %d, size %d!\n", virtAddr, size); 00199 return AddressErrorException; 00200 } 00201 00202 // we must have either a TLB or a page table, but not both! 00203 ASSERT(tlb == NULL || pageTable == NULL); 00204 ASSERT(tlb != NULL || pageTable != NULL); 00205 00206 // calculate the virtual page number, and offset within the page, 00207 // from the virtual address 00208 vpn = (unsigned) virtAddr / PageSize; 00209 offset = (unsigned) virtAddr % PageSize; 00210 00211 if (tlb == NULL) { // => page table => vpn is index into table 00212 if (vpn >= pageTableSize) { 00213 DEBUG('a', "virtual page # %d too large for page table size %d!\n", 00214 virtAddr, pageTableSize); 00215 return AddressErrorException; 00216 } else if (!pageTable[vpn].valid) { 00217 DEBUG('a', "virtual page # %d too large for page table size %d!\n", 00218 virtAddr, pageTableSize); 00219 return PageFaultException; 00220 } 00221 entry = &pageTable[vpn]; 00222 } else { 00223 for (entry = NULL, i = 0; i < TLBSize; i++) 00224 if (tlb[i].valid && (tlb[i].virtualPage == vpn)) { 00225 entry = &tlb[i]; // FOUND! 00226 break; 00227 } 00228 if (entry == NULL) { // not found 00229 DEBUG('a', "*** no valid TLB entry found for this virtual page!\n"); 00230 return PageFaultException; // really, this is a TLB fault, 00231 // the page may be in memory, 00232 // but not in the TLB 00233 } 00234 } 00235 00236 if (entry->readOnly && writing) { // trying to write to a read-only page 00237 DEBUG('a', "%d mapped read-only at %d in TLB!\n", virtAddr, i); 00238 return ReadOnlyException; 00239 } 00240 pageFrame = entry->physicalPage; 00241 00242 // if the pageFrame is too big, there is something really wrong! 00243 // An invalid translation was loaded into the page table or TLB. 00244 if (pageFrame >= NumPhysPages) { 00245 DEBUG('a', "*** frame %d > %d!\n", pageFrame, NumPhysPages); 00246 return BusErrorException; 00247 } 00248 entry->use = TRUE; // set the use, dirty bits 00249 if (writing) 00250 entry->dirty = TRUE; 00251 *physAddr = pageFrame * PageSize + offset; 00252 ASSERT((*physAddr >= 0) && ((*physAddr + size) <= MemorySize)); 00253 DEBUG('a', "phys addr = 0x%x\n", *physAddr); 00254 return NoException; 00255 }

Generated on Thu Sep 16 12:33:46 2004 for NachOS by doxygen 1.3.8