smmu_v3_ptops.cc revision 14039
1/*
2 * Copyright (c) 2013, 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#include "dev/arm/smmu_v3_ptops.hh"
41
42#include "base/bitfield.hh"
43#include "base/logging.hh"
44
45bool
46V7LPageTableOps::isValid(pte_t pte, unsigned level) const
47{
48    switch (level) {
49        case 1: return  pte & 0x1;
50        case 2: return  pte & 0x1;
51        case 3: return (pte & 0x1) && (pte & 0x2);
52        default: panic("bad level %d", level);
53    }
54}
55
56bool
57V7LPageTableOps::isLeaf(pte_t pte, unsigned level) const
58{
59    switch (level) {
60        case 1: return !(pte & 0x2);
61        case 2: return !(pte & 0x2);
62        case 3: return true;
63        default: panic("bad level %d", level);
64    }
65}
66
67bool
68V7LPageTableOps::isWritable(pte_t pte, unsigned level, bool stage2) const
69{
70    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
71}
72
73Addr
74V7LPageTableOps::nextLevelPointer(pte_t pte, unsigned level) const
75{
76    if (isLeaf(pte, level)) {
77        switch (level) {
78            case 1: return mbits(pte, 39, 30);
79            case 2: return mbits(pte, 39, 21);
80            case 3: return mbits(pte, 39, 12);
81            default: panic("bad level %d", level);
82        }
83    } else {
84        return mbits(pte, 39, 12);
85    }
86}
87
88Addr
89V7LPageTableOps::index(Addr va, unsigned level) const
90{
91    // In theory this should be configurable...
92    const int n = 12;
93
94    switch (level) {
95        case 1: return bits(va, 26+n, 30) << 3; break;
96        case 2: return bits(va, 29, 21) << 3; break;
97        case 3: return bits(va, 20, 12) << 3; break;
98        default: panic("bad level %d", level);
99    }
100}
101
102Addr
103V7LPageTableOps::pageMask(pte_t pte, unsigned level) const
104{
105    switch (level) {
106        case 1: return ~mask(30);
107        case 2: return ~mask(21);
108        case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12);
109        default: panic("bad level %d", level);
110    }
111}
112
113Addr
114V7LPageTableOps::walkMask(unsigned level) const
115{
116    switch (level) {
117        case 1: return mask(39, 30);
118        case 2: return mask(39, 21);
119        case 3: return mask(39, 12);
120        default: panic("bad level %d", level);
121    }
122}
123
124unsigned
125V7LPageTableOps::firstLevel() const
126{
127    return 1;
128}
129
130unsigned
131V7LPageTableOps::lastLevel() const
132{
133    return 3;
134}
135
136bool
137V8PageTableOps4k::isValid(pte_t pte, unsigned level) const
138{
139    switch (level) {
140        case 0: return  pte & 0x1;
141        case 1: return  pte & 0x1;
142        case 2: return  pte & 0x1;
143        case 3: return (pte & 0x1) && (pte & 0x2);
144        default: panic("bad level %d", level);
145    }
146}
147
148bool
149V8PageTableOps4k::isLeaf(pte_t pte, unsigned level) const
150{
151    switch (level) {
152        case 0: return false;
153        case 1: return !(pte & 0x2);
154        case 2: return !(pte & 0x2);
155        case 3: return true;
156        default: panic("bad level %d", level);
157    }
158}
159
160bool
161V8PageTableOps4k::isWritable(pte_t pte, unsigned level, bool stage2) const
162{
163    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
164}
165
166Addr
167V8PageTableOps4k::nextLevelPointer(pte_t pte, unsigned level) const
168{
169    if (isLeaf(pte, level)) {
170        switch (level) {
171            // no level 0 here
172            case 1: return mbits(pte, 47, 30);
173            case 2: return mbits(pte, 47, 21);
174            case 3: return mbits(pte, 47, 12);
175            default: panic("bad level %d", level);
176        }
177    } else {
178        return mbits(pte, 47, 12);
179    }
180}
181
182Addr
183V8PageTableOps4k::index(Addr va, unsigned level) const
184{
185    switch (level) {
186        case 0: return bits(va, 47, 39) << 3; break;
187        case 1: return bits(va, 38, 30) << 3; break;
188        case 2: return bits(va, 29, 21) << 3; break;
189        case 3: return bits(va, 20, 12) << 3; break;
190        default: panic("bad level %d", level);
191    }
192}
193
194Addr
195V8PageTableOps4k::pageMask(pte_t pte, unsigned level) const
196{
197    switch (level) {
198        // no level 0 here
199        case 1: return ~mask(30);
200        case 2: return ~mask(21);
201        case 3: return bits(pte, 52) ? ~mask(16) : ~mask(12);
202        default: panic("bad level %d", level);
203    }
204}
205
206Addr
207V8PageTableOps4k::walkMask(unsigned level) const
208{
209    switch (level) {
210        case 0: return mask(47, 39);
211        case 1: return mask(47, 30);
212        case 2: return mask(47, 21);
213        case 3: return mask(47, 12);
214        default: panic("bad level %d", level);
215    }
216}
217
218unsigned
219V8PageTableOps4k::firstLevel() const
220{
221    return 0;
222}
223
224unsigned
225V8PageTableOps4k::lastLevel() const
226{
227    return 3;
228}
229
230bool
231V8PageTableOps64k::isValid(pte_t pte, unsigned level) const
232{
233    switch (level) {
234        case 1: return  pte & 0x1;
235        case 2: return  pte & 0x1;
236        case 3: return (pte & 0x1) && (pte & 0x2);
237        default: panic("bad level %d", level);
238    }
239}
240
241bool
242V8PageTableOps64k::isLeaf(pte_t pte, unsigned level) const
243{
244    switch (level) {
245        case 1: return false;
246        case 2: return !(pte & 0x2);
247        case 3: return true;
248        default: panic("bad level %d", level);
249    }
250}
251
252bool
253V8PageTableOps64k::isWritable(pte_t pte, unsigned level, bool stage2) const
254{
255    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
256}
257
258Addr
259V8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const
260{
261    if (isLeaf(pte, level)) {
262        switch (level) {
263            // no level 1 here
264            case 2: return mbits(pte, 47, 29);
265            case 3: return mbits(pte, 47, 16);
266            default: panic("bad level %d", level);
267        }
268    } else {
269        return mbits(pte, 47, 16);
270    }
271}
272
273Addr
274V8PageTableOps64k::index(Addr va, unsigned level) const
275{
276    switch (level) {
277        case 1: return bits(va, 47, 42) << 3; break;
278        case 2: return bits(va, 41, 29) << 3; break;
279        case 3: return bits(va, 28, 16) << 3; break;
280        default: panic("bad level %d", level);
281    }
282}
283
284Addr
285V8PageTableOps64k::pageMask(pte_t pte, unsigned level) const
286{
287    switch (level) {
288        // no level 1 here
289        case 2: return ~mask(29);
290        case 3: return bits(pte, 52) ? ~mask(21) : ~mask(16);
291        default: panic("bad level %d", level);
292    }
293}
294
295Addr
296V8PageTableOps64k::walkMask(unsigned level) const
297{
298    switch (level) {
299        case 1: return mask(47, 42);
300        case 2: return mask(47, 29);
301        case 3: return mask(47, 16);
302        default: panic("bad level %d", level);
303    }
304}
305
306unsigned
307V8PageTableOps64k::firstLevel() const
308{
309    return 1;
310}
311
312unsigned
313V8PageTableOps64k::lastLevel() const
314{
315    return 3;
316}
317