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
4810687SAndreas.Sandberg@ARM.com#include "arch/generic/tlb.hh"
497678Sgblack@eecs.umich.edu#include "sim/faults.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     */
8112749Sgiacomo.travaglini@arm.com    WholeTranslationState(const RequestPtr &_req, uint8_t *_data,
8212749Sgiacomo.travaglini@arm.com                          uint64_t *_res, 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     */
9512749Sgiacomo.travaglini@arm.com    WholeTranslationState(const RequestPtr &_req, const RequestPtr &_sreqLow,
9612749Sgiacomo.travaglini@arm.com                          const RequestPtr &_sreqHigh, uint8_t *_data,
9712749Sgiacomo.travaglini@arm.com                          uint64_t *_res, 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
11410379Sandreas.hansson@arm.com    finish(const 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    /**
15610824SAndreas.Sandberg@ARM.com     * Check if this request is strictly ordered device access.  We
15710824SAndreas.Sandberg@ARM.com     * only need to check the main request because the flags will have
15810824SAndreas.Sandberg@ARM.com     * been copied here on a split translation.
1597049Stjones1@inf.ed.ac.uk     */
1606973Stjones1@inf.ed.ac.uk    bool
16110824SAndreas.Sandberg@ARM.com    isStrictlyOrdered() const
1626973Stjones1@inf.ed.ac.uk    {
16310824SAndreas.Sandberg@ARM.com        return mainReq->isStrictlyOrdered();
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    {
19912749Sgiacomo.travaglini@arm.com        mainReq.reset();
2006973Stjones1@inf.ed.ac.uk        if (isSplit) {
20112749Sgiacomo.travaglini@arm.com            sreqLow.reset();
20212749Sgiacomo.travaglini@arm.com            sreqHigh.reset();
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 */
2178486Sgblack@eecs.umich.edutemplate <class ExecContextPtr>
2186973Stjones1@inf.ed.ac.ukclass DataTranslation : public BaseTLB::Translation
2196973Stjones1@inf.ed.ac.uk{
2206973Stjones1@inf.ed.ac.uk  protected:
2218486Sgblack@eecs.umich.edu    ExecContextPtr 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:
2268486Sgblack@eecs.umich.edu    DataTranslation(ExecContextPtr _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
2318486Sgblack@eecs.umich.edu    DataTranslation(ExecContextPtr _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
25212749Sgiacomo.travaglini@arm.com    finish(const Fault &fault, const 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)) {
25810177SMitchell.Hayenga@ARM.com            if (state->getFault() == NoFault) {
25910177SMitchell.Hayenga@ARM.com                // Don't access the request if faulted (due to squash)
26010177SMitchell.Hayenga@ARM.com                req->setTranslateLatency();
26110177SMitchell.Hayenga@ARM.com            }
2626973Stjones1@inf.ed.ac.uk            xc->finishTranslation(state);
2636973Stjones1@inf.ed.ac.uk        }
2646973Stjones1@inf.ed.ac.uk        delete this;
2656973Stjones1@inf.ed.ac.uk    }
2669258SAli.Saidi@ARM.com
2679258SAli.Saidi@ARM.com    bool
2689258SAli.Saidi@ARM.com    squashed() const
2699258SAli.Saidi@ARM.com    {
2709258SAli.Saidi@ARM.com        return xc->isSquashed();
2719258SAli.Saidi@ARM.com    }
2726973Stjones1@inf.ed.ac.uk};
2736973Stjones1@inf.ed.ac.uk
2746973Stjones1@inf.ed.ac.uk#endif // __CPU_TRANSLATION_HH__
275