1419b0af8Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2419b0af8Sopenharmony_ci/*
3419b0af8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
4419b0af8Sopenharmony_ci */
5419b0af8Sopenharmony_ci
6419b0af8Sopenharmony_ci#ifndef __POINTER_AUTH_COMMON_H__
7419b0af8Sopenharmony_ci#define __POINTER_AUTH_COMMON_H__
8419b0af8Sopenharmony_ci
9419b0af8Sopenharmony_ci#define is_addr_error(addr) (((addr) >> 48) ^ 0xffff)
10419b0af8Sopenharmony_ci
11419b0af8Sopenharmony_ci#define pauth_sign(type, key, addr, mod) \
12419b0af8Sopenharmony_ci	pauth_common(pac, type, key, addr, mod)
13419b0af8Sopenharmony_ci
14419b0af8Sopenharmony_ci#define pauth_validate(type, key, addr, mod) \
15419b0af8Sopenharmony_ci	pauth_common(aut, type, key, addr, mod)
16419b0af8Sopenharmony_ci
17419b0af8Sopenharmony_ci#define pauth_strip(type, addr) \
18419b0af8Sopenharmony_ci({ \
19419b0af8Sopenharmony_ci	const void *__addr = (addr); \
20419b0af8Sopenharmony_ci\
21419b0af8Sopenharmony_ci	asm ("xpac" #type " %0\n" : "+r" (__addr)); \
22419b0af8Sopenharmony_ci	(typeof (addr))__addr; \
23419b0af8Sopenharmony_ci})
24419b0af8Sopenharmony_ci
25419b0af8Sopenharmony_ci#define pauth_hash(addr, mod) ((unsigned int) (pauth_pacga(addr, mod) >> 32))
26419b0af8Sopenharmony_ci
27419b0af8Sopenharmony_ci#define pauth_common(prefix, type, key, addr, mod) \
28419b0af8Sopenharmony_ci({ \
29419b0af8Sopenharmony_ci	const void *__addr = (addr); \
30419b0af8Sopenharmony_ci	unsigned long __mod = (unsigned long)(mod); \
31419b0af8Sopenharmony_ci\
32419b0af8Sopenharmony_ci	if (__builtin_constant_p(mod) && (__mod == 0)) \
33419b0af8Sopenharmony_ci		asm (#prefix #type "z" #key " %0\n" : "+r" (__addr)); \
34419b0af8Sopenharmony_ci	else \
35419b0af8Sopenharmony_ci		asm (#prefix #type #key " %0, %1\n" : "+r" (__addr) : \
36419b0af8Sopenharmony_ci			"r" (__mod)); \
37419b0af8Sopenharmony_ci	(typeof (addr))(__addr); \
38419b0af8Sopenharmony_ci})
39419b0af8Sopenharmony_ci
40419b0af8Sopenharmony_ci#define pauth_get_raw_data(addr) \
41419b0af8Sopenharmony_ci({ \
42419b0af8Sopenharmony_ci	const void *__addr; \
43419b0af8Sopenharmony_ci	asm ("mov %0, %1\n" : "=&r" (__addr) : \
44419b0af8Sopenharmony_ci		"r" (addr)); \
45419b0af8Sopenharmony_ci	(void *)(__addr); \
46419b0af8Sopenharmony_ci})
47419b0af8Sopenharmony_ci
48419b0af8Sopenharmony_ci#define pauth_sign_function(fun, mod, key) \
49419b0af8Sopenharmony_ci({ \
50419b0af8Sopenharmony_ci	const void *__fun = (fun); \
51419b0af8Sopenharmony_ci	unsigned long __mod = (unsigned long)(mod); \
52419b0af8Sopenharmony_ci	asm ("paci" #key " %0, %1\n" : "+r" (__fun) :   \
53419b0af8Sopenharmony_ci		"r" (__mod));  \
54419b0af8Sopenharmony_ci	(void *)(__fun); \
55419b0af8Sopenharmony_ci})
56419b0af8Sopenharmony_ci
57419b0af8Sopenharmony_ci#define pauth_pacda(addr, mod)	pauth_common(pac, d, a, addr, mod)
58419b0af8Sopenharmony_ci
59419b0af8Sopenharmony_ci#define pauth_pacdb(addr, mod)	pauth_common(pac, d, b, addr, mod)
60419b0af8Sopenharmony_ci
61419b0af8Sopenharmony_ci#define pauth_pacia(addr, mod)	pauth_common(pac, i, a, addr, mod)
62419b0af8Sopenharmony_ci
63419b0af8Sopenharmony_ci#define pauth_pacib(addr, mod)	pauth_common(pac, i, b, addr, mod)
64419b0af8Sopenharmony_ci
65419b0af8Sopenharmony_ci#define pauth_pacga(addr, mod) \
66419b0af8Sopenharmony_ci({ \
67419b0af8Sopenharmony_ci	const void *__addr = (addr); \
68419b0af8Sopenharmony_ci	unsigned long __mod = (unsigned long)(mod); \
69419b0af8Sopenharmony_ci	unsigned long __pac; \
70419b0af8Sopenharmony_ci\
71419b0af8Sopenharmony_ci	asm ("pacga %0, %1, %2\n" : "=r" (__pac) : "r" (__addr), \
72419b0af8Sopenharmony_ci		"r" (__mod)); \
73419b0af8Sopenharmony_ci	__pac; \
74419b0af8Sopenharmony_ci})
75419b0af8Sopenharmony_ci
76419b0af8Sopenharmony_ci#define pauth_autda(addr, mod)	pauth_common(aut, d, a, addr, mod)
77419b0af8Sopenharmony_ci
78419b0af8Sopenharmony_ci#define pauth_autdb(addr, mod)	pauth_common(aut, d, b, addr, mod)
79419b0af8Sopenharmony_ci
80419b0af8Sopenharmony_ci#define pauth_autia(addr, mod)	pauth_common(aut, i, a, addr, mod)
81419b0af8Sopenharmony_ci
82419b0af8Sopenharmony_ci#define pauth_autib(addr, mod)	pauth_common(aut, i, b, addr, mod)
83419b0af8Sopenharmony_ci
84419b0af8Sopenharmony_ci#define pauth_xpacd(addr)		pauth_strip(d, addr)
85419b0af8Sopenharmony_ci
86419b0af8Sopenharmony_ci#define pauth_xpaci(addr)		pauth_strip(i, addr)
87419b0af8Sopenharmony_ci
88419b0af8Sopenharmony_ci#endif /* __POINTER_AUTH_COMMON_H__ */
89