Skip to content

Commit fcad5b8

Browse files
committed
string: add __mtag_tag_zero_region
Add optimized __mtag_tag_zero_region(dst, len) operation to AOR. It tags the memory according to the tag of the dst pointer then memsets it to 0 and returns dst. It requires MTE support. The memory remains untagged if tagging is not enabled for it. The dst must be 16 bytes aligned and len must be a multiple of 16. Similar to __mtag_tag_region, but uses the zeroing instructions.
1 parent f8d6aec commit fcad5b8

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed

string/Dir.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ string-tests := \
3030
build/bin/test/memrchr \
3131
build/bin/test/memcmp \
3232
build/bin/test/__mtag_tag_region \
33+
build/bin/test/__mtag_tag_zero_region \
3334
build/bin/test/strcpy \
3435
build/bin/test/stpcpy \
3536
build/bin/test/strcmp \
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* __mtag_tag_zero_region - tag memory and fill it with zero bytes
3+
*
4+
* Copyright (c) 2021, Arm Limited.
5+
* SPDX-License-Identifier: MIT
6+
*/
7+
8+
/* Assumptions:
9+
*
10+
* ARMv8-a, AArch64, MTE, LP64 ABI.
11+
*
12+
* Interface contract:
13+
* Address is 16 byte aligned and size is multiple of 16.
14+
* Returns the passed pointer.
15+
* The memory region may remain untagged if tagging is not enabled.
16+
*/
17+
18+
#include "../asmdefs.h"
19+
20+
#if __ARM_FEATURE_MEMORY_TAGGING
21+
22+
#define dstin x0
23+
#define count x1
24+
#define dst x2
25+
#define dstend x3
26+
#define tmp x4
27+
#define zva_val x4
28+
29+
ENTRY (__mtag_tag_zero_region)
30+
PTR_ARG (0)
31+
SIZE_ARG (1)
32+
33+
add dstend, dstin, count
34+
35+
cmp count, 96
36+
b.hi L(set_long)
37+
38+
tbnz count, 6, L(set96)
39+
40+
/* Set 0, 16, 32, or 48 bytes. */
41+
lsr tmp, count, 5
42+
add tmp, dstin, tmp, lsl 4
43+
cbz count, L(end)
44+
stzg dstin, [dstin]
45+
stzg dstin, [tmp]
46+
stzg dstin, [dstend, -16]
47+
L(end):
48+
ret
49+
50+
.p2align 4
51+
/* Set 64..96 bytes. Write 64 bytes from the start and
52+
32 bytes from the end. */
53+
L(set96):
54+
stz2g dstin, [dstin]
55+
stz2g dstin, [dstin, 32]
56+
stz2g dstin, [dstend, -32]
57+
ret
58+
59+
.p2align 4
60+
/* Size is > 96 bytes. */
61+
L(set_long):
62+
cmp count, 160
63+
b.lo L(no_zva)
64+
65+
#ifndef SKIP_ZVA_CHECK
66+
mrs zva_val, dczid_el0
67+
and zva_val, zva_val, 31
68+
cmp zva_val, 4 /* ZVA size is 64 bytes. */
69+
b.ne L(no_zva)
70+
#endif
71+
stz2g dstin, [dstin]
72+
stz2g dstin, [dstin, 32]
73+
bic dst, dstin, 63
74+
sub count, dstend, dst /* Count is now 64 too large. */
75+
sub count, count, 128 /* Adjust count and bias for loop. */
76+
77+
.p2align 4
78+
L(zva_loop):
79+
add dst, dst, 64
80+
dc gzva, dst
81+
subs count, count, 64
82+
b.hi L(zva_loop)
83+
stz2g dstin, [dstend, -64]
84+
stz2g dstin, [dstend, -32]
85+
ret
86+
87+
L(no_zva):
88+
sub dst, dstin, 32 /* Dst is biased by -32. */
89+
sub count, count, 64 /* Adjust count for loop. */
90+
L(no_zva_loop):
91+
stz2g dstin, [dst, 32]
92+
stz2g dstin, [dst, 64]!
93+
subs count, count, 64
94+
b.hi L(no_zva_loop)
95+
stz2g dstin, [dstend, -64]
96+
stz2g dstin, [dstend, -32]
97+
ret
98+
99+
END (__mtag_tag_zero_region)
100+
#endif

