1 /* 2 * ARM v8.3-PAuth Operations 3 * 4 * Copyright (c) 2019 Linaro, Ltd. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "internals.h" 23 #include "cpu-features.h" 24 #include "exec/exec-all.h" 25 #include "exec/cpu_ldst.h" 26 #include "exec/helper-proto.h" 27 #include "tcg/tcg-gvec-desc.h" 28 #include "qemu/xxhash.h" 29 30 31 static uint64_t pac_cell_shuffle(uint64_t i) 32 { 33 uint64_t o = 0; 34 35 o |= extract64(i, 52, 4); 36 o |= extract64(i, 24, 4) << 4; 37 o |= extract64(i, 44, 4) << 8; 38 o |= extract64(i, 0, 4) << 12; 39 40 o |= extract64(i, 28, 4) << 16; 41 o |= extract64(i, 48, 4) << 20; 42 o |= extract64(i, 4, 4) << 24; 43 o |= extract64(i, 40, 4) << 28; 44 45 o |= extract64(i, 32, 4) << 32; 46 o |= extract64(i, 12, 4) << 36; 47 o |= extract64(i, 56, 4) << 40; 48 o |= extract64(i, 20, 4) << 44; 49 50 o |= extract64(i, 8, 4) << 48; 51 o |= extract64(i, 36, 4) << 52; 52 o |= extract64(i, 16, 4) << 56; 53 o |= extract64(i, 60, 4) << 60; 54 55 return o; 56 } 57 58 static uint64_t pac_cell_inv_shuffle(uint64_t i) 59 { 60 uint64_t o = 0; 61 62 o |= extract64(i, 12, 4); 63 o |= extract64(i, 24, 4) << 4; 64 o |= extract64(i, 48, 4) << 8; 65 o |= extract64(i, 36, 4) << 12; 66 67 o |= extract64(i, 56, 4) << 16; 68 o |= extract64(i, 44, 4) << 20; 69 o |= extract64(i, 4, 4) << 24; 70 o |= extract64(i, 16, 4) << 28; 71 72 o |= i & MAKE_64BIT_MASK(32, 4); 73 o |= extract64(i, 52, 4) << 36; 74 o |= extract64(i, 28, 4) << 40; 75 o |= extract64(i, 8, 4) << 44; 76 77 o |= extract64(i, 20, 4) << 48; 78 o |= extract64(i, 0, 4) << 52; 79 o |= extract64(i, 40, 4) << 56; 80 o |= i & MAKE_64BIT_MASK(60, 4); 81 82 return o; 83 } 84 85 static uint64_t pac_sub(uint64_t i) 86 { 87 static const uint8_t sub[16] = { 88 0xb, 0x6, 0x8, 0xf, 0xc, 0x0, 0x9, 0xe, 89 0x3, 0x7, 0x4, 0x5, 0xd, 0x2, 0x1, 0xa, 90 }; 91 uint64_t o = 0; 92 int b; 93 94 for (b = 0; b < 64; b += 4) { 95 o |= (uint64_t)sub[(i >> b) & 0xf] << b; 96 } 97 return o; 98 } 99 100 static uint64_t pac_sub1(uint64_t i) 101 { 102 static const uint8_t sub1[16] = { 103 0xa, 0xd, 0xe, 0x6, 0xf, 0x7, 0x3, 0x5, 104 0x9, 0x8, 0x0, 0xc, 0xb, 0x1, 0x2, 0x4, 105 }; 106 uint64_t o = 0; 107 int b; 108 109 for (b = 0; b < 64; b += 4) { 110 o |= (uint64_t)sub1[(i >> b) & 0xf] << b; 111 } 112 return o; 113 } 114 115 static uint64_t pac_inv_sub(uint64_t i) 116 { 117 static const uint8_t inv_sub[16] = { 118 0x5, 0xe, 0xd, 0x8, 0xa, 0xb, 0x1, 0x9, 119 0x2, 0x6, 0xf, 0x0, 0x4, 0xc, 0x7, 0x3, 120 }; 121 uint64_t o = 0; 122 int b; 123 124 for (b = 0; b < 64; b += 4) { 125 o |= (uint64_t)inv_sub[(i >> b) & 0xf] << b; 126 } 127 return o; 128 } 129 130 static int rot_cell(int cell, int n) 131 { 132 /* 4-bit rotate left by n. */ 133 cell |= cell << 4; 134 return extract32(cell, 4 - n, 4); 135 } 136 137 static uint64_t pac_mult(uint64_t i) 138 { 139 uint64_t o = 0; 140 int b; 141 142 for (b = 0; b < 4 * 4; b += 4) { 143 int i0, i4, i8, ic, t0, t1, t2, t3; 144 145 i0 = extract64(i, b, 4); 146 i4 = extract64(i, b + 4 * 4, 4); 147 i8 = extract64(i, b + 8 * 4, 4); 148 ic = extract64(i, b + 12 * 4, 4); 149 150 t0 = rot_cell(i8, 1) ^ rot_cell(i4, 2) ^ rot_cell(i0, 1); 151 t1 = rot_cell(ic, 1) ^ rot_cell(i4, 1) ^ rot_cell(i0, 2); 152 t2 = rot_cell(ic, 2) ^ rot_cell(i8, 1) ^ rot_cell(i0, 1); 153 t3 = rot_cell(ic, 1) ^ rot_cell(i8, 2) ^ rot_cell(i4, 1); 154 155 o |= (uint64_t)t3 << b; 156 o |= (uint64_t)t2 << (b + 4 * 4); 157 o |= (uint64_t)t1 << (b + 8 * 4); 158 o |= (uint64_t)t0 << (b + 12 * 4); 159 } 160 return o; 161 } 162 163 static uint64_t tweak_cell_rot(uint64_t cell) 164 { 165 return (cell >> 1) | (((cell ^ (cell >> 1)) & 1) << 3); 166 } 167 168 static uint64_t tweak_shuffle(uint64_t i) 169 { 170 uint64_t o = 0; 171 172 o |= extract64(i, 16, 4) << 0; 173 o |= extract64(i, 20, 4) << 4; 174 o |= tweak_cell_rot(extract64(i, 24, 4)) << 8; 175 o |= extract64(i, 28, 4) << 12; 176 177 o |= tweak_cell_rot(extract64(i, 44, 4)) << 16; 178 o |= extract64(i, 8, 4) << 20; 179 o |= extract64(i, 12, 4) << 24; 180 o |= tweak_cell_rot(extract64(i, 32, 4)) << 28; 181 182 o |= extract64(i, 48, 4) << 32; 183 o |= extract64(i, 52, 4) << 36; 184 o |= extract64(i, 56, 4) << 40; 185 o |= tweak_cell_rot(extract64(i, 60, 4)) << 44; 186 187 o |= tweak_cell_rot(extract64(i, 0, 4)) << 48; 188 o |= extract64(i, 4, 4) << 52; 189 o |= tweak_cell_rot(extract64(i, 40, 4)) << 56; 190 o |= tweak_cell_rot(extract64(i, 36, 4)) << 60; 191 192 return o; 193 } 194 195 static uint64_t tweak_cell_inv_rot(uint64_t cell) 196 { 197 return ((cell << 1) & 0xf) | ((cell & 1) ^ (cell >> 3)); 198 } 199 200 static uint64_t tweak_inv_shuffle(uint64_t i) 201 { 202 uint64_t o = 0; 203 204 o |= tweak_cell_inv_rot(extract64(i, 48, 4)); 205 o |= extract64(i, 52, 4) << 4; 206 o |= extract64(i, 20, 4) << 8; 207 o |= extract64(i, 24, 4) << 12; 208 209 o |= extract64(i, 0, 4) << 16; 210 o |= extract64(i, 4, 4) << 20; 211 o |= tweak_cell_inv_rot(extract64(i, 8, 4)) << 24; 212 o |= extract64(i, 12, 4) << 28; 213 214 o |= tweak_cell_inv_rot(extract64(i, 28, 4)) << 32; 215 o |= tweak_cell_inv_rot(extract64(i, 60, 4)) << 36; 216 o |= tweak_cell_inv_rot(extract64(i, 56, 4)) << 40; 217 o |= tweak_cell_inv_rot(extract64(i, 16, 4)) << 44; 218 219 o |= extract64(i, 32, 4) << 48; 220 o |= extract64(i, 36, 4) << 52; 221 o |= extract64(i, 40, 4) << 56; 222 o |= tweak_cell_inv_rot(extract64(i, 44, 4)) << 60; 223 224 return o; 225 } 226 227 static uint64_t pauth_computepac_architected(uint64_t data, uint64_t modifier, 228 ARMPACKey key, bool isqarma3) 229 { 230 static const uint64_t RC[5] = { 231 0x0000000000000000ull, 232 0x13198A2E03707344ull, 233 0xA4093822299F31D0ull, 234 0x082EFA98EC4E6C89ull, 235 0x452821E638D01377ull, 236 }; 237 const uint64_t alpha = 0xC0AC29B7C97C50DDull; 238 int iterations = isqarma3 ? 2 : 4; 239 /* 240 * Note that in the ARM pseudocode, key0 contains bits <127:64> 241 * and key1 contains bits <63:0> of the 128-bit key. 242 */ 243 uint64_t key0 = key.hi, key1 = key.lo; 244 uint64_t workingval, runningmod, roundkey, modk0; 245 int i; 246 247 modk0 = (key0 << 63) | ((key0 >> 1) ^ (key0 >> 63)); 248 runningmod = modifier; 249 workingval = data ^ key0; 250 251 for (i = 0; i <= iterations; ++i) { 252 roundkey = key1 ^ runningmod; 253 workingval ^= roundkey; 254 workingval ^= RC[i]; 255 if (i > 0) { 256 workingval = pac_cell_shuffle(workingval); 257 workingval = pac_mult(workingval); 258 } 259 if (isqarma3) { 260 workingval = pac_sub1(workingval); 261 } else { 262 workingval = pac_sub(workingval); 263 } 264 runningmod = tweak_shuffle(runningmod); 265 } 266 roundkey = modk0 ^ runningmod; 267 workingval ^= roundkey; 268 workingval = pac_cell_shuffle(workingval); 269 workingval = pac_mult(workingval); 270 if (isqarma3) { 271 workingval = pac_sub1(workingval); 272 } else { 273 workingval = pac_sub(workingval); 274 } 275 workingval = pac_cell_shuffle(workingval); 276 workingval = pac_mult(workingval); 277 workingval ^= key1; 278 workingval = pac_cell_inv_shuffle(workingval); 279 if (isqarma3) { 280 workingval = pac_sub1(workingval); 281 } else { 282 workingval = pac_inv_sub(workingval); 283 } 284 workingval = pac_mult(workingval); 285 workingval = pac_cell_inv_shuffle(workingval); 286 workingval ^= key0; 287 workingval ^= runningmod; 288 for (i = 0; i <= iterations; ++i) { 289 if (isqarma3) { 290 workingval = pac_sub1(workingval); 291 } else { 292 workingval = pac_inv_sub(workingval); 293 } 294 if (i < iterations) { 295 workingval = pac_mult(workingval); 296 workingval = pac_cell_inv_shuffle(workingval); 297 } 298 runningmod = tweak_inv_shuffle(runningmod); 299 roundkey = key1 ^ runningmod; 300 workingval ^= RC[iterations - i]; 301 workingval ^= roundkey; 302 workingval ^= alpha; 303 } 304 workingval ^= modk0; 305 306 return workingval; 307 } 308 309 static uint64_t pauth_computepac_impdef(uint64_t data, uint64_t modifier, 310 ARMPACKey key) 311 { 312 return qemu_xxhash64_4(data, modifier, key.lo, key.hi); 313 } 314 315 static uint64_t pauth_computepac(CPUARMState *env, uint64_t data, 316 uint64_t modifier, ARMPACKey key) 317 { 318 if (cpu_isar_feature(aa64_pauth_qarma5, env_archcpu(env))) { 319 return pauth_computepac_architected(data, modifier, key, false); 320 } else if (cpu_isar_feature(aa64_pauth_qarma3, env_archcpu(env))) { 321 return pauth_computepac_architected(data, modifier, key, true); 322 } else { 323 return pauth_computepac_impdef(data, modifier, key); 324 } 325 } 326 327 static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier, 328 ARMPACKey *key, bool data) 329 { 330 ARMCPU *cpu = env_archcpu(env); 331 ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env); 332 ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false); 333 ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu); 334 uint64_t pac, ext_ptr, ext, test; 335 int bot_bit, top_bit; 336 337 /* If tagged pointers are in use, use ptr<55>, otherwise ptr<63>. */ 338 if (param.tbi) { 339 ext = sextract64(ptr, 55, 1); 340 } else { 341 ext = sextract64(ptr, 63, 1); 342 } 343 344 /* Build a pointer with known good extension bits. */ 345 top_bit = 64 - 8 * param.tbi; 346 bot_bit = 64 - param.tsz; 347 ext_ptr = deposit64(ptr, bot_bit, top_bit - bot_bit, ext); 348 349 pac = pauth_computepac(env, ext_ptr, modifier, *key); 350 351 /* 352 * Check if the ptr has good extension bits and corrupt the 353 * pointer authentication code if not. 354 */ 355 test = sextract64(ptr, bot_bit, top_bit - bot_bit); 356 if (test != 0 && test != -1) { 357 if (pauth_feature >= PauthFeat_2) { 358 /* No action required */ 359 } else if (pauth_feature == PauthFeat_EPAC) { 360 pac = 0; 361 } else { 362 /* 363 * Note that our top_bit is one greater than the pseudocode's 364 * version, hence "- 2" here. 365 */ 366 pac ^= MAKE_64BIT_MASK(top_bit - 2, 1); 367 } 368 } 369 370 /* 371 * Preserve the determination between upper and lower at bit 55, 372 * and insert pointer authentication code. 373 */ 374 if (pauth_feature >= PauthFeat_2) { 375 pac ^= ptr; 376 } 377 if (param.tbi) { 378 ptr &= ~MAKE_64BIT_MASK(bot_bit, 55 - bot_bit + 1); 379 pac &= MAKE_64BIT_MASK(bot_bit, 54 - bot_bit + 1); 380 } else { 381 ptr &= MAKE_64BIT_MASK(0, bot_bit); 382 pac &= ~(MAKE_64BIT_MASK(55, 1) | MAKE_64BIT_MASK(0, bot_bit)); 383 } 384 ext &= MAKE_64BIT_MASK(55, 1); 385 return pac | ext | ptr; 386 } 387 388 static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param) 389 { 390 uint64_t mask = pauth_ptr_mask(param); 391 392 /* Note that bit 55 is used whether or not the regime has 2 ranges. */ 393 if (extract64(ptr, 55, 1)) { 394 return ptr | mask; 395 } else { 396 return ptr & ~mask; 397 } 398 } 399 400 static G_NORETURN 401 void pauth_fail_exception(CPUARMState *env, bool data, 402 int keynumber, uintptr_t ra) 403 { 404 raise_exception_ra(env, EXCP_UDEF, syn_pacfail(data, keynumber), 405 exception_target_el(env), ra); 406 } 407 408 static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier, 409 ARMPACKey *key, bool data, int keynumber, 410 uintptr_t ra, bool is_combined) 411 { 412 ARMCPU *cpu = env_archcpu(env); 413 ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env); 414 ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false); 415 ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu); 416 int bot_bit, top_bit; 417 uint64_t pac, orig_ptr, cmp_mask; 418 419 orig_ptr = pauth_original_ptr(ptr, param); 420 pac = pauth_computepac(env, orig_ptr, modifier, *key); 421 bot_bit = 64 - param.tsz; 422 top_bit = 64 - 8 * param.tbi; 423 424 cmp_mask = MAKE_64BIT_MASK(bot_bit, top_bit - bot_bit); 425 cmp_mask &= ~MAKE_64BIT_MASK(55, 1); 426 427 if (pauth_feature >= PauthFeat_2) { 428 ARMPauthFeature fault_feature = 429 is_combined ? PauthFeat_FPACCOMBINED : PauthFeat_FPAC; 430 uint64_t result = ptr ^ (pac & cmp_mask); 431 432 if (pauth_feature >= fault_feature 433 && ((result ^ sextract64(result, 55, 1)) & cmp_mask)) { 434 pauth_fail_exception(env, data, keynumber, ra); 435 } 436 return result; 437 } 438 439 if ((pac ^ ptr) & cmp_mask) { 440 int error_code = (keynumber << 1) | (keynumber ^ 1); 441 if (param.tbi) { 442 return deposit64(orig_ptr, 53, 2, error_code); 443 } else { 444 return deposit64(orig_ptr, 61, 2, error_code); 445 } 446 } 447 return orig_ptr; 448 } 449 450 static uint64_t pauth_strip(CPUARMState *env, uint64_t ptr, bool data) 451 { 452 ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env); 453 ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false); 454 455 return pauth_original_ptr(ptr, param); 456 } 457 458 static G_NORETURN 459 void pauth_trap(CPUARMState *env, int target_el, uintptr_t ra) 460 { 461 raise_exception_ra(env, EXCP_UDEF, syn_pactrap(), target_el, ra); 462 } 463 464 static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra) 465 { 466 if (el < 2 && arm_is_el2_enabled(env)) { 467 uint64_t hcr = arm_hcr_el2_eff(env); 468 bool trap = !(hcr & HCR_API); 469 if (el == 0) { 470 /* Trap only applies to EL1&0 regime. */ 471 trap &= (hcr & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE); 472 } 473 /* FIXME: ARMv8.3-NV: HCR_NV trap takes precedence for ERETA[AB]. */ 474 if (trap) { 475 pauth_trap(env, 2, ra); 476 } 477 } 478 if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) { 479 if (!(env->cp15.scr_el3 & SCR_API)) { 480 pauth_trap(env, 3, ra); 481 } 482 } 483 } 484 485 static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit) 486 { 487 return (arm_sctlr(env, el) & bit) != 0; 488 } 489 490 uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y) 491 { 492 int el = arm_current_el(env); 493 if (!pauth_key_enabled(env, el, SCTLR_EnIA)) { 494 return x; 495 } 496 pauth_check_trap(env, el, GETPC()); 497 return pauth_addpac(env, x, y, &env->keys.apia, false); 498 } 499 500 uint64_t HELPER(pacib)(CPUARMState *env, uint64_t x, uint64_t y) 501 { 502 int el = arm_current_el(env); 503 if (!pauth_key_enabled(env, el, SCTLR_EnIB)) { 504 return x; 505 } 506 pauth_check_trap(env, el, GETPC()); 507 return pauth_addpac(env, x, y, &env->keys.apib, false); 508 } 509 510 uint64_t HELPER(pacda)(CPUARMState *env, uint64_t x, uint64_t y) 511 { 512 int el = arm_current_el(env); 513 if (!pauth_key_enabled(env, el, SCTLR_EnDA)) { 514 return x; 515 } 516 pauth_check_trap(env, el, GETPC()); 517 return pauth_addpac(env, x, y, &env->keys.apda, true); 518 } 519 520 uint64_t HELPER(pacdb)(CPUARMState *env, uint64_t x, uint64_t y) 521 { 522 int el = arm_current_el(env); 523 if (!pauth_key_enabled(env, el, SCTLR_EnDB)) { 524 return x; 525 } 526 pauth_check_trap(env, el, GETPC()); 527 return pauth_addpac(env, x, y, &env->keys.apdb, true); 528 } 529 530 uint64_t HELPER(pacga)(CPUARMState *env, uint64_t x, uint64_t y) 531 { 532 uint64_t pac; 533 534 pauth_check_trap(env, arm_current_el(env), GETPC()); 535 pac = pauth_computepac(env, x, y, env->keys.apga); 536 537 return pac & 0xffffffff00000000ull; 538 } 539 540 static uint64_t pauth_autia(CPUARMState *env, uint64_t x, uint64_t y, 541 uintptr_t ra, bool is_combined) 542 { 543 int el = arm_current_el(env); 544 if (!pauth_key_enabled(env, el, SCTLR_EnIA)) { 545 return x; 546 } 547 pauth_check_trap(env, el, ra); 548 return pauth_auth(env, x, y, &env->keys.apia, false, 0, ra, is_combined); 549 } 550 551 uint64_t HELPER(autia)(CPUARMState *env, uint64_t x, uint64_t y) 552 { 553 return pauth_autia(env, x, y, GETPC(), false); 554 } 555 556 uint64_t HELPER(autia_combined)(CPUARMState *env, uint64_t x, uint64_t y) 557 { 558 return pauth_autia(env, x, y, GETPC(), true); 559 } 560 561 static uint64_t pauth_autib(CPUARMState *env, uint64_t x, uint64_t y, 562 uintptr_t ra, bool is_combined) 563 { 564 int el = arm_current_el(env); 565 if (!pauth_key_enabled(env, el, SCTLR_EnIB)) { 566 return x; 567 } 568 pauth_check_trap(env, el, ra); 569 return pauth_auth(env, x, y, &env->keys.apib, false, 1, ra, is_combined); 570 } 571 572 uint64_t HELPER(autib)(CPUARMState *env, uint64_t x, uint64_t y) 573 { 574 return pauth_autib(env, x, y, GETPC(), false); 575 } 576 577 uint64_t HELPER(autib_combined)(CPUARMState *env, uint64_t x, uint64_t y) 578 { 579 return pauth_autib(env, x, y, GETPC(), true); 580 } 581 582 static uint64_t pauth_autda(CPUARMState *env, uint64_t x, uint64_t y, 583 uintptr_t ra, bool is_combined) 584 { 585 int el = arm_current_el(env); 586 if (!pauth_key_enabled(env, el, SCTLR_EnDA)) { 587 return x; 588 } 589 pauth_check_trap(env, el, ra); 590 return pauth_auth(env, x, y, &env->keys.apda, true, 0, ra, is_combined); 591 } 592 593 uint64_t HELPER(autda)(CPUARMState *env, uint64_t x, uint64_t y) 594 { 595 return pauth_autda(env, x, y, GETPC(), false); 596 } 597 598 uint64_t HELPER(autda_combined)(CPUARMState *env, uint64_t x, uint64_t y) 599 { 600 return pauth_autda(env, x, y, GETPC(), true); 601 } 602 603 static uint64_t pauth_autdb(CPUARMState *env, uint64_t x, uint64_t y, 604 uintptr_t ra, bool is_combined) 605 { 606 int el = arm_current_el(env); 607 if (!pauth_key_enabled(env, el, SCTLR_EnDB)) { 608 return x; 609 } 610 pauth_check_trap(env, el, ra); 611 return pauth_auth(env, x, y, &env->keys.apdb, true, 1, ra, is_combined); 612 } 613 614 uint64_t HELPER(autdb)(CPUARMState *env, uint64_t x, uint64_t y) 615 { 616 return pauth_autdb(env, x, y, GETPC(), false); 617 } 618 619 uint64_t HELPER(autdb_combined)(CPUARMState *env, uint64_t x, uint64_t y) 620 { 621 return pauth_autdb(env, x, y, GETPC(), true); 622 } 623 624 uint64_t HELPER(xpaci)(CPUARMState *env, uint64_t a) 625 { 626 return pauth_strip(env, a, false); 627 } 628 629 uint64_t HELPER(xpacd)(CPUARMState *env, uint64_t a) 630 { 631 return pauth_strip(env, a, true); 632 } 633