table_walker.hh revision 7608
17404SAli.Saidi@ARM.com/*
27404SAli.Saidi@ARM.com * Copyright (c) 2010 ARM Limited
37404SAli.Saidi@ARM.com * All rights reserved
47404SAli.Saidi@ARM.com *
57404SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67404SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77404SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87404SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97404SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107404SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117404SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127404SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137404SAli.Saidi@ARM.com *
147404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
157404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
167404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
177404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
187404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
197404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
207404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
217404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
227404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
237404SAli.Saidi@ARM.com * this software without specific prior written permission.
247404SAli.Saidi@ARM.com *
257404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
267404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
277404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
287404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
297404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
357404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367404SAli.Saidi@ARM.com *
377404SAli.Saidi@ARM.com * Authors: Ali Saidi
387404SAli.Saidi@ARM.com */
397404SAli.Saidi@ARM.com
407404SAli.Saidi@ARM.com#ifndef __ARCH_ARM_TABLE_WALKER_HH__
417404SAli.Saidi@ARM.com#define __ARCH_ARM_TABLE_WALKER_HH__
427404SAli.Saidi@ARM.com
437578Sdam.sunwoo@arm.com#include <list>
447578Sdam.sunwoo@arm.com
457404SAli.Saidi@ARM.com#include "arch/arm/miscregs.hh"
467404SAli.Saidi@ARM.com#include "arch/arm/tlb.hh"
477404SAli.Saidi@ARM.com#include "mem/mem_object.hh"
487404SAli.Saidi@ARM.com#include "mem/request.hh"
497404SAli.Saidi@ARM.com#include "mem/request.hh"
507404SAli.Saidi@ARM.com#include "params/ArmTableWalker.hh"
517404SAli.Saidi@ARM.com#include "sim/faults.hh"
527404SAli.Saidi@ARM.com#include "sim/eventq.hh"
537404SAli.Saidi@ARM.com
547404SAli.Saidi@ARM.comclass DmaPort;
557404SAli.Saidi@ARM.comclass ThreadContext;
567404SAli.Saidi@ARM.com
577404SAli.Saidi@ARM.comnamespace ArmISA {
587404SAli.Saidi@ARM.comclass Translation;
597404SAli.Saidi@ARM.comclass TLB;
607404SAli.Saidi@ARM.com
617404SAli.Saidi@ARM.comclass TableWalker : public MemObject
627404SAli.Saidi@ARM.com{
637404SAli.Saidi@ARM.com  protected:
647404SAli.Saidi@ARM.com    struct L1Descriptor {
657404SAli.Saidi@ARM.com        /** Type of page table entry ARM DDI 0406B: B3-8*/
667404SAli.Saidi@ARM.com        enum EntryType {
677404SAli.Saidi@ARM.com            Ignore,
687404SAli.Saidi@ARM.com            PageTable,
697404SAli.Saidi@ARM.com            Section,
707404SAli.Saidi@ARM.com            Reserved
717404SAli.Saidi@ARM.com        };
727404SAli.Saidi@ARM.com
737436Sdam.sunwoo@arm.com        /** The raw bits of the entry */
747404SAli.Saidi@ARM.com        uint32_t data;
757404SAli.Saidi@ARM.com
767436Sdam.sunwoo@arm.com        /** This entry has been modified (access flag set) and needs to be
777436Sdam.sunwoo@arm.com         * written back to memory */
787436Sdam.sunwoo@arm.com        bool _dirty;
797436Sdam.sunwoo@arm.com
807404SAli.Saidi@ARM.com        EntryType type() const
817404SAli.Saidi@ARM.com        {
827404SAli.Saidi@ARM.com            return (EntryType)(data & 0x3);
837404SAli.Saidi@ARM.com        }
847404SAli.Saidi@ARM.com
857404SAli.Saidi@ARM.com        /** Is the page a Supersection (16MB)?*/
867404SAli.Saidi@ARM.com        bool supersection() const
877404SAli.Saidi@ARM.com        {
887404SAli.Saidi@ARM.com            return bits(data, 18);
897404SAli.Saidi@ARM.com        }
907404SAli.Saidi@ARM.com
917404SAli.Saidi@ARM.com        /** Return the physcal address of the entry, bits in position*/
927404SAli.Saidi@ARM.com        Addr paddr() const
937404SAli.Saidi@ARM.com        {
947404SAli.Saidi@ARM.com            if (supersection())
957404SAli.Saidi@ARM.com                panic("Super sections not implemented\n");
967404SAli.Saidi@ARM.com            return mbits(data, 31,20);
977404SAli.Saidi@ARM.com        }
987404SAli.Saidi@ARM.com
997404SAli.Saidi@ARM.com        /** Return the physical frame, bits shifted right */
1007404SAli.Saidi@ARM.com        Addr pfn() const
1017404SAli.Saidi@ARM.com        {
1027404SAli.Saidi@ARM.com            if (supersection())
1037404SAli.Saidi@ARM.com                panic("Super sections not implemented\n");
1047404SAli.Saidi@ARM.com            return bits(data, 31,20);
1057404SAli.Saidi@ARM.com        }
1067404SAli.Saidi@ARM.com
1077404SAli.Saidi@ARM.com        /** Is the translation global (no asid used)? */
1087404SAli.Saidi@ARM.com        bool global() const
1097404SAli.Saidi@ARM.com        {
1107608SGene.Wu@arm.com            return bits(data, 17);
1117404SAli.Saidi@ARM.com        }
1127404SAli.Saidi@ARM.com
1137404SAli.Saidi@ARM.com        /** Is the translation not allow execution? */
1147404SAli.Saidi@ARM.com        bool xn() const
1157404SAli.Saidi@ARM.com        {
1167608SGene.Wu@arm.com            return bits(data, 4);
1177404SAli.Saidi@ARM.com        }
1187404SAli.Saidi@ARM.com
1197404SAli.Saidi@ARM.com        /** Three bit access protection flags */
1207404SAli.Saidi@ARM.com        uint8_t ap() const
1217404SAli.Saidi@ARM.com        {
1227404SAli.Saidi@ARM.com            return (bits(data, 15) << 2) | bits(data,11,10);
1237404SAli.Saidi@ARM.com        }
1247404SAli.Saidi@ARM.com
1257404SAli.Saidi@ARM.com        /** Domain Client/Manager: ARM DDI 0406B: B3-31 */
1267404SAli.Saidi@ARM.com        uint8_t domain() const
1277404SAli.Saidi@ARM.com        {
1287404SAli.Saidi@ARM.com            return bits(data,8,5);
1297404SAli.Saidi@ARM.com        }
1307404SAli.Saidi@ARM.com
1317404SAli.Saidi@ARM.com        /** Address of L2 descriptor if it exists */
1327404SAli.Saidi@ARM.com        Addr l2Addr() const
1337404SAli.Saidi@ARM.com        {
1347404SAli.Saidi@ARM.com            return mbits(data, 31,10);
1357404SAli.Saidi@ARM.com        }
1367404SAli.Saidi@ARM.com
1377436Sdam.sunwoo@arm.com        /** Memory region attributes: ARM DDI 0406B: B3-32.
1387436Sdam.sunwoo@arm.com         * These bits are largly ignored by M5 and only used to
1397436Sdam.sunwoo@arm.com         * provide the illusion that the memory system cares about
1407436Sdam.sunwoo@arm.com         * anything but cachable vs. uncachable.
1417436Sdam.sunwoo@arm.com         */
1427404SAli.Saidi@ARM.com        uint8_t texcb() const
1437404SAli.Saidi@ARM.com        {
1447406SAli.Saidi@ARM.com            return bits(data, 2) | bits(data,3) << 1 | bits(data, 14, 12) << 2;
1457404SAli.Saidi@ARM.com        }
1467404SAli.Saidi@ARM.com
1477436Sdam.sunwoo@arm.com        /** If the section is shareable. See texcb() comment. */
1487436Sdam.sunwoo@arm.com        bool shareable() const
1497436Sdam.sunwoo@arm.com        {
1507436Sdam.sunwoo@arm.com            return bits(data, 16);
1517436Sdam.sunwoo@arm.com        }
1527436Sdam.sunwoo@arm.com
1537436Sdam.sunwoo@arm.com        /** Set access flag that this entry has been touched. Mark
1547436Sdam.sunwoo@arm.com         * the entry as requiring a writeback, in the future.
1557436Sdam.sunwoo@arm.com         */
1567436Sdam.sunwoo@arm.com        void setAp0()
1577436Sdam.sunwoo@arm.com        {
1587436Sdam.sunwoo@arm.com            data |= 1 << 10;
1597436Sdam.sunwoo@arm.com            _dirty = true;
1607436Sdam.sunwoo@arm.com        }
1617436Sdam.sunwoo@arm.com
1627436Sdam.sunwoo@arm.com        /** This entry needs to be written back to memory */
1637436Sdam.sunwoo@arm.com        bool dirty() const
1647436Sdam.sunwoo@arm.com        {
1657436Sdam.sunwoo@arm.com            return _dirty;
1667436Sdam.sunwoo@arm.com        }
1677404SAli.Saidi@ARM.com    };
1687404SAli.Saidi@ARM.com
1697404SAli.Saidi@ARM.com    /** Level 2 page table descriptor */
1707404SAli.Saidi@ARM.com    struct L2Descriptor {
1717404SAli.Saidi@ARM.com
1727436Sdam.sunwoo@arm.com        /** The raw bits of the entry. */
1737404SAli.Saidi@ARM.com        uint32_t data;
1747404SAli.Saidi@ARM.com
1757436Sdam.sunwoo@arm.com        /** This entry has been modified (access flag set) and needs to be
1767436Sdam.sunwoo@arm.com         * written back to memory */
1777436Sdam.sunwoo@arm.com        bool _dirty;
1787436Sdam.sunwoo@arm.com
1797404SAli.Saidi@ARM.com        /** Is the entry invalid */
1807404SAli.Saidi@ARM.com        bool invalid() const
1817404SAli.Saidi@ARM.com        {
1827404SAli.Saidi@ARM.com            return bits(data, 1,0) == 0;;
1837404SAli.Saidi@ARM.com        }
1847404SAli.Saidi@ARM.com
1857404SAli.Saidi@ARM.com        /** What is the size of the mapping? */
1867404SAli.Saidi@ARM.com        bool large() const
1877404SAli.Saidi@ARM.com        {
1887404SAli.Saidi@ARM.com            return bits(data, 1) == 0;
1897404SAli.Saidi@ARM.com        }
1907404SAli.Saidi@ARM.com
1917404SAli.Saidi@ARM.com        /** Is execution allowed on this mapping? */
1927404SAli.Saidi@ARM.com        bool xn() const
1937404SAli.Saidi@ARM.com        {
1947404SAli.Saidi@ARM.com            return large() ? bits(data, 15) : bits(data, 0);
1957404SAli.Saidi@ARM.com        }
1967404SAli.Saidi@ARM.com
1977404SAli.Saidi@ARM.com        /** Is the translation global (no asid used)? */
1987404SAli.Saidi@ARM.com        bool global() const
1997404SAli.Saidi@ARM.com        {
2007404SAli.Saidi@ARM.com            return !bits(data, 11);
2017404SAli.Saidi@ARM.com        }
2027404SAli.Saidi@ARM.com
2037404SAli.Saidi@ARM.com        /** Three bit access protection flags */
2047404SAli.Saidi@ARM.com        uint8_t ap() const
2057404SAli.Saidi@ARM.com        {
2067404SAli.Saidi@ARM.com           return bits(data, 5, 4) | (bits(data, 9) << 2);
2077404SAli.Saidi@ARM.com        }
2087404SAli.Saidi@ARM.com
2097404SAli.Saidi@ARM.com        /** Memory region attributes: ARM DDI 0406B: B3-32 */
2107404SAli.Saidi@ARM.com        uint8_t texcb() const
2117404SAli.Saidi@ARM.com        {
2127404SAli.Saidi@ARM.com            return large() ?
2137406SAli.Saidi@ARM.com                (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 14, 12) << 2)) :
2147406SAli.Saidi@ARM.com                (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 8, 6) << 2));
2157404SAli.Saidi@ARM.com        }
2167404SAli.Saidi@ARM.com
2177404SAli.Saidi@ARM.com        /** Return the physical frame, bits shifted right */
2187404SAli.Saidi@ARM.com        Addr pfn() const
2197404SAli.Saidi@ARM.com        {
2207404SAli.Saidi@ARM.com            return large() ? bits(data, 31, 16) : bits(data, 31, 12);
2217404SAli.Saidi@ARM.com        }
2227404SAli.Saidi@ARM.com
2237436Sdam.sunwoo@arm.com        /** If the section is shareable. See texcb() comment. */
2247436Sdam.sunwoo@arm.com        bool shareable() const
2257436Sdam.sunwoo@arm.com        {
2267436Sdam.sunwoo@arm.com            return bits(data, 10);
2277436Sdam.sunwoo@arm.com        }
2287436Sdam.sunwoo@arm.com
2297436Sdam.sunwoo@arm.com        /** Set access flag that this entry has been touched. Mark
2307436Sdam.sunwoo@arm.com         * the entry as requiring a writeback, in the future.
2317436Sdam.sunwoo@arm.com         */
2327436Sdam.sunwoo@arm.com        void setAp0()
2337436Sdam.sunwoo@arm.com        {
2347436Sdam.sunwoo@arm.com            data |= 1 << 4;
2357436Sdam.sunwoo@arm.com            _dirty = true;
2367436Sdam.sunwoo@arm.com        }
2377436Sdam.sunwoo@arm.com
2387436Sdam.sunwoo@arm.com        /** This entry needs to be written back to memory */
2397436Sdam.sunwoo@arm.com        bool dirty() const
2407436Sdam.sunwoo@arm.com        {
2417436Sdam.sunwoo@arm.com            return _dirty;
2427436Sdam.sunwoo@arm.com        }
2437436Sdam.sunwoo@arm.com
2447404SAli.Saidi@ARM.com    };
2457404SAli.Saidi@ARM.com
2467439Sdam.sunwoo@arm.com    struct WalkerState //: public SimObject
2477439Sdam.sunwoo@arm.com    {
2487439Sdam.sunwoo@arm.com        /** Thread context that we're doing the walk for */
2497439Sdam.sunwoo@arm.com        ThreadContext *tc;
2507439Sdam.sunwoo@arm.com
2517439Sdam.sunwoo@arm.com        /** Request that is currently being serviced */
2527439Sdam.sunwoo@arm.com        RequestPtr req;
2537439Sdam.sunwoo@arm.com
2547439Sdam.sunwoo@arm.com        /** Context ID that we're servicing the request under */
2557439Sdam.sunwoo@arm.com        uint8_t contextId;
2567439Sdam.sunwoo@arm.com
2577439Sdam.sunwoo@arm.com        /** Translation state for delayed requests */
2587439Sdam.sunwoo@arm.com        TLB::Translation *transState;
2597439Sdam.sunwoo@arm.com
2607439Sdam.sunwoo@arm.com        /** The fault that we are going to return */
2617439Sdam.sunwoo@arm.com        Fault fault;
2627439Sdam.sunwoo@arm.com
2637439Sdam.sunwoo@arm.com        /** The virtual address that is being translated */
2647439Sdam.sunwoo@arm.com        Addr vaddr;
2657439Sdam.sunwoo@arm.com
2667439Sdam.sunwoo@arm.com        /** Cached copy of the sctlr as it existed when translation began */
2677439Sdam.sunwoo@arm.com        SCTLR sctlr;
2687439Sdam.sunwoo@arm.com
2697439Sdam.sunwoo@arm.com        /** Cached copy of the cpsr as it existed when the translation began */
2707439Sdam.sunwoo@arm.com        CPSR cpsr;
2717439Sdam.sunwoo@arm.com
2727439Sdam.sunwoo@arm.com        /** Width of the base address held in TTRB0 */
2737439Sdam.sunwoo@arm.com        uint32_t N;
2747439Sdam.sunwoo@arm.com
2757439Sdam.sunwoo@arm.com        /** If the access is a write */
2767439Sdam.sunwoo@arm.com        bool isWrite;
2777439Sdam.sunwoo@arm.com
2787439Sdam.sunwoo@arm.com        /** If the access is not from user mode */
2797439Sdam.sunwoo@arm.com        bool isPriv;
2807439Sdam.sunwoo@arm.com
2817439Sdam.sunwoo@arm.com        /** If the access is a fetch (for execution, and no-exec) must be checked?*/
2827439Sdam.sunwoo@arm.com        bool isFetch;
2837439Sdam.sunwoo@arm.com
2847439Sdam.sunwoo@arm.com        /** If the mode is timing or atomic */
2857439Sdam.sunwoo@arm.com        bool timing;
2867439Sdam.sunwoo@arm.com
2877439Sdam.sunwoo@arm.com        /** Save mode for use in delayed response */
2887439Sdam.sunwoo@arm.com        BaseTLB::Mode mode;
2897439Sdam.sunwoo@arm.com
2907439Sdam.sunwoo@arm.com        L1Descriptor l1Desc;
2917439Sdam.sunwoo@arm.com        L2Descriptor l2Desc;
2927439Sdam.sunwoo@arm.com
2937439Sdam.sunwoo@arm.com        /** Whether L1/L2 descriptor response is delayed in timing mode */
2947439Sdam.sunwoo@arm.com        bool delayed;
2957439Sdam.sunwoo@arm.com
2967439Sdam.sunwoo@arm.com        TableWalker *tableWalker;
2977439Sdam.sunwoo@arm.com
2987439Sdam.sunwoo@arm.com        void doL1Descriptor();
2997439Sdam.sunwoo@arm.com        void doL2Descriptor();
3007439Sdam.sunwoo@arm.com
3017439Sdam.sunwoo@arm.com        std::string name() const {return tableWalker->name();}
3027439Sdam.sunwoo@arm.com    };
3037439Sdam.sunwoo@arm.com
3047439Sdam.sunwoo@arm.com
3057578Sdam.sunwoo@arm.com    std::list<WalkerState *> stateQueue;
3067439Sdam.sunwoo@arm.com
3077404SAli.Saidi@ARM.com    /** Port to issue translation requests from */
3087404SAli.Saidi@ARM.com    DmaPort *port;
3097404SAli.Saidi@ARM.com
3107404SAli.Saidi@ARM.com    /** TLB that is initiating these table walks */
3117404SAli.Saidi@ARM.com    TLB *tlb;
3127404SAli.Saidi@ARM.com
3137404SAli.Saidi@ARM.com    /** Cached copy of the sctlr as it existed when translation began */
3147404SAli.Saidi@ARM.com    SCTLR sctlr;
3157404SAli.Saidi@ARM.com
3167439Sdam.sunwoo@arm.com    WalkerState *currState;
3177437Sdam.sunwoo@arm.com
3187404SAli.Saidi@ARM.com  public:
3197404SAli.Saidi@ARM.com    typedef ArmTableWalkerParams Params;
3207404SAli.Saidi@ARM.com    TableWalker(const Params *p);
3217404SAli.Saidi@ARM.com    virtual ~TableWalker();
3227404SAli.Saidi@ARM.com
3237404SAli.Saidi@ARM.com    const Params *
3247404SAli.Saidi@ARM.com    params() const
3257404SAli.Saidi@ARM.com    {
3267404SAli.Saidi@ARM.com        return dynamic_cast<const Params *>(_params);
3277404SAli.Saidi@ARM.com    }
3287404SAli.Saidi@ARM.com
3297404SAli.Saidi@ARM.com    virtual unsigned int drain(Event *de) { panic("write me\n"); }
3307404SAli.Saidi@ARM.com    virtual Port *getPort(const std::string &if_name, int idx = -1);
3317404SAli.Saidi@ARM.com
3327404SAli.Saidi@ARM.com    Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode,
3337404SAli.Saidi@ARM.com            TLB::Translation *_trans, bool timing);
3347404SAli.Saidi@ARM.com
3357404SAli.Saidi@ARM.com    void setTlb(TLB *_tlb) { tlb = _tlb; }
3367439Sdam.sunwoo@arm.com    void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
3377439Sdam.sunwoo@arm.com                  uint8_t texcb, bool s);
3387404SAli.Saidi@ARM.com
3397404SAli.Saidi@ARM.com  private:
3407404SAli.Saidi@ARM.com
3417404SAli.Saidi@ARM.com    void doL1Descriptor();
3427437Sdam.sunwoo@arm.com    void doL1DescriptorWrapper();
3437437Sdam.sunwoo@arm.com    EventWrapper<TableWalker, &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
3447404SAli.Saidi@ARM.com
3457404SAli.Saidi@ARM.com    void doL2Descriptor();
3467437Sdam.sunwoo@arm.com    void doL2DescriptorWrapper();
3477437Sdam.sunwoo@arm.com    EventWrapper<TableWalker, &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
3487404SAli.Saidi@ARM.com
3497404SAli.Saidi@ARM.com
3507404SAli.Saidi@ARM.com};
3517404SAli.Saidi@ARM.com
3527404SAli.Saidi@ARM.com
3537404SAli.Saidi@ARM.com} // namespace ArmISA
3547404SAli.Saidi@ARM.com
3557404SAli.Saidi@ARM.com#endif //__ARCH_ARM_TABLE_WALKER_HH__
3567404SAli.Saidi@ARM.com
357