| /* |
| * Copyright (c) 2014, 2018-2019, 2021 Arm Limited |
| * All rights reserved |
| * |
| * The license below extends only to copyright in the software and shall |
| * not be construed as granting a license to any other intellectual |
| * property including but not limited to intellectual property relating |
| * to a hardware implementation of the functionality of the software |
| * licensed hereunder. You may use the software subject to the license |
| * terms below provided that you ensure that this notice is replicated |
| * unmodified and in its entirety in all distributions of the software, |
| * modified or unmodified, in source code or in binary form. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef __DEV_ARM_SMMU_V3_CACHES_HH__ |
| #define __DEV_ARM_SMMU_V3_CACHES_HH__ |
| |
| #include <stdint.h> |
| |
| #include <array> |
| #include <cstddef> |
| #include <string> |
| #include <vector> |
| |
| #include "base/random.hh" |
| #include "base/statistics.hh" |
| #include "base/types.hh" |
| |
| #define WALK_CACHE_LEVELS 4 |
| |
| enum { |
| SMMU_CACHE_REPL_ROUND_ROBIN, |
| SMMU_CACHE_REPL_RANDOM, |
| SMMU_CACHE_REPL_LRU, |
| }; |
| |
| class SMMUv3BaseCache |
| { |
| protected: |
| int replacementPolicy; |
| size_t nextToReplace; |
| Random random; |
| uint32_t useStamp; |
| |
| struct SMMUv3BaseCacheStats : public Stats::Group |
| { |
| SMMUv3BaseCacheStats(Stats::Group *parent, const std::string &name); |
| |
| Stats::Formula averageLookups; |
| Stats::Scalar totalLookups; |
| |
| Stats::Formula averageMisses; |
| Stats::Scalar totalMisses; |
| |
| Stats::Formula averageUpdates; |
| Stats::Scalar totalUpdates; |
| |
| Stats::Formula averageHitRate; |
| |
| Stats::Scalar insertions; |
| } baseCacheStats; |
| |
| static int decodePolicyName(const std::string &policy_name); |
| |
| public: |
| SMMUv3BaseCache(const std::string &policy_name, uint32_t seed, |
| Stats::Group *parent, const std::string &name); |
| virtual ~SMMUv3BaseCache() {} |
| }; |
| |
| class SMMUTLB : public SMMUv3BaseCache |
| { |
| public: |
| enum AllocPolicy { |
| ALLOC_ANY_WAY, |
| ALLOC_ANY_BUT_LAST_WAY, |
| ALLOC_LAST_WAY, |
| }; |
| |
| struct Entry |
| { |
| bool valid; |
| bool prefetched; |
| mutable uint32_t lastUsed; |
| |
| // TAGS |
| uint32_t sid; |
| uint32_t ssid; |
| Addr va; |
| Addr vaMask; |
| |
| // EXTRA TAGS |
| uint16_t asid; |
| uint16_t vmid; |
| |
| // OUTPUTS |
| Addr pa; |
| uint8_t permissions; |
| }; |
| |
| SMMUTLB(unsigned numEntries, unsigned _associativity, |
| const std::string &policy, Stats::Group *parent, |
| const std::string &name); |
| SMMUTLB(const SMMUTLB& tlb) = delete; |
| virtual ~SMMUTLB() {} |
| |
| const Entry *lookup(uint32_t sid, uint32_t ssid, Addr va, |
| bool updStats=true); |
| const Entry *lookupAnyVA(uint32_t sid, uint32_t ssid, |
| bool updStats=true); |
| void store(const Entry &incoming, AllocPolicy alloc); |
| |
| void invalidateSSID(uint32_t sid, uint32_t ssid); |
| void invalidateSID(uint32_t sid); |
| void invalidateVA(Addr va, uint16_t asid, uint16_t vmid); |
| void invalidateVAA(Addr va, uint16_t vmid); |
| void invalidateASID(uint16_t asid, uint16_t vmid); |
| void invalidateVMID(uint16_t vmid); |
| void invalidateAll(); |
| |
| private: |
| typedef std::vector<Entry> Set; |
| std::vector<Set> sets; |
| |
| size_t associativity; |
| |
| size_t pickSetIdx(uint32_t sid, uint32_t ssid) const; |
| size_t pickSetIdx(Addr va) const; |
| size_t pickEntryIdxToReplace(const Set &set, AllocPolicy alloc); |
| }; |
| |
| class ARMArchTLB : public SMMUv3BaseCache |
| { |
| public: |
| struct Entry |
| { |
| bool valid; |
| mutable uint32_t lastUsed; |
| |
| // TAGS |
| Addr va; |
| Addr vaMask; |
| uint16_t asid; |
| uint16_t vmid; |
| |
| // OUTPUTS |
| Addr pa; |
| uint8_t permissions; |
| }; |
| |
| ARMArchTLB(unsigned numEntries, unsigned _associativity, |
| const std::string &policy, Stats::Group *parent); |
| virtual ~ARMArchTLB() {} |
| |
| const Entry *lookup(Addr va, uint16_t asid, uint16_t vmid, |
| bool updStats=true); |
| |
| void store(const Entry &incoming); |
| |
| void invalidateVA(Addr va, uint16_t asid, uint16_t vmid); |
| void invalidateVAA(Addr va, uint16_t vmid); |
| void invalidateASID(uint16_t asid, uint16_t vmid); |
| void invalidateVMID(uint16_t vmid); |
| void invalidateAll(); |
| |
| private: |
| typedef std::vector<Entry> Set; |
| std::vector<Set> sets; |
| |
| size_t associativity; |
| |
| size_t pickSetIdx(Addr va, uint16_t asid, uint16_t vmid) const; |
| size_t pickEntryIdxToReplace(const Set &set); |
| }; |
| |
| class IPACache : public SMMUv3BaseCache |
| { |
| public: |
| struct Entry |
| { |
| bool valid; |
| mutable uint32_t lastUsed; |
| |
| // TAGS |
| Addr ipa; |
| Addr ipaMask; |
| uint16_t vmid; |
| |
| // OUTPUTS |
| Addr pa; |
| uint8_t permissions; |
| }; |
| |
| IPACache(unsigned numEntries, unsigned _associativity, |
| const std::string &policy, Stats::Group *parent); |
| virtual ~IPACache() {} |
| |
| const Entry *lookup(Addr ipa, uint16_t vmid, bool updStats=true); |
| void store(const Entry &incoming); |
| |
| void invalidateIPA(Addr ipa, uint16_t vmid); |
| void invalidateIPAA(Addr ipa); |
| void invalidateVMID(uint16_t vmid); |
| void invalidateAll(); |
| |
| private: |
| typedef std::vector<Entry> Set; |
| std::vector<Set> sets; |
| |
| size_t associativity; |
| |
| size_t pickSetIdx(Addr ipa, uint16_t vmid) const; |
| size_t pickEntryIdxToReplace(const Set &set); |
| }; |
| |
| class ConfigCache : public SMMUv3BaseCache |
| { |
| public: |
| struct Entry |
| { |
| bool valid; |
| mutable uint32_t lastUsed; |
| |
| // TAGS |
| uint32_t sid; |
| uint32_t ssid; |
| |
| // OUTPUTS |
| bool stage1_en; |
| bool stage2_en; |
| Addr ttb0; |
| Addr ttb1; |
| Addr httb; |
| uint16_t asid; |
| uint16_t vmid; |
| uint8_t stage1_tg; |
| uint8_t stage2_tg; |
| uint8_t t0sz; |
| uint8_t s2t0sz; |
| }; |
| |
| ConfigCache(unsigned numEntries, unsigned _associativity, |
| const std::string &policy, Stats::Group *parent); |
| virtual ~ConfigCache() {} |
| |
| const Entry *lookup(uint32_t sid, uint32_t ssid, bool updStats=true); |
| void store(const Entry &incoming); |
| |
| void invalidateSSID(uint32_t sid, uint32_t ssid); |
| void invalidateSID(uint32_t sid); |
| void invalidateAll(); |
| |
| private: |
| typedef std::vector<Entry> Set; |
| std::vector<Set> sets; |
| |
| size_t associativity; |
| |
| size_t pickSetIdx(uint32_t sid, uint32_t ssid) const; |
| size_t pickEntryIdxToReplace(const Set &set); |
| }; |
| |
| class WalkCache : public SMMUv3BaseCache |
| { |
| public: |
| struct Entry |
| { |
| bool valid; |
| mutable uint32_t lastUsed; |
| |
| // TAGS |
| Addr va; |
| Addr vaMask; |
| uint16_t asid; |
| uint16_t vmid; |
| unsigned stage; |
| unsigned level; |
| |
| // OUTPUTS |
| bool leaf; |
| Addr pa; |
| uint8_t permissions; |
| }; |
| |
| WalkCache(const std::array<unsigned, 2*WALK_CACHE_LEVELS> &_sizes, |
| unsigned _associativity, const std::string &policy, |
| Stats::Group *parent); |
| virtual ~WalkCache() {} |
| |
| const Entry *lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid, |
| unsigned stage, unsigned level, bool updStats=true); |
| void store(const Entry &incoming); |
| |
| void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, |
| const bool leaf_only); |
| void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only); |
| void invalidateASID(uint16_t asid, uint16_t vmid); |
| void invalidateVMID(uint16_t vmid); |
| void invalidateAll(); |
| |
| protected: |
| struct WalkCacheStats : public Stats::Group |
| { |
| WalkCacheStats(Stats::Group *parent); |
| ~WalkCacheStats(); |
| |
| std::vector<Stats::Formula*> averageLookupsByStageLevel; |
| Stats::Vector2d totalLookupsByStageLevel; |
| |
| std::vector<Stats::Formula*> averageMissesByStageLevel; |
| Stats::Vector2d totalMissesByStageLevel; |
| |
| std::vector<Stats::Formula*> averageUpdatesByStageLevel; |
| Stats::Vector2d totalUpdatesByStageLevel; |
| |
| std::vector<Stats::Formula*> averageHitRateByStageLevel; |
| |
| Stats::Vector2d insertionsByStageLevel; |
| } walkCacheStats; |
| private: |
| typedef std::vector<Entry> Set; |
| std::vector<Set> sets; |
| |
| size_t associativity; |
| std::array<unsigned, 2*WALK_CACHE_LEVELS> sizes; |
| std::array<unsigned, 2*WALK_CACHE_LEVELS> offsets; |
| |
| size_t pickSetIdx(Addr va, Addr vaMask, |
| unsigned stage, unsigned level) const; |
| |
| size_t pickEntryIdxToReplace(const Set &set, |
| unsigned stage, unsigned level); |
| }; |
| |
| #endif /* __DEV_ARM_SMMU_V3_CACHES_HH__ */ |