smmu_v3_ptops.cc revision 14100:6ef1220dc6da
12810SN/A/* 210028SGiacomo.Gabrielli@arm.com * Copyright (c) 2013, 2018-2019 ARM Limited 310028SGiacomo.Gabrielli@arm.com * All rights reserved 410028SGiacomo.Gabrielli@arm.com * 510028SGiacomo.Gabrielli@arm.com * The license below extends only to copyright in the software and shall 610028SGiacomo.Gabrielli@arm.com * not be construed as granting a license to any other intellectual 710028SGiacomo.Gabrielli@arm.com * property including but not limited to intellectual property relating 810028SGiacomo.Gabrielli@arm.com * to a hardware implementation of the functionality of the software 910028SGiacomo.Gabrielli@arm.com * licensed hereunder. You may use the software subject to the license 1010028SGiacomo.Gabrielli@arm.com * terms below provided that you ensure that this notice is replicated 1110028SGiacomo.Gabrielli@arm.com * unmodified and in its entirety in all distributions of the software, 1210028SGiacomo.Gabrielli@arm.com * modified or unmodified, in source code or in binary form. 1310028SGiacomo.Gabrielli@arm.com * 142810SN/A * Redistribution and use in source and binary forms, with or without 152810SN/A * modification, are permitted provided that the following conditions are 162810SN/A * met: redistributions of source code must retain the above copyright 172810SN/A * notice, this list of conditions and the following disclaimer; 182810SN/A * redistributions in binary form must reproduce the above copyright 192810SN/A * notice, this list of conditions and the following disclaimer in the 202810SN/A * documentation and/or other materials provided with the distribution; 212810SN/A * neither the name of the copyright holders nor the names of its 222810SN/A * contributors may be used to endorse or promote products derived from 232810SN/A * this software without specific prior written permission. 242810SN/A * 252810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362810SN/A * 372810SN/A * Authors: Stan Czerniawski 382810SN/A */ 392810SN/A 402810SN/A#include "dev/arm/smmu_v3_ptops.hh" 412810SN/A 422810SN/A#include "base/bitfield.hh" 432810SN/A#include "base/logging.hh" 442810SN/A 452810SN/Abool 462810SN/AV7LPageTableOps::isValid(pte_t pte, unsigned level) const 472810SN/A{ 482810SN/A switch (level) { 498232Snate@binkert.org case 1: return pte & 0x1; 505338Sstever@gmail.com case 2: return pte & 0x1; 512810SN/A case 3: return (pte & 0x1) && (pte & 0x2); 5210623Smitch.hayenga@arm.com default: panic("bad level %d", level); 5310623Smitch.hayenga@arm.com } 5410623Smitch.hayenga@arm.com} 5510623Smitch.hayenga@arm.com 5610623Smitch.hayenga@arm.combool 5710623Smitch.hayenga@arm.comV7LPageTableOps::isLeaf(pte_t pte, unsigned level) const 5810623Smitch.hayenga@arm.com{ 5910623Smitch.hayenga@arm.com switch (level) { 6010623Smitch.hayenga@arm.com case 1: return !(pte & 0x2); 6110623Smitch.hayenga@arm.com case 2: return !(pte & 0x2); 6210623Smitch.hayenga@arm.com case 3: return true; 6310623Smitch.hayenga@arm.com default: panic("bad level %d", level); 6410623Smitch.hayenga@arm.com } 6510623Smitch.hayenga@arm.com} 6610623Smitch.hayenga@arm.com 6710623Smitch.hayenga@arm.combool 6810623Smitch.hayenga@arm.comV7LPageTableOps::isWritable(pte_t pte, unsigned level, bool stage2) const 6910623Smitch.hayenga@arm.com{ 7010623Smitch.hayenga@arm.com return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 7110623Smitch.hayenga@arm.com} 7210623Smitch.hayenga@arm.com 7310623Smitch.hayenga@arm.comAddr 7410623Smitch.hayenga@arm.comV7LPageTableOps::nextLevelPointer(pte_t pte, unsigned level) const 7510623Smitch.hayenga@arm.com{ 7610623Smitch.hayenga@arm.com if (isLeaf(pte, level)) { 7710623Smitch.hayenga@arm.com switch (level) { 7810623Smitch.hayenga@arm.com case 1: return mbits(pte, 39, 30); 7910623Smitch.hayenga@arm.com case 2: return mbits(pte, 39, 21); 8010623Smitch.hayenga@arm.com case 3: return mbits(pte, 39, 12); 8110623Smitch.hayenga@arm.com default: panic("bad level %d", level); 8210623Smitch.hayenga@arm.com } 8310623Smitch.hayenga@arm.com } else { 8410623Smitch.hayenga@arm.com return mbits(pte, 39, 12); 853861SN/A } 8610623Smitch.hayenga@arm.com} 8710623Smitch.hayenga@arm.com 883861SN/AAddr 895875Ssteve.reinhardt@amd.comV7LPageTableOps::index(Addr va, unsigned level) const 9010623Smitch.hayenga@arm.com{ 915875Ssteve.reinhardt@amd.com // In theory this should be configurable... 925875Ssteve.reinhardt@amd.com const int n = 12; 932810SN/A 9410623Smitch.hayenga@arm.com switch (level) { 9510623Smitch.hayenga@arm.com case 1: return bits(va, 26+n, 30) << 3; break; 9610623Smitch.hayenga@arm.com case 2: return bits(va, 29, 21) << 3; break; 9710028SGiacomo.Gabrielli@arm.com case 3: return bits(va, 20, 12) << 3; break; 988832SAli.Saidi@ARM.com default: panic("bad level %d", level); 992810SN/A } 10010623Smitch.hayenga@arm.com} 10110053Smitch.hayenga+gem5@gmail.com 10210623Smitch.hayenga@arm.comAddr 10310623Smitch.hayenga@arm.comV7LPageTableOps::pageMask(pte_t pte, unsigned level) const 1043861SN/A{ 10510623Smitch.hayenga@arm.com switch (level) { 1065875Ssteve.reinhardt@amd.com case 1: return ~mask(30); 10710623Smitch.hayenga@arm.com case 2: return ~mask(21); 10810623Smitch.hayenga@arm.com case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12); 1093861SN/A default: panic("bad level %d", level); 11010623Smitch.hayenga@arm.com } 1115875Ssteve.reinhardt@amd.com} 11210623Smitch.hayenga@arm.com 11310623Smitch.hayenga@arm.comAddr 1145875Ssteve.reinhardt@amd.comV7LPageTableOps::walkMask(unsigned level) const 11510623Smitch.hayenga@arm.com{ 11610623Smitch.hayenga@arm.com switch (level) { 11710623Smitch.hayenga@arm.com case 1: return mask(39, 30); 11810623Smitch.hayenga@arm.com case 2: return mask(39, 21); 11910623Smitch.hayenga@arm.com case 3: return mask(39, 12); 1205875Ssteve.reinhardt@amd.com default: panic("bad level %d", level); 1213861SN/A } 12210623Smitch.hayenga@arm.com} 12310623Smitch.hayenga@arm.com 12410028SGiacomo.Gabrielli@arm.comunsigned 12510623Smitch.hayenga@arm.comV7LPageTableOps::firstLevel(uint8_t tsz) const 1265875Ssteve.reinhardt@amd.com{ 12710623Smitch.hayenga@arm.com return 1; 1285875Ssteve.reinhardt@amd.com} 12910623Smitch.hayenga@arm.com 13010623Smitch.hayenga@arm.comunsigned 1315875Ssteve.reinhardt@amd.comV7LPageTableOps::lastLevel() const 1325875Ssteve.reinhardt@amd.com{ 13310623Smitch.hayenga@arm.com return 3; 1345875Ssteve.reinhardt@amd.com} 13510623Smitch.hayenga@arm.com 13610623Smitch.hayenga@arm.combool 13710623Smitch.hayenga@arm.comV8PageTableOps4k::isValid(pte_t pte, unsigned level) const 13810623Smitch.hayenga@arm.com{ 13910623Smitch.hayenga@arm.com switch (level) { 14010623Smitch.hayenga@arm.com case 0: return pte & 0x1; 14110623Smitch.hayenga@arm.com case 1: return pte & 0x1; 14210623Smitch.hayenga@arm.com case 2: return pte & 0x1; 14310623Smitch.hayenga@arm.com case 3: return (pte & 0x1) && (pte & 0x2); 14410623Smitch.hayenga@arm.com default: panic("bad level %d", level); 14510623Smitch.hayenga@arm.com } 14610623Smitch.hayenga@arm.com} 1475875Ssteve.reinhardt@amd.com 14810623Smitch.hayenga@arm.combool 1495875Ssteve.reinhardt@amd.comV8PageTableOps4k::isLeaf(pte_t pte, unsigned level) const 1505875Ssteve.reinhardt@amd.com{ 1515875Ssteve.reinhardt@amd.com switch (level) { 1525875Ssteve.reinhardt@amd.com case 0: return false; 1535875Ssteve.reinhardt@amd.com case 1: return !(pte & 0x2); 15410623Smitch.hayenga@arm.com case 2: return !(pte & 0x2); 15510028SGiacomo.Gabrielli@arm.com case 3: return true; 1565875Ssteve.reinhardt@amd.com default: panic("bad level %d", level); 15710623Smitch.hayenga@arm.com } 15810623Smitch.hayenga@arm.com} 15910623Smitch.hayenga@arm.com 16010623Smitch.hayenga@arm.combool 16110623Smitch.hayenga@arm.comV8PageTableOps4k::isWritable(pte_t pte, unsigned level, bool stage2) const 16210623Smitch.hayenga@arm.com{ 1635875Ssteve.reinhardt@amd.com return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 1643861SN/A} 1658831Smrinmoy.ghosh@arm.com 16610623Smitch.hayenga@arm.comAddr 16710623Smitch.hayenga@arm.comV8PageTableOps4k::nextLevelPointer(pte_t pte, unsigned level) const 16810623Smitch.hayenga@arm.com{ 16910623Smitch.hayenga@arm.com if (isLeaf(pte, level)) { 17010623Smitch.hayenga@arm.com switch (level) { 17110623Smitch.hayenga@arm.com // no level 0 here 17210623Smitch.hayenga@arm.com case 1: return mbits(pte, 47, 30); 17310623Smitch.hayenga@arm.com case 2: return mbits(pte, 47, 21); 17410623Smitch.hayenga@arm.com case 3: return mbits(pte, 47, 12); 17510623Smitch.hayenga@arm.com default: panic("bad level %d", level); 17610623Smitch.hayenga@arm.com } 17710623Smitch.hayenga@arm.com } else { 17810623Smitch.hayenga@arm.com return mbits(pte, 47, 12); 17910623Smitch.hayenga@arm.com } 18010623Smitch.hayenga@arm.com} 18110623Smitch.hayenga@arm.com 18210623Smitch.hayenga@arm.comAddr 18310623Smitch.hayenga@arm.comV8PageTableOps4k::index(Addr va, unsigned level) const 18410623Smitch.hayenga@arm.com{ 18510623Smitch.hayenga@arm.com switch (level) { 18610623Smitch.hayenga@arm.com case 0: return bits(va, 47, 39) << 3; break; 18710623Smitch.hayenga@arm.com case 1: return bits(va, 38, 30) << 3; break; 18810623Smitch.hayenga@arm.com case 2: return bits(va, 29, 21) << 3; break; 18910623Smitch.hayenga@arm.com case 3: return bits(va, 20, 12) << 3; break; 19010623Smitch.hayenga@arm.com default: panic("bad level %d", level); 19110623Smitch.hayenga@arm.com } 19210623Smitch.hayenga@arm.com} 19310623Smitch.hayenga@arm.com 19410623Smitch.hayenga@arm.comAddr 19510623Smitch.hayenga@arm.comV8PageTableOps4k::pageMask(pte_t pte, unsigned level) const 19610623Smitch.hayenga@arm.com{ 19710623Smitch.hayenga@arm.com switch (level) { 19810623Smitch.hayenga@arm.com // no level 0 here 19910623Smitch.hayenga@arm.com case 1: return ~mask(30); 20010623Smitch.hayenga@arm.com case 2: return ~mask(21); 20110623Smitch.hayenga@arm.com case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12); 2028831Smrinmoy.ghosh@arm.com default: panic("bad level %d", level); 2038831Smrinmoy.ghosh@arm.com } 2048831Smrinmoy.ghosh@arm.com} 2058831Smrinmoy.ghosh@arm.com 20610623Smitch.hayenga@arm.comAddr 2078831Smrinmoy.ghosh@arm.comV8PageTableOps4k::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(uint8_t tsz) const 220{ 221 if (tsz >= 16 && tsz <= 24) return 0; 222 if (tsz >= 25 && tsz <= 33) return 1; 223 if (tsz >= 34 && tsz <= 39) return 2; 224 225 panic("Unsupported TnSZ: %d\n", tsz); 226} 227 228unsigned 229V8PageTableOps4k::lastLevel() const 230{ 231 return 3; 232} 233 234bool 235V8PageTableOps16k::isValid(pte_t pte, unsigned level) const 236{ 237 switch (level) { 238 case 0: return pte & 0x1; 239 case 1: return pte & 0x1; 240 case 2: return pte & 0x1; 241 case 3: return (pte & 0x1) && (pte & 0x2); 242 default: panic("bad level %d", level); 243 } 244} 245 246bool 247V8PageTableOps16k::isLeaf(pte_t pte, unsigned level) const 248{ 249 switch (level) { 250 case 0: return false; 251 case 1: return false; 252 case 2: return !(pte & 0x2); 253 case 3: return true; 254 default: panic("bad level %d", level); 255 } 256} 257 258bool 259V8PageTableOps16k::isWritable(pte_t pte, unsigned level, bool stage2) const 260{ 261 return stage2 ? bits(pte, 7, 6) == 3 : bits(pte, 7) == 0; 262} 263 264Addr 265V8PageTableOps16k::nextLevelPointer(pte_t pte, unsigned level) const 266{ 267 if (isLeaf(pte, level)) { 268 switch (level) { 269 // no level 0 here 270 case 1: return mbits(pte, 47, 36); 271 case 2: return mbits(pte, 47, 25); 272 case 3: return mbits(pte, 47, 14); 273 default: panic("bad level %d", level); 274 } 275 } else { 276 return mbits(pte, 47, 12); 277 } 278} 279 280Addr 281V8PageTableOps16k::index(Addr va, unsigned level) const 282{ 283 switch (level) { 284 case 0: return bits(va, 47, 47) << 3; break; 285 case 1: return bits(va, 46, 36) << 3; break; 286 case 2: return bits(va, 35, 25) << 3; break; 287 case 3: return bits(va, 24, 14) << 3; break; 288 default: panic("bad level %d", level); 289 } 290} 291 292Addr 293V8PageTableOps16k::pageMask(pte_t pte, unsigned level) const 294{ 295 switch (level) { 296 // no level 0 here 297 case 1: return ~mask(36); 298 // 16K granule supports contiguous entries also at L2; - 1G 299 case 2: return bits(pte, 52) ? ~mask(30) : ~mask(25); 300 // as well as at L3; - 2M 301 case 3: return bits(pte, 52) ? ~mask(21) : ~mask(14); 302 default: panic("bad level %d", level); 303 } 304} 305 306Addr 307V8PageTableOps16k::walkMask(unsigned level) const 308{ 309 switch (level) { 310 case 0: return ~mask(47); 311 case 1: return ~mask(36); 312 case 2: return ~mask(25); 313 case 3: return ~mask(14); 314 default: panic("bad level %d", level); 315 } 316} 317 318unsigned 319V8PageTableOps16k::firstLevel(uint8_t tsz) const 320{ 321 if (tsz == 16) return 0; 322 if (tsz >= 17 && tsz <= 27) return 1; 323 if (tsz >= 28 && tsz <= 38) return 2; 324 if (tsz == 39) return 3; 325 326 panic("Unsupported TnSZ: %d\n", tsz); 327} 328 329unsigned 330V8PageTableOps16k::lastLevel() const 331{ 332 return 3; 333} 334 335bool 336V8PageTableOps64k::isValid(pte_t pte, unsigned level) const 337{ 338 switch (level) { 339 case 1: return pte & 0x1; 340 case 2: return pte & 0x1; 341 case 3: return (pte & 0x1) && (pte & 0x2); 342 default: panic("bad level %d", level); 343 } 344} 345 346bool 347V8PageTableOps64k::isLeaf(pte_t pte, unsigned level) const 348{ 349 switch (level) { 350 case 1: return false; 351 case 2: return !(pte & 0x2); 352 case 3: return true; 353 default: panic("bad level %d", level); 354 } 355} 356 357bool 358V8PageTableOps64k::isWritable(pte_t pte, unsigned level, bool stage2) const 359{ 360 return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0; 361} 362 363Addr 364V8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const 365{ 366 if (isLeaf(pte, level)) { 367 switch (level) { 368 // no level 1 here 369 case 2: return mbits(pte, 47, 29); 370 case 3: return mbits(pte, 47, 16); 371 default: panic("bad level %d", level); 372 } 373 } else { 374 return mbits(pte, 47, 16); 375 } 376} 377 378Addr 379V8PageTableOps64k::index(Addr va, unsigned level) const 380{ 381 switch (level) { 382 case 1: return bits(va, 47, 42) << 3; break; 383 case 2: return bits(va, 41, 29) << 3; break; 384 case 3: return bits(va, 28, 16) << 3; break; 385 default: panic("bad level %d", level); 386 } 387} 388 389Addr 390V8PageTableOps64k::pageMask(pte_t pte, unsigned level) const 391{ 392 switch (level) { 393 // no level 1 here 394 case 2: return ~mask(29); 395 case 3: return bits(pte, 52) ? ~mask(21) : ~mask(16); 396 default: panic("bad level %d", level); 397 } 398} 399 400Addr 401V8PageTableOps64k::walkMask(unsigned level) const 402{ 403 switch (level) { 404 case 1: return mask(47, 42); 405 case 2: return mask(47, 29); 406 case 3: return mask(47, 16); 407 default: panic("bad level %d", level); 408 } 409} 410 411unsigned 412V8PageTableOps64k::firstLevel(uint8_t tsz) const 413{ 414 if (tsz >= 12 && tsz <= 21) return 1; 415 if (tsz >= 22 && tsz <= 34) return 2; 416 if (tsz >= 35 && tsz <= 39) return 3; 417 418 panic("Unsupported TnSZ: %d\n", tsz); 419} 420 421unsigned 422V8PageTableOps64k::lastLevel() const 423{ 424 return 3; 425} 426