smmu_v3_ptops.cc revision 14098
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 231V8PageTableOps16k::isValid(pte_t pte, unsigned level) const 232{ 233 switch (level) { 234 case 0: return pte & 0x1; 235 case 1: return pte & 0x1; 236 case 2: return pte & 0x1; 237 case 3: return (pte & 0x1) && (pte & 0x2); 238 default: panic("bad level %d", level); 239 } 240} 241 242bool 243V8PageTableOps16k::isLeaf(pte_t pte, unsigned level) const 244{ 245 switch (level) { 246 case 0: return false; 247 case 1: return false; 248 case 2: return !(pte & 0x2); 249 case 3: return true; 250 default: panic("bad level %d", level); 251 } 252} 253 254bool 255V8PageTableOps16k::isWritable(pte_t pte, unsigned level, bool stage2) const 256{ 257 return stage2 ? bits(pte, 7, 6) == 3 : bits(pte, 7) == 0; 258} 259 260Addr 261V8PageTableOps16k::nextLevelPointer(pte_t pte, unsigned level) const 262{ 263 if (isLeaf(pte, level)) { 264 switch (level) { 265 // no level 0 here 266 case 1: return mbits(pte, 47, 36); 267 case 2: return mbits(pte, 47, 25); 268 case 3: return mbits(pte, 47, 14); 269 default: panic("bad level %d", level); 270 } 271 } else { 272 return mbits(pte, 47, 12); 273 } 274} 275 276Addr 277V8PageTableOps16k::index(Addr va, unsigned level) const 278{ 279 switch (level) { 280 case 0: return bits(va, 47, 47) << 3; break; 281 case 1: return bits(va, 46, 36) << 3; break; 282 case 2: return bits(va, 35, 25) << 3; break; 283 case 3: return bits(va, 24, 14) << 3; break; 284 default: panic("bad level %d", level); 285 } 286} 287 288Addr 289V8PageTableOps16k::pageMask(pte_t pte, unsigned level) const 290{ 291 switch (level) { 292 // no level 0 here 293 case 1: return ~mask(36); 294 // 16K granule supports contiguous entries also at L2; - 1G 295 case 2: return bits(pte, 52) ? ~mask(30) : ~mask(25); 296 // as well as at L3; - 2M 297 case 3: return bits(pte, 52) ? ~mask(21) : ~mask(14); 298 default: panic("bad level %d", level); 299 } 300} 301 302Addr 303V8PageTableOps16k::walkMask(unsigned level) const 304{ 305 switch (level) { 306 case 0: return ~mask(47); 307 case 1: return ~mask(36); 308 case 2: return ~mask(25); 309 case 3: return ~mask(14); 310 default: panic("bad level %d", level); 311 } 312} 313 314unsigned 315V8PageTableOps16k::firstLevel() const 316{ 317 return 0; 318} 319 320unsigned 321V8PageTableOps16k::lastLevel() const 322{ 323 return 3; 324} 325 326bool 327V8PageTableOps64k::isValid(pte_t pte, unsigned level) const 328{ 329 switch (level) { 330 case 1: return pte & 0x1; 331 case 2: return pte & 0x1; 332 case 3: return (pte & 0x1) && (pte & 0x2); 333 default: panic("bad level %d", level); 334 } 335} 336 337bool 338V8PageTableOps64k::isLeaf(pte_t pte, unsigned level) const 339{ 340 switch (level) { 341 case 1: return false; 342 case 2: return !(pte & 0x2); 343 case 3: return true; 344 default: panic("bad level %d", level); 345 } 346} 347 348bool 349V8PageTableOps64k::isWritable(pte_t pte, unsigned level, bool stage2) const 350{ 351 return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 352} 353 354Addr 355V8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const 356{ 357 if (isLeaf(pte, level)) { 358 switch (level) { 359 // no level 1 here 360 case 2: return mbits(pte, 47, 29); 361 case 3: return mbits(pte, 47, 16); 362 default: panic("bad level %d", level); 363 } 364 } else { 365 return mbits(pte, 47, 16); 366 } 367} 368 369Addr 370V8PageTableOps64k::index(Addr va, unsigned level) const 371{ 372 switch (level) { 373 case 1: return bits(va, 47, 42) << 3; break; 374 case 2: return bits(va, 41, 29) << 3; break; 375 case 3: return bits(va, 28, 16) << 3; break; 376 default: panic("bad level %d", level); 377 } 378} 379 380Addr 381V8PageTableOps64k::pageMask(pte_t pte, unsigned level) const 382{ 383 switch (level) { 384 // no level 1 here 385 case 2: return ~mask(29); 386 case 3: return bits(pte, 52) ? ~mask(21) : ~mask(16); 387 default: panic("bad level %d", level); 388 } 389} 390 391Addr 392V8PageTableOps64k::walkMask(unsigned level) const 393{ 394 switch (level) { 395 case 1: return mask(47, 42); 396 case 2: return mask(47, 29); 397 case 3: return mask(47, 16); 398 default: panic("bad level %d", level); 399 } 400} 401 402unsigned 403V8PageTableOps64k::firstLevel() const 404{ 405 return 1; 406} 407 408unsigned 409V8PageTableOps64k::lastLevel() const 410{ 411 return 3; 412} 413