Main Page   Compound List   File List   Compound 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 && ((unsigned) 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 Mon Feb 10 09:54:48 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