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 --- 21 unchanged lines hidden (view full) --- 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 */ |
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 |
63 /** 64 * Single translation state. We set the number of outstanding 65 * translations to one and indicate that it is not split. 66 */ |
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 |
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 */ |
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 */ |
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 */ |
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. */ |
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 */ |
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 */ |
156 bool 157 isPrefetch() const 158 { 159 return mainReq->isPrefetch(); 160 } 161 |
162 /** Get the physical address of this request. */ |
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 */ |
174 unsigned 175 getFlags() 176 { 177 return mainReq->getFlags(); 178 } 179 |
180 /** Delete all requests that make up this translation. */ |
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 */ |
202template <class ExecContext> 203class DataTranslation : public BaseTLB::Translation 204{ 205 protected: 206 ExecContext *xc; 207 WholeTranslationState *state; 208 int index; 209 --- 4 unchanged lines hidden (view full) --- 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 */ |
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__ |