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/tlb.hh" 37
| 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/tlb.hh" 37
|
| 38/** 39 * This class captures the state of an address translation. A translation 40 * can be split in two if the ISA supports it and the memory access crosses 41 * a page boundary. In this case, this class is shared by two data 42 * translations (below). Otherwise it is used by a single data translation 43 * class. When each part of the translation is finished, the finish 44 * function is called which will indicate whether the whole translation is 45 * completed or not. There are also functions for accessing parts of the 46 * translation state which deal with the possible split correctly. 47 */
|
38class WholeTranslationState 39{ 40 protected: 41 int outstanding; 42 Fault faults[2]; 43 44 public: 45 bool isSplit; 46 RequestPtr mainReq; 47 RequestPtr sreqLow; 48 RequestPtr sreqHigh; 49 uint8_t *data; 50 uint64_t *res; 51 BaseTLB::Mode mode; 52
| 48class WholeTranslationState 49{ 50 protected: 51 int outstanding; 52 Fault faults[2]; 53 54 public: 55 bool isSplit; 56 RequestPtr mainReq; 57 RequestPtr sreqLow; 58 RequestPtr sreqHigh; 59 uint8_t *data; 60 uint64_t *res; 61 BaseTLB::Mode mode; 62
|
53 /** Single translation state. */
| 63 /** 64 * Single translation state. We set the number of outstanding 65 * translations to one and indicate that it is not split. 66 */
|
54 WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 55 BaseTLB::Mode _mode) 56 : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL), 57 sreqHigh(NULL), data(_data), res(_res), mode(_mode) 58 { 59 faults[0] = faults[1] = NoFault; 60 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 61 } 62
| 67 WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 68 BaseTLB::Mode _mode) 69 : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL), 70 sreqHigh(NULL), data(_data), res(_res), mode(_mode) 71 { 72 faults[0] = faults[1] = NoFault; 73 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 74 } 75
|
63 /** Split translation state. */
| 76 /** 77 * Split translation state. We copy all state into this class, set the 78 * number of outstanding translations to two and then mark this as a 79 * split translation. 80 */
|
64 WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 65 RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 66 BaseTLB::Mode _mode) 67 : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow), 68 sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode) 69 { 70 faults[0] = faults[1] = NoFault; 71 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 72 } 73
| 81 WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 82 RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 83 BaseTLB::Mode _mode) 84 : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow), 85 sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode) 86 { 87 faults[0] = faults[1] = NoFault; 88 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 89 } 90
|
| 91 /** 92 * Finish part of a translation. If there is only one request then this 93 * translation is completed. If the request has been split in two then 94 * the outstanding count determines whether the translation is complete. 95 * In this case, flags from the split request are copied to the main 96 * request to make it easier to access them later on. 97 */
|
74 bool 75 finish(Fault fault, int index) 76 { 77 assert(outstanding); 78 faults[index] = fault; 79 outstanding--; 80 if (isSplit && outstanding == 0) { 81 82 // For ease later, we copy some state to the main request. 83 if (faults[0] == NoFault) { 84 mainReq->setPaddr(sreqLow->getPaddr()); 85 } 86 mainReq->setFlags(sreqLow->getFlags()); 87 mainReq->setFlags(sreqHigh->getFlags()); 88 } 89 return outstanding == 0; 90 } 91
| 98 bool 99 finish(Fault fault, int index) 100 { 101 assert(outstanding); 102 faults[index] = fault; 103 outstanding--; 104 if (isSplit && outstanding == 0) { 105 106 // For ease later, we copy some state to the main request. 107 if (faults[0] == NoFault) { 108 mainReq->setPaddr(sreqLow->getPaddr()); 109 } 110 mainReq->setFlags(sreqLow->getFlags()); 111 mainReq->setFlags(sreqHigh->getFlags()); 112 } 113 return outstanding == 0; 114 } 115
|
| 116 /** 117 * Determine whether this translation produced a fault. Both parts of the 118 * translation must be checked if this is a split translation. 119 */
|
92 Fault 93 getFault() const 94 { 95 if (!isSplit) 96 return faults[0]; 97 else if (faults[0] != NoFault) 98 return faults[0]; 99 else if (faults[1] != NoFault) 100 return faults[1]; 101 else 102 return NoFault; 103 } 104
| 120 Fault 121 getFault() const 122 { 123 if (!isSplit) 124 return faults[0]; 125 else if (faults[0] != NoFault) 126 return faults[0]; 127 else if (faults[1] != NoFault) 128 return faults[1]; 129 else 130 return NoFault; 131 } 132
|
| 133 /** Remove all faults from the translation. */
|
105 void 106 setNoFault() 107 { 108 faults[0] = faults[1] = NoFault; 109 } 110
| 134 void 135 setNoFault() 136 { 137 faults[0] = faults[1] = NoFault; 138 } 139
|
| 140 /** 141 * Check if this request is uncacheable. We only need to check the main 142 * request because the flags will have been copied here on a split 143 * translation. 144 */
|
111 bool 112 isUncacheable() const 113 { 114 return mainReq->isUncacheable(); 115 } 116
| 145 bool 146 isUncacheable() const 147 { 148 return mainReq->isUncacheable(); 149 } 150
|
| 151 /** 152 * Check if this request is a prefetch. We only need to check the main 153 * request because the flags will have been copied here on a split 154 * translation. 155 */
|
117 bool 118 isPrefetch() const 119 { 120 return mainReq->isPrefetch(); 121 } 122
| 156 bool 157 isPrefetch() const 158 { 159 return mainReq->isPrefetch(); 160 } 161
|
| 162 /** Get the physical address of this request. */
|
123 Addr 124 getPaddr() const 125 { 126 return mainReq->getPaddr(); 127 } 128
| 163 Addr 164 getPaddr() const 165 { 166 return mainReq->getPaddr(); 167 } 168
|
| 169 /** 170 * Get the flags associated with this request. We only need to access 171 * the main request because the flags will have been copied here on a 172 * split translation. 173 */
|
129 unsigned 130 getFlags() 131 { 132 return mainReq->getFlags(); 133 } 134
| 174 unsigned 175 getFlags() 176 { 177 return mainReq->getFlags(); 178 } 179
|
| 180 /** Delete all requests that make up this translation. */
|
135 void 136 deleteReqs() 137 { 138 delete mainReq; 139 if (isSplit) { 140 delete sreqLow; 141 delete sreqHigh; 142 } 143 } 144}; 145
| 181 void 182 deleteReqs() 183 { 184 delete mainReq; 185 if (isSplit) { 186 delete sreqLow; 187 delete sreqHigh; 188 } 189 } 190}; 191
|
| 192 193/** 194 * This class represents part of a data address translation. All state for 195 * the translation is held in WholeTranslationState (above). Therefore this 196 * class does not need to know whether the translation is split or not. The 197 * index variable determines this but is simply passed on to the state class. 198 * When this part of the translation is completed, finish is called. If the 199 * translation state class indicate that the whole translation is complete 200 * then the execution context is informed. 201 */
|
146template <class ExecContext> 147class DataTranslation : public BaseTLB::Translation 148{ 149 protected: 150 ExecContext *xc; 151 WholeTranslationState *state; 152 int index; 153 154 public: 155 DataTranslation(ExecContext *_xc, WholeTranslationState* _state) 156 : xc(_xc), state(_state), index(0) 157 { 158 } 159 160 DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 161 int _index) 162 : xc(_xc), state(_state), index(_index) 163 { 164 } 165
| 202template <class ExecContext> 203class DataTranslation : public BaseTLB::Translation 204{ 205 protected: 206 ExecContext *xc; 207 WholeTranslationState *state; 208 int index; 209 210 public: 211 DataTranslation(ExecContext *_xc, WholeTranslationState* _state) 212 : xc(_xc), state(_state), index(0) 213 { 214 } 215 216 DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 217 int _index) 218 : xc(_xc), state(_state), index(_index) 219 { 220 } 221
|
| 222 /** 223 * Finish this part of the translation and indicate that the whole 224 * translation is complete if the state says so. 225 */
|
166 void 167 finish(Fault fault, RequestPtr req, ThreadContext *tc, 168 BaseTLB::Mode mode) 169 { 170 assert(state); 171 assert(mode == state->mode); 172 if (state->finish(fault, index)) { 173 xc->finishTranslation(state); 174 } 175 delete this; 176 } 177}; 178 179#endif // __CPU_TRANSLATION_HH__
| 226 void 227 finish(Fault fault, RequestPtr req, ThreadContext *tc, 228 BaseTLB::Mode mode) 229 { 230 assert(state); 231 assert(mode == state->mode); 232 if (state->finish(fault, index)) { 233 xc->finishTranslation(state); 234 } 235 delete this; 236 } 237}; 238 239#endif // __CPU_TRANSLATION_HH__
|