translation.hh revision 7678
16973Stjones1@inf.ed.ac.uk/* 26973Stjones1@inf.ed.ac.uk * Copyright (c) 2002-2005 The Regents of The University of Michigan 36973Stjones1@inf.ed.ac.uk * Copyright (c) 2009 The University of Edinburgh 46973Stjones1@inf.ed.ac.uk * All rights reserved. 56973Stjones1@inf.ed.ac.uk * 66973Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without 76973Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are 86973Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright 96973Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer; 106973Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright 116973Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the 126973Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution; 136973Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its 146973Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from 156973Stjones1@inf.ed.ac.uk * this software without specific prior written permission. 166973Stjones1@inf.ed.ac.uk * 176973Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186973Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196973Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206973Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216973Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226973Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236973Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246973Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256973Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266973Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276973Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286973Stjones1@inf.ed.ac.uk * 296973Stjones1@inf.ed.ac.uk * Authors: Gabe Black 306973Stjones1@inf.ed.ac.uk * Timothy M. Jones 316973Stjones1@inf.ed.ac.uk */ 326973Stjones1@inf.ed.ac.uk 336973Stjones1@inf.ed.ac.uk#ifndef __CPU_TRANSLATION_HH__ 346973Stjones1@inf.ed.ac.uk#define __CPU_TRANSLATION_HH__ 356973Stjones1@inf.ed.ac.uk 367678Sgblack@eecs.umich.edu#include "sim/faults.hh" 376973Stjones1@inf.ed.ac.uk#include "sim/tlb.hh" 386973Stjones1@inf.ed.ac.uk 397049Stjones1@inf.ed.ac.uk/** 407049Stjones1@inf.ed.ac.uk * This class captures the state of an address translation. A translation 417049Stjones1@inf.ed.ac.uk * can be split in two if the ISA supports it and the memory access crosses 427049Stjones1@inf.ed.ac.uk * a page boundary. In this case, this class is shared by two data 437049Stjones1@inf.ed.ac.uk * translations (below). Otherwise it is used by a single data translation 447049Stjones1@inf.ed.ac.uk * class. When each part of the translation is finished, the finish 457049Stjones1@inf.ed.ac.uk * function is called which will indicate whether the whole translation is 467049Stjones1@inf.ed.ac.uk * completed or not. There are also functions for accessing parts of the 477049Stjones1@inf.ed.ac.uk * translation state which deal with the possible split correctly. 487049Stjones1@inf.ed.ac.uk */ 496973Stjones1@inf.ed.ac.ukclass WholeTranslationState 506973Stjones1@inf.ed.ac.uk{ 516973Stjones1@inf.ed.ac.uk protected: 526973Stjones1@inf.ed.ac.uk int outstanding; 536973Stjones1@inf.ed.ac.uk Fault faults[2]; 546973Stjones1@inf.ed.ac.uk 556973Stjones1@inf.ed.ac.uk public: 566973Stjones1@inf.ed.ac.uk bool isSplit; 576973Stjones1@inf.ed.ac.uk RequestPtr mainReq; 586973Stjones1@inf.ed.ac.uk RequestPtr sreqLow; 596973Stjones1@inf.ed.ac.uk RequestPtr sreqHigh; 606973Stjones1@inf.ed.ac.uk uint8_t *data; 616973Stjones1@inf.ed.ac.uk uint64_t *res; 626973Stjones1@inf.ed.ac.uk BaseTLB::Mode mode; 636973Stjones1@inf.ed.ac.uk 647049Stjones1@inf.ed.ac.uk /** 657049Stjones1@inf.ed.ac.uk * Single translation state. We set the number of outstanding 667049Stjones1@inf.ed.ac.uk * translations to one and indicate that it is not split. 677049Stjones1@inf.ed.ac.uk */ 686973Stjones1@inf.ed.ac.uk WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 696973Stjones1@inf.ed.ac.uk BaseTLB::Mode _mode) 706973Stjones1@inf.ed.ac.uk : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL), 716973Stjones1@inf.ed.ac.uk sreqHigh(NULL), data(_data), res(_res), mode(_mode) 726973Stjones1@inf.ed.ac.uk { 736973Stjones1@inf.ed.ac.uk faults[0] = faults[1] = NoFault; 746973Stjones1@inf.ed.ac.uk assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 756973Stjones1@inf.ed.ac.uk } 766973Stjones1@inf.ed.ac.uk 777049Stjones1@inf.ed.ac.uk /** 787049Stjones1@inf.ed.ac.uk * Split translation state. We copy all state into this class, set the 797049Stjones1@inf.ed.ac.uk * number of outstanding translations to two and then mark this as a 807049Stjones1@inf.ed.ac.uk * split translation. 817049Stjones1@inf.ed.ac.uk */ 826973Stjones1@inf.ed.ac.uk WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 836973Stjones1@inf.ed.ac.uk RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 846973Stjones1@inf.ed.ac.uk BaseTLB::Mode _mode) 856973Stjones1@inf.ed.ac.uk : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow), 866973Stjones1@inf.ed.ac.uk sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode) 876973Stjones1@inf.ed.ac.uk { 886973Stjones1@inf.ed.ac.uk faults[0] = faults[1] = NoFault; 896973Stjones1@inf.ed.ac.uk assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 906973Stjones1@inf.ed.ac.uk } 916973Stjones1@inf.ed.ac.uk 927049Stjones1@inf.ed.ac.uk /** 937049Stjones1@inf.ed.ac.uk * Finish part of a translation. If there is only one request then this 947049Stjones1@inf.ed.ac.uk * translation is completed. If the request has been split in two then 957049Stjones1@inf.ed.ac.uk * the outstanding count determines whether the translation is complete. 967049Stjones1@inf.ed.ac.uk * In this case, flags from the split request are copied to the main 977049Stjones1@inf.ed.ac.uk * request to make it easier to access them later on. 987049Stjones1@inf.ed.ac.uk */ 996973Stjones1@inf.ed.ac.uk bool 1006973Stjones1@inf.ed.ac.uk finish(Fault fault, int index) 1016973Stjones1@inf.ed.ac.uk { 1026973Stjones1@inf.ed.ac.uk assert(outstanding); 1036973Stjones1@inf.ed.ac.uk faults[index] = fault; 1046973Stjones1@inf.ed.ac.uk outstanding--; 1056973Stjones1@inf.ed.ac.uk if (isSplit && outstanding == 0) { 1066973Stjones1@inf.ed.ac.uk 1076973Stjones1@inf.ed.ac.uk // For ease later, we copy some state to the main request. 1086973Stjones1@inf.ed.ac.uk if (faults[0] == NoFault) { 1096973Stjones1@inf.ed.ac.uk mainReq->setPaddr(sreqLow->getPaddr()); 1106973Stjones1@inf.ed.ac.uk } 1116973Stjones1@inf.ed.ac.uk mainReq->setFlags(sreqLow->getFlags()); 1126973Stjones1@inf.ed.ac.uk mainReq->setFlags(sreqHigh->getFlags()); 1136973Stjones1@inf.ed.ac.uk } 1146973Stjones1@inf.ed.ac.uk return outstanding == 0; 1156973Stjones1@inf.ed.ac.uk } 1166973Stjones1@inf.ed.ac.uk 1177049Stjones1@inf.ed.ac.uk /** 1187049Stjones1@inf.ed.ac.uk * Determine whether this translation produced a fault. Both parts of the 1197049Stjones1@inf.ed.ac.uk * translation must be checked if this is a split translation. 1207049Stjones1@inf.ed.ac.uk */ 1216973Stjones1@inf.ed.ac.uk Fault 1226973Stjones1@inf.ed.ac.uk getFault() const 1236973Stjones1@inf.ed.ac.uk { 1246973Stjones1@inf.ed.ac.uk if (!isSplit) 1256973Stjones1@inf.ed.ac.uk return faults[0]; 1266973Stjones1@inf.ed.ac.uk else if (faults[0] != NoFault) 1276973Stjones1@inf.ed.ac.uk return faults[0]; 1286973Stjones1@inf.ed.ac.uk else if (faults[1] != NoFault) 1296973Stjones1@inf.ed.ac.uk return faults[1]; 1306973Stjones1@inf.ed.ac.uk else 1316973Stjones1@inf.ed.ac.uk return NoFault; 1326973Stjones1@inf.ed.ac.uk } 1336973Stjones1@inf.ed.ac.uk 1347049Stjones1@inf.ed.ac.uk /** Remove all faults from the translation. */ 1356973Stjones1@inf.ed.ac.uk void 1366973Stjones1@inf.ed.ac.uk setNoFault() 1376973Stjones1@inf.ed.ac.uk { 1386973Stjones1@inf.ed.ac.uk faults[0] = faults[1] = NoFault; 1396973Stjones1@inf.ed.ac.uk } 1406973Stjones1@inf.ed.ac.uk 1417049Stjones1@inf.ed.ac.uk /** 1427049Stjones1@inf.ed.ac.uk * Check if this request is uncacheable. We only need to check the main 1437049Stjones1@inf.ed.ac.uk * request because the flags will have been copied here on a split 1447049Stjones1@inf.ed.ac.uk * translation. 1457049Stjones1@inf.ed.ac.uk */ 1466973Stjones1@inf.ed.ac.uk bool 1476973Stjones1@inf.ed.ac.uk isUncacheable() const 1486973Stjones1@inf.ed.ac.uk { 1496973Stjones1@inf.ed.ac.uk return mainReq->isUncacheable(); 1506973Stjones1@inf.ed.ac.uk } 1516973Stjones1@inf.ed.ac.uk 1527049Stjones1@inf.ed.ac.uk /** 1537049Stjones1@inf.ed.ac.uk * Check if this request is a prefetch. We only need to check the main 1547049Stjones1@inf.ed.ac.uk * request because the flags will have been copied here on a split 1557049Stjones1@inf.ed.ac.uk * translation. 1567049Stjones1@inf.ed.ac.uk */ 1576973Stjones1@inf.ed.ac.uk bool 1586973Stjones1@inf.ed.ac.uk isPrefetch() const 1596973Stjones1@inf.ed.ac.uk { 1606973Stjones1@inf.ed.ac.uk return mainReq->isPrefetch(); 1616973Stjones1@inf.ed.ac.uk } 1626973Stjones1@inf.ed.ac.uk 1637049Stjones1@inf.ed.ac.uk /** Get the physical address of this request. */ 1646973Stjones1@inf.ed.ac.uk Addr 1656973Stjones1@inf.ed.ac.uk getPaddr() const 1666973Stjones1@inf.ed.ac.uk { 1676973Stjones1@inf.ed.ac.uk return mainReq->getPaddr(); 1686973Stjones1@inf.ed.ac.uk } 1696973Stjones1@inf.ed.ac.uk 1707049Stjones1@inf.ed.ac.uk /** 1717049Stjones1@inf.ed.ac.uk * Get the flags associated with this request. We only need to access 1727049Stjones1@inf.ed.ac.uk * the main request because the flags will have been copied here on a 1737049Stjones1@inf.ed.ac.uk * split translation. 1747049Stjones1@inf.ed.ac.uk */ 1756973Stjones1@inf.ed.ac.uk unsigned 1766973Stjones1@inf.ed.ac.uk getFlags() 1776973Stjones1@inf.ed.ac.uk { 1786973Stjones1@inf.ed.ac.uk return mainReq->getFlags(); 1796973Stjones1@inf.ed.ac.uk } 1806973Stjones1@inf.ed.ac.uk 1817049Stjones1@inf.ed.ac.uk /** Delete all requests that make up this translation. */ 1826973Stjones1@inf.ed.ac.uk void 1836973Stjones1@inf.ed.ac.uk deleteReqs() 1846973Stjones1@inf.ed.ac.uk { 1856973Stjones1@inf.ed.ac.uk delete mainReq; 1866973Stjones1@inf.ed.ac.uk if (isSplit) { 1876973Stjones1@inf.ed.ac.uk delete sreqLow; 1886973Stjones1@inf.ed.ac.uk delete sreqHigh; 1896973Stjones1@inf.ed.ac.uk } 1906973Stjones1@inf.ed.ac.uk } 1916973Stjones1@inf.ed.ac.uk}; 1926973Stjones1@inf.ed.ac.uk 1937049Stjones1@inf.ed.ac.uk 1947049Stjones1@inf.ed.ac.uk/** 1957049Stjones1@inf.ed.ac.uk * This class represents part of a data address translation. All state for 1967049Stjones1@inf.ed.ac.uk * the translation is held in WholeTranslationState (above). Therefore this 1977049Stjones1@inf.ed.ac.uk * class does not need to know whether the translation is split or not. The 1987049Stjones1@inf.ed.ac.uk * index variable determines this but is simply passed on to the state class. 1997049Stjones1@inf.ed.ac.uk * When this part of the translation is completed, finish is called. If the 2007049Stjones1@inf.ed.ac.uk * translation state class indicate that the whole translation is complete 2017049Stjones1@inf.ed.ac.uk * then the execution context is informed. 2027049Stjones1@inf.ed.ac.uk */ 2036973Stjones1@inf.ed.ac.uktemplate <class ExecContext> 2046973Stjones1@inf.ed.ac.ukclass DataTranslation : public BaseTLB::Translation 2056973Stjones1@inf.ed.ac.uk{ 2066973Stjones1@inf.ed.ac.uk protected: 2076973Stjones1@inf.ed.ac.uk ExecContext *xc; 2086973Stjones1@inf.ed.ac.uk WholeTranslationState *state; 2096973Stjones1@inf.ed.ac.uk int index; 2106973Stjones1@inf.ed.ac.uk 2116973Stjones1@inf.ed.ac.uk public: 2126973Stjones1@inf.ed.ac.uk DataTranslation(ExecContext *_xc, WholeTranslationState* _state) 2136973Stjones1@inf.ed.ac.uk : xc(_xc), state(_state), index(0) 2146973Stjones1@inf.ed.ac.uk { 2156973Stjones1@inf.ed.ac.uk } 2166973Stjones1@inf.ed.ac.uk 2176973Stjones1@inf.ed.ac.uk DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 2186973Stjones1@inf.ed.ac.uk int _index) 2196973Stjones1@inf.ed.ac.uk : xc(_xc), state(_state), index(_index) 2206973Stjones1@inf.ed.ac.uk { 2216973Stjones1@inf.ed.ac.uk } 2226973Stjones1@inf.ed.ac.uk 2237049Stjones1@inf.ed.ac.uk /** 2247049Stjones1@inf.ed.ac.uk * Finish this part of the translation and indicate that the whole 2257049Stjones1@inf.ed.ac.uk * translation is complete if the state says so. 2267049Stjones1@inf.ed.ac.uk */ 2276973Stjones1@inf.ed.ac.uk void 2286973Stjones1@inf.ed.ac.uk finish(Fault fault, RequestPtr req, ThreadContext *tc, 2296973Stjones1@inf.ed.ac.uk BaseTLB::Mode mode) 2306973Stjones1@inf.ed.ac.uk { 2316973Stjones1@inf.ed.ac.uk assert(state); 2326973Stjones1@inf.ed.ac.uk assert(mode == state->mode); 2336973Stjones1@inf.ed.ac.uk if (state->finish(fault, index)) { 2346973Stjones1@inf.ed.ac.uk xc->finishTranslation(state); 2356973Stjones1@inf.ed.ac.uk } 2366973Stjones1@inf.ed.ac.uk delete this; 2376973Stjones1@inf.ed.ac.uk } 2386973Stjones1@inf.ed.ac.uk}; 2396973Stjones1@inf.ed.ac.uk 2406973Stjones1@inf.ed.ac.uk#endif // __CPU_TRANSLATION_HH__ 241