smmu_v3_ptops.cc revision 14039
12740SN/A/*
27534Ssteve.reinhardt@amd.com * Copyright (c) 2013, 2018-2019 ARM Limited
31046SN/A * All rights reserved
41046SN/A *
51046SN/A * The license below extends only to copyright in the software and shall
61046SN/A * not be construed as granting a license to any other intellectual
71046SN/A * property including but not limited to intellectual property relating
81046SN/A * to a hardware implementation of the functionality of the software
91046SN/A * licensed hereunder.  You may use the software subject to the license
101046SN/A * terms below provided that you ensure that this notice is replicated
111046SN/A * unmodified and in its entirety in all distributions of the software,
121046SN/A * modified or unmodified, in source code or in binary form.
131046SN/A *
141046SN/A * Redistribution and use in source and binary forms, with or without
151046SN/A * modification, are permitted provided that the following conditions are
161046SN/A * met: redistributions of source code must retain the above copyright
171046SN/A * notice, this list of conditions and the following disclaimer;
181046SN/A * redistributions in binary form must reproduce the above copyright
191046SN/A * notice, this list of conditions and the following disclaimer in the
201046SN/A * documentation and/or other materials provided with the distribution;
211046SN/A * neither the name of the copyright holders nor the names of its
221046SN/A * contributors may be used to endorse or promote products derived from
231046SN/A * this software without specific prior written permission.
241046SN/A *
251046SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
261046SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272665SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282665SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292665SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
301046SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
315766Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
328331Ssteve.reinhardt@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
331438SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
346654Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
356654Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
366654Snate@binkert.org *
376654Snate@binkert.org * Authors: Stan Czerniawski
386654Snate@binkert.org */
394762Snate@binkert.org
406654Snate@binkert.org#include "dev/arm/smmu_v3_ptops.hh"
413102Sstever@eecs.umich.edu
423102Sstever@eecs.umich.edu#include "base/bitfield.hh"
433102Sstever@eecs.umich.edu#include "base/logging.hh"
443102Sstever@eecs.umich.edu
456654Snate@binkert.orgbool
463102Sstever@eecs.umich.eduV7LPageTableOps::isValid(pte_t pte, unsigned level) const
473102Sstever@eecs.umich.edu{
487528Ssteve.reinhardt@amd.com    switch (level) {
498839Sandreas.hansson@arm.com        case 1: return  pte & 0x1;
503102Sstever@eecs.umich.edu        case 2: return  pte & 0x1;
516654Snate@binkert.org        case 3: return (pte & 0x1) && (pte & 0x2);
526654Snate@binkert.org        default: panic("bad level %d", level);
53679SN/A    }
54679SN/A}
55679SN/A
56679SN/Abool
57679SN/AV7LPageTableOps::isLeaf(pte_t pte, unsigned level) const
58679SN/A{
591692SN/A    switch (level) {
60679SN/A        case 1: return !(pte & 0x2);
61679SN/A        case 2: return !(pte & 0x2);
62679SN/A        case 3: return true;
63679SN/A        default: panic("bad level %d", level);
64679SN/A    }
65679SN/A}
66679SN/A
67679SN/Abool
68679SN/AV7LPageTableOps::isWritable(pte_t pte, unsigned level, bool stage2) const
69679SN/A{
70679SN/A    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
71679SN/A}
72679SN/A
73679SN/AAddr
741692SN/AV7LPageTableOps::nextLevelPointer(pte_t pte, unsigned level) const
75679SN/A{
76679SN/A    if (isLeaf(pte, level)) {
77679SN/A        switch (level) {
78679SN/A            case 1: return mbits(pte, 39, 30);
79679SN/A            case 2: return mbits(pte, 39, 21);
80679SN/A            case 3: return mbits(pte, 39, 12);
81679SN/A            default: panic("bad level %d", level);
82679SN/A        }
83679SN/A    } else {
84679SN/A        return mbits(pte, 39, 12);
85679SN/A    }
86679SN/A}
87679SN/A
88679SN/AAddr
89679SN/AV7LPageTableOps::index(Addr va, unsigned level) const
902740SN/A{
91679SN/A    // In theory this should be configurable...
92679SN/A    const int n = 12;
93679SN/A
944762Snate@binkert.org    switch (level) {
954762Snate@binkert.org        case 1: return bits(va, 26+n, 30) << 3; break;
964762Snate@binkert.org        case 2: return bits(va, 29, 21) << 3; break;
972738SN/A        case 3: return bits(va, 20, 12) << 3; break;
982738SN/A        default: panic("bad level %d", level);
992738SN/A    }
1007673Snate@binkert.org}
1017673Snate@binkert.org
1028331Ssteve.reinhardt@amd.comAddr
1038331Ssteve.reinhardt@amd.comV7LPageTableOps::pageMask(pte_t pte, unsigned level) const
1047673Snate@binkert.org{
1052740SN/A    switch (level) {
1062740SN/A        case 1: return ~mask(30);
1072740SN/A        case 2: return ~mask(21);
1082740SN/A        case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12);
1091692SN/A        default: panic("bad level %d", level);
1101427SN/A    }
1117493Ssteve.reinhardt@amd.com}
1127493Ssteve.reinhardt@amd.com
1137493Ssteve.reinhardt@amd.comAddr
1147493Ssteve.reinhardt@amd.comV7LPageTableOps::walkMask(unsigned level) const
1151427SN/A{
1167493Ssteve.reinhardt@amd.com    switch (level) {
117679SN/A        case 1: return mask(39, 30);
118679SN/A        case 2: return mask(39, 21);
119679SN/A        case 3: return mask(39, 12);
1202740SN/A        default: panic("bad level %d", level);
121679SN/A    }
122679SN/A}
1231310SN/A
1246654Snate@binkert.orgunsigned
1254762Snate@binkert.orgV7LPageTableOps::firstLevel() const
1262740SN/A{
1272740SN/A    return 1;
1282740SN/A}
1292740SN/A
1302740SN/Aunsigned
1312740SN/AV7LPageTableOps::lastLevel() const
1327673Snate@binkert.org{
1332740SN/A    return 3;
1342740SN/A}
1352740SN/A
1362740SN/Abool
1374762Snate@binkert.orgV8PageTableOps4k::isValid(pte_t pte, unsigned level) const
1384762Snate@binkert.org{
1392740SN/A    switch (level) {
1404762Snate@binkert.org        case 0: return  pte & 0x1;
1414762Snate@binkert.org        case 1: return  pte & 0x1;
1424762Snate@binkert.org        case 2: return  pte & 0x1;
1434762Snate@binkert.org        case 3: return (pte & 0x1) && (pte & 0x2);
144679SN/A        default: panic("bad level %d", level);
1452711SN/A    }
146679SN/A}
1472711SN/A
1482711SN/Abool
1491692SN/AV8PageTableOps4k::isLeaf(pte_t pte, unsigned level) const
1501310SN/A{
1511427SN/A    switch (level) {
1522740SN/A        case 0: return false;
1532740SN/A        case 1: return !(pte & 0x2);
1542740SN/A        case 2: return !(pte & 0x2);
1552740SN/A        case 3: return true;
1562740SN/A        default: panic("bad level %d", level);
1572740SN/A    }
1582740SN/A}
1597528Ssteve.reinhardt@amd.com
1603105Sstever@eecs.umich.edubool
1612740SN/AV8PageTableOps4k::isWritable(pte_t pte, unsigned level, bool stage2) const
1621310SN/A{
1631692SN/A    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
1641585SN/A}
1651692SN/A
1661692SN/AAddr
1671692SN/AV8PageTableOps4k::nextLevelPointer(pte_t pte, unsigned level) const
1681692SN/A{
1691692SN/A    if (isLeaf(pte, level)) {
1702740SN/A        switch (level) {
1712740SN/A            // no level 0 here
1722740SN/A            case 1: return mbits(pte, 47, 30);
1732740SN/A            case 2: return mbits(pte, 47, 21);
1741692SN/A            case 3: return mbits(pte, 47, 12);
1755610Snate@binkert.org            default: panic("bad level %d", level);
1761692SN/A        }
1772740SN/A    } else {
1781692SN/A        return mbits(pte, 47, 12);
1797528Ssteve.reinhardt@amd.com    }
1803105Sstever@eecs.umich.edu}
1812740SN/A
1822712SN/AAddr
1835610Snate@binkert.orgV8PageTableOps4k::index(Addr va, unsigned level) const
1845610Snate@binkert.org{
1851692SN/A    switch (level) {
1864762Snate@binkert.org        case 0: return bits(va, 47, 39) << 3; break;
1874762Snate@binkert.org        case 1: return bits(va, 38, 30) << 3; break;
1884762Snate@binkert.org        case 2: return bits(va, 29, 21) << 3; break;
1895610Snate@binkert.org        case 3: return bits(va, 20, 12) << 3; break;
1904762Snate@binkert.org        default: panic("bad level %d", level);
1915610Snate@binkert.org    }
1924859Snate@binkert.org}
1938597Ssteve.reinhardt@amd.com
1948597Ssteve.reinhardt@amd.comAddr
1958597Ssteve.reinhardt@amd.comV8PageTableOps4k::pageMask(pte_t pte, unsigned level) const
1968597Ssteve.reinhardt@amd.com{
1978597Ssteve.reinhardt@amd.com    switch (level) {
1988597Ssteve.reinhardt@amd.com        // no level 0 here
1998597Ssteve.reinhardt@amd.com        case 1: return ~mask(30);
2008597Ssteve.reinhardt@amd.com        case 2: return ~mask(21);
2018597Ssteve.reinhardt@amd.com        case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12);
2028597Ssteve.reinhardt@amd.com        default: panic("bad level %d", level);
2038597Ssteve.reinhardt@amd.com    }
2048597Ssteve.reinhardt@amd.com}
2058597Ssteve.reinhardt@amd.com
2068597Ssteve.reinhardt@amd.comAddr
2072740SN/AV8PageTableOps4k::walkMask(unsigned level) const
2082740SN/A{
2092740SN/A    switch (level) {
2102740SN/A        case 0: return mask(47, 39);
2112740SN/A        case 1: return mask(47, 30);
2122740SN/A        case 2: return mask(47, 21);
2132740SN/A        case 3: return mask(47, 12);
2142740SN/A        default: panic("bad level %d", level);
2151527SN/A    }
2162740SN/A}
2171585SN/A
2181427SN/Aunsigned
2192738SN/AV8PageTableOps4k::firstLevel() const
2202738SN/A{
2213105Sstever@eecs.umich.edu    return 0;
2222738SN/A}
2231427SN/A
2241427SN/Aunsigned
2251427SN/AV8PageTableOps4k::lastLevel() const
2261427SN/A{
2271427SN/A    return 3;
2281427SN/A}
2291427SN/A
2301427SN/Abool
2311427SN/AV8PageTableOps64k::isValid(pte_t pte, unsigned level) const
2321427SN/A{
2331427SN/A    switch (level) {
2341427SN/A        case 1: return  pte & 0x1;
2357493Ssteve.reinhardt@amd.com        case 2: return  pte & 0x1;
2361427SN/A        case 3: return (pte & 0x1) && (pte & 0x2);
2371427SN/A        default: panic("bad level %d", level);
2381427SN/A    }
2393100SN/A}
2403100SN/A
2413100SN/Abool
2423100SN/AV8PageTableOps64k::isLeaf(pte_t pte, unsigned level) const
2433100SN/A{
2443100SN/A    switch (level) {
2453105Sstever@eecs.umich.edu        case 1: return false;
2463105Sstever@eecs.umich.edu        case 2: return !(pte & 0x2);
2473105Sstever@eecs.umich.edu        case 3: return true;
2483105Sstever@eecs.umich.edu        default: panic("bad level %d", level);
2493105Sstever@eecs.umich.edu    }
2508321Ssteve.reinhardt@amd.com}
2513105Sstever@eecs.umich.edu
2523105Sstever@eecs.umich.edubool
2533105Sstever@eecs.umich.eduV8PageTableOps64k::isWritable(pte_t pte, unsigned level, bool stage2) const
2543105Sstever@eecs.umich.edu{
2553105Sstever@eecs.umich.edu    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
2568321Ssteve.reinhardt@amd.com}
2578321Ssteve.reinhardt@amd.com
2588321Ssteve.reinhardt@amd.comAddr
2598321Ssteve.reinhardt@amd.comV8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const
2608321Ssteve.reinhardt@amd.com{
2618321Ssteve.reinhardt@amd.com    if (isLeaf(pte, level)) {
2628321Ssteve.reinhardt@amd.com        switch (level) {
2638321Ssteve.reinhardt@amd.com            // no level 1 here
2648321Ssteve.reinhardt@amd.com            case 2: return mbits(pte, 47, 29);
2658321Ssteve.reinhardt@amd.com            case 3: return mbits(pte, 47, 16);
2668321Ssteve.reinhardt@amd.com            default: panic("bad level %d", level);
2678321Ssteve.reinhardt@amd.com        }
2688321Ssteve.reinhardt@amd.com    } else {
2698321Ssteve.reinhardt@amd.com        return mbits(pte, 47, 16);
2703105Sstever@eecs.umich.edu    }
2713105Sstever@eecs.umich.edu}
2723105Sstever@eecs.umich.edu
2733105Sstever@eecs.umich.eduAddr
2743105Sstever@eecs.umich.eduV8PageTableOps64k::index(Addr va, unsigned level) const
2753105Sstever@eecs.umich.edu{
2763105Sstever@eecs.umich.edu    switch (level) {
2773105Sstever@eecs.umich.edu        case 1: return bits(va, 47, 42) << 3; break;
2783105Sstever@eecs.umich.edu        case 2: return bits(va, 41, 29) << 3; break;
2793105Sstever@eecs.umich.edu        case 3: return bits(va, 28, 16) << 3; break;
2803105Sstever@eecs.umich.edu        default: panic("bad level %d", level);
2813105Sstever@eecs.umich.edu    }
2823105Sstever@eecs.umich.edu}
2833105Sstever@eecs.umich.edu
2843105Sstever@eecs.umich.eduAddr
2853105Sstever@eecs.umich.eduV8PageTableOps64k::pageMask(pte_t pte, unsigned level) const
2863105Sstever@eecs.umich.edu{
2871585SN/A    switch (level) {
2881310SN/A        // no level 1 here
2891310SN/A        case 2: return ~mask(29);
2901310SN/A        case 3: return bits(pte, 52) ? ~mask(21) : ~mask(16);
2911310SN/A        default: panic("bad level %d", level);
2927673Snate@binkert.org    }
2931310SN/A}
2941310SN/A
2951310SN/AAddr
2961310SN/AV8PageTableOps64k::walkMask(unsigned level) const
2971427SN/A{
2981310SN/A    switch (level) {
2991310SN/A        case 1: return mask(47, 42);
3002738SN/A        case 2: return mask(47, 29);
3013105Sstever@eecs.umich.edu        case 3: return mask(47, 16);
3022738SN/A        default: panic("bad level %d", level);
3032738SN/A    }
3042740SN/A}
3052740SN/A
3062740SN/Aunsigned
3072740SN/AV8PageTableOps64k::firstLevel() const
3082740SN/A{
3092740SN/A    return 1;
3102740SN/A}
3113105Sstever@eecs.umich.edu
3121310SN/Aunsigned
3133105Sstever@eecs.umich.eduV8PageTableOps64k::lastLevel() const
3143105Sstever@eecs.umich.edu{
3153105Sstever@eecs.umich.edu    return 3;
3163105Sstever@eecs.umich.edu}
3173105Sstever@eecs.umich.edu