smmu_v3_caches.hh revision 14101
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        uint8_t t0sz;
256        uint8_t s2t0sz;
257    };
258
259    ConfigCache(unsigned numEntries, unsigned _associativity,
260                const std::string &policy);
261    virtual ~ConfigCache() {}
262
263    const Entry *lookup(uint32_t sid, uint32_t ssid, bool updStats=true);
264    void store(const Entry &incoming);
265
266    void invalidateSSID(uint32_t sid, uint32_t ssid);
267    void invalidateSID(uint32_t sid);
268    void invalidateAll();
269
270  private:
271    typedef std::vector<Entry> Set;
272    std::vector<Set> sets;
273
274    size_t associativity;
275
276    size_t pickSetIdx(uint32_t sid, uint32_t ssid) const;
277    size_t pickEntryIdxToReplace(const Set &set);
278};
279
280class WalkCache : public SMMUv3BaseCache
281{
282  public:
283    struct Entry
284    {
285        bool valid;
286        mutable uint32_t lastUsed;
287
288        // TAGS
289        Addr va;
290        Addr vaMask;
291        uint16_t asid;
292        uint16_t vmid;
293        unsigned stage;
294        unsigned level;
295
296        // OUTPUTS
297        bool leaf;
298        Addr pa;
299        uint8_t permissions;
300    };
301
302    WalkCache(const std::array<unsigned, 2*WALK_CACHE_LEVELS> &_sizes,
303              unsigned _associativity, const std::string &policy);
304    virtual ~WalkCache() {}
305
306    const Entry *lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid,
307                        unsigned stage, unsigned level, bool updStats=true);
308    void store(const Entry &incoming);
309
310    void invalidateVA(Addr va, uint16_t asid, uint16_t vmid);
311    void invalidateVAA(Addr va, uint16_t vmid);
312    void invalidateASID(uint16_t asid, uint16_t vmid);
313    void invalidateVMID(uint16_t vmid);
314    void invalidateAll();
315
316    void regStats(const std::string &name) override;
317
318  protected:
319    unsigned int lookupsByStageLevel[2][WALK_CACHE_LEVELS];
320    Stats::Formula averageLookupsByStageLevel[2][WALK_CACHE_LEVELS];
321    Stats::Scalar totalLookupsByStageLevel[2][WALK_CACHE_LEVELS];
322
323    unsigned int missesByStageLevel[2][WALK_CACHE_LEVELS];
324    Stats::Formula averageMissesByStageLevel[2][WALK_CACHE_LEVELS];
325    Stats::Scalar totalMissesByStageLevel[2][WALK_CACHE_LEVELS];
326
327    unsigned int updatesByStageLevel[2][WALK_CACHE_LEVELS];
328    Stats::Formula averageUpdatesByStageLevel[2][WALK_CACHE_LEVELS];
329    Stats::Scalar totalUpdatesByStageLevel[2][WALK_CACHE_LEVELS];
330
331    Stats::Formula averageHitRateByStageLevel[2][WALK_CACHE_LEVELS];
332
333    Stats::Scalar insertionsByStageLevel[2][WALK_CACHE_LEVELS];
334
335  private:
336    typedef std::vector<Entry> Set;
337    std::vector<Set> sets;
338
339    size_t associativity;
340    std::array<unsigned, 2*WALK_CACHE_LEVELS> sizes;
341    std::array<unsigned, 2*WALK_CACHE_LEVELS> offsets;
342
343    size_t pickSetIdx(Addr va, Addr vaMask,
344                      unsigned stage, unsigned level) const;
345
346    size_t pickEntryIdxToReplace(const Set &set,
347                                 unsigned stage, unsigned level);
348};
349
350#endif /* __DEV_ARM_SMMU_V3_CACHES_HH__ */
351