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