1 /* This test program is part of GDB, the GNU debugger.
3 Copyright 2021-2022 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Exercise AArch64's Memory Tagging Extension with tagged pointers. */
20 /* This test was based on the documentation for the AArch64 Memory Tagging
21 Extension from the Linux Kernel, found in the sources in
22 Documentation/arm64/memory-tagging-extension.rst. */
30 #include <sys/prctl.h>
32 /* From arch/arm64/include/uapi/asm/hwcap.h */
33 #define HWCAP2_MTE (1 << 18)
35 /* From arch/arm64/include/uapi/asm/mman.h */
38 /* From include/uapi/linux/prctl.h */
39 #define PR_SET_TAGGED_ADDR_CTRL 55
40 #define PR_GET_TAGGED_ADDR_CTRL 56
41 #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
42 #define PR_MTE_TCF_SHIFT 1
43 #define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
44 #define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
45 #define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
46 #define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
47 #define PR_MTE_TAG_SHIFT 3
48 #define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
51 access_memory (unsigned char *tagged_ptr
, unsigned char *untagged_ptr
)
57 main (int argc
, char **argv
)
59 unsigned char *tagged_ptr
;
60 unsigned char *untagged_ptr
;
61 unsigned long page_sz
= sysconf (_SC_PAGESIZE
);
62 unsigned long hwcap2
= getauxval(AT_HWCAP2
);
64 /* Bail out if MTE is not supported. */
65 if (!(hwcap2
& HWCAP2_MTE
))
68 /* Enable the tagged address ABI, synchronous MTE tag check faults and
69 allow all non-zero tags in the randomly generated set. */
70 if (prctl (PR_SET_TAGGED_ADDR_CTRL
,
71 PR_TAGGED_ADDR_ENABLE
| PR_MTE_TCF_SYNC
72 | (0xfffe << PR_MTE_TAG_SHIFT
),
75 perror ("prctl () failed");
79 /* Create a mapping that will have PROT_MTE set. */
80 tagged_ptr
= mmap (0, page_sz
, PROT_READ
| PROT_WRITE
,
81 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
82 if (tagged_ptr
== MAP_FAILED
)
84 perror ("mmap () failed");
88 /* Create another mapping that won't have PROT_MTE set. */
89 untagged_ptr
= mmap (0, page_sz
, PROT_READ
| PROT_WRITE
,
90 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
91 if (untagged_ptr
== MAP_FAILED
)
93 perror ("mmap () failed");
97 /* Enable MTE on the above anonymous mmap. */
98 if (mprotect (tagged_ptr
, page_sz
, PROT_READ
| PROT_WRITE
| PROT_MTE
))
100 perror ("mprotect () failed");
104 access_memory (tagged_ptr
, untagged_ptr
);