xref: /aosp_15_r20/trusty/kernel/app/pactest/pactest.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2022, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker  *
12*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker  *
15*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker  */
23*344aa361SAndroid Build Coastguard Worker 
24*344aa361SAndroid Build Coastguard Worker /*
25*344aa361SAndroid Build Coastguard Worker  * Tests for ARM64 FEAT_Puth (Pointer Authentication Codes)
26*344aa361SAndroid Build Coastguard Worker  * This is a CPU feature at ARM-A v8.3
27*344aa361SAndroid Build Coastguard Worker  * Since this is an ARM64 feature, this should not be built for other arches.
28*344aa361SAndroid Build Coastguard Worker  */
29*344aa361SAndroid Build Coastguard Worker #ifndef ARCH_ARM64
30*344aa361SAndroid Build Coastguard Worker #error PAC is an ARM64 feature
31*344aa361SAndroid Build Coastguard Worker #endif
32*344aa361SAndroid Build Coastguard Worker 
33*344aa361SAndroid Build Coastguard Worker #include "pactest.h"
34*344aa361SAndroid Build Coastguard Worker #include <arch/arm64/sregs.h>
35*344aa361SAndroid Build Coastguard Worker #include <arch/ops.h>
36*344aa361SAndroid Build Coastguard Worker #include <err.h>
37*344aa361SAndroid Build Coastguard Worker #include <lib/unittest/unittest.h>
38*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
39*344aa361SAndroid Build Coastguard Worker #include <platform/random.h>
40*344aa361SAndroid Build Coastguard Worker #include <stdio.h>
41*344aa361SAndroid Build Coastguard Worker 
42*344aa361SAndroid Build Coastguard Worker #define MASK(bits) ((1ull << (bits)) - 1)
43*344aa361SAndroid Build Coastguard Worker 
44*344aa361SAndroid Build Coastguard Worker /*
45*344aa361SAndroid Build Coastguard Worker  * Test addresses for each translation table (TT).
46*344aa361SAndroid Build Coastguard Worker  * Address bit 55 is used to select between page translation tables to use.
47*344aa361SAndroid Build Coastguard Worker  * TT0 is used for user addresses, while TT1 is kernel addresses.
48*344aa361SAndroid Build Coastguard Worker  */
49*344aa361SAndroid Build Coastguard Worker #define PACTEST_TT0_ADDRESS \
50*344aa361SAndroid Build Coastguard Worker     (0x1234567890abcdefu & MASK(MMU_USER_SIZE_SHIFT)) & ~(1ull << 55)
51*344aa361SAndroid Build Coastguard Worker #define PACTEST_TT1_ADDRESS \
52*344aa361SAndroid Build Coastguard Worker     (0x1234567890abcdefu | (~0ull << MMU_KERNEL_SIZE_SHIFT)) | (1ull << 55)
53*344aa361SAndroid Build Coastguard Worker #define PACTEST_MODIFIER 0xfedcba0987654321u
54*344aa361SAndroid Build Coastguard Worker 
55*344aa361SAndroid Build Coastguard Worker /* Helper function for parameterized calling of specific PAC instructions */
pacxx(bool instr_not_data,bool key_a_not_b,uint64_t address,uint64_t modifier)56*344aa361SAndroid Build Coastguard Worker static uint64_t pacxx(bool instr_not_data,
57*344aa361SAndroid Build Coastguard Worker                       bool key_a_not_b,
58*344aa361SAndroid Build Coastguard Worker                       uint64_t address,
59*344aa361SAndroid Build Coastguard Worker                       uint64_t modifier) {
60*344aa361SAndroid Build Coastguard Worker     if (key_a_not_b) {
61*344aa361SAndroid Build Coastguard Worker         if (instr_not_data) {
62*344aa361SAndroid Build Coastguard Worker             __asm__(".arch_extension pauth\n"
63*344aa361SAndroid Build Coastguard Worker                     "\tPACIA %0, %1"
64*344aa361SAndroid Build Coastguard Worker                     : "+r"(address)
65*344aa361SAndroid Build Coastguard Worker                     : "r"(modifier));
66*344aa361SAndroid Build Coastguard Worker         } else {
67*344aa361SAndroid Build Coastguard Worker             __asm__(".arch_extension pauth\n"
68*344aa361SAndroid Build Coastguard Worker                     "\tPACDA %0, %1"
69*344aa361SAndroid Build Coastguard Worker                     : "+r"(address)
70*344aa361SAndroid Build Coastguard Worker                     : "r"(modifier));
71*344aa361SAndroid Build Coastguard Worker         }
72*344aa361SAndroid Build Coastguard Worker     } else {
73*344aa361SAndroid Build Coastguard Worker         if (instr_not_data) {
74*344aa361SAndroid Build Coastguard Worker             __asm__(".arch_extension pauth\n"
75*344aa361SAndroid Build Coastguard Worker                     "\tPACIB %0, %1"
76*344aa361SAndroid Build Coastguard Worker                     : "+r"(address)
77*344aa361SAndroid Build Coastguard Worker                     : "r"(modifier));
78*344aa361SAndroid Build Coastguard Worker         } else {
79*344aa361SAndroid Build Coastguard Worker             __asm__(".arch_extension pauth\n"
80*344aa361SAndroid Build Coastguard Worker                     "\tPACDB %0, %1"
81*344aa361SAndroid Build Coastguard Worker                     : "+r"(address)
82*344aa361SAndroid Build Coastguard Worker                     : "r"(modifier));
83*344aa361SAndroid Build Coastguard Worker         }
84*344aa361SAndroid Build Coastguard Worker     }
85*344aa361SAndroid Build Coastguard Worker 
86*344aa361SAndroid Build Coastguard Worker     return address;
87*344aa361SAndroid Build Coastguard Worker }
88*344aa361SAndroid Build Coastguard Worker 
89*344aa361SAndroid Build Coastguard Worker /*
90*344aa361SAndroid Build Coastguard Worker  * Helper function for parameterized calling of specific PAC instructions.
91*344aa361SAndroid Build Coastguard Worker  * The instructions are implemented in assembly as they may generate exceptions
92*344aa361SAndroid Build Coastguard Worker  * (FEAT_FPAC) which need catching.
93*344aa361SAndroid Build Coastguard Worker  */
autxx(bool instr_not_data,bool key_a_not_b,uint64_t address,uint64_t modifier,uint64_t * result)94*344aa361SAndroid Build Coastguard Worker static int autxx(bool instr_not_data,
95*344aa361SAndroid Build Coastguard Worker                  bool key_a_not_b,
96*344aa361SAndroid Build Coastguard Worker                  uint64_t address,
97*344aa361SAndroid Build Coastguard Worker                  uint64_t modifier,
98*344aa361SAndroid Build Coastguard Worker                  uint64_t* result) {
99*344aa361SAndroid Build Coastguard Worker     if (key_a_not_b) {
100*344aa361SAndroid Build Coastguard Worker         if (instr_not_data) {
101*344aa361SAndroid Build Coastguard Worker             return pactest_autia(address, modifier, result);
102*344aa361SAndroid Build Coastguard Worker         } else {
103*344aa361SAndroid Build Coastguard Worker             return pactest_autda(address, modifier, result);
104*344aa361SAndroid Build Coastguard Worker         }
105*344aa361SAndroid Build Coastguard Worker     } else {
106*344aa361SAndroid Build Coastguard Worker         if (instr_not_data) {
107*344aa361SAndroid Build Coastguard Worker             return pactest_autib(address, modifier, result);
108*344aa361SAndroid Build Coastguard Worker         } else {
109*344aa361SAndroid Build Coastguard Worker             return pactest_autdb(address, modifier, result);
110*344aa361SAndroid Build Coastguard Worker         }
111*344aa361SAndroid Build Coastguard Worker     }
112*344aa361SAndroid Build Coastguard Worker }
113*344aa361SAndroid Build Coastguard Worker 
get_nibble(uint64_t reg,uint8_t shift)114*344aa361SAndroid Build Coastguard Worker static uint8_t get_nibble(uint64_t reg, uint8_t shift) {
115*344aa361SAndroid Build Coastguard Worker     return (reg >> shift) & 0xf;
116*344aa361SAndroid Build Coastguard Worker }
117*344aa361SAndroid Build Coastguard Worker 
get_pac_features(uint8_t nibble)118*344aa361SAndroid Build Coastguard Worker static const char* get_pac_features(uint8_t nibble) {
119*344aa361SAndroid Build Coastguard Worker     switch (nibble) {
120*344aa361SAndroid Build Coastguard Worker     case 0b0001:
121*344aa361SAndroid Build Coastguard Worker         return "PAuth";
122*344aa361SAndroid Build Coastguard Worker     case 0b0010:
123*344aa361SAndroid Build Coastguard Worker         return "PAuth + EPAC";
124*344aa361SAndroid Build Coastguard Worker     case 0b0011:
125*344aa361SAndroid Build Coastguard Worker         return "PAuth + PAuth2";
126*344aa361SAndroid Build Coastguard Worker     case 0b0100:
127*344aa361SAndroid Build Coastguard Worker         return "Pauth + Pauth2 + FPAC";
128*344aa361SAndroid Build Coastguard Worker     case 0b0101:
129*344aa361SAndroid Build Coastguard Worker         return "Pauth + Pauth2 + FPAC + FPACCOMBINE";
130*344aa361SAndroid Build Coastguard Worker     }
131*344aa361SAndroid Build Coastguard Worker 
132*344aa361SAndroid Build Coastguard Worker     return "<unknown>";
133*344aa361SAndroid Build Coastguard Worker }
134*344aa361SAndroid Build Coastguard Worker 
TEST(pactest,pauth_supported)135*344aa361SAndroid Build Coastguard Worker TEST(pactest, pauth_supported) {
136*344aa361SAndroid Build Coastguard Worker     if (!arch_pac_address_supported()) {
137*344aa361SAndroid Build Coastguard Worker         trusty_unittest_printf("[   INFO   ] PAuth is not supported\n");
138*344aa361SAndroid Build Coastguard Worker         GTEST_SKIP();
139*344aa361SAndroid Build Coastguard Worker     }
140*344aa361SAndroid Build Coastguard Worker 
141*344aa361SAndroid Build Coastguard Worker     const uint64_t isar1 = ARM64_READ_SYSREG(id_aa64isar1_el1);
142*344aa361SAndroid Build Coastguard Worker     const uint64_t isar2 = ARM64_READ_SYSREG(id_aa64isar2_el1);
143*344aa361SAndroid Build Coastguard Worker     const uint8_t pacfrac = get_nibble(isar2, ID_AA64ISAR2_EL1_PAC_FRAC_SHIFT);
144*344aa361SAndroid Build Coastguard Worker     const uint8_t apa3 = get_nibble(isar2, ID_AA64ISAR2_EL1_APA3_SHIFT);
145*344aa361SAndroid Build Coastguard Worker     const uint8_t apa = get_nibble(isar1, ID_AA64ISAR1_EL1_APA_SHIFT);
146*344aa361SAndroid Build Coastguard Worker     const uint8_t api = get_nibble(isar1, ID_AA64ISAR1_EL1_API_SHIFT);
147*344aa361SAndroid Build Coastguard Worker     const char *algo = "none", *features = "", *cpf = "";
148*344aa361SAndroid Build Coastguard Worker 
149*344aa361SAndroid Build Coastguard Worker     if (apa3) {
150*344aa361SAndroid Build Coastguard Worker         algo = "QARMA3";
151*344aa361SAndroid Build Coastguard Worker         features = get_pac_features(apa3);
152*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(apa, 0);
153*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(api, 0);
154*344aa361SAndroid Build Coastguard Worker     } else if (apa) {
155*344aa361SAndroid Build Coastguard Worker         algo = "QARMA5";
156*344aa361SAndroid Build Coastguard Worker         features = get_pac_features(apa);
157*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(api, 0);
158*344aa361SAndroid Build Coastguard Worker     } else if (api) {
159*344aa361SAndroid Build Coastguard Worker         algo = "implementation defined";
160*344aa361SAndroid Build Coastguard Worker         features = get_pac_features(api);
161*344aa361SAndroid Build Coastguard Worker     }
162*344aa361SAndroid Build Coastguard Worker 
163*344aa361SAndroid Build Coastguard Worker     if (pacfrac == 1) {
164*344aa361SAndroid Build Coastguard Worker         cpf = ", CONSTPACFIELD";
165*344aa361SAndroid Build Coastguard Worker     } else {
166*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(pacfrac, 0);
167*344aa361SAndroid Build Coastguard Worker     }
168*344aa361SAndroid Build Coastguard Worker 
169*344aa361SAndroid Build Coastguard Worker     /* Log the support in case later trying to debug a test */
170*344aa361SAndroid Build Coastguard Worker     trusty_unittest_printf("[   INFO   ] algo: %s\n", algo);
171*344aa361SAndroid Build Coastguard Worker     trusty_unittest_printf("[   INFO   ] feat: %s%s\n", features, cpf);
172*344aa361SAndroid Build Coastguard Worker test_abort:;
173*344aa361SAndroid Build Coastguard Worker }
174*344aa361SAndroid Build Coastguard Worker 
TEST(pactest,fpac_supported)175*344aa361SAndroid Build Coastguard Worker TEST(pactest, fpac_supported) {
176*344aa361SAndroid Build Coastguard Worker     uint64_t val;
177*344aa361SAndroid Build Coastguard Worker     int rc;
178*344aa361SAndroid Build Coastguard Worker 
179*344aa361SAndroid Build Coastguard Worker     if (!arch_pac_exception_supported()) {
180*344aa361SAndroid Build Coastguard Worker         trusty_unittest_printf("[   INFO   ] FPAC is not supported\n");
181*344aa361SAndroid Build Coastguard Worker         GTEST_SKIP();
182*344aa361SAndroid Build Coastguard Worker     }
183*344aa361SAndroid Build Coastguard Worker 
184*344aa361SAndroid Build Coastguard Worker     rc = pactest_autia(PACTEST_TT0_ADDRESS, PACTEST_MODIFIER, &val);
185*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(rc, ERR_FAULT);
186*344aa361SAndroid Build Coastguard Worker test_abort:;
187*344aa361SAndroid Build Coastguard Worker }
188*344aa361SAndroid Build Coastguard Worker 
TEST(pactest,enabled)189*344aa361SAndroid Build Coastguard Worker TEST(pactest, enabled) {
190*344aa361SAndroid Build Coastguard Worker     const uint64_t sctlr_el1 = ARM64_READ_SYSREG(SCTLR_EL1);
191*344aa361SAndroid Build Coastguard Worker 
192*344aa361SAndroid Build Coastguard Worker     /* Check the expected keys are enabled */
193*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(sctlr_el1 & SCTLR_EL1_ENIA,
194*344aa361SAndroid Build Coastguard Worker               arch_pac_address_supported() ? SCTLR_EL1_ENIA : 0);
195*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(sctlr_el1 & SCTLR_EL1_ENIB, 0);
196*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(sctlr_el1 & SCTLR_EL1_ENDA, 0);
197*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(sctlr_el1 & SCTLR_EL1_ENDB, 0);
198*344aa361SAndroid Build Coastguard Worker }
199*344aa361SAndroid Build Coastguard Worker 
TEST(pactest,keys)200*344aa361SAndroid Build Coastguard Worker TEST(pactest, keys) {
201*344aa361SAndroid Build Coastguard Worker     if (!arch_pac_address_supported()) {
202*344aa361SAndroid Build Coastguard Worker         GTEST_SKIP();
203*344aa361SAndroid Build Coastguard Worker     }
204*344aa361SAndroid Build Coastguard Worker 
205*344aa361SAndroid Build Coastguard Worker     const struct packeys* thread_keys = &get_current_thread()->arch.packeys;
206*344aa361SAndroid Build Coastguard Worker     const uint64_t keyi_lo = ARM64_READ_SYSREG(APIAKeyLo_EL1);
207*344aa361SAndroid Build Coastguard Worker     const uint64_t keyi_hi = ARM64_READ_SYSREG(APIAKeyHi_EL1);
208*344aa361SAndroid Build Coastguard Worker 
209*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(thread_keys->apia[0], keyi_lo);
210*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(thread_keys->apia[1], keyi_hi);
211*344aa361SAndroid Build Coastguard Worker 
212*344aa361SAndroid Build Coastguard Worker     /*
213*344aa361SAndroid Build Coastguard Worker      * Check the keys are neither all 0's of all 1's.
214*344aa361SAndroid Build Coastguard Worker      * While these values are valid, it may indicate incorrect initialisation.
215*344aa361SAndroid Build Coastguard Worker      */
216*344aa361SAndroid Build Coastguard Worker     EXPECT_NE(UINT64_MAX, keyi_lo);
217*344aa361SAndroid Build Coastguard Worker     EXPECT_NE(UINT64_MAX, keyi_hi);
218*344aa361SAndroid Build Coastguard Worker     EXPECT_NE(0, keyi_lo);
219*344aa361SAndroid Build Coastguard Worker     EXPECT_NE(0, keyi_hi);
220*344aa361SAndroid Build Coastguard Worker test_abort:;
221*344aa361SAndroid Build Coastguard Worker }
222*344aa361SAndroid Build Coastguard Worker 
223*344aa361SAndroid Build Coastguard Worker typedef struct {
224*344aa361SAndroid Build Coastguard Worker     bool translation_table;
225*344aa361SAndroid Build Coastguard Worker     bool instr_not_data;
226*344aa361SAndroid Build Coastguard Worker     bool key_a_not_b;
227*344aa361SAndroid Build Coastguard Worker     bool key_enabled;
228*344aa361SAndroid Build Coastguard Worker } pactest_t;
229*344aa361SAndroid Build Coastguard Worker 
get_params(pactest_t * p)230*344aa361SAndroid Build Coastguard Worker static void get_params(pactest_t* p) {
231*344aa361SAndroid Build Coastguard Worker     const bool* const* params = GetParam();
232*344aa361SAndroid Build Coastguard Worker     p->translation_table = *params[0];
233*344aa361SAndroid Build Coastguard Worker     /* Invert for more logical test ordering: AI, AD, BI, BD */
234*344aa361SAndroid Build Coastguard Worker     p->instr_not_data = !*params[1];
235*344aa361SAndroid Build Coastguard Worker     p->key_a_not_b = !*params[2];
236*344aa361SAndroid Build Coastguard Worker }
237*344aa361SAndroid Build Coastguard Worker 
TEST_F_SETUP(pactest)238*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(pactest) {
239*344aa361SAndroid Build Coastguard Worker     uint64_t key_enabled_bit;
240*344aa361SAndroid Build Coastguard Worker 
241*344aa361SAndroid Build Coastguard Worker     get_params(_state);
242*344aa361SAndroid Build Coastguard Worker 
243*344aa361SAndroid Build Coastguard Worker     if (_state->instr_not_data) {
244*344aa361SAndroid Build Coastguard Worker         key_enabled_bit = _state->key_a_not_b ? SCTLR_EL1_ENIA : SCTLR_EL1_ENIB;
245*344aa361SAndroid Build Coastguard Worker     } else {
246*344aa361SAndroid Build Coastguard Worker         key_enabled_bit = _state->key_a_not_b ? SCTLR_EL1_ENDA : SCTLR_EL1_ENDB;
247*344aa361SAndroid Build Coastguard Worker     }
248*344aa361SAndroid Build Coastguard Worker 
249*344aa361SAndroid Build Coastguard Worker     _state->key_enabled = ARM64_READ_SYSREG(SCTLR_EL1) & key_enabled_bit;
250*344aa361SAndroid Build Coastguard Worker }
251*344aa361SAndroid Build Coastguard Worker 
TEST_F_TEARDOWN(pactest)252*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(pactest) {}
253*344aa361SAndroid Build Coastguard Worker 
user_param_to_string(const void * param,char * buf,size_t buf_size)254*344aa361SAndroid Build Coastguard Worker static void user_param_to_string(const void* param,
255*344aa361SAndroid Build Coastguard Worker                                  char* buf,
256*344aa361SAndroid Build Coastguard Worker                                  size_t buf_size) {
257*344aa361SAndroid Build Coastguard Worker     pactest_t p;
258*344aa361SAndroid Build Coastguard Worker     get_params(&p);
259*344aa361SAndroid Build Coastguard Worker 
260*344aa361SAndroid Build Coastguard Worker     snprintf(buf, buf_size, "TT%u/%s%s", p.translation_table ? 1 : 0,
261*344aa361SAndroid Build Coastguard Worker              p.instr_not_data ? "PACI" : "PACD", p.key_a_not_b ? "A" : "B");
262*344aa361SAndroid Build Coastguard Worker }
263*344aa361SAndroid Build Coastguard Worker 
264*344aa361SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(pac,
265*344aa361SAndroid Build Coastguard Worker                          pactest,
266*344aa361SAndroid Build Coastguard Worker                          testing_Combine(testing_Bool(),
267*344aa361SAndroid Build Coastguard Worker                                          testing_Bool(),
268*344aa361SAndroid Build Coastguard Worker                                          testing_Bool()),
269*344aa361SAndroid Build Coastguard Worker                          user_param_to_string);
270*344aa361SAndroid Build Coastguard Worker 
TEST_P(pactest,instr)271*344aa361SAndroid Build Coastguard Worker TEST_P(pactest, instr) {
272*344aa361SAndroid Build Coastguard Worker     if (!arch_pac_address_supported()) {
273*344aa361SAndroid Build Coastguard Worker         GTEST_SKIP();
274*344aa361SAndroid Build Coastguard Worker     }
275*344aa361SAndroid Build Coastguard Worker 
276*344aa361SAndroid Build Coastguard Worker     const uint64_t test_address = _state->translation_table
277*344aa361SAndroid Build Coastguard Worker                                           ? PACTEST_TT1_ADDRESS
278*344aa361SAndroid Build Coastguard Worker                                           : PACTEST_TT0_ADDRESS;
279*344aa361SAndroid Build Coastguard Worker     uint64_t address = test_address;
280*344aa361SAndroid Build Coastguard Worker     int rc;
281*344aa361SAndroid Build Coastguard Worker 
282*344aa361SAndroid Build Coastguard Worker     if (_state->key_enabled) {
283*344aa361SAndroid Build Coastguard Worker         /* Test instruction adds a PAC */
284*344aa361SAndroid Build Coastguard Worker         address = pacxx(_state->instr_not_data, _state->key_a_not_b, address,
285*344aa361SAndroid Build Coastguard Worker                         PACTEST_MODIFIER);
286*344aa361SAndroid Build Coastguard Worker 
287*344aa361SAndroid Build Coastguard Worker         /* Address should have been modified to include PAC */
288*344aa361SAndroid Build Coastguard Worker         EXPECT_NE(test_address, address);
289*344aa361SAndroid Build Coastguard Worker 
290*344aa361SAndroid Build Coastguard Worker         uint64_t pac_address = address;
291*344aa361SAndroid Build Coastguard Worker 
292*344aa361SAndroid Build Coastguard Worker         /* Check AUT returns the original pointer */
293*344aa361SAndroid Build Coastguard Worker         rc = autxx(_state->instr_not_data, _state->key_a_not_b, address,
294*344aa361SAndroid Build Coastguard Worker                    PACTEST_MODIFIER, &address);
295*344aa361SAndroid Build Coastguard Worker 
296*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(rc, 0)
297*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(test_address, address);
298*344aa361SAndroid Build Coastguard Worker 
299*344aa361SAndroid Build Coastguard Worker         /* Check the pointer is invalidated when the modifier is changed */
300*344aa361SAndroid Build Coastguard Worker         rc = autxx(_state->instr_not_data, _state->key_a_not_b, pac_address,
301*344aa361SAndroid Build Coastguard Worker                    ~PACTEST_MODIFIER, &address);
302*344aa361SAndroid Build Coastguard Worker         if (arch_pac_exception_supported()) {
303*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(rc, ERR_FAULT);
304*344aa361SAndroid Build Coastguard Worker         } else {
305*344aa361SAndroid Build Coastguard Worker             /* Address should have been invalidated */
306*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(rc, 0);
307*344aa361SAndroid Build Coastguard Worker             EXPECT_NE(address, test_address);
308*344aa361SAndroid Build Coastguard Worker         }
309*344aa361SAndroid Build Coastguard Worker     } else { /* Key disabled */
310*344aa361SAndroid Build Coastguard Worker 
311*344aa361SAndroid Build Coastguard Worker         address = pacxx(_state->instr_not_data, _state->key_a_not_b, address,
312*344aa361SAndroid Build Coastguard Worker                         PACTEST_MODIFIER);
313*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(test_address, address);
314*344aa361SAndroid Build Coastguard Worker 
315*344aa361SAndroid Build Coastguard Worker         rc = autxx(_state->instr_not_data, _state->key_a_not_b, address,
316*344aa361SAndroid Build Coastguard Worker                    PACTEST_MODIFIER, &address);
317*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(rc, 0)
318*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(test_address, address);
319*344aa361SAndroid Build Coastguard Worker     }
320*344aa361SAndroid Build Coastguard Worker test_abort:;
321*344aa361SAndroid Build Coastguard Worker }
322*344aa361SAndroid Build Coastguard Worker 
TEST_P(pactest,pac_length)323*344aa361SAndroid Build Coastguard Worker TEST_P(pactest, pac_length) {
324*344aa361SAndroid Build Coastguard Worker     if (!arch_pac_address_supported()) {
325*344aa361SAndroid Build Coastguard Worker         GTEST_SKIP();
326*344aa361SAndroid Build Coastguard Worker     }
327*344aa361SAndroid Build Coastguard Worker 
328*344aa361SAndroid Build Coastguard Worker     uint8_t top = 0, bot = 64;
329*344aa361SAndroid Build Coastguard Worker 
330*344aa361SAndroid Build Coastguard Worker     /*
331*344aa361SAndroid Build Coastguard Worker      * Probe a number of times in order to ensure we find the top and bottom
332*344aa361SAndroid Build Coastguard Worker      * bits used.  Odds of missing correct bounds are about P=(1/2)^32.
333*344aa361SAndroid Build Coastguard Worker      */
334*344aa361SAndroid Build Coastguard Worker     for (uint16_t t = 0; t < 32; t++) {
335*344aa361SAndroid Build Coastguard Worker         uint64_t val, orig;
336*344aa361SAndroid Build Coastguard Worker 
337*344aa361SAndroid Build Coastguard Worker         /* Get 64-bit random value */
338*344aa361SAndroid Build Coastguard Worker         platform_random_get_bytes((void*)&orig, sizeof(orig));
339*344aa361SAndroid Build Coastguard Worker 
340*344aa361SAndroid Build Coastguard Worker         /*
341*344aa361SAndroid Build Coastguard Worker          * Select which of T0SZ or T1SZ we should probe.
342*344aa361SAndroid Build Coastguard Worker          * Address bit 55 is used to select between page translation tables
343*344aa361SAndroid Build Coastguard Worker          * to use (e.g. TTBRx and TxSZ, where x is 0 or 1).
344*344aa361SAndroid Build Coastguard Worker          */
345*344aa361SAndroid Build Coastguard Worker         val = orig & ~(1ull << 55);
346*344aa361SAndroid Build Coastguard Worker         if (_state->translation_table) {
347*344aa361SAndroid Build Coastguard Worker             val |= 1ull << 55;
348*344aa361SAndroid Build Coastguard Worker         }
349*344aa361SAndroid Build Coastguard Worker 
350*344aa361SAndroid Build Coastguard Worker         /* Call specific instruction variant */
351*344aa361SAndroid Build Coastguard Worker         val = pacxx(_state->instr_not_data, _state->key_a_not_b, val, 0);
352*344aa361SAndroid Build Coastguard Worker 
353*344aa361SAndroid Build Coastguard Worker         /* Remove un-changed bits and clear bit 55 */
354*344aa361SAndroid Build Coastguard Worker         val ^= orig;
355*344aa361SAndroid Build Coastguard Worker         val &= ~(1ull << 55);
356*344aa361SAndroid Build Coastguard Worker 
357*344aa361SAndroid Build Coastguard Worker         /* Find highest and lowest set bit positions */
358*344aa361SAndroid Build Coastguard Worker         if (val) {
359*344aa361SAndroid Build Coastguard Worker             top = MAX(top, 63 - __builtin_clzll(val));
360*344aa361SAndroid Build Coastguard Worker             bot = MIN(bot, __builtin_ctzll(val));
361*344aa361SAndroid Build Coastguard Worker         }
362*344aa361SAndroid Build Coastguard Worker     }
363*344aa361SAndroid Build Coastguard Worker 
364*344aa361SAndroid Build Coastguard Worker     if (_state->key_enabled) {
365*344aa361SAndroid Build Coastguard Worker         /* If this is not true, the PAC key not be functioning */
366*344aa361SAndroid Build Coastguard Worker         ASSERT_GT(top, bot);
367*344aa361SAndroid Build Coastguard Worker 
368*344aa361SAndroid Build Coastguard Worker         /* Count bit range, except bit 55 if it is in the range */
369*344aa361SAndroid Build Coastguard Worker         int bits = (top + 1) - bot;
370*344aa361SAndroid Build Coastguard Worker         if (bot < 55 && top > 55) {
371*344aa361SAndroid Build Coastguard Worker             bits--;
372*344aa361SAndroid Build Coastguard Worker         }
373*344aa361SAndroid Build Coastguard Worker 
374*344aa361SAndroid Build Coastguard Worker         trusty_unittest_printf("[   INFO   ] PAC bits %" PRIu8 ":%" PRIu8
375*344aa361SAndroid Build Coastguard Worker                                " = %d effective bits\n",
376*344aa361SAndroid Build Coastguard Worker                                top, bot, bits);
377*344aa361SAndroid Build Coastguard Worker     } else {
378*344aa361SAndroid Build Coastguard Worker         trusty_unittest_printf("[   INFO   ] PAC key disabled\n");
379*344aa361SAndroid Build Coastguard Worker 
380*344aa361SAndroid Build Coastguard Worker         ASSERT_EQ(top, 0);
381*344aa361SAndroid Build Coastguard Worker         ASSERT_EQ(bot, 64);
382*344aa361SAndroid Build Coastguard Worker     }
383*344aa361SAndroid Build Coastguard Worker 
384*344aa361SAndroid Build Coastguard Worker test_abort:;
385*344aa361SAndroid Build Coastguard Worker }
386*344aa361SAndroid Build Coastguard Worker 
387*344aa361SAndroid Build Coastguard Worker PORT_TEST(pactest, "com.android.kernel.pactest");
388