smmu_v3_ptops.cc revision 14039:4991b2a345a1
1/* 2 * Copyright (c) 2013, 2018-2019 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Stan Czerniawski 38 */ 39 40#include "dev/arm/smmu_v3_ptops.hh" 41 42#include "base/bitfield.hh" 43#include "base/logging.hh" 44 45bool 46V7LPageTableOps::isValid(pte_t pte, unsigned level) const 47{ 48 switch (level) { 49 case 1: return pte & 0x1; 50 case 2: return pte & 0x1; 51 case 3: return (pte & 0x1) && (pte & 0x2); 52 default: panic("bad level %d", level); 53 } 54} 55 56bool 57V7LPageTableOps::isLeaf(pte_t pte, unsigned level) const 58{ 59 switch (level) { 60 case 1: return !(pte & 0x2); 61 case 2: return !(pte & 0x2); 62 case 3: return true; 63 default: panic("bad level %d", level); 64 } 65} 66 67bool 68V7LPageTableOps::isWritable(pte_t pte, unsigned level, bool stage2) const 69{ 70 return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 71} 72 73Addr 74V7LPageTableOps::nextLevelPointer(pte_t pte, unsigned level) const 75{ 76 if (isLeaf(pte, level)) { 77 switch (level) { 78 case 1: return mbits(pte, 39, 30); 79 case 2: return mbits(pte, 39, 21); 80 case 3: return mbits(pte, 39, 12); 81 default: panic("bad level %d", level); 82 } 83 } else { 84 return mbits(pte, 39, 12); 85 } 86} 87 88Addr 89V7LPageTableOps::index(Addr va, unsigned level) const 90{ 91 // In theory this should be configurable... 92 const int n = 12; 93 94 switch (level) { 95 case 1: return bits(va, 26+n, 30) << 3; break; 96 case 2: return bits(va, 29, 21) << 3; break; 97 case 3: return bits(va, 20, 12) << 3; break; 98 default: panic("bad level %d", level); 99 } 100} 101 102Addr 103V7LPageTableOps::pageMask(pte_t pte, unsigned level) const 104{ 105 switch (level) { 106 case 1: return ~mask(30); 107 case 2: return ~mask(21); 108 case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12); 109 default: panic("bad level %d", level); 110 } 111} 112 113Addr 114V7LPageTableOps::walkMask(unsigned level) const 115{ 116 switch (level) { 117 case 1: return mask(39, 30); 118 case 2: return mask(39, 21); 119 case 3: return mask(39, 12); 120 default: panic("bad level %d", level); 121 } 122} 123 124unsigned 125V7LPageTableOps::firstLevel() const 126{ 127 return 1; 128} 129 130unsigned 131V7LPageTableOps::lastLevel() const 132{ 133 return 3; 134} 135 136bool 137V8PageTableOps4k::isValid(pte_t pte, unsigned level) const 138{ 139 switch (level) { 140 case 0: return pte & 0x1; 141 case 1: return pte & 0x1; 142 case 2: return pte & 0x1; 143 case 3: return (pte & 0x1) && (pte & 0x2); 144 default: panic("bad level %d", level); 145 } 146} 147 148bool 149V8PageTableOps4k::isLeaf(pte_t pte, unsigned level) const 150{ 151 switch (level) { 152 case 0: return false; 153 case 1: return !(pte & 0x2); 154 case 2: return !(pte & 0x2); 155 case 3: return true; 156 default: panic("bad level %d", level); 157 } 158} 159 160bool 161V8PageTableOps4k::isWritable(pte_t pte, unsigned level, bool stage2) const 162{ 163 return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 164} 165 166Addr 167V8PageTableOps4k::nextLevelPointer(pte_t pte, unsigned level) const 168{ 169 if (isLeaf(pte, level)) { 170 switch (level) { 171 // no level 0 here 172 case 1: return mbits(pte, 47, 30); 173 case 2: return mbits(pte, 47, 21); 174 case 3: return mbits(pte, 47, 12); 175 default: panic("bad level %d", level); 176 } 177 } else { 178 return mbits(pte, 47, 12); 179 } 180} 181 182Addr 183V8PageTableOps4k::index(Addr va, unsigned level) const 184{ 185 switch (level) { 186 case 0: return bits(va, 47, 39) << 3; break; 187 case 1: return bits(va, 38, 30) << 3; break; 188 case 2: return bits(va, 29, 21) << 3; break; 189 case 3: return bits(va, 20, 12) << 3; break; 190 default: panic("bad level %d", level); 191 } 192} 193 194Addr 195V8PageTableOps4k::pageMask(pte_t pte, unsigned level) const 196{ 197 switch (level) { 198 // no level 0 here 199 case 1: return ~mask(30); 200 case 2: return ~mask(21); 201 case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12); 202 default: panic("bad level %d", level); 203 } 204} 205 206Addr 207V8PageTableOps4k::walkMask(unsigned level) const 208{ 209 switch (level) { 210 case 0: return mask(47, 39); 211 case 1: return mask(47, 30); 212 case 2: return mask(47, 21); 213 case 3: return mask(47, 12); 214 default: panic("bad level %d", level); 215 } 216} 217 218unsigned 219V8PageTableOps4k::firstLevel() const 220{ 221 return 0; 222} 223 224unsigned 225V8PageTableOps4k::lastLevel() const 226{ 227 return 3; 228} 229 230bool 231V8PageTableOps64k::isValid(pte_t pte, unsigned level) const 232{ 233 switch (level) { 234 case 1: return pte & 0x1; 235 case 2: return pte & 0x1; 236 case 3: return (pte & 0x1) && (pte & 0x2); 237 default: panic("bad level %d", level); 238 } 239} 240 241bool 242V8PageTableOps64k::isLeaf(pte_t pte, unsigned level) const 243{ 244 switch (level) { 245 case 1: return false; 246 case 2: return !(pte & 0x2); 247 case 3: return true; 248 default: panic("bad level %d", level); 249 } 250} 251 252bool 253V8PageTableOps64k::isWritable(pte_t pte, unsigned level, bool stage2) const 254{ 255 return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 256} 257 258Addr 259V8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const 260{ 261 if (isLeaf(pte, level)) { 262 switch (level) { 263 // no level 1 here 264 case 2: return mbits(pte, 47, 29); 265 case 3: return mbits(pte, 47, 16); 266 default: panic("bad level %d", level); 267 } 268 } else { 269 return mbits(pte, 47, 16); 270 } 271} 272 273Addr 274V8PageTableOps64k::index(Addr va, unsigned level) const 275{ 276 switch (level) { 277 case 1: return bits(va, 47, 42) << 3; break; 278 case 2: return bits(va, 41, 29) << 3; break; 279 case 3: return bits(va, 28, 16) << 3; break; 280 default: panic("bad level %d", level); 281 } 282} 283 284Addr 285V8PageTableOps64k::pageMask(pte_t pte, unsigned level) const 286{ 287 switch (level) { 288 // no level 1 here 289 case 2: return ~mask(29); 290 case 3: return bits(pte, 52) ? ~mask(21) : ~mask(16); 291 default: panic("bad level %d", level); 292 } 293} 294 295Addr 296V8PageTableOps64k::walkMask(unsigned level) const 297{ 298 switch (level) { 299 case 1: return mask(47, 42); 300 case 2: return mask(47, 29); 301 case 3: return mask(47, 16); 302 default: panic("bad level %d", level); 303 } 304} 305 306unsigned 307V8PageTableOps64k::firstLevel() const 308{ 309 return 1; 310} 311 312unsigned 313V8PageTableOps64k::lastLevel() const 314{ 315 return 3; 316} 317