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