Page principale | Hiérarchie des classes | Liste des classes | Répertoires | Liste des fichiers | Membres de classe | Membres de fichier

translate.cc

Aller à la documentation de ce fichier.
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-1996 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 "main.h"
00034 
00035 // Routines for converting Words and Short Words to and from the
00036 // simulated machine's format of little endian.  These end up
00037 // being NOPs when the host machine is also little endian (DEC and Intel).
00038 
00039 unsigned int
00040 WordToHost(unsigned int word) {
00041 #ifdef HOST_IS_BIG_ENDIAN
00042          register unsigned long result;
00043          result = (word >> 24) & 0x000000ff;
00044          result |= (word >> 8) & 0x0000ff00;
00045          result |= (word << 8) & 0x00ff0000;
00046          result |= (word << 24) & 0xff000000;
00047          return result;
00048 #else 
00049          return word;
00050 #endif /* HOST_IS_BIG_ENDIAN */
00051 }
00052 
00053 unsigned short
00054 ShortToHost(unsigned short shortword) {
00055 #ifdef HOST_IS_BIG_ENDIAN
00056          register unsigned short result;
00057          result = (shortword << 8) & 0xff00;
00058          result |= (shortword >> 8) & 0x00ff;
00059          return result;
00060 #else 
00061          return shortword;
00062 #endif /* HOST_IS_BIG_ENDIAN */
00063 }
00064 
00065 unsigned int
00066 WordToMachine(unsigned int word) { return WordToHost(word); }
00067 
00068 unsigned short
00069 ShortToMachine(unsigned short shortword) { return ShortToHost(shortword); }
00070 
00071 
00072 //----------------------------------------------------------------------
00073 // Machine::ReadMem
00074 //      Read "size" (1, 2, or 4) bytes of virtual memory at "addr" into 
00075 //      the location pointed to by "value".
00076 //
00077 //      Returns FALSE if the translation step from virtual to physical memory
00078 //      failed.
00079 //
00080 //      "addr" -- the virtual address to read from
00081 //      "size" -- the number of bytes to read (1, 2, or 4)
00082 //      "value" -- the place to write the result
00083 //----------------------------------------------------------------------
00084 
00085 bool
00086 Machine::ReadMem(int addr, int size, int *value)
00087 {
00088     int data;
00089     ExceptionType exception;
00090     int physicalAddress;
00091     
00092     DEBUG(dbgAddr, "Reading VA " << addr << ", size " << size);
00093     
00094     exception = Translate(addr, &physicalAddress, size, FALSE);
00095     if (exception != NoException) {
00096         RaiseException(exception, addr);
00097         return FALSE;
00098     }
00099     switch (size) {
00100       case 1:
00101         data = mainMemory[physicalAddress];
00102         *value = data;
00103         break;
00104         
00105       case 2:
00106         data = *(unsigned short *) &mainMemory[physicalAddress];
00107         *value = ShortToHost(data);
00108         break;
00109         
00110       case 4:
00111         data = *(unsigned int *) &mainMemory[physicalAddress];
00112         *value = WordToHost(data);
00113         break;
00114 
00115       default: ASSERT(FALSE);
00116     }
00117     
00118     DEBUG(dbgAddr, "\tvalue read = " << *value);
00119     return (TRUE);
00120 }
00121 
00122 //----------------------------------------------------------------------
00123 // Machine::WriteMem
00124 //      Write "size" (1, 2, or 4) bytes of the contents of "value" into
00125 //      virtual memory at location "addr".
00126 //
00127 //      Returns FALSE if the translation step from virtual to physical memory
00128 //      failed.
00129 //
00130 //      "addr" -- the virtual address to write to
00131 //      "size" -- the number of bytes to be written (1, 2, or 4)
00132 //      "value" -- the data to be written
00133 //----------------------------------------------------------------------
00134 
00135 bool
00136 Machine::WriteMem(int addr, int size, int value)
00137 {
00138     ExceptionType exception;
00139     int physicalAddress;
00140      
00141     DEBUG(dbgAddr, "Writing VA " << addr << ", size " << size << ", value " << value);
00142 
00143     exception = Translate(addr, &physicalAddress, size, TRUE);
00144     if (exception != NoException) {
00145         RaiseException(exception, addr);
00146         return FALSE;
00147     }
00148     switch (size) {
00149       case 1:
00150         mainMemory[physicalAddress] = (unsigned char) (value & 0xff);
00151         break;
00152 
00153       case 2:
00154         *(unsigned short *) &mainMemory[physicalAddress]
00155                 = ShortToMachine((unsigned short) (value & 0xffff));
00156         break;
00157       
00158       case 4:
00159         *(unsigned int *) &mainMemory[physicalAddress]
00160                 = WordToMachine((unsigned int) value);
00161         break;
00162         
00163       default: ASSERT(FALSE);
00164     }
00165     
00166     return TRUE;
00167 }
00168 
00169 //----------------------------------------------------------------------
00170 // Machine::Translate
00171 //      Translate a virtual address into a physical address, using 
00172 //      either a page table or a TLB.  Check for alignment and all sorts 
00173 //      of other errors, and if everything is ok, set the use/dirty bits in 
00174 //      the translation table entry, and store the translated physical 
00175 //      address in "physAddr".  If there was an error, returns the type
00176 //      of the exception.
00177 //
00178 //      "virtAddr" -- the virtual address to translate
00179 //      "physAddr" -- the place to store the physical address
00180 //      "size" -- the amount of memory being read or written
00181 //      "writing" -- if TRUE, check the "read-only" bit in the TLB
00182 //----------------------------------------------------------------------
00183 
00184 ExceptionType
00185 Machine::Translate(int virtAddr, int* physAddr, int size, bool writing)
00186 {
00187     int i;
00188     unsigned int vpn, offset;
00189     TranslationEntry *entry;
00190     unsigned int pageFrame;
00191 
00192     DEBUG(dbgAddr, "\tTranslate " << virtAddr << (writing ? " , write" : " , read"));
00193 
00194 // check for alignment errors
00195     if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){
00196         DEBUG(dbgAddr, "Alignment problem at " << virtAddr << ", size " << size);
00197         return AddressErrorException;
00198     }
00199     
00200     // we must have either a TLB or a page table, but not both!
00201     ASSERT(tlb == NULL || pageTable == NULL);   
00202     ASSERT(tlb != NULL || pageTable != NULL);   
00203 
00204 // calculate the virtual page number, and offset within the page,
00205 // from the virtual address
00206     vpn = (unsigned) virtAddr / PageSize;
00207     offset = (unsigned) virtAddr % PageSize;
00208     
00209     if (tlb == NULL) {          // => page table => vpn is index into table
00210         if (vpn >= pageTableSize) {
00211             DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
00212             return AddressErrorException;
00213         } else if (!pageTable[vpn].valid) {
00214             DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
00215             return PageFaultException;
00216         }
00217         entry = &pageTable[vpn];
00218     } else {
00219         for (entry = NULL, i = 0; i < TLBSize; i++)
00220             if (tlb[i].valid && (tlb[i].virtualPage == ((int)vpn))) {
00221                 entry = &tlb[i];                        // FOUND!
00222                 break;
00223             }
00224         if (entry == NULL) {                            // not found
00225             DEBUG(dbgAddr, "Invalid TLB entry for this virtual page!");
00226             return PageFaultException;          // really, this is a TLB fault,
00227                                                 // the page may be in memory,
00228                                                 // but not in the TLB
00229         }
00230     }
00231 
00232     if (entry->readOnly && writing) {   // trying to write to a read-only page
00233         DEBUG(dbgAddr, "Write to read-only page at " << virtAddr);
00234         return ReadOnlyException;
00235     }
00236     pageFrame = entry->physicalPage;
00237 
00238     // if the pageFrame is too big, there is something really wrong! 
00239     // An invalid translation was loaded into the page table or TLB. 
00240     if (pageFrame >= NumPhysPages) { 
00241         DEBUG(dbgAddr, "Illegal pageframe " << pageFrame);
00242         return BusErrorException;
00243     }
00244     entry->use = TRUE;          // set the use, dirty bits
00245     if (writing)
00246         entry->dirty = TRUE;
00247     *physAddr = pageFrame * PageSize + offset;
00248     ASSERT((*physAddr >= 0) && ((*physAddr + size) <= MemorySize));
00249     DEBUG(dbgAddr, "phys addr = " << *physAddr);
00250     return NoException;
00251 }

Généré le Sun Jan 15 00:44:24 2006 pour Architecture Cible de NachOS : par  doxygen 1.4.4