misc: Merged release-staging-v19.0.0.0 into develop
[gem5.git] / src / arch / arm / pauth_helpers.cc
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2020 Metempsy Technology Consulting
4 // All rights reserved
5 //
6 // The license below extends only to copyright in the software and shall
7 // not be construed as granting a license to any other intellectual
8 // property including but not limited to intellectual property relating
9 // to a hardware implementation of the functionality of the software
10 // licensed hereunder. You may use the software subject to the license
11 // terms below provided that you ensure that this notice is replicated
12 // unmodified and in its entirety in all distributions of the software,
13 // modified or unmodified, in source code or in binary form.
14 //
15 // Redistribution and use in source and binary forms, with or without
16 // modification, are permitted provided that the following conditions are
17 // met: redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer;
19 // redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution;
22 // neither the name of the copyright holders nor the names of its
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
38 #include "arch/arm/pauth_helpers.hh"
39
40 #include "arch/arm/faults.hh"
41 #include "base/bitfield.hh"
42
43 using namespace ArmISA;
44 using namespace std;
45
46 bool
47 ArmISA::calculateTBI(ThreadContext* tc, ExceptionLevel el,
48 uint64_t ptr, bool data)
49 {
50 bool tbi = false;
51 if (upperAndLowerRange(tc, el)) {
52
53 ExceptionLevel s1_el = s1TranslationRegime(tc, el);
54 assert (s1_el == EL1 || s1_el == EL2);
55 TCR tcr = (s1_el == EL1) ? tc->readMiscReg(MISCREG_TCR_EL1):
56 tc->readMiscReg(MISCREG_TCR_EL2);
57 bool b55 = bits(ptr, 55) == 1;
58 if (data)
59 tbi = b55 ? tcr.tbi1 == 1 : tcr.tbi0 == 1;
60 else
61 tbi = b55 ? (tcr.tbi1 == 1 && tcr.tbid1 == 0) :
62 (tcr.tbi0 == 1 && tcr.tbid0 == 0);
63
64 }
65 else if (el == EL2) {
66 TCR tcr = tc->readMiscReg(MISCREG_TCR_EL2);
67 tbi = data ? tcr.tbi == 1 : (tcr.tbi == 1 && tcr.tbid == 0);
68 }
69 else if (el == EL3) {
70 TCR tcr = tc->readMiscReg(MISCREG_TCR_EL3);
71 tbi = data ? tcr.tbi == 1 : (tcr.tbi == 1 && tcr.tbid == 0);
72 }
73 return tbi;
74 }
75
76 int
77 ArmISA::calculateBottomPACBit(ThreadContext* tc, ExceptionLevel el,
78 bool top_bit)
79 {
80 uint32_t tsz_field;
81 bool using64k;
82 if (upperAndLowerRange(tc, el)) {
83 ExceptionLevel s1_el = s1TranslationRegime(tc, el);
84 assert (s1_el == EL1 || s1_el == EL2);
85 if (s1_el == EL1) {
86 // EL1 translation regime registers
87 TCR tcr = tc->readMiscReg(MISCREG_TCR_EL1);
88 tsz_field = top_bit ? (uint32_t)tcr.t1sz : (uint32_t)tcr.t0sz;
89 using64k = top_bit ? tcr.tg1 == 0x3 : tcr.tg0 == 0x1;
90 } else {
91 // EL2 translation regime registers
92 TCR tcr = tc->readMiscReg(MISCREG_TCR_EL2);
93 assert (ArmSystem::haveEL(tc, EL2));
94 tsz_field = top_bit? (uint32_t)tcr.t1sz : (uint32_t)tcr.t0sz;
95 using64k = top_bit ? tcr.tg1 == 0x3 : tcr.tg0 == 0x1;
96 }
97 } else {
98 TCR tcr2 = tc->readMiscReg(MISCREG_TCR_EL2);
99 TCR tcr3 = tc->readMiscReg(MISCREG_TCR_EL3);
100 tsz_field = el == EL2 ? (uint32_t)tcr2.t0sz: (uint32_t)tcr3.t0sz;
101 using64k = el == EL2 ? tcr2.tg0 == 0x1 : tcr3.tg0 == 0x1 ;
102 }
103 uint32_t max_limit_tsz_field = using64k ? 47 : 48;
104 tsz_field = min(tsz_field, max_limit_tsz_field);
105 const AA64MMFR2 mm_fr2 = tc->readMiscReg(MISCREG_ID_AA64MMFR2_EL1);
106
107 uint32_t tszmin = (using64k && (bool)mm_fr2.varange) ? 12 : 16;
108 tsz_field = max(tsz_field, tszmin);
109
110 return (64-tsz_field);
111 }
112
113 Fault
114 ArmISA::trapPACUse(ThreadContext *tc, ExceptionLevel target_el)
115 {
116 assert(ArmSystem::haveEL(tc, target_el) &&
117 target_el != EL0 && (target_el >= currEL(tc)));
118
119 switch (target_el) {
120 case EL2:
121 return std::make_shared<HypervisorTrap>(0x0, 0, EC_TRAPPED_PAC);
122 case EL3:
123 return std::make_shared<SecureMonitorTrap>(0x0, 0, EC_TRAPPED_PAC);
124 default:
125 return NoFault;
126 }
127 }
128
129 uint64_t
130 ArmISA::addPAC (ThreadContext* tc, ExceptionLevel el, uint64_t ptr,
131 uint64_t modifier, uint64_t k1, uint64_t k0, bool data)
132 {
133 uint64_t PAC;
134 uint64_t result;
135 uint64_t ext_ptr;
136 bool selbit;
137
138 bool tbi = calculateTBI(tc, el, ptr, data);
139 int top_bit = tbi ? 55 : 63;
140 bool b55 = bits(ptr, 55);
141 bool b63 = bits(ptr, 63);
142 // If tagged pointers are in use for a regime with two TTBRs,use bit<55> of
143 // the pointer to select between upper and lower ranges, and preserve this.
144 // This handles the awkward case where there is apparently no correct
145 // choice between the upper and lower address range - ie an addr of
146 // 1xxxxxxx0... with TBI0=0 and TBI1=1 and 0xxxxxxx1 with TBI1=0 and TBI0=1
147
148 if (upperAndLowerRange(tc, el)) {
149 ExceptionLevel s1_el = s1TranslationRegime(tc, el);
150 assert (s1_el == EL1 || s1_el == EL2);
151 if (s1_el == EL1) {
152 // EL1 translation regime registers
153 TCR tcr = tc->readMiscReg(MISCREG_TCR_EL1);
154 if (data) {
155 selbit = (tcr.tbi1 == 1 || tcr.tbi0 == 1) ? b55: b63;
156 } else {
157 selbit = ((tcr.tbi1 == 1 && tcr.tbid1 == 0)
158 || (tcr.tbi0 == 1 && tcr.tbid0 == 0)) ? b55 : b63;
159 }
160 } else {
161 // EL2 translation regime registers
162 TCR tcr = tc->readMiscReg(MISCREG_TCR_EL2);
163 bool have_el2 = ArmSystem::haveEL(tc, EL2);
164 if (data) {
165 selbit = (have_el2 &&
166 (tcr.tbi0 == 1 || tcr.tbi1 == 1))? b55: b63;
167 }
168 else
169 {
170 selbit = (have_el2 &&
171 ((tcr.tbi1 == 1 && tcr.tbid1 == 0) ||
172 (tcr.tbi0 == 1 && tcr.tbid0 == 0)))? b55: b63;
173 }
174 }
175 } else {
176 selbit = tbi ? b55: b63;
177 }
178
179 int bottom_PAC_bit = calculateBottomPACBit(tc, el, selbit);
180 // The pointer authentication code field takes all the available
181 // bits in between
182
183 uint32_t nbits = (top_bit+1) - bottom_PAC_bit;
184 uint64_t pacbits = ((uint64_t)0x1 << nbits) -1; // 2^n -1;
185 uint64_t mask = pacbits << bottom_PAC_bit; // creates mask
186
187 if (selbit) {
188 ext_ptr = ptr | mask;
189 } else {
190 ext_ptr = ptr & ~mask;
191 }
192
193 PAC = QARMA::computePAC(ext_ptr, modifier, k1, k0);
194 // Check if the ptr has good extension bits and corrupt the
195 // pointer authentication code if not;
196 uint64_t t = bits(ptr, top_bit, bottom_PAC_bit);
197 if (t != 0x0 && t != pacbits) {
198 PAC ^= ((uint64_t)0x1 << (top_bit-1));
199 }
200 // Preserve the determination between upper and lower address
201 // at bit<55> and insert PAC
202 if (tbi) {
203 // ptr<63:56>:selbit:PAC<54:bottom_PAC_bit>:ptr<bottom_PAC_bit-1:0>;
204 result = ptr & 0xFF00000000000000;
205 } else {
206 // PAC<63:56>:selbit:PAC<54:bottom_PAC_bit>:ptr<bottom_PAC_bit-1:0>;
207 result = PAC & 0xFF00000000000000;
208 }
209
210 uint64_t masked_PAC = PAC & 0x007FFFFFFFFFFFFF;
211 uint64_t pacbit_mask = ((uint64_t)0x1 << bottom_PAC_bit) -1;
212 uint64_t masked_ptr = ptr & pacbit_mask;
213
214 masked_PAC &= ~pacbit_mask;
215 result |= ((uint64_t)selbit << 55) | masked_PAC | masked_ptr;
216
217 return result;
218 }
219
220
221 uint64_t
222 ArmISA::auth(ThreadContext *tc, ExceptionLevel el, uint64_t ptr,
223 uint64_t modifier, uint64_t k1, uint64_t k0, bool data,
224 uint8_t errorcode)
225 {
226 uint64_t PAC;
227 uint64_t result;
228 uint64_t original_ptr;
229 // Reconstruct the extension field used of adding the PAC to the pointer
230 bool tbi = calculateTBI(tc, el, ptr, data);
231 bool selbit = (bool) bits(ptr, 55);
232
233 int bottom_PAC_bit = calculateBottomPACBit(tc, el, selbit);
234
235 uint32_t top_tbi = tbi? 56: 64;
236 uint32_t nbits = top_tbi - bottom_PAC_bit;
237 uint64_t pacbits = ((uint64_t)0x1 << nbits) -1; // 2^n -1;
238 uint64_t mask = (pacbits << bottom_PAC_bit); // creates mask
239
240 if (selbit) {
241 original_ptr = ptr | mask;
242 } else {
243 original_ptr = ptr & ~mask;
244 }
245
246
247 PAC = QARMA::computePAC(original_ptr, modifier, k1, k0);
248 // Check pointer authentication code
249
250 // <bottom_PAC_bit:0>
251 uint64_t low_mask = ((uint64_t)0x1 << bottom_PAC_bit) -1;
252 // <54:bottom_PAC_bit>
253 uint64_t pac_mask = 0x007FFFFFFFFFFFFF & ~low_mask;
254
255 uint64_t masked_pac = PAC & pac_mask;
256 uint64_t masked_ptr = ptr & pac_mask;
257
258 if (tbi) {
259 if (masked_pac == masked_ptr) {
260 result = original_ptr;
261 } else {
262 uint64_t mask2= ~((uint64_t)0x3 << 53);
263 result = original_ptr & mask2;
264 result |= (uint64_t)errorcode << 53;
265 }
266 } else {
267 if ((masked_pac == masked_ptr) && ((PAC >>56)==(ptr >> 56))) {
268 result = original_ptr;
269 } else {
270 uint64_t mask2 = ~((uint64_t)0x3 << 61);
271 result = original_ptr & mask2;
272 result |= (uint64_t)errorcode << 61;
273 }
274 }
275 return result;
276 }
277
278 Fault
279 ArmISA::authDA(ThreadContext * tc, uint64_t X, uint64_t Y, uint64_t* out)
280 {
281 /*
282 Returns a 64-bit value containing X, but replacing the pointer
283 authentication code field bits with the extension of the address bits.
284 The instruction checks a pointer
285 authentication code in the pointer authentication code field bits of X,
286 using the same algorithm and key as AddPACDA().
287 */
288
289 bool trapEL2;
290 bool trapEL3;
291 bool enable;
292
293 uint64_t hi_key= tc->readMiscReg(MISCREG_APDAKeyHi_EL1);
294 uint64_t lo_key= tc->readMiscReg(MISCREG_APDAKeyLo_EL1);
295
296 ExceptionLevel el = currEL(tc);
297 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
298 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
299 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
300 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
301 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
302 bool have_el3 = ArmSystem::haveEL(tc, EL3);
303
304 switch (el)
305 {
306 case EL0:
307 {
308 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
309 enable = IsEL1Regime ? (bool)sc1.enda : (bool)sc2.enda;
310 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
311 (hcr.tge == 0 || hcr.e2h == 0));
312 trapEL3 = have_el3 && scr3.api == 0;
313 break;
314 }
315 case EL1:
316 enable = sc1.enda;
317 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
318 trapEL3 = have_el3 && scr3.api == 0;
319 break;
320 case EL2:
321 enable = sc2.enda;
322 trapEL2 = false;
323 trapEL3 = have_el3 && scr3.api == 0;
324 break;
325 case EL3:
326 enable = sc3.enda;
327 trapEL2 = false;
328 trapEL3 = false;
329 break;
330 default:
331 // Unreachable
332 break;
333 }
334 if (!enable)
335 *out = X;
336 else if (trapEL2)
337 return trapPACUse(tc, EL2);
338 else if (trapEL3)
339 return trapPACUse(tc, EL3);
340 else {
341 *out = auth(tc, el, X, Y, hi_key, lo_key, true, 0x1);
342 }
343 return NoFault;
344 }
345
346 Fault
347 ArmISA::authDB(ThreadContext* tc, uint64_t X, uint64_t Y, uint64_t* out)
348 {
349 /*
350 Returns a 64-bit value containing X, but replacing the pointer
351 authentication code field bits with the extension of the address bits.
352 The instruction checks a pointer
353 authentication code in the pointer authentication code field bits of X,
354 using the same algorithm and key as AddPACDA().
355 */
356
357 bool trapEL2;
358 bool trapEL3;
359 bool enable;
360
361 uint64_t hi_key= tc->readMiscReg(MISCREG_APDBKeyHi_EL1);
362 uint64_t lo_key= tc->readMiscReg(MISCREG_APDBKeyLo_EL1);
363
364 ExceptionLevel el = currEL(tc);
365 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
366 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
367 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
368 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
369
370 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
371 bool have_el3 = ArmSystem::haveEL(tc, EL3);
372
373 switch (el)
374 {
375 case EL0:
376 {
377 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
378 enable = IsEL1Regime ? (bool)sc1.endb : (bool)sc2.endb;
379 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
380 (hcr.tge == 0 || hcr.e2h == 0));
381 trapEL3 = have_el3 && scr3.api == 0;
382 break;
383 }
384 case EL1:
385 enable = sc1.endb;
386 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
387 trapEL3 = have_el3 && scr3.api == 0;
388 break;
389 case EL2:
390 enable = sc2.endb;
391 trapEL2 = false;
392 trapEL3 = have_el3 && scr3.api == 0;
393 break;
394 case EL3:
395 enable = sc3.endb;
396 trapEL2 = false;
397 trapEL3 = false;
398 break;
399 default:
400 //unreachable
401 break;
402 }
403 if (!enable)
404 *out = X;
405 else if (trapEL2)
406 return trapPACUse(tc, EL2);
407 else if (trapEL3)
408 return trapPACUse(tc, EL3);
409 else
410 *out = auth(tc, el, X, Y, hi_key, lo_key, true, 0x2);
411
412 return NoFault;
413 }
414
415
416 Fault
417 ArmISA::authIA(ThreadContext * tc, uint64_t X, uint64_t Y, uint64_t* out)
418 {
419 /*
420 Returns a 64-bit value containing X, but replacing the pointer
421 authentication code field bits with the extension of the address bits.
422 The instruction checks a pointer
423 authentication code in the pointer authentication code field bits of X,
424 using the same algorithm and key as AddPACDA().
425 */
426
427 bool trapEL2;
428 bool trapEL3;
429 bool enable;
430
431 uint64_t hi_key= tc->readMiscReg(MISCREG_APIAKeyHi_EL1);
432 uint64_t lo_key= tc->readMiscReg(MISCREG_APIAKeyLo_EL1);
433
434 ExceptionLevel el = currEL(tc);
435 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
436 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
437 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
438 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
439 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
440 bool have_el3 = ArmSystem::haveEL(tc, EL3);
441
442 switch (el)
443 {
444 case EL0:
445 {
446 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
447 enable = IsEL1Regime ? (bool)sc1.enia : (bool)sc2.enia;
448 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
449 (hcr.tge == 0 || hcr.e2h == 0));
450 trapEL3 = have_el3 && scr3.api == 0;
451 break;
452 }
453 case EL1:
454 {
455 enable = sc1.enia;
456 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
457 trapEL3 = have_el3 && scr3.api == 0;
458 break;
459 }
460 case EL2:
461 {
462 enable = sc2.enia;
463 trapEL2 = false;
464 trapEL3 = have_el3 && scr3.api == 0;
465 break;
466 }
467 case EL3:
468 {
469 enable = sc3.enia;
470 trapEL2 = false;
471 trapEL3 = false;
472 break;
473 }
474 default:
475 //unreachable
476 break;
477 }
478 if (!enable)
479 *out = X;
480 else if (trapEL2)
481 return trapPACUse(tc, EL2);
482 else if (trapEL3)
483 return trapPACUse(tc, EL3);
484 else
485 *out = auth(tc, el, X, Y, hi_key, lo_key, false, 0x1);
486
487 return NoFault;
488 }
489
490 Fault
491 ArmISA::authIB(ThreadContext *tc, uint64_t X, uint64_t Y, uint64_t* out)
492 {
493 /*
494 Returns a 64-bit value containing X, but replacing the pointer
495 authentication code field bits with the extension of the address bits.
496 The instruction checks a pointer
497 authentication code in the pointer authentication code field bits of X,
498 using the same algorithm and key as AddPACDA().
499 */
500
501 bool trapEL2;
502 bool trapEL3;
503 bool enable;
504
505 uint64_t hi_key= tc->readMiscReg(MISCREG_APIBKeyHi_EL1);
506 uint64_t lo_key= tc->readMiscReg(MISCREG_APIBKeyLo_EL1);
507
508 ExceptionLevel el = currEL(tc);
509 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
510 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
511 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
512 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
513 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
514 bool have_el3 = ArmSystem::haveEL(tc, EL3);
515
516 switch (el)
517 {
518 case EL0:
519 {
520 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
521 enable = IsEL1Regime ? (bool)sc1.enib : (bool)sc2.enib;
522 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
523 (hcr.tge == 0 || hcr.e2h == 0));
524 trapEL3 = have_el3 && scr3.api == 0;
525 break;
526 }
527 case EL1:
528 {
529 enable = sc1.enib;
530 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
531 trapEL3 = have_el3 && scr3.api == 0;
532 break;
533 }
534 case EL2:
535 {
536 enable = sc2.enib;
537 trapEL2 = false;
538 trapEL3 = have_el3 && scr3.api == 0;
539 break;
540 }
541 case EL3:
542 {
543 enable = sc3.enib;
544 trapEL2 = false;
545 trapEL3 = false;
546 break;
547 }
548 default:
549 //unreachable
550 break;
551 }
552 if (!enable)
553 *out = X;
554 else if (trapEL2)
555 return trapPACUse(tc, EL2);
556 else if (trapEL3)
557 return trapPACUse(tc, EL3);
558 else
559 *out = auth(tc, el, X, Y, hi_key, lo_key, false, 0x2);
560
561 return NoFault;
562 }
563
564
565
566 Fault
567 ArmISA::addPACDA(ThreadContext* tc, uint64_t X, uint64_t Y, uint64_t* out)
568 {
569 bool trapEL2;
570 bool trapEL3;
571 bool enable;
572
573 uint64_t hi_key= tc->readMiscReg(MISCREG_APDAKeyHi_EL1);
574 uint64_t lo_key= tc->readMiscReg(MISCREG_APDAKeyLo_EL1);
575
576 ExceptionLevel el = currEL(tc);
577 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
578 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
579 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
580 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
581 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
582 bool have_el3 = ArmSystem::haveEL(tc, EL3);
583
584 switch (el)
585 {
586 case EL0:
587 {
588 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
589 enable = IsEL1Regime ? (bool)sc1.enda : (bool)sc2.enda;
590 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
591 (hcr.tge == 0 || hcr.e2h == 0));
592 trapEL3 = have_el3 && scr3.api == 0;
593 break;
594 }
595 case EL1:
596 {
597 enable = sc1.enda;
598 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
599 trapEL3 = have_el3 && scr3.api == 0;
600 break;
601 }
602 case EL2:
603 {
604 enable = sc2.enda;
605 trapEL2 = false;
606 trapEL3 = have_el3 && scr3.api == 0;
607 break;
608 }
609 case EL3:
610 {
611 enable = sc3.enda;
612 trapEL2 = false;
613 trapEL3 = false;
614 break;
615 }
616 }
617 if (!enable)
618 *out = X;
619 else if (trapEL2)
620 return trapPACUse(tc, EL2);
621 else if (trapEL3)
622 return trapPACUse(tc, EL3);
623 else
624 *out = addPAC(tc, el, X, Y, hi_key, lo_key, true);
625
626 return NoFault;
627 }
628
629
630 Fault
631 ArmISA::addPACDB(ThreadContext* tc, uint64_t X, uint64_t Y, uint64_t* out)
632 {
633 bool trapEL2;
634 bool trapEL3;
635 bool enable;
636
637 uint64_t hi_key= tc->readMiscReg(MISCREG_APDBKeyHi_EL1);
638 uint64_t lo_key= tc->readMiscReg(MISCREG_APDBKeyLo_EL1);
639
640 ExceptionLevel el = currEL(tc);
641 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
642 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
643 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
644 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
645 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
646 bool have_el3 = ArmSystem::haveEL(tc, EL3);
647
648 switch (el)
649 {
650 case EL0:
651 {
652 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
653 enable = IsEL1Regime ? (bool)sc1.endb : (bool)sc2.endb;
654 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
655 (hcr.tge == 0 || hcr.e2h == 0));
656 trapEL3 = have_el3 && scr3.api == 0;
657 break;
658 }
659 case EL1:
660 enable = sc1.endb;
661 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
662 trapEL3 = have_el3 && scr3.api == 0;
663 break;
664 case EL2:
665 enable = sc2.endb;
666 trapEL2 = false;
667 trapEL3 = have_el3 && scr3.api == 0;
668 break;
669 case EL3:
670 enable = sc3.endb;
671 trapEL2 = false;
672 trapEL3 = false;
673 break;
674 default:
675 // unreachable
676 break;
677 }
678 if (!enable)
679 *out = X;
680 else if (trapEL2)
681 return trapPACUse(tc, EL2);
682 else if (trapEL3)
683 return trapPACUse(tc, EL3);
684 else
685 *out = addPAC(tc, el, X, Y, hi_key, lo_key, true);
686
687 return NoFault;
688 }
689
690
691 Fault
692 ArmISA::addPACGA(ThreadContext * tc, uint64_t X, uint64_t Y, uint64_t* out)
693 {
694 bool trapEL2;
695 bool trapEL3;
696
697 uint64_t hi_key= tc->readMiscReg(MISCREG_APGAKeyHi_EL1);
698 uint64_t lo_key= tc->readMiscReg(MISCREG_APGAKeyLo_EL1);
699
700 ExceptionLevel el = currEL(tc);
701 SCR sc3 = tc->readMiscReg(MISCREG_SCR_EL3);
702 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
703 bool have_el3 = ArmSystem::haveEL(tc, EL3);
704
705 switch (el)
706 {
707 case EL0:
708 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
709 (hcr.tge == '0' || hcr.e2h == 0));
710 trapEL3 = have_el3 && sc3.api == 0;
711 break;
712 case EL1:
713 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
714 trapEL3 = have_el3 && sc3.api == 0;
715 break;
716 case EL2:
717 trapEL2 = false;
718 trapEL3 = have_el3 && sc3.api == 0;
719 break;
720 case EL3:
721 trapEL2 = false;
722 trapEL3 = false;
723 break;
724 default:
725 //unreachable
726 break;
727 }
728 if (trapEL2)
729 return trapPACUse(tc, EL2);
730 else if (trapEL3)
731 return trapPACUse(tc, EL3);
732 else
733 *out = QARMA::computePAC(X, Y, hi_key, lo_key) & 0xFFFFFFFF00000000;
734
735 return NoFault;
736 }
737
738
739 Fault
740 ArmISA::addPACIA(ThreadContext * tc, uint64_t X, uint64_t Y, uint64_t* out){
741 bool trapEL2;
742 bool trapEL3;
743 bool enable;
744
745 uint64_t hi_key= tc->readMiscReg(MISCREG_APIAKeyHi_EL1);
746 uint64_t lo_key= tc->readMiscReg(MISCREG_APIAKeyLo_EL1);
747
748 ExceptionLevel el = currEL(tc);
749 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
750 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
751 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
752 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
753 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
754 bool have_el3 = ArmSystem::haveEL(tc, EL3);
755
756 switch (el)
757 {
758 case EL0:
759 {
760 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
761 enable = IsEL1Regime ? (bool)sc1.enia : (bool)sc2.enia;
762 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
763 (hcr.tge == 0 || hcr.e2h == 0));
764 trapEL3 = have_el3 && scr3.api == 0;
765 break;
766 }
767 case EL1:
768 enable = sc1.enia;
769 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
770 trapEL3 = have_el3 && scr3.api == 0;
771 break;
772 case EL2:
773 enable = sc2.enia;
774 trapEL2 = false;
775 trapEL3 = have_el3 && scr3.api == 0;
776 break;
777 case EL3:
778 enable = sc3.enia;
779 trapEL2 = false;
780 trapEL3 = false;
781 break;
782 default:
783 //unreachable
784 break;
785 }
786 if (!enable)
787 *out = X;
788 else if (trapEL2)
789 return trapPACUse(tc, EL2);
790 else if (trapEL3)
791 return trapPACUse(tc, EL3);
792 else
793 *out = addPAC(tc, el, X, Y, hi_key, lo_key, false);
794
795 return NoFault;
796 }
797
798 Fault
799 ArmISA::addPACIB(ThreadContext* tc, uint64_t X, uint64_t Y, uint64_t* out){
800 bool trapEL2;
801 bool trapEL3;
802 bool enable;
803
804 uint64_t hi_key= tc->readMiscReg(MISCREG_APIBKeyHi_EL1);
805 uint64_t lo_key= tc->readMiscReg(MISCREG_APIBKeyLo_EL1);
806
807 ExceptionLevel el = currEL(tc);
808 SCTLR sc1 = tc->readMiscReg(MISCREG_SCTLR_EL1);
809 SCTLR sc2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
810 SCTLR sc3 = tc->readMiscReg(MISCREG_SCTLR_EL3);
811 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
812 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
813 bool have_el3 = ArmSystem::haveEL(tc, EL3);
814
815 switch (el)
816 {
817 case EL0:
818 {
819 bool IsEL1Regime = s1TranslationRegime(tc, el) == EL1;
820 enable = IsEL1Regime ? (bool)sc1.enib : (bool)sc2.enib;
821 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
822 (hcr.tge == 0 || hcr.e2h == 0));
823 trapEL3 = have_el3 && scr3.api == 0;
824 break;
825 }
826 case EL1:
827 enable = sc1.enib;
828 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
829 trapEL3 = have_el3 && scr3.api == 0;
830 break;
831 case EL2:
832 enable = sc2.enib;
833 trapEL2 = false;
834 trapEL3 = have_el3 && scr3.api == 0;
835 break;
836 case EL3:
837 enable = sc3.enib;
838 trapEL2 = false;
839 trapEL3 = false;
840 break;
841 default:
842 // Unnaccessible
843 break;
844 }
845
846 if (!enable)
847 *out = X;
848 else if (trapEL2)
849 return trapPACUse(tc, EL2);
850 else if (trapEL3)
851 return trapPACUse(tc, EL3);
852 else
853 *out = addPAC(tc, el, X, Y, hi_key, lo_key, false);
854
855 return NoFault;
856 }
857
858
859
860 Fault
861 ArmISA::stripPAC(ThreadContext* tc, uint64_t A, bool data, uint64_t* out){
862 bool trapEL2;
863 bool trapEL3;
864
865 uint64_t ptr;
866
867 ExceptionLevel el = currEL(tc);
868
869 bool tbi = calculateTBI(tc, el, A, data);
870 bool selbit = (bool) bits(A, 55);
871 int bottom_PAC_bit = calculateBottomPACBit(tc, el, selbit);
872
873 int top_bit = tbi ? 55 : 63;
874 uint32_t nbits = (top_bit+1) - bottom_PAC_bit;
875 uint64_t pacbits = ((uint64_t)0x1 << nbits) -1; // 2^n -1;
876 uint64_t mask = pacbits << bottom_PAC_bit; // creates mask
877
878
879 if (selbit) {
880 ptr = A | mask;
881 } else {
882 ptr = A & ~mask;
883 }
884
885 SCR scr3 = tc->readMiscReg(MISCREG_SCR_EL3);
886 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
887 bool have_el3 = ArmSystem::haveEL(tc, EL3);
888
889 switch (el)
890 {
891 case EL0:
892 trapEL2 = (EL2Enabled(tc) && hcr.api == 0 &&
893 (hcr.tge == 0 || hcr.e2h == 0));
894 trapEL3 = have_el3 && scr3.api == 0;
895 break;
896 case EL1:
897 trapEL2 = EL2Enabled(tc) && hcr.api == 0;
898 trapEL3 = have_el3 && scr3.api == 0;
899 break;
900 case EL2:
901 trapEL2 = false;
902 trapEL3 = have_el3 && scr3.api == 0;
903 break;
904 case EL3:
905 trapEL2 = false;
906 trapEL3 = false;
907 break;
908 default:
909 // Unnaccessible
910 break;
911 }
912 if (trapEL2)
913 return trapPACUse(tc, EL2);
914 else if (trapEL3)
915 return trapPACUse(tc, EL3);
916 else
917 *out = ptr;
918
919 return NoFault;
920 }
921