translation.hh revision 7944
16973Stjones1@inf.ed.ac.uk/* 27944SGiacomo.Gabrielli@arm.com * Copyright (c) 2011 ARM Limited 37944SGiacomo.Gabrielli@arm.com * All rights reserved. 47944SGiacomo.Gabrielli@arm.com * 57944SGiacomo.Gabrielli@arm.com * The license below extends only to copyright in the software and shall 67944SGiacomo.Gabrielli@arm.com * not be construed as granting a license to any other intellectual 77944SGiacomo.Gabrielli@arm.com * property including but not limited to intellectual property relating 87944SGiacomo.Gabrielli@arm.com * to a hardware implementation of the functionality of the software 97944SGiacomo.Gabrielli@arm.com * licensed hereunder. You may use the software subject to the license 107944SGiacomo.Gabrielli@arm.com * terms below provided that you ensure that this notice is replicated 117944SGiacomo.Gabrielli@arm.com * unmodified and in its entirety in all distributions of the software, 127944SGiacomo.Gabrielli@arm.com * modified or unmodified, in source code or in binary form. 137944SGiacomo.Gabrielli@arm.com * 146973Stjones1@inf.ed.ac.uk * Copyright (c) 2002-2005 The Regents of The University of Michigan 156973Stjones1@inf.ed.ac.uk * Copyright (c) 2009 The University of Edinburgh 166973Stjones1@inf.ed.ac.uk * All rights reserved. 176973Stjones1@inf.ed.ac.uk * 186973Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without 196973Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are 206973Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright 216973Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer; 226973Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright 236973Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the 246973Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution; 256973Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its 266973Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from 276973Stjones1@inf.ed.ac.uk * this software without specific prior written permission. 286973Stjones1@inf.ed.ac.uk * 296973Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 306973Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 316973Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 326973Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 336973Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 346973Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 356973Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 366973Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 376973Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 386973Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 396973Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 406973Stjones1@inf.ed.ac.uk * 416973Stjones1@inf.ed.ac.uk * Authors: Gabe Black 426973Stjones1@inf.ed.ac.uk * Timothy M. Jones 436973Stjones1@inf.ed.ac.uk */ 446973Stjones1@inf.ed.ac.uk 456973Stjones1@inf.ed.ac.uk#ifndef __CPU_TRANSLATION_HH__ 466973Stjones1@inf.ed.ac.uk#define __CPU_TRANSLATION_HH__ 476973Stjones1@inf.ed.ac.uk 487678Sgblack@eecs.umich.edu#include "sim/faults.hh" 496973Stjones1@inf.ed.ac.uk#include "sim/tlb.hh" 506973Stjones1@inf.ed.ac.uk 517049Stjones1@inf.ed.ac.uk/** 527049Stjones1@inf.ed.ac.uk * This class captures the state of an address translation. A translation 537049Stjones1@inf.ed.ac.uk * can be split in two if the ISA supports it and the memory access crosses 547049Stjones1@inf.ed.ac.uk * a page boundary. In this case, this class is shared by two data 557049Stjones1@inf.ed.ac.uk * translations (below). Otherwise it is used by a single data translation 567049Stjones1@inf.ed.ac.uk * class. When each part of the translation is finished, the finish 577049Stjones1@inf.ed.ac.uk * function is called which will indicate whether the whole translation is 587049Stjones1@inf.ed.ac.uk * completed or not. There are also functions for accessing parts of the 597049Stjones1@inf.ed.ac.uk * translation state which deal with the possible split correctly. 607049Stjones1@inf.ed.ac.uk */ 616973Stjones1@inf.ed.ac.ukclass WholeTranslationState 626973Stjones1@inf.ed.ac.uk{ 636973Stjones1@inf.ed.ac.uk protected: 646973Stjones1@inf.ed.ac.uk int outstanding; 656973Stjones1@inf.ed.ac.uk Fault faults[2]; 666973Stjones1@inf.ed.ac.uk 676973Stjones1@inf.ed.ac.uk public: 687944SGiacomo.Gabrielli@arm.com bool delay; 696973Stjones1@inf.ed.ac.uk bool isSplit; 706973Stjones1@inf.ed.ac.uk RequestPtr mainReq; 716973Stjones1@inf.ed.ac.uk RequestPtr sreqLow; 726973Stjones1@inf.ed.ac.uk RequestPtr sreqHigh; 736973Stjones1@inf.ed.ac.uk uint8_t *data; 746973Stjones1@inf.ed.ac.uk uint64_t *res; 756973Stjones1@inf.ed.ac.uk BaseTLB::Mode mode; 766973Stjones1@inf.ed.ac.uk 777049Stjones1@inf.ed.ac.uk /** 787049Stjones1@inf.ed.ac.uk * Single translation state. We set the number of outstanding 797049Stjones1@inf.ed.ac.uk * translations to one and indicate that it is not split. 807049Stjones1@inf.ed.ac.uk */ 816973Stjones1@inf.ed.ac.uk WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 826973Stjones1@inf.ed.ac.uk BaseTLB::Mode _mode) 837944SGiacomo.Gabrielli@arm.com : outstanding(1), delay(false), isSplit(false), mainReq(_req), 847944SGiacomo.Gabrielli@arm.com sreqLow(NULL), sreqHigh(NULL), data(_data), res(_res), mode(_mode) 856973Stjones1@inf.ed.ac.uk { 866973Stjones1@inf.ed.ac.uk faults[0] = faults[1] = NoFault; 876973Stjones1@inf.ed.ac.uk assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 886973Stjones1@inf.ed.ac.uk } 896973Stjones1@inf.ed.ac.uk 907049Stjones1@inf.ed.ac.uk /** 917049Stjones1@inf.ed.ac.uk * Split translation state. We copy all state into this class, set the 927049Stjones1@inf.ed.ac.uk * number of outstanding translations to two and then mark this as a 937049Stjones1@inf.ed.ac.uk * split translation. 947049Stjones1@inf.ed.ac.uk */ 956973Stjones1@inf.ed.ac.uk WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 966973Stjones1@inf.ed.ac.uk RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 976973Stjones1@inf.ed.ac.uk BaseTLB::Mode _mode) 987944SGiacomo.Gabrielli@arm.com : outstanding(2), delay(false), isSplit(true), mainReq(_req), 997944SGiacomo.Gabrielli@arm.com sreqLow(_sreqLow), sreqHigh(_sreqHigh), data(_data), res(_res), 1007944SGiacomo.Gabrielli@arm.com mode(_mode) 1016973Stjones1@inf.ed.ac.uk { 1026973Stjones1@inf.ed.ac.uk faults[0] = faults[1] = NoFault; 1036973Stjones1@inf.ed.ac.uk assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 1046973Stjones1@inf.ed.ac.uk } 1056973Stjones1@inf.ed.ac.uk 1067049Stjones1@inf.ed.ac.uk /** 1077049Stjones1@inf.ed.ac.uk * Finish part of a translation. If there is only one request then this 1087049Stjones1@inf.ed.ac.uk * translation is completed. If the request has been split in two then 1097049Stjones1@inf.ed.ac.uk * the outstanding count determines whether the translation is complete. 1107049Stjones1@inf.ed.ac.uk * In this case, flags from the split request are copied to the main 1117049Stjones1@inf.ed.ac.uk * request to make it easier to access them later on. 1127049Stjones1@inf.ed.ac.uk */ 1136973Stjones1@inf.ed.ac.uk bool 1146973Stjones1@inf.ed.ac.uk finish(Fault fault, int index) 1156973Stjones1@inf.ed.ac.uk { 1166973Stjones1@inf.ed.ac.uk assert(outstanding); 1176973Stjones1@inf.ed.ac.uk faults[index] = fault; 1186973Stjones1@inf.ed.ac.uk outstanding--; 1196973Stjones1@inf.ed.ac.uk if (isSplit && outstanding == 0) { 1206973Stjones1@inf.ed.ac.uk 1216973Stjones1@inf.ed.ac.uk // For ease later, we copy some state to the main request. 1226973Stjones1@inf.ed.ac.uk if (faults[0] == NoFault) { 1236973Stjones1@inf.ed.ac.uk mainReq->setPaddr(sreqLow->getPaddr()); 1246973Stjones1@inf.ed.ac.uk } 1256973Stjones1@inf.ed.ac.uk mainReq->setFlags(sreqLow->getFlags()); 1266973Stjones1@inf.ed.ac.uk mainReq->setFlags(sreqHigh->getFlags()); 1276973Stjones1@inf.ed.ac.uk } 1286973Stjones1@inf.ed.ac.uk return outstanding == 0; 1296973Stjones1@inf.ed.ac.uk } 1306973Stjones1@inf.ed.ac.uk 1317049Stjones1@inf.ed.ac.uk /** 1327049Stjones1@inf.ed.ac.uk * Determine whether this translation produced a fault. Both parts of the 1337049Stjones1@inf.ed.ac.uk * translation must be checked if this is a split translation. 1347049Stjones1@inf.ed.ac.uk */ 1356973Stjones1@inf.ed.ac.uk Fault 1366973Stjones1@inf.ed.ac.uk getFault() const 1376973Stjones1@inf.ed.ac.uk { 1386973Stjones1@inf.ed.ac.uk if (!isSplit) 1396973Stjones1@inf.ed.ac.uk return faults[0]; 1406973Stjones1@inf.ed.ac.uk else if (faults[0] != NoFault) 1416973Stjones1@inf.ed.ac.uk return faults[0]; 1426973Stjones1@inf.ed.ac.uk else if (faults[1] != NoFault) 1436973Stjones1@inf.ed.ac.uk return faults[1]; 1446973Stjones1@inf.ed.ac.uk else 1456973Stjones1@inf.ed.ac.uk return NoFault; 1466973Stjones1@inf.ed.ac.uk } 1476973Stjones1@inf.ed.ac.uk 1487049Stjones1@inf.ed.ac.uk /** Remove all faults from the translation. */ 1496973Stjones1@inf.ed.ac.uk void 1506973Stjones1@inf.ed.ac.uk setNoFault() 1516973Stjones1@inf.ed.ac.uk { 1526973Stjones1@inf.ed.ac.uk faults[0] = faults[1] = NoFault; 1536973Stjones1@inf.ed.ac.uk } 1546973Stjones1@inf.ed.ac.uk 1557049Stjones1@inf.ed.ac.uk /** 1567049Stjones1@inf.ed.ac.uk * Check if this request is uncacheable. We only need to check the main 1577049Stjones1@inf.ed.ac.uk * request because the flags will have been copied here on a split 1587049Stjones1@inf.ed.ac.uk * translation. 1597049Stjones1@inf.ed.ac.uk */ 1606973Stjones1@inf.ed.ac.uk bool 1616973Stjones1@inf.ed.ac.uk isUncacheable() const 1626973Stjones1@inf.ed.ac.uk { 1636973Stjones1@inf.ed.ac.uk return mainReq->isUncacheable(); 1646973Stjones1@inf.ed.ac.uk } 1656973Stjones1@inf.ed.ac.uk 1667049Stjones1@inf.ed.ac.uk /** 1677049Stjones1@inf.ed.ac.uk * Check if this request is a prefetch. We only need to check the main 1687049Stjones1@inf.ed.ac.uk * request because the flags will have been copied here on a split 1697049Stjones1@inf.ed.ac.uk * translation. 1707049Stjones1@inf.ed.ac.uk */ 1716973Stjones1@inf.ed.ac.uk bool 1726973Stjones1@inf.ed.ac.uk isPrefetch() const 1736973Stjones1@inf.ed.ac.uk { 1746973Stjones1@inf.ed.ac.uk return mainReq->isPrefetch(); 1756973Stjones1@inf.ed.ac.uk } 1766973Stjones1@inf.ed.ac.uk 1777049Stjones1@inf.ed.ac.uk /** Get the physical address of this request. */ 1786973Stjones1@inf.ed.ac.uk Addr 1796973Stjones1@inf.ed.ac.uk getPaddr() const 1806973Stjones1@inf.ed.ac.uk { 1816973Stjones1@inf.ed.ac.uk return mainReq->getPaddr(); 1826973Stjones1@inf.ed.ac.uk } 1836973Stjones1@inf.ed.ac.uk 1847049Stjones1@inf.ed.ac.uk /** 1857049Stjones1@inf.ed.ac.uk * Get the flags associated with this request. We only need to access 1867049Stjones1@inf.ed.ac.uk * the main request because the flags will have been copied here on a 1877049Stjones1@inf.ed.ac.uk * split translation. 1887049Stjones1@inf.ed.ac.uk */ 1896973Stjones1@inf.ed.ac.uk unsigned 1906973Stjones1@inf.ed.ac.uk getFlags() 1916973Stjones1@inf.ed.ac.uk { 1926973Stjones1@inf.ed.ac.uk return mainReq->getFlags(); 1936973Stjones1@inf.ed.ac.uk } 1946973Stjones1@inf.ed.ac.uk 1957049Stjones1@inf.ed.ac.uk /** Delete all requests that make up this translation. */ 1966973Stjones1@inf.ed.ac.uk void 1976973Stjones1@inf.ed.ac.uk deleteReqs() 1986973Stjones1@inf.ed.ac.uk { 1996973Stjones1@inf.ed.ac.uk delete mainReq; 2006973Stjones1@inf.ed.ac.uk if (isSplit) { 2016973Stjones1@inf.ed.ac.uk delete sreqLow; 2026973Stjones1@inf.ed.ac.uk delete sreqHigh; 2036973Stjones1@inf.ed.ac.uk } 2046973Stjones1@inf.ed.ac.uk } 2056973Stjones1@inf.ed.ac.uk}; 2066973Stjones1@inf.ed.ac.uk 2077049Stjones1@inf.ed.ac.uk 2087049Stjones1@inf.ed.ac.uk/** 2097049Stjones1@inf.ed.ac.uk * This class represents part of a data address translation. All state for 2107049Stjones1@inf.ed.ac.uk * the translation is held in WholeTranslationState (above). Therefore this 2117049Stjones1@inf.ed.ac.uk * class does not need to know whether the translation is split or not. The 2127049Stjones1@inf.ed.ac.uk * index variable determines this but is simply passed on to the state class. 2137049Stjones1@inf.ed.ac.uk * When this part of the translation is completed, finish is called. If the 2147049Stjones1@inf.ed.ac.uk * translation state class indicate that the whole translation is complete 2157049Stjones1@inf.ed.ac.uk * then the execution context is informed. 2167049Stjones1@inf.ed.ac.uk */ 2176973Stjones1@inf.ed.ac.uktemplate <class ExecContext> 2186973Stjones1@inf.ed.ac.ukclass DataTranslation : public BaseTLB::Translation 2196973Stjones1@inf.ed.ac.uk{ 2206973Stjones1@inf.ed.ac.uk protected: 2216973Stjones1@inf.ed.ac.uk ExecContext *xc; 2226973Stjones1@inf.ed.ac.uk WholeTranslationState *state; 2236973Stjones1@inf.ed.ac.uk int index; 2246973Stjones1@inf.ed.ac.uk 2256973Stjones1@inf.ed.ac.uk public: 2266973Stjones1@inf.ed.ac.uk DataTranslation(ExecContext *_xc, WholeTranslationState* _state) 2276973Stjones1@inf.ed.ac.uk : xc(_xc), state(_state), index(0) 2286973Stjones1@inf.ed.ac.uk { 2296973Stjones1@inf.ed.ac.uk } 2306973Stjones1@inf.ed.ac.uk 2316973Stjones1@inf.ed.ac.uk DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 2326973Stjones1@inf.ed.ac.uk int _index) 2336973Stjones1@inf.ed.ac.uk : xc(_xc), state(_state), index(_index) 2346973Stjones1@inf.ed.ac.uk { 2356973Stjones1@inf.ed.ac.uk } 2366973Stjones1@inf.ed.ac.uk 2377049Stjones1@inf.ed.ac.uk /** 2387944SGiacomo.Gabrielli@arm.com * Signal the translation state that the translation has been delayed due 2397944SGiacomo.Gabrielli@arm.com * to a hw page table walk. Split requests are transparently handled. 2407944SGiacomo.Gabrielli@arm.com */ 2417944SGiacomo.Gabrielli@arm.com void 2427944SGiacomo.Gabrielli@arm.com markDelayed() 2437944SGiacomo.Gabrielli@arm.com { 2447944SGiacomo.Gabrielli@arm.com state->delay = true; 2457944SGiacomo.Gabrielli@arm.com } 2467944SGiacomo.Gabrielli@arm.com 2477944SGiacomo.Gabrielli@arm.com /** 2487049Stjones1@inf.ed.ac.uk * Finish this part of the translation and indicate that the whole 2497049Stjones1@inf.ed.ac.uk * translation is complete if the state says so. 2507049Stjones1@inf.ed.ac.uk */ 2516973Stjones1@inf.ed.ac.uk void 2526973Stjones1@inf.ed.ac.uk finish(Fault fault, RequestPtr req, ThreadContext *tc, 2536973Stjones1@inf.ed.ac.uk BaseTLB::Mode mode) 2546973Stjones1@inf.ed.ac.uk { 2556973Stjones1@inf.ed.ac.uk assert(state); 2566973Stjones1@inf.ed.ac.uk assert(mode == state->mode); 2576973Stjones1@inf.ed.ac.uk if (state->finish(fault, index)) { 2586973Stjones1@inf.ed.ac.uk xc->finishTranslation(state); 2596973Stjones1@inf.ed.ac.uk } 2606973Stjones1@inf.ed.ac.uk delete this; 2616973Stjones1@inf.ed.ac.uk } 2626973Stjones1@inf.ed.ac.uk}; 2636973Stjones1@inf.ed.ac.uk 2646973Stjones1@inf.ed.ac.uk#endif // __CPU_TRANSLATION_HH__ 265