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