1/* 2 * Copyright (c) 2014, 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#ifndef __DEV_ARM_SMMU_V3_CACHES_HH__ 41#define __DEV_ARM_SMMU_V3_CACHES_HH__ 42 43#include <stdint.h> 44 45#include <array> 46#include <cstddef> 47#include <string> 48#include <vector> 49 50#include "base/random.hh" 51#include "base/statistics.hh" 52#include "base/types.hh" 53 54#define WALK_CACHE_LEVELS 4 55 56enum { 57 SMMU_CACHE_REPL_ROUND_ROBIN, 58 SMMU_CACHE_REPL_RANDOM, 59 SMMU_CACHE_REPL_LRU, 60}; 61 62class SMMUv3BaseCache 63{ 64 protected: 65 int replacementPolicy; 66 size_t nextToReplace; 67 Random random; 68 uint32_t useStamp; 69 70 Stats::Formula averageLookups; 71 Stats::Scalar totalLookups; 72 73 Stats::Formula averageMisses; 74 Stats::Scalar totalMisses; 75 76 Stats::Formula averageUpdates; 77 Stats::Scalar totalUpdates; 78 79 Stats::Formula averageHitRate; 80 81 Stats::Scalar insertions; 82 83 static int decodePolicyName(const std::string &policy_name); 84 85 public: 86 SMMUv3BaseCache(const std::string &policy_name, uint32_t seed); 87 virtual ~SMMUv3BaseCache() {} 88 89 virtual void regStats(const std::string &name); 90}; 91 92class SMMUTLB : public SMMUv3BaseCache 93{ 94 public: 95 enum AllocPolicy { 96 ALLOC_ANY_WAY, 97 ALLOC_ANY_BUT_LAST_WAY, 98 ALLOC_LAST_WAY, 99 }; 100 101 struct Entry 102 { 103 bool valid; 104 bool prefetched; 105 mutable uint32_t lastUsed; 106 107 // TAGS 108 uint32_t sid; 109 uint32_t ssid; 110 Addr va; 111 Addr vaMask; 112 113 // EXTRA TAGS 114 uint16_t asid; 115 uint16_t vmid; 116 117 // OUTPUTS 118 Addr pa; 119 uint8_t permissions; 120 }; 121 122 SMMUTLB(unsigned numEntries, unsigned _associativity, 123 const std::string &policy); 124 SMMUTLB(const SMMUTLB& tlb) = delete; 125 virtual ~SMMUTLB() {} 126 127 const Entry *lookup(uint32_t sid, uint32_t ssid, Addr va, 128 bool updStats=true); 129 const Entry *lookupAnyVA(uint32_t sid, uint32_t ssid, 130 bool updStats=true); 131 void store(const Entry &incoming, AllocPolicy alloc); 132 133 void invalidateSSID(uint32_t sid, uint32_t ssid); 134 void invalidateSID(uint32_t sid); 135 void invalidateVA(Addr va, uint16_t asid, uint16_t vmid); 136 void invalidateVAA(Addr va, uint16_t vmid); 137 void invalidateASID(uint16_t asid, uint16_t vmid); 138 void invalidateVMID(uint16_t vmid); 139 void invalidateAll(); 140 141 private: 142 typedef std::vector<Entry> Set; 143 std::vector<Set> sets; 144 145 size_t associativity; 146 147 size_t pickSetIdx(uint32_t sid, uint32_t ssid) const; 148 size_t pickSetIdx(Addr va) const; 149 size_t pickEntryIdxToReplace(const Set &set, AllocPolicy alloc); 150}; 151 152class ARMArchTLB : public SMMUv3BaseCache 153{ 154 public: 155 struct Entry 156 { 157 bool valid; 158 mutable uint32_t lastUsed; 159 160 // TAGS 161 Addr va; 162 Addr vaMask; 163 uint16_t asid; 164 uint16_t vmid; 165 166 // OUTPUTS 167 Addr pa; 168 uint8_t permissions; 169 }; 170 171 ARMArchTLB(unsigned numEntries, unsigned _associativity, 172 const std::string &policy); 173 virtual ~ARMArchTLB() {} 174 175 const Entry *lookup(Addr va, uint16_t asid, uint16_t vmid, 176 bool updStats=true); 177 178 void store(const Entry &incoming); 179 180 void invalidateVA(Addr va, uint16_t asid, uint16_t vmid); 181 void invalidateVAA(Addr va, uint16_t vmid); 182 void invalidateASID(uint16_t asid, uint16_t vmid); 183 void invalidateVMID(uint16_t vmid); 184 void invalidateAll(); 185 186 private: 187 typedef std::vector<Entry> Set; 188 std::vector<Set> sets; 189 190 size_t associativity; 191 192 size_t pickSetIdx(Addr va, uint16_t asid, uint16_t vmid) const; 193 size_t pickEntryIdxToReplace(const Set &set); 194}; 195 196class IPACache : public SMMUv3BaseCache 197{ 198 public: 199 struct Entry 200 { 201 bool valid; 202 mutable uint32_t lastUsed; 203 204 // TAGS 205 Addr ipa; 206 Addr ipaMask; 207 uint16_t vmid; 208 209 // OUTPUTS 210 Addr pa; 211 uint8_t permissions; 212 }; 213 214 IPACache(unsigned numEntries, unsigned _associativity, 215 const std::string &policy); 216 virtual ~IPACache() {} 217 218 const Entry *lookup(Addr ipa, uint16_t vmid, bool updStats=true); 219 void store(const Entry &incoming); 220 221 void invalidateIPA(Addr ipa, uint16_t vmid); 222 void invalidateIPAA(Addr ipa); 223 void invalidateVMID(uint16_t vmid); 224 void invalidateAll(); 225 226 private: 227 typedef std::vector<Entry> Set; 228 std::vector<Set> sets; 229 230 size_t associativity; 231 232 size_t pickSetIdx(Addr ipa, uint16_t vmid) const; 233 size_t pickEntryIdxToReplace(const Set &set); 234}; 235 236class ConfigCache : public SMMUv3BaseCache 237{ 238 public: 239 struct Entry 240 { 241 bool valid; 242 mutable uint32_t lastUsed; 243 244 // TAGS 245 uint32_t sid; 246 uint32_t ssid; 247 248 // OUTPUTS 249 bool stage1_en; 250 bool stage2_en; 251 Addr ttb0; 252 Addr ttb1; 253 Addr httb; 254 uint16_t asid; 255 uint16_t vmid; 256 uint8_t stage1_tg; 257 uint8_t stage2_tg; 258 uint8_t t0sz; 259 uint8_t s2t0sz; 260 }; 261 262 ConfigCache(unsigned numEntries, unsigned _associativity, 263 const std::string &policy); 264 virtual ~ConfigCache() {} 265 266 const Entry *lookup(uint32_t sid, uint32_t ssid, bool updStats=true); 267 void store(const Entry &incoming); 268 269 void invalidateSSID(uint32_t sid, uint32_t ssid); 270 void invalidateSID(uint32_t sid); 271 void invalidateAll(); 272 273 private: 274 typedef std::vector<Entry> Set; 275 std::vector<Set> sets; 276 277 size_t associativity; 278 279 size_t pickSetIdx(uint32_t sid, uint32_t ssid) const; 280 size_t pickEntryIdxToReplace(const Set &set); 281}; 282 283class WalkCache : public SMMUv3BaseCache 284{ 285 public: 286 struct Entry 287 { 288 bool valid; 289 mutable uint32_t lastUsed; 290 291 // TAGS 292 Addr va; 293 Addr vaMask; 294 uint16_t asid; 295 uint16_t vmid; 296 unsigned stage; 297 unsigned level; 298 299 // OUTPUTS 300 bool leaf; 301 Addr pa; 302 uint8_t permissions; 303 }; 304 305 WalkCache(const std::array<unsigned, 2*WALK_CACHE_LEVELS> &_sizes, 306 unsigned _associativity, const std::string &policy); 307 virtual ~WalkCache() {} 308 309 const Entry *lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid, 310 unsigned stage, unsigned level, bool updStats=true); 311 void store(const Entry &incoming); 312 313 void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, 314 const bool leaf_only); 315 void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only); 316 void invalidateASID(uint16_t asid, uint16_t vmid); 317 void invalidateVMID(uint16_t vmid); 318 void invalidateAll(); 319 320 void regStats(const std::string &name) override; 321 322 protected: 323 unsigned int lookupsByStageLevel[2][WALK_CACHE_LEVELS]; 324 Stats::Formula averageLookupsByStageLevel[2][WALK_CACHE_LEVELS]; 325 Stats::Scalar totalLookupsByStageLevel[2][WALK_CACHE_LEVELS]; 326 327 unsigned int missesByStageLevel[2][WALK_CACHE_LEVELS]; 328 Stats::Formula averageMissesByStageLevel[2][WALK_CACHE_LEVELS]; 329 Stats::Scalar totalMissesByStageLevel[2][WALK_CACHE_LEVELS]; 330 331 unsigned int updatesByStageLevel[2][WALK_CACHE_LEVELS]; 332 Stats::Formula averageUpdatesByStageLevel[2][WALK_CACHE_LEVELS]; 333 Stats::Scalar totalUpdatesByStageLevel[2][WALK_CACHE_LEVELS]; 334 335 Stats::Formula averageHitRateByStageLevel[2][WALK_CACHE_LEVELS]; 336 337 Stats::Scalar insertionsByStageLevel[2][WALK_CACHE_LEVELS]; 338 339 private: 340 typedef std::vector<Entry> Set; 341 std::vector<Set> sets; 342 343 size_t associativity; 344 std::array<unsigned, 2*WALK_CACHE_LEVELS> sizes; 345 std::array<unsigned, 2*WALK_CACHE_LEVELS> offsets; 346 347 size_t pickSetIdx(Addr va, Addr vaMask, 348 unsigned stage, unsigned level) const; 349 350 size_t pickEntryIdxToReplace(const Set &set, 351 unsigned stage, unsigned level); 352}; 353 354#endif /* __DEV_ARM_SMMU_V3_CACHES_HH__ */ 355