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