1/*
2 * __mtag_tag_region - tag memory
3 *
4 * Copyright (c) 2021-2022, Arm Limited.
5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
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
29ENTRY (__mtag_tag_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	stg	dstin, [dstin]
45	stg	dstin, [tmp]
46	stg	dstin, [dstend, -16]
47L(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.  */
53L(set96):
54	st2g	dstin, [dstin]
55	st2g	dstin, [dstin, 32]
56	st2g	dstin, [dstend, -32]
57	ret
58
59	.p2align 4
60	/* Size is > 96 bytes.  */
61L(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	st2g	dstin, [dstin]
72	st2g	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
78L(zva_loop):
79	add	dst, dst, 64
80	dc	gva, dst
81	subs	count, count, 64
82	b.hi	L(zva_loop)
83	st2g	dstin, [dstend, -64]
84	st2g	dstin, [dstend, -32]
85	ret
86
87L(no_zva):
88	sub	dst, dstin, 32		/* Dst is biased by -32.  */
89	sub	count, count, 64	/* Adjust count for loop.  */
90L(no_zva_loop):
91	st2g	dstin, [dst, 32]
92	st2g	dstin, [dst, 64]!
93	subs	count, count, 64
94	b.hi	L(no_zva_loop)
95	st2g	dstin, [dstend, -64]
96	st2g	dstin, [dstend, -32]
97	ret
98
99END (__mtag_tag_region)
100#endif
101