string/include/stringlib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ int __strncmp_aarch64_sve (const char *, const char *, size_t);
5656
# endif
5757
# if __ARM_FEATURE_MEMORY_TAGGING
5858
void *__mtag_tag_region (void *, size_t);
59+
void *__mtag_tag_zero_region (void *, size_t);
5960
# endif
6061
#elif __arm__
6162
void *__memcpy_arm (void *__restrict, const void *__restrict, size_t);
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* __mtag_tag_zero_region test.
3+
*
4+
* Copyright (c) 2021, Arm Limited.
5+
* SPDX-License-Identifier: MIT
6+
*/
7+
8+
#if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST
9+
#include <stdint.h>
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <string.h>
13+
#include "mte.h"
14+
#include "stringlib.h"
15+
#include "stringtest.h"
16+
17+
static void
18+
mtag_quoteat (const char *prefix, void *p, int len, int at)
19+
{
20+
/* Print tag, untag and quote the context. */
21+
printf ("location: %p\n", __arm_mte_get_tag ((char *) p + at));
22+
untag_buffer (p, len, 1);
23+
p = untag_pointer (p);
24+
quoteat (prefix, p, len, at);
25+
}
26+
27+
#define F(x) {#x, x},
28+
29+
static const struct fun
30+
{
31+
const char *name;
32+
void *(*fun) (void *s, size_t n);
33+
} funtab[] = {
34+
// clang-format off
35+
#if __aarch64__
36+
F(__mtag_tag_zero_region)
37+
#endif
38+
{0, 0}
39+
// clang-format on
40+
};
41+
#undef F
42+
43+
#define A 64
44+
#define LEN 250000
45+
static unsigned char *sbuf;
46+
47+
static void *
48+
alignup (void *p)
49+
{
50+
return (void *) (((uintptr_t) p + A - 1) & -A);
51+
}
52+
53+
static void
54+
test (const struct fun *fun, int salign, int len)
55+
{
56+
unsigned char *src = alignup (sbuf);
57+
unsigned char *s = src + salign;
58+
void *p;
59+
int i;
60+
61+
if (err_count >= ERR_LIMIT)
62+
return;
63+
if (len > LEN || salign >= A)
64+
abort ();
65+
for (i = 0; i < len + 2 * A; i++)
66+
src[i] = '?';
67+
for (i = 0; i < len; i++)
68+
s[i] = 'a' + i % 23;
69+
70+
src = tag_buffer (src, len + 2 * A, 1);
71+
s = src + salign;
72+
/* Use different tag. */
73+
s = __arm_mte_increment_tag (s, 1);
74+
p = fun->fun (s, len);
75+
76+
if (p != s)
77+
ERR ("%s(%p,..) returned %p\n", fun->name, s, p);
78+
79+
for (i = 0; i < salign; i++)
80+
{
81+
if (src[i] != '?')
82+
{
83+
ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
84+
mtag_quoteat ("got head", src, len + 2 * A, i);
85+
return;
86+
}
87+
}
88+
89+
for (; i < salign + len; i++)
90+
{
91+
if (s[i - salign] != 0)
92+
{
93+
ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
94+
mtag_quoteat ("got body", src, len + 2 * A, i);
95+
return;
96+
}
97+
}
98+
99+
for (; i < len + 2 * A; i++)
100+
{
101+
if (src[i] != '?')
102+
{
103+
ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
104+
mtag_quoteat ("got tail", src, len + 2 * A, i);
105+
return;
106+
}
107+
}
108+
109+
untag_buffer (src, len + 2 * A, 1);
110+
}
111+
112+
int
113+
main ()
114+
{
115+
if (!mte_enabled ())
116+
return 0;
117+
118+
sbuf = mte_mmap (LEN + 3 * A);
119+
int r = 0;
120+
for (int i = 0; funtab[i].name; i++)
121+
{
122+
err_count = 0;
123+
for (int s = 0; s < A; s += 16)
124+
{
125+
int n;
126+
for (n = 0; n < 200; n += 16)
127+
{
128+
test (funtab + i, s, n);
129+
}
130+
for (; n < LEN; n *= 2)
131+
{
132+
test (funtab + i, s, n);
133+
}
134+
}
135+
printf ("%s %s\n", err_count ? "FAIL" : "PASS", funtab[i].name);
136+
if (err_count)
137+
r = -1;
138+
}
139+
return r;
140+
}
141+
#else
142+
int
143+
main ()
144+
{
145+
return 0;
146+
}
147+
#endif

0 commit comments

Comments
 (0)