smmu_v3_ptops.cc revision 14098
110268SGeoffrey.Blake@arm.com/*
210268SGeoffrey.Blake@arm.com * Copyright (c) 2013, 2018-2019 ARM Limited
310268SGeoffrey.Blake@arm.com * All rights reserved
410268SGeoffrey.Blake@arm.com *
510268SGeoffrey.Blake@arm.com * The license below extends only to copyright in the software and shall
610268SGeoffrey.Blake@arm.com * not be construed as granting a license to any other intellectual
710268SGeoffrey.Blake@arm.com * property including but not limited to intellectual property relating
810268SGeoffrey.Blake@arm.com * to a hardware implementation of the functionality of the software
910268SGeoffrey.Blake@arm.com * licensed hereunder.  You may use the software subject to the license
1010268SGeoffrey.Blake@arm.com * terms below provided that you ensure that this notice is replicated
1110268SGeoffrey.Blake@arm.com * unmodified and in its entirety in all distributions of the software,
1210268SGeoffrey.Blake@arm.com * modified or unmodified, in source code or in binary form.
1310268SGeoffrey.Blake@arm.com *
1410268SGeoffrey.Blake@arm.com * Redistribution and use in source and binary forms, with or without
1510268SGeoffrey.Blake@arm.com * modification, are permitted provided that the following conditions are
1610268SGeoffrey.Blake@arm.com * met: redistributions of source code must retain the above copyright
1710268SGeoffrey.Blake@arm.com * notice, this list of conditions and the following disclaimer;
1810268SGeoffrey.Blake@arm.com * redistributions in binary form must reproduce the above copyright
1910268SGeoffrey.Blake@arm.com * notice, this list of conditions and the following disclaimer in the
2010268SGeoffrey.Blake@arm.com * documentation and/or other materials provided with the distribution;
2110268SGeoffrey.Blake@arm.com * neither the name of the copyright holders nor the names of its
2210268SGeoffrey.Blake@arm.com * contributors may be used to endorse or promote products derived from
2310268SGeoffrey.Blake@arm.com * this software without specific prior written permission.
2410268SGeoffrey.Blake@arm.com *
2510268SGeoffrey.Blake@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610268SGeoffrey.Blake@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710268SGeoffrey.Blake@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810268SGeoffrey.Blake@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910268SGeoffrey.Blake@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010268SGeoffrey.Blake@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110268SGeoffrey.Blake@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210268SGeoffrey.Blake@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310268SGeoffrey.Blake@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410268SGeoffrey.Blake@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510268SGeoffrey.Blake@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610268SGeoffrey.Blake@arm.com *
3710268SGeoffrey.Blake@arm.com * Authors: Stan Czerniawski
3810268SGeoffrey.Blake@arm.com */
3910268SGeoffrey.Blake@arm.com
4011420Sdavid.guillen@arm.com#include "dev/arm/smmu_v3_ptops.hh"
4110268SGeoffrey.Blake@arm.com
4210268SGeoffrey.Blake@arm.com#include "base/bitfield.hh"
4310268SGeoffrey.Blake@arm.com#include "base/logging.hh"
4410268SGeoffrey.Blake@arm.com
4510268SGeoffrey.Blake@arm.combool
4610268SGeoffrey.Blake@arm.comV7LPageTableOps::isValid(pte_t pte, unsigned level) const
4710268SGeoffrey.Blake@arm.com{
4810268SGeoffrey.Blake@arm.com    switch (level) {
4910268SGeoffrey.Blake@arm.com        case 1: return  pte & 0x1;
5010268SGeoffrey.Blake@arm.com        case 2: return  pte & 0x1;
5110268SGeoffrey.Blake@arm.com        case 3: return (pte & 0x1) && (pte & 0x2);
5210268SGeoffrey.Blake@arm.com        default: panic("bad level %d", level);
5310268SGeoffrey.Blake@arm.com    }
5411420Sdavid.guillen@arm.com}
5512469Sglenn.bergmans@arm.com
5611420Sdavid.guillen@arm.combool
5711420Sdavid.guillen@arm.comV7LPageTableOps::isLeaf(pte_t pte, unsigned level) const
5812469Sglenn.bergmans@arm.com{
5912469Sglenn.bergmans@arm.com    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
231V8PageTableOps16k::isValid(pte_t pte, unsigned level) const
232{
233    switch (level) {
234        case 0: return  pte & 0x1;
235        case 1: return  pte & 0x1;
236        case 2: return  pte & 0x1;
237        case 3: return (pte & 0x1) && (pte & 0x2);
238        default: panic("bad level %d", level);
239    }
240}
241
242bool
243V8PageTableOps16k::isLeaf(pte_t pte, unsigned level) const
244{
245    switch (level) {
246        case 0: return false;
247        case 1: return false;
248        case 2: return !(pte & 0x2);
249        case 3: return true;
250        default: panic("bad level %d", level);
251    }
252}
253
254bool
255V8PageTableOps16k::isWritable(pte_t pte, unsigned level, bool stage2) const
256{
257    return stage2 ? bits(pte, 7, 6) == 3 : bits(pte, 7) == 0;
258}
259
260Addr
261V8PageTableOps16k::nextLevelPointer(pte_t pte, unsigned level) const
262{
263    if (isLeaf(pte, level)) {
264        switch (level) {
265            // no level 0 here
266            case 1: return mbits(pte, 47, 36);
267            case 2: return mbits(pte, 47, 25);
268            case 3: return mbits(pte, 47, 14);
269            default: panic("bad level %d", level);
270        }
271    } else {
272        return mbits(pte, 47, 12);
273    }
274}
275
276Addr
277V8PageTableOps16k::index(Addr va, unsigned level) const
278{
279    switch (level) {
280        case 0: return bits(va, 47, 47) << 3; break;
281        case 1: return bits(va, 46, 36) << 3; break;
282        case 2: return bits(va, 35, 25) << 3; break;
283        case 3: return bits(va, 24, 14) << 3; break;
284        default: panic("bad level %d", level);
285    }
286}
287
288Addr
289V8PageTableOps16k::pageMask(pte_t pte, unsigned level) const
290{
291    switch (level) {
292        // no level 0 here
293        case 1: return ~mask(36);
294        // 16K granule supports contiguous entries also at L2; - 1G
295        case 2: return bits(pte, 52) ? ~mask(30) : ~mask(25);
296        // as well as at L3; - 2M
297        case 3: return bits(pte, 52) ? ~mask(21) : ~mask(14);
298        default: panic("bad level %d", level);
299    }
300}
301
302Addr
303V8PageTableOps16k::walkMask(unsigned level) const
304{
305    switch (level) {
306        case 0: return ~mask(47);
307        case 1: return ~mask(36);
308        case 2: return ~mask(25);
309        case 3: return ~mask(14);
310        default: panic("bad level %d", level);
311    }
312}
313
314unsigned
315V8PageTableOps16k::firstLevel() const
316{
317    return 0;
318}
319
320unsigned
321V8PageTableOps16k::lastLevel() const
322{
323    return 3;
324}
325
326bool
327V8PageTableOps64k::isValid(pte_t pte, unsigned level) const
328{
329    switch (level) {
330        case 1: return  pte & 0x1;
331        case 2: return  pte & 0x1;
332        case 3: return (pte & 0x1) && (pte & 0x2);
333        default: panic("bad level %d", level);
334    }
335}
336
337bool
338V8PageTableOps64k::isLeaf(pte_t pte, unsigned level) const
339{
340    switch (level) {
341        case 1: return false;
342        case 2: return !(pte & 0x2);
343        case 3: return true;
344        default: panic("bad level %d", level);
345    }
346}
347
348bool
349V8PageTableOps64k::isWritable(pte_t pte, unsigned level, bool stage2) const
350{
351    return stage2 ? bits(pte, 7, 6)==3 : bits(pte, 7)==0;
352}
353
354Addr
355V8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const
356{
357    if (isLeaf(pte, level)) {
358        switch (level) {
359            // no level 1 here
360            case 2: return mbits(pte, 47, 29);
361            case 3: return mbits(pte, 47, 16);
362            default: panic("bad level %d", level);
363        }
364    } else {
365        return mbits(pte, 47, 16);
366    }
367}
368
369Addr
370V8PageTableOps64k::index(Addr va, unsigned level) const
371{
372    switch (level) {
373        case 1: return bits(va, 47, 42) << 3; break;
374        case 2: return bits(va, 41, 29) << 3; break;
375        case 3: return bits(va, 28, 16) << 3; break;
376        default: panic("bad level %d", level);
377    }
378}
379
380Addr
381V8PageTableOps64k::pageMask(pte_t pte, unsigned level) const
382{
383    switch (level) {
384        // no level 1 here
385        case 2: return ~mask(29);
386        case 3: return bits(pte, 52) ? ~mask(21) : ~mask(16);
387        default: panic("bad level %d", level);
388    }
389}
390
391Addr
392V8PageTableOps64k::walkMask(unsigned level) const
393{
394    switch (level) {
395        case 1: return mask(47, 42);
396        case 2: return mask(47, 29);
397        case 3: return mask(47, 16);
398        default: panic("bad level %d", level);
399    }
400}
401
402unsigned
403V8PageTableOps64k::firstLevel() const
404{
405    return 1;
406}
407
408unsigned
409V8PageTableOps64k::lastLevel() const
410{
411    return 3;
412}
413