smmu_v3_caches.hh revision 14039
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 invalidateVA(Addr va, uint16_t asid, uint16_t vmid);
134    void invalidateVAA(Addr va, uint16_t vmid);
135    void invalidateASID(uint16_t asid, uint16_t vmid);
136    void invalidateVMID(uint16_t vmid);
137    void invalidateAll();
138
139  private:
140    typedef std::vector<Entry> Set;
141    std::vector<Set> sets;
142
143    size_t associativity;
144
145    size_t pickSetIdx(Addr va) const;
146    size_t pickEntryIdxToReplace(const Set &set, AllocPolicy alloc);
147};
148
149class ARMArchTLB : public SMMUv3BaseCache
150{
151  public:
152    struct Entry
153    {
154        bool valid;
155        mutable uint32_t lastUsed;
156
157        // TAGS
158        Addr va;
159        Addr vaMask;
160        uint16_t asid;
161        uint16_t vmid;
162
163        // OUTPUTS
164        Addr pa;
165        uint8_t permissions;
166    };
167
168    ARMArchTLB(unsigned numEntries, unsigned _associativity,
169               const std::string &policy);
170    virtual ~ARMArchTLB() {}
171
172    const Entry *lookup(Addr va, uint16_t asid, uint16_t vmid,
173                        bool updStats=true);
174
175    void store(const Entry &incoming);
176
177    void invalidateVA(Addr va, uint16_t asid, uint16_t vmid);
178    void invalidateVAA(Addr va, uint16_t vmid);
179    void invalidateASID(uint16_t asid, uint16_t vmid);
180    void invalidateVMID(uint16_t vmid);
181    void invalidateAll();
182
183  private:
184    typedef std::vector<Entry> Set;
185    std::vector<Set> sets;
186
187    size_t associativity;
188
189    size_t pickSetIdx(Addr va, uint16_t asid, uint16_t vmid) const;
190    size_t pickEntryIdxToReplace(const Set &set);
191};
192
193class IPACache : public SMMUv3BaseCache
194{
195  public:
196    struct Entry
197    {
198        bool valid;
199        mutable uint32_t lastUsed;
200
201        // TAGS
202        Addr ipa;
203        Addr ipaMask;
204        uint16_t vmid;
205
206        // OUTPUTS
207        Addr pa;
208        uint8_t permissions;
209    };
210
211    IPACache(unsigned numEntries, unsigned _associativity,
212             const std::string &policy);
213    virtual ~IPACache() {}
214
215    const Entry *lookup(Addr ipa, uint16_t vmid, bool updStats=true);
216    void store(const Entry &incoming);
217
218    void invalidateIPA(Addr ipa, uint16_t vmid);
219    void invalidateIPAA(Addr ipa);
220    void invalidateVMID(uint16_t vmid);
221    void invalidateAll();
222
223  private:
224    typedef std::vector<Entry> Set;
225    std::vector<Set> sets;
226
227    size_t associativity;
228
229    size_t pickSetIdx(Addr ipa, uint16_t vmid) const;
230    size_t pickEntryIdxToReplace(const Set &set);
231};
232
233class ConfigCache : public SMMUv3BaseCache
234{
235  public:
236    struct Entry
237    {
238        bool valid;
239        mutable uint32_t lastUsed;
240
241        // TAGS
242        uint32_t sid;
243        uint32_t ssid;
244
245        // OUTPUTS
246        bool stage1_en;
247        bool stage2_en;
248        Addr ttb0;
249        Addr ttb1;
250        Addr httb;
251        uint16_t asid;
252        uint16_t vmid;
253        uint8_t stage1_tg;
254        uint8_t stage2_tg;
255    };
256
257    ConfigCache(unsigned numEntries, unsigned _associativity,
258                const std::string &policy);
259    virtual ~ConfigCache() {}
260
261    const Entry *lookup(uint32_t sid, uint32_t ssid, bool updStats=true);
262    void store(const Entry &incoming);
263
264    void invalidateSSID(uint32_t sid, uint32_t ssid);
265    void invalidateSID(uint32_t sid);
266    void invalidateAll();
267
268  private:
269    typedef std::vector<Entry> Set;
270    std::vector<Set> sets;
271
272    size_t associativity;
273
274    size_t pickSetIdx(uint32_t sid, uint32_t ssid) const;
275    size_t pickEntryIdxToReplace(const Set &set);
276};
277
278class WalkCache : public SMMUv3BaseCache
279{
280  public:
281    struct Entry
282    {
283        bool valid;
284        mutable uint32_t lastUsed;
285
286        // TAGS
287        Addr va;
288        Addr vaMask;
289        uint16_t asid;
290        uint16_t vmid;
291        unsigned stage;
292        unsigned level;
293
294        // OUTPUTS
295        bool leaf;
296        Addr pa;
297        uint8_t permissions;
298    };
299
300    WalkCache(const std::array<unsigned, 2*WALK_CACHE_LEVELS> &_sizes,
301              unsigned _associativity, const std::string &policy);
302    virtual ~WalkCache() {}
303
304    const Entry *lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid,
305                        unsigned stage, unsigned level, bool updStats=true);
306    void store(const Entry &incoming);
307
308    void invalidateVA(Addr va, uint16_t asid, uint16_t vmid);
309    void invalidateVAA(Addr va, uint16_t vmid);
310    void invalidateASID(uint16_t asid, uint16_t vmid);
311    void invalidateVMID(uint16_t vmid);
312    void invalidateAll();
313
314    void regStats(const std::string &name) override;
315
316  protected:
317    unsigned int lookupsByStageLevel[2][WALK_CACHE_LEVELS];
318    Stats::Formula averageLookupsByStageLevel[2][WALK_CACHE_LEVELS];
319    Stats::Scalar totalLookupsByStageLevel[2][WALK_CACHE_LEVELS];
320
321    unsigned int missesByStageLevel[2][WALK_CACHE_LEVELS];
322    Stats::Formula averageMissesByStageLevel[2][WALK_CACHE_LEVELS];
323    Stats::Scalar totalMissesByStageLevel[2][WALK_CACHE_LEVELS];
324
325    unsigned int updatesByStageLevel[2][WALK_CACHE_LEVELS];
326    Stats::Formula averageUpdatesByStageLevel[2][WALK_CACHE_LEVELS];
327    Stats::Scalar totalUpdatesByStageLevel[2][WALK_CACHE_LEVELS];
328
329    Stats::Formula averageHitRateByStageLevel[2][WALK_CACHE_LEVELS];
330
331    Stats::Scalar insertionsByStageLevel[2][WALK_CACHE_LEVELS];
332
333  private:
334    typedef std::vector<Entry> Set;
335    std::vector<Set> sets;
336
337    size_t associativity;
338    std::array<unsigned, 2*WALK_CACHE_LEVELS> sizes;
339    std::array<unsigned, 2*WALK_CACHE_LEVELS> offsets;
340
341    size_t pickSetIdx(Addr va, Addr vaMask,
342                      unsigned stage, unsigned level) const;
343
344    size_t pickEntryIdxToReplace(const Set &set,
345                                 unsigned stage, unsigned level);
346};
347
348#endif /* __DEV_ARM_SMMU_V3_CACHES_HH__ */
349