1/*
2 * __mtag_tag_zero_region test.
3 *
4 * Copyright (c) 2021, Arm Limited.
5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
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
17static void
18mtag_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
29static 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
45static unsigned char *sbuf;
46
47static void *
48alignup (void *p)
49{
50  return (void *) (((uintptr_t) p + A - 1) & -A);
51}
52
53static void
54test (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
112int
113main ()
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
142int
143main ()
144{
145  return 0;
146}
147#endif
148