1139825Simp/*
286230Stmm * __mtag_tag_region test.
386230Stmm *
486230Stmm * Copyright (c) 2021, Arm Limited.
586230Stmm * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
686230Stmm */
786230Stmm
886230Stmm#if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST
986230Stmm#include <stdint.h>
1086230Stmm#include <stdio.h>
1186230Stmm#include <stdlib.h>
1286230Stmm#include <string.h>
1386230Stmm#include "mte.h"
1486230Stmm#include "stringlib.h"
1586230Stmm#include "stringtest.h"
1686230Stmm
1786230Stmmstatic void
1886230Stmmmtag_quoteat (const char *prefix, void *p, int len, int at)
1986230Stmm{
2086230Stmm  /* Print tag, untag and quote the context.  */
2186230Stmm  printf ("location: %p\n", __arm_mte_get_tag ((char *) p + at));
2286230Stmm  untag_buffer (p, len, 1);
2386230Stmm  p = untag_pointer (p);
2486230Stmm  quoteat (prefix, p, len, at);
2586230Stmm}
2686230Stmm
2786230Stmm#define F(x) {#x, x},
2886230Stmm
2986230Stmmstatic const struct fun
3086230Stmm{
3186230Stmm  const char *name;
3286230Stmm  void *(*fun) (void *s, size_t n);
3386230Stmm} funtab[] = {
3486230Stmm// clang-format off
3586230Stmm#if __aarch64__
3686230Stmm  F(__mtag_tag_region)
3786230Stmm#endif
3886230Stmm  {0, 0}
3986230Stmm  // clang-format on
40200922Smarius};
4186230Stmm#undef F
4286230Stmm
43167308Smarius#define A 64
4486230Stmm#define LEN 250000
4586230Stmmstatic unsigned char *sbuf;
4686230Stmm
47200923Smariusstatic void *
4890705Stmmalignup (void *p)
4990705Stmm{
5090705Stmm  return (void *) (((uintptr_t) p + A - 1) & -A);
51200923Smarius}
52200923Smarius
53200923Smariusstatic void
5486230Stmmtest (const struct fun *fun, int salign, int len)
5586230Stmm{
5690705Stmm  unsigned char *src = alignup (sbuf);
5790705Stmm  unsigned char *s = src + salign;
5890705Stmm  void *p;
5986230Stmm  int i;
60185008Smarius
6190705Stmm  if (err_count >= ERR_LIMIT)
6290705Stmm    return;
6390705Stmm  if (len > LEN || salign >= A)
6490705Stmm    abort ();
6590705Stmm  for (i = 0; i < len + 2 * A; i++)
6686230Stmm    src[i] = '?';
67200922Smarius  for (i = 0; i < len; i++)
68200922Smarius    s[i] = 'a';
69200922Smarius
7086230Stmm  src = tag_buffer (src, len + 2 * A, 1);
71171730Smarius  s = src + salign;
7286230Stmm  /* Use different tag.  */
7386230Stmm  s = __arm_mte_increment_tag (s, 1);
7486230Stmm  p = fun->fun (s, len);
7586230Stmm
76200923Smarius  if (p != s)
77200923Smarius    ERR ("%s(%p,..) returned %p\n", fun->name, s, p);
7890705Stmm
79200923Smarius  for (i = 0; i < salign; i++)
80200923Smarius    {
81200923Smarius      if (src[i] != '?')
82200923Smarius	{
83200923Smarius	  ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
84200923Smarius	  mtag_quoteat ("got head", src, len + 2 * A, i);
85200923Smarius	  return;
86200923Smarius	}
87200922Smarius    }
88200922Smarius
89200923Smarius  for (; i < salign + len; i++)
90200923Smarius    {
91200923Smarius      if (s[i - salign] != 'a')
92200922Smarius	{
93200923Smarius	  ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
94200922Smarius	  mtag_quoteat ("got body", src, len + 2 * A, i);
9586230Stmm	  return;
9686230Stmm	}
97200923Smarius    }
98200923Smarius
99200923Smarius  for (; i < len + 2 * A; i++)
100200923Smarius    {
101200923Smarius      if (src[i] != '?')
102200923Smarius	{
103200923Smarius	  ERR ("%s(align %d, %d) failed\n", fun->name, salign, len);
104200923Smarius	  mtag_quoteat ("got tail", src, len + 2 * A, i);
105200923Smarius	  return;
106200923Smarius	}
107200923Smarius    }
108200923Smarius
109200923Smarius  untag_buffer (src, len + 2 * A, 1);
110200923Smarius}
111200923Smarius
112200923Smariusint
113200923Smariusmain ()
114200923Smarius{
115200923Smarius  if (!mte_enabled ())
116200923Smarius    return 0;
117200923Smarius
118200923Smarius  sbuf = mte_mmap (LEN + 3 * A);
119200923Smarius  int r = 0;
120200923Smarius  for (int i = 0; funtab[i].name; i++)
121200923Smarius    {
122200923Smarius      err_count = 0;
123200923Smarius      for (int s = 0; s < A; s += 16)
124200923Smarius	{
125200923Smarius	  int n;
126200923Smarius	  for (n = 0; n < 200; n += 16)
127185008Smarius	    {
128108802Stmm	      test (funtab + i, s, n);
129108802Stmm	    }
130108802Stmm	  for (; n < LEN; n *= 2)
131108802Stmm	    {
132200922Smarius	      test (funtab + i, s, n);
133108802Stmm	    }
134200922Smarius	}
135108802Stmm      printf ("%s %s\n", err_count ? "FAIL" : "PASS", funtab[i].name);
136108802Stmm      if (err_count)
137108802Stmm	r = -1;
138108802Stmm    }
139108802Stmm  return r;
140108802Stmm}
141108802Stmm#else
142108802Stmmint
143108802Stmmmain ()
14486230Stmm{
14586230Stmm  return 0;
14686230Stmm}
14786230Stmm#endif
148200923Smarius