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