xref: /linux/include/linux/arm-rsi-cmds.h (revision 303bff3637d13f0ecbb280c7cb403470c440a2a6)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2023 ARM Ltd.
4  */
5 
6 #ifndef __LINUX_ARM_RSI_CMDS_H_
7 #define __LINUX_ARM_RSI_CMDS_H_
8 
9 #include <linux/arm-smccc-rsi.h>
10 #include <linux/jump_label.h>
11 #include <linux/string.h>
12 #include <asm/memory.h>
13 
14 #ifdef CONFIG_ARM_RMM_RSI
15 DECLARE_STATIC_KEY_FALSE(rsi_present);
16 
17 void __init arm64_rsi_init(void);
18 
19 bool arm64_rsi_is_protected(phys_addr_t base, size_t size);
20 
is_realm_world(void)21 static inline bool is_realm_world(void)
22 {
23 	return static_branch_unlikely(&rsi_present);
24 }
25 #else
arm64_rsi_init(void)26 static inline void arm64_rsi_init(void) { }
27 
arm64_rsi_is_protected(phys_addr_t base,size_t size)28 static inline bool arm64_rsi_is_protected(phys_addr_t base, size_t size)
29 {
30 	return false;
31 }
32 
is_realm_world(void)33 static inline bool is_realm_world(void) { return false; }
34 #endif
35 
36 #define RSI_GRANULE_SHIFT		12
37 #define RSI_GRANULE_SIZE		(_AC(1, UL) << RSI_GRANULE_SHIFT)
38 
39 enum ripas {
40 	RSI_RIPAS_EMPTY = 0,
41 	RSI_RIPAS_RAM = 1,
42 	RSI_RIPAS_DESTROYED = 2,
43 	RSI_RIPAS_DEV = 3,
44 };
45 
rsi_request_version(unsigned long req,unsigned long * out_lower,unsigned long * out_higher)46 static inline unsigned long rsi_request_version(unsigned long req,
47 						unsigned long *out_lower,
48 						unsigned long *out_higher)
49 {
50 	struct arm_smccc_res res;
51 
52 	arm_smccc_smc(SMC_RSI_ABI_VERSION, req, 0, 0, 0, 0, 0, 0, &res);
53 
54 	if (out_lower)
55 		*out_lower = res.a1;
56 	if (out_higher)
57 		*out_higher = res.a2;
58 
59 	return res.a0;
60 }
61 
rsi_get_realm_config(struct realm_config * cfg)62 static inline unsigned long rsi_get_realm_config(struct realm_config *cfg)
63 {
64 	struct arm_smccc_res res;
65 
66 	arm_smccc_smc(SMC_RSI_REALM_CONFIG, virt_to_phys(cfg),
67 		      0, 0, 0, 0, 0, 0, &res);
68 	return res.a0;
69 }
70 
rsi_ipa_state_get(phys_addr_t start,phys_addr_t end,enum ripas * state,phys_addr_t * top)71 static inline unsigned long rsi_ipa_state_get(phys_addr_t start,
72 					      phys_addr_t end,
73 					      enum ripas *state,
74 					      phys_addr_t *top)
75 {
76 	struct arm_smccc_res res;
77 
78 	arm_smccc_smc(SMC_RSI_IPA_STATE_GET,
79 		      start, end, 0, 0, 0, 0, 0,
80 		      &res);
81 
82 	if (res.a0 == RSI_SUCCESS) {
83 		if (top)
84 			*top = res.a1;
85 		if (state)
86 			*state = res.a2;
87 	}
88 
89 	return res.a0;
90 }
91 
rsi_set_addr_range_state(phys_addr_t start,phys_addr_t end,enum ripas state,unsigned long flags,phys_addr_t * top)92 static inline long rsi_set_addr_range_state(phys_addr_t start,
93 					    phys_addr_t end,
94 					    enum ripas state,
95 					    unsigned long flags,
96 					    phys_addr_t *top)
97 {
98 	struct arm_smccc_res res;
99 
100 	arm_smccc_smc(SMC_RSI_IPA_STATE_SET, start, end, state,
101 		      flags, 0, 0, 0, &res);
102 
103 	if (top)
104 		*top = res.a1;
105 
106 	if (res.a2 != RSI_ACCEPT)
107 		return -EPERM;
108 
109 	return res.a0;
110 }
111 
rsi_set_memory_range(phys_addr_t start,phys_addr_t end,enum ripas state,unsigned long flags)112 static inline int rsi_set_memory_range(phys_addr_t start, phys_addr_t end,
113 				       enum ripas state, unsigned long flags)
114 {
115 	unsigned long ret;
116 	phys_addr_t top;
117 
118 	while (start != end) {
119 		ret = rsi_set_addr_range_state(start, end, state, flags, &top);
120 		if (ret || top < start || top > end)
121 			return -EINVAL;
122 		start = top;
123 	}
124 
125 	return 0;
126 }
127 
128 /*
129  * Convert the specified range to RAM. Do not use this if you rely on the
130  * contents of a page that may already be in RAM state.
131  */
rsi_set_memory_range_protected(phys_addr_t start,phys_addr_t end)132 static inline int rsi_set_memory_range_protected(phys_addr_t start,
133 						 phys_addr_t end)
134 {
135 	return rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
136 				    RSI_CHANGE_DESTROYED);
137 }
138 
139 /*
140  * Convert the specified range to RAM. Do not convert any pages that may have
141  * been DESTROYED, without our permission.
142  */
rsi_set_memory_range_protected_safe(phys_addr_t start,phys_addr_t end)143 static inline int rsi_set_memory_range_protected_safe(phys_addr_t start,
144 						      phys_addr_t end)
145 {
146 	return rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
147 				    RSI_NO_CHANGE_DESTROYED);
148 }
149 
rsi_set_memory_range_shared(phys_addr_t start,phys_addr_t end)150 static inline int rsi_set_memory_range_shared(phys_addr_t start,
151 					      phys_addr_t end)
152 {
153 	return rsi_set_memory_range(start, end, RSI_RIPAS_EMPTY,
154 				    RSI_CHANGE_DESTROYED);
155 }
156 
157 #define RSI_ATTEST_CHALLENGE_MIN_SIZE	32
158 #define RSI_ATTEST_CHALLENGE_MAX_SIZE	64
159 
160 struct rsi_attestation_token_init_args {
161 	unsigned long fid;
162 	u8 challenge[RSI_ATTEST_CHALLENGE_MAX_SIZE];
163 };
164 
165 /**
166  * rsi_attestation_token_init - Initialise the operation to retrieve an
167  * attestation token.
168  *
169  * @challenge:	The challenge data to be used in the attestation token
170  *		generation.
171  * @size:	Size of the challenge data in bytes.
172  *
173  * Initialises the attestation token generation and returns an upper bound
174  * on the attestation token size that can be used to allocate an adequate
175  * buffer. The caller is expected to subsequently call
176  * rsi_attestation_token_continue() to retrieve the attestation token data on
177  * the same CPU.
178  *
179  * Returns:
180  *  On success, returns the upper limit of the attestation report size.
181  *  Otherwise, -EINVAL
182  */
183 static inline long
rsi_attestation_token_init(const u8 * challenge,unsigned long size)184 rsi_attestation_token_init(const u8 *challenge, unsigned long size)
185 {
186 	union {
187 		struct arm_smccc_1_2_regs regs;
188 		struct rsi_attestation_token_init_args init;
189 	} args = { 0 };
190 
191 	if (!challenge || size < RSI_ATTEST_CHALLENGE_MIN_SIZE ||
192 	    size > RSI_ATTEST_CHALLENGE_MAX_SIZE)
193 		return -EINVAL;
194 
195 	args.init.fid = SMC_RSI_ATTESTATION_TOKEN_INIT;
196 	memcpy(args.init.challenge, challenge, size);
197 	arm_smccc_1_2_smc(&args.regs, &args.regs);
198 
199 	if (args.regs.a0 == RSI_SUCCESS)
200 		return args.regs.a1;
201 
202 	return -EINVAL;
203 }
204 
205 /**
206  * rsi_attestation_token_continue - Continue the operation to retrieve an
207  * attestation token.
208  *
209  * @granule: {I}PA of the Granule to which the token will be written.
210  * @offset:  Offset within Granule to start of buffer in bytes.
211  * @size:    The size of the buffer.
212  * @len:     The number of bytes written to the buffer.
213  *
214  * Retrieves up to a RSI_GRANULE_SIZE worth of token data per call. The caller
215  * is expected to call rsi_attestation_token_init() before calling this
216  * function to retrieve the attestation token.
217  *
218  * Return:
219  * * %RSI_SUCCESS     - Attestation token retrieved successfully.
220  * * %RSI_INCOMPLETE  - Token generation is not complete.
221  * * %RSI_ERROR_INPUT - A parameter was not valid.
222  * * %RSI_ERROR_STATE - Attestation not in progress.
223  */
rsi_attestation_token_continue(phys_addr_t granule,unsigned long offset,unsigned long size,unsigned long * len)224 static inline unsigned long rsi_attestation_token_continue(phys_addr_t granule,
225 							   unsigned long offset,
226 							   unsigned long size,
227 							   unsigned long *len)
228 {
229 	struct arm_smccc_res res;
230 
231 	arm_smccc_1_1_invoke(SMC_RSI_ATTESTATION_TOKEN_CONTINUE,
232 			     granule, offset, size, 0, &res);
233 
234 	if (len)
235 		*len = res.a1;
236 	return res.a0;
237 }
238 
239 #endif /* __LINUX_ARM_RSI_CMDS_H_ */
240