table_walker.hh revision 7439
17404SAli.Saidi@ARM.com/*
210717Sandreas.hansson@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
3810037SARM gem5 Developers */
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
437404SAli.Saidi@ARM.com#include "arch/arm/miscregs.hh"
447578Sdam.sunwoo@arm.com#include "arch/arm/tlb.hh"
457578Sdam.sunwoo@arm.com#include "mem/mem_object.hh"
467404SAli.Saidi@ARM.com#include "mem/request.hh"
4710037SARM gem5 Developers#include "mem/request.hh"
487404SAli.Saidi@ARM.com#include "params/ArmTableWalker.hh"
497404SAli.Saidi@ARM.com#include "sim/faults.hh"
507404SAli.Saidi@ARM.com#include "sim/eventq.hh"
517404SAli.Saidi@ARM.com#include "base/fifo_buffer.hh"
527404SAli.Saidi@ARM.com
537404SAli.Saidi@ARM.comclass DmaPort;
547404SAli.Saidi@ARM.comclass ThreadContext;
5510873Sandreas.sandberg@arm.com
5610873Sandreas.sandberg@arm.comnamespace ArmISA {
577404SAli.Saidi@ARM.comclass Translation;
587404SAli.Saidi@ARM.comclass TLB;
597404SAli.Saidi@ARM.com
6010037SARM gem5 Developersclass TableWalker : public MemObject
617404SAli.Saidi@ARM.com{
627404SAli.Saidi@ARM.com  protected:
637404SAli.Saidi@ARM.com    struct L1Descriptor {
647694SAli.Saidi@ARM.com        /** Type of page table entry ARM DDI 0406B: B3-8*/
6510037SARM gem5 Developers        enum EntryType {
6610037SARM gem5 Developers            Ignore,
6710037SARM gem5 Developers            PageTable,
6810037SARM gem5 Developers            Section,
6910037SARM gem5 Developers            Reserved
7010037SARM gem5 Developers        };
7110037SARM gem5 Developers
7210037SARM gem5 Developers        /** The raw bits of the entry */
7310037SARM gem5 Developers        uint32_t data;
7410037SARM gem5 Developers
7510037SARM gem5 Developers        /** This entry has been modified (access flag set) and needs to be
7610037SARM gem5 Developers         * written back to memory */
7710037SARM gem5 Developers        bool _dirty;
7810037SARM gem5 Developers
7910037SARM gem5 Developers        EntryType type() const
8010037SARM gem5 Developers        {
8110037SARM gem5 Developers            return (EntryType)(data & 0x3);
8210037SARM gem5 Developers        }
8310037SARM gem5 Developers
8410037SARM gem5 Developers        /** Is the page a Supersection (16MB)?*/
8510037SARM gem5 Developers        bool supersection() const
8610037SARM gem5 Developers        {
8710037SARM gem5 Developers            return bits(data, 18);
8810037SARM gem5 Developers        }
8910037SARM gem5 Developers
9010037SARM gem5 Developers        /** Return the physcal address of the entry, bits in position*/
9110037SARM gem5 Developers        Addr paddr() const
9210037SARM gem5 Developers        {
937404SAli.Saidi@ARM.com            if (supersection())
947404SAli.Saidi@ARM.com                panic("Super sections not implemented\n");
957404SAli.Saidi@ARM.com            return mbits(data, 31,20);
967404SAli.Saidi@ARM.com        }
977404SAli.Saidi@ARM.com
987404SAli.Saidi@ARM.com        /** Return the physical frame, bits shifted right */
997404SAli.Saidi@ARM.com        Addr pfn() const
1007404SAli.Saidi@ARM.com        {
1017436Sdam.sunwoo@arm.com            if (supersection())
1027404SAli.Saidi@ARM.com                panic("Super sections not implemented\n");
1037404SAli.Saidi@ARM.com            return bits(data, 31,20);
1047436Sdam.sunwoo@arm.com        }
1057436Sdam.sunwoo@arm.com
1067436Sdam.sunwoo@arm.com        /** Is the translation global (no asid used)? */
1077436Sdam.sunwoo@arm.com        bool global() const
10810037SARM gem5 Developers        {
10910537Sandreas.hansson@arm.com            return bits(data, 4);
11010037SARM gem5 Developers        }
11110037SARM gem5 Developers
11210037SARM gem5 Developers        /** Is the translation not allow execution? */
11310037SARM gem5 Developers        bool xn() const
11410037SARM gem5 Developers        {
11510037SARM gem5 Developers            return bits(data, 17);
11610037SARM gem5 Developers        }
11710037SARM gem5 Developers
11810037SARM gem5 Developers        /** Three bit access protection flags */
11910037SARM gem5 Developers        uint8_t ap() const
12010037SARM gem5 Developers        {
12110037SARM gem5 Developers            return (bits(data, 15) << 2) | bits(data,11,10);
12210037SARM gem5 Developers        }
12310037SARM gem5 Developers
12410037SARM gem5 Developers        /** Domain Client/Manager: ARM DDI 0406B: B3-31 */
12510037SARM gem5 Developers        uint8_t domain() const
12610037SARM gem5 Developers        {
12710037SARM gem5 Developers            return bits(data,8,5);
12810037SARM gem5 Developers        }
1297404SAli.Saidi@ARM.com
1307404SAli.Saidi@ARM.com        /** Address of L2 descriptor if it exists */
1317404SAli.Saidi@ARM.com        Addr l2Addr() const
1327404SAli.Saidi@ARM.com        {
1337404SAli.Saidi@ARM.com            return mbits(data, 31,10);
1347404SAli.Saidi@ARM.com        }
1357404SAli.Saidi@ARM.com
1367404SAli.Saidi@ARM.com        /** Memory region attributes: ARM DDI 0406B: B3-32.
1377404SAli.Saidi@ARM.com         * These bits are largly ignored by M5 and only used to
1387404SAli.Saidi@ARM.com         * provide the illusion that the memory system cares about
1397404SAli.Saidi@ARM.com         * anything but cachable vs. uncachable.
1407404SAli.Saidi@ARM.com         */
1417404SAli.Saidi@ARM.com        uint8_t texcb() const
1427404SAli.Saidi@ARM.com        {
1437404SAli.Saidi@ARM.com            return bits(data, 2) | bits(data,3) << 1 | bits(data, 14, 12) << 2;
1447404SAli.Saidi@ARM.com        }
1457946SGiacomo.Gabrielli@arm.com
1467404SAli.Saidi@ARM.com        /** If the section is shareable. See texcb() comment. */
1477694SAli.Saidi@ARM.com        bool shareable() const
1487694SAli.Saidi@ARM.com        {
1497694SAli.Saidi@ARM.com            return bits(data, 16);
1507694SAli.Saidi@ARM.com        }
1517694SAli.Saidi@ARM.com
1527946SGiacomo.Gabrielli@arm.com        /** Set access flag that this entry has been touched. Mark
1537694SAli.Saidi@ARM.com         * the entry as requiring a writeback, in the future.
1547694SAli.Saidi@ARM.com         */
1557404SAli.Saidi@ARM.com        void setAp0()
1567404SAli.Saidi@ARM.com        {
1577404SAli.Saidi@ARM.com            data |= 1 << 10;
1587404SAli.Saidi@ARM.com            _dirty = true;
1597404SAli.Saidi@ARM.com        }
1607404SAli.Saidi@ARM.com
1617946SGiacomo.Gabrielli@arm.com        /** This entry needs to be written back to memory */
1627404SAli.Saidi@ARM.com        bool dirty() const
1637404SAli.Saidi@ARM.com        {
1647404SAli.Saidi@ARM.com            return _dirty;
16510037SARM gem5 Developers        }
1667404SAli.Saidi@ARM.com    };
16710037SARM gem5 Developers
1687404SAli.Saidi@ARM.com    /** Level 2 page table descriptor */
1697404SAli.Saidi@ARM.com    struct L2Descriptor {
1707404SAli.Saidi@ARM.com
1717404SAli.Saidi@ARM.com        /** The raw bits of the entry. */
1727404SAli.Saidi@ARM.com        uint32_t data;
1737608SGene.Wu@arm.com
1747404SAli.Saidi@ARM.com        /** This entry has been modified (access flag set) and needs to be
1757404SAli.Saidi@ARM.com         * written back to memory */
1767404SAli.Saidi@ARM.com        bool _dirty;
1777404SAli.Saidi@ARM.com
1787404SAli.Saidi@ARM.com        /** Is the entry invalid */
1797946SGiacomo.Gabrielli@arm.com        bool invalid() const
1807404SAli.Saidi@ARM.com        {
1817404SAli.Saidi@ARM.com            return bits(data, 1,0) == 0;;
1827404SAli.Saidi@ARM.com        }
18310037SARM gem5 Developers
1847404SAli.Saidi@ARM.com        /** What is the size of the mapping? */
18510037SARM gem5 Developers        bool large() const
1867404SAli.Saidi@ARM.com        {
1877404SAli.Saidi@ARM.com            return bits(data, 1) == 0;
1887404SAli.Saidi@ARM.com        }
1897404SAli.Saidi@ARM.com
1907404SAli.Saidi@ARM.com        /** Is execution allowed on this mapping? */
1917946SGiacomo.Gabrielli@arm.com        bool xn() const
1927404SAli.Saidi@ARM.com        {
1937404SAli.Saidi@ARM.com            return large() ? bits(data, 15) : bits(data, 0);
1947436Sdam.sunwoo@arm.com        }
1957436Sdam.sunwoo@arm.com
1967436Sdam.sunwoo@arm.com        /** Is the translation global (no asid used)? */
1977436Sdam.sunwoo@arm.com        bool global() const
1987436Sdam.sunwoo@arm.com        {
1997404SAli.Saidi@ARM.com            return !bits(data, 11);
2007404SAli.Saidi@ARM.com        }
2017946SGiacomo.Gabrielli@arm.com
2027404SAli.Saidi@ARM.com        /** Three bit access protection flags */
2037404SAli.Saidi@ARM.com        uint8_t ap() const
2047436Sdam.sunwoo@arm.com        {
2057436Sdam.sunwoo@arm.com           return bits(data, 5, 4) | (bits(data, 9) << 2);
2067436Sdam.sunwoo@arm.com        }
2077436Sdam.sunwoo@arm.com
2087436Sdam.sunwoo@arm.com        /** Memory region attributes: ARM DDI 0406B: B3-32 */
2097436Sdam.sunwoo@arm.com        uint8_t texcb() const
2107436Sdam.sunwoo@arm.com        {
2117436Sdam.sunwoo@arm.com            return large() ?
2127436Sdam.sunwoo@arm.com                (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 14, 12) << 2)) :
2137436Sdam.sunwoo@arm.com                (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 8, 6) << 2));
2147436Sdam.sunwoo@arm.com        }
2157436Sdam.sunwoo@arm.com
2167436Sdam.sunwoo@arm.com        /** Return the physical frame, bits shifted right */
2177436Sdam.sunwoo@arm.com        Addr pfn() const
2187436Sdam.sunwoo@arm.com        {
2197436Sdam.sunwoo@arm.com            return large() ? bits(data, 31, 16) : bits(data, 31, 12);
2207436Sdam.sunwoo@arm.com        }
2217436Sdam.sunwoo@arm.com
2227436Sdam.sunwoo@arm.com        /** If the section is shareable. See texcb() comment. */
2237436Sdam.sunwoo@arm.com        bool shareable() const
22410037SARM gem5 Developers        {
22510037SARM gem5 Developers            return bits(data, 10);
22610037SARM gem5 Developers        }
22710037SARM gem5 Developers
22810037SARM gem5 Developers        /** Set access flag that this entry has been touched. Mark
22910037SARM gem5 Developers         * the entry as requiring a writeback, in the future.
23010037SARM gem5 Developers         */
23110037SARM gem5 Developers        void setAp0()
23210037SARM gem5 Developers        {
23310037SARM gem5 Developers            data |= 1 << 4;
23410037SARM gem5 Developers            _dirty = true;
23510037SARM gem5 Developers        }
23610037SARM gem5 Developers
23710037SARM gem5 Developers        /** This entry needs to be written back to memory */
23810037SARM gem5 Developers        bool dirty() const
2397404SAli.Saidi@ARM.com        {
2407404SAli.Saidi@ARM.com            return _dirty;
2417404SAli.Saidi@ARM.com        }
24210037SARM gem5 Developers
24310037SARM gem5 Developers    };
2447436Sdam.sunwoo@arm.com
24510037SARM gem5 Developers    struct WalkerState //: public SimObject
24610037SARM gem5 Developers    {
2477404SAli.Saidi@ARM.com        /** Thread context that we're doing the walk for */
2487436Sdam.sunwoo@arm.com        ThreadContext *tc;
2497436Sdam.sunwoo@arm.com
2507436Sdam.sunwoo@arm.com        /** Request that is currently being serviced */
2517436Sdam.sunwoo@arm.com        RequestPtr req;
25210037SARM gem5 Developers
25310537Sandreas.hansson@arm.com        /** Context ID that we're servicing the request under */
25410037SARM gem5 Developers        uint8_t contextId;
25510037SARM gem5 Developers
25610037SARM gem5 Developers        /** Translation state for delayed requests */
25710037SARM gem5 Developers        TLB::Translation *transState;
25810537Sandreas.hansson@arm.com
25910537Sandreas.hansson@arm.com        /** The fault that we are going to return */
26010037SARM gem5 Developers        Fault fault;
26110037SARM gem5 Developers
26210037SARM gem5 Developers        /** The virtual address that is being translated */
26310037SARM gem5 Developers        Addr vaddr;
26410037SARM gem5 Developers
26510037SARM gem5 Developers        /** Cached copy of the sctlr as it existed when translation began */
26610037SARM gem5 Developers        SCTLR sctlr;
26710037SARM gem5 Developers
26810037SARM gem5 Developers        /** Cached copy of the cpsr as it existed when the translation began */
26910037SARM gem5 Developers        CPSR cpsr;
27010037SARM gem5 Developers
27110037SARM gem5 Developers        /** Width of the base address held in TTRB0 */
27210037SARM gem5 Developers        uint32_t N;
27310037SARM gem5 Developers
27410037SARM gem5 Developers        /** If the access is a write */
27510037SARM gem5 Developers        bool isWrite;
27610037SARM gem5 Developers
27710037SARM gem5 Developers        /** If the access is not from user mode */
27810037SARM gem5 Developers        bool isPriv;
27910037SARM gem5 Developers
28010037SARM gem5 Developers        /** If the access is a fetch (for execution, and no-exec) must be checked?*/
28110037SARM gem5 Developers        bool isFetch;
28210037SARM gem5 Developers
28310037SARM gem5 Developers        /** If the mode is timing or atomic */
28410037SARM gem5 Developers        bool timing;
28510037SARM gem5 Developers
28610037SARM gem5 Developers        /** Save mode for use in delayed response */
28710037SARM gem5 Developers        BaseTLB::Mode mode;
28810037SARM gem5 Developers
2897404SAli.Saidi@ARM.com        L1Descriptor l1Desc;
2907404SAli.Saidi@ARM.com        L2Descriptor l2Desc;
2917404SAli.Saidi@ARM.com
2927946SGiacomo.Gabrielli@arm.com        /** Whether L1/L2 descriptor response is delayed in timing mode */
2937404SAli.Saidi@ARM.com        bool delayed;
2947404SAli.Saidi@ARM.com
2957404SAli.Saidi@ARM.com        TableWalker *tableWalker;
2967404SAli.Saidi@ARM.com
2977404SAli.Saidi@ARM.com        void doL1Descriptor();
2987404SAli.Saidi@ARM.com        void doL2Descriptor();
2997404SAli.Saidi@ARM.com
3007404SAli.Saidi@ARM.com        std::string name() const {return tableWalker->name();}
3017404SAli.Saidi@ARM.com    };
3027404SAli.Saidi@ARM.com
3037404SAli.Saidi@ARM.com
3047404SAli.Saidi@ARM.com    FifoBuffer<WalkerState> stateQueue;
3057404SAli.Saidi@ARM.com
3067404SAli.Saidi@ARM.com    /** Port to issue translation requests from */
3077404SAli.Saidi@ARM.com    DmaPort *port;
30810037SARM gem5 Developers
3097404SAli.Saidi@ARM.com    /** TLB that is initiating these table walks */
3107404SAli.Saidi@ARM.com    TLB *tlb;
3117404SAli.Saidi@ARM.com
3127404SAli.Saidi@ARM.com    /** Cached copy of the sctlr as it existed when translation began */
3137404SAli.Saidi@ARM.com    SCTLR sctlr;
3147404SAli.Saidi@ARM.com
3157404SAli.Saidi@ARM.com    WalkerState *currState;
3167404SAli.Saidi@ARM.com
3177404SAli.Saidi@ARM.com  public:
3187404SAli.Saidi@ARM.com    typedef ArmTableWalkerParams Params;
3197404SAli.Saidi@ARM.com    TableWalker(const Params *p);
3207404SAli.Saidi@ARM.com    virtual ~TableWalker();
3217404SAli.Saidi@ARM.com
3227404SAli.Saidi@ARM.com    const Params *
3237946SGiacomo.Gabrielli@arm.com    params() const
3247946SGiacomo.Gabrielli@arm.com    {
3257404SAli.Saidi@ARM.com        return dynamic_cast<const Params *>(_params);
3267404SAli.Saidi@ARM.com    }
3277404SAli.Saidi@ARM.com
3287404SAli.Saidi@ARM.com    virtual unsigned int drain(Event *de) { panic("write me\n"); }
3297404SAli.Saidi@ARM.com    virtual Port *getPort(const std::string &if_name, int idx = -1);
3307404SAli.Saidi@ARM.com
3317404SAli.Saidi@ARM.com    Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode,
3327404SAli.Saidi@ARM.com            TLB::Translation *_trans, bool timing);
3337694SAli.Saidi@ARM.com
3347694SAli.Saidi@ARM.com    void setTlb(TLB *_tlb) { tlb = _tlb; }
3357694SAli.Saidi@ARM.com    void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
3367694SAli.Saidi@ARM.com                  uint8_t texcb, bool s);
3377694SAli.Saidi@ARM.com
3387694SAli.Saidi@ARM.com  private:
3397694SAli.Saidi@ARM.com
3407694SAli.Saidi@ARM.com    void doL1Descriptor();
3417694SAli.Saidi@ARM.com    void doL1DescriptorWrapper();
3427436Sdam.sunwoo@arm.com    EventWrapper<TableWalker, &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
3437436Sdam.sunwoo@arm.com
3447436Sdam.sunwoo@arm.com    void doL2Descriptor();
3457436Sdam.sunwoo@arm.com    void doL2DescriptorWrapper();
3467436Sdam.sunwoo@arm.com    EventWrapper<TableWalker, &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
3477436Sdam.sunwoo@arm.com
3487436Sdam.sunwoo@arm.com
3497436Sdam.sunwoo@arm.com};
3507436Sdam.sunwoo@arm.com
3517436Sdam.sunwoo@arm.com
3527436Sdam.sunwoo@arm.com} // namespace ArmISA
3537436Sdam.sunwoo@arm.com
3547436Sdam.sunwoo@arm.com#endif //__ARCH_ARM_TABLE_WALKER_HH__
3557436Sdam.sunwoo@arm.com
3567436Sdam.sunwoo@arm.com