translation.hh revision 7678
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * Copyright (c) 2009 The University of Edinburgh 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Gabe Black 30 * Timothy M. Jones 31 */ 32 33#ifndef __CPU_TRANSLATION_HH__ 34#define __CPU_TRANSLATION_HH__ 35 36#include "sim/faults.hh" 37#include "sim/tlb.hh" 38 39/** 40 * This class captures the state of an address translation. A translation 41 * can be split in two if the ISA supports it and the memory access crosses 42 * a page boundary. In this case, this class is shared by two data 43 * translations (below). Otherwise it is used by a single data translation 44 * class. When each part of the translation is finished, the finish 45 * function is called which will indicate whether the whole translation is 46 * completed or not. There are also functions for accessing parts of the 47 * translation state which deal with the possible split correctly. 48 */ 49class WholeTranslationState 50{ 51 protected: 52 int outstanding; 53 Fault faults[2]; 54 55 public: 56 bool isSplit; 57 RequestPtr mainReq; 58 RequestPtr sreqLow; 59 RequestPtr sreqHigh; 60 uint8_t *data; 61 uint64_t *res; 62 BaseTLB::Mode mode; 63 64 /** 65 * Single translation state. We set the number of outstanding 66 * translations to one and indicate that it is not split. 67 */ 68 WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 69 BaseTLB::Mode _mode) 70 : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL), 71 sreqHigh(NULL), data(_data), res(_res), mode(_mode) 72 { 73 faults[0] = faults[1] = NoFault; 74 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 75 } 76 77 /** 78 * Split translation state. We copy all state into this class, set the 79 * number of outstanding translations to two and then mark this as a 80 * split translation. 81 */ 82 WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 83 RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 84 BaseTLB::Mode _mode) 85 : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow), 86 sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode) 87 { 88 faults[0] = faults[1] = NoFault; 89 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 90 } 91 92 /** 93 * Finish part of a translation. If there is only one request then this 94 * translation is completed. If the request has been split in two then 95 * the outstanding count determines whether the translation is complete. 96 * In this case, flags from the split request are copied to the main 97 * request to make it easier to access them later on. 98 */ 99 bool 100 finish(Fault fault, int index) 101 { 102 assert(outstanding); 103 faults[index] = fault; 104 outstanding--; 105 if (isSplit && outstanding == 0) { 106 107 // For ease later, we copy some state to the main request. 108 if (faults[0] == NoFault) { 109 mainReq->setPaddr(sreqLow->getPaddr()); 110 } 111 mainReq->setFlags(sreqLow->getFlags()); 112 mainReq->setFlags(sreqHigh->getFlags()); 113 } 114 return outstanding == 0; 115 } 116 117 /** 118 * Determine whether this translation produced a fault. Both parts of the 119 * translation must be checked if this is a split translation. 120 */ 121 Fault 122 getFault() const 123 { 124 if (!isSplit) 125 return faults[0]; 126 else if (faults[0] != NoFault) 127 return faults[0]; 128 else if (faults[1] != NoFault) 129 return faults[1]; 130 else 131 return NoFault; 132 } 133 134 /** Remove all faults from the translation. */ 135 void 136 setNoFault() 137 { 138 faults[0] = faults[1] = NoFault; 139 } 140 141 /** 142 * Check if this request is uncacheable. We only need to check the main 143 * request because the flags will have been copied here on a split 144 * translation. 145 */ 146 bool 147 isUncacheable() const 148 { 149 return mainReq->isUncacheable(); 150 } 151 152 /** 153 * Check if this request is a prefetch. We only need to check the main 154 * request because the flags will have been copied here on a split 155 * translation. 156 */ 157 bool 158 isPrefetch() const 159 { 160 return mainReq->isPrefetch(); 161 } 162 163 /** Get the physical address of this request. */ 164 Addr 165 getPaddr() const 166 { 167 return mainReq->getPaddr(); 168 } 169 170 /** 171 * Get the flags associated with this request. We only need to access 172 * the main request because the flags will have been copied here on a 173 * split translation. 174 */ 175 unsigned 176 getFlags() 177 { 178 return mainReq->getFlags(); 179 } 180 181 /** Delete all requests that make up this translation. */ 182 void 183 deleteReqs() 184 { 185 delete mainReq; 186 if (isSplit) { 187 delete sreqLow; 188 delete sreqHigh; 189 } 190 } 191}; 192 193 194/** 195 * This class represents part of a data address translation. All state for 196 * the translation is held in WholeTranslationState (above). Therefore this 197 * class does not need to know whether the translation is split or not. The 198 * index variable determines this but is simply passed on to the state class. 199 * When this part of the translation is completed, finish is called. If the 200 * translation state class indicate that the whole translation is complete 201 * then the execution context is informed. 202 */ 203template <class ExecContext> 204class DataTranslation : public BaseTLB::Translation 205{ 206 protected: 207 ExecContext *xc; 208 WholeTranslationState *state; 209 int index; 210 211 public: 212 DataTranslation(ExecContext *_xc, WholeTranslationState* _state) 213 : xc(_xc), state(_state), index(0) 214 { 215 } 216 217 DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 218 int _index) 219 : xc(_xc), state(_state), index(_index) 220 { 221 } 222 223 /** 224 * Finish this part of the translation and indicate that the whole 225 * translation is complete if the state says so. 226 */ 227 void 228 finish(Fault fault, RequestPtr req, ThreadContext *tc, 229 BaseTLB::Mode mode) 230 { 231 assert(state); 232 assert(mode == state->mode); 233 if (state->finish(fault, index)) { 234 xc->finishTranslation(state); 235 } 236 delete this; 237 } 238}; 239 240#endif // __CPU_TRANSLATION_HH__ 241