124657f2cSSteven Price // SPDX-License-Identifier: GPL-2.0
224657f2cSSteven Price /*
324657f2cSSteven Price * Copyright (C) 2023-2026 ARM Ltd.
424657f2cSSteven Price */
524657f2cSSteven Price
624657f2cSSteven Price #include <linux/arm-rmi-cmds.h>
724657f2cSSteven Price #include <linux/cpufeature.h>
824657f2cSSteven Price #include <linux/memblock.h>
9c20b65a0SSteven Price #include <linux/memory.h>
10bc1360caSSteven Price #include <linux/mmzone.h>
1124657f2cSSteven Price #include <linux/slab.h>
1224657f2cSSteven Price
1324657f2cSSteven Price #include <asm/memory.h>
1424657f2cSSteven Price #include <asm/pgtable-hwdef.h>
1524657f2cSSteven Price
1624657f2cSSteven Price /* RMM v2.0 defines RmiFeatureRegister0 to RmiFeatureRegister4. */
1724657f2cSSteven Price static unsigned long rmi_feat_reg_cache[5] __ro_after_init;
18c20b65a0SSteven Price static bool arm64_rmm_active;
19c20b65a0SSteven Price static bool arm64_rmi_is_available;
20c20b65a0SSteven Price
21c20b65a0SSteven Price /* is_rmm_active: Returns if the RMM is ACTIVE */
is_rmm_active(void)22c20b65a0SSteven Price bool is_rmm_active(void)
23c20b65a0SSteven Price {
24c20b65a0SSteven Price return READ_ONCE(arm64_rmm_active);
25c20b65a0SSteven Price }
26c20b65a0SSteven Price EXPORT_SYMBOL_GPL(is_rmm_active);
27c20b65a0SSteven Price
28c20b65a0SSteven Price /*
29c20b65a0SSteven Price * is_rmi_available: Returns if the RMM is ACTIVE and is configured with static
30c20b65a0SSteven Price * carveout for metadata nad L1GPTs.
31c20b65a0SSteven Price */
is_rmi_available(void)32c20b65a0SSteven Price bool is_rmi_available(void)
33c20b65a0SSteven Price {
34c20b65a0SSteven Price return READ_ONCE(arm64_rmi_is_available);
35c20b65a0SSteven Price }
36c20b65a0SSteven Price EXPORT_SYMBOL_GPL(is_rmi_available);
3724657f2cSSteven Price
38bc1360caSSteven Price /*
39bc1360caSSteven Price * rmi_granule_range_delegate() - Delegate granules
40bc1360caSSteven Price * @base: PA of the first granule of the range
41bc1360caSSteven Price * @top: PA of the first granule after the range
42bc1360caSSteven Price * @out_top: PA of the first granule not delegated
43bc1360caSSteven Price *
44bc1360caSSteven Price * Delegate a range of granule for use by the realm world. If the entire range
45bc1360caSSteven Price * was delegated then @out_top == @top, otherwise the function should be called
46bc1360caSSteven Price * again with @base == @out_top.
47bc1360caSSteven Price *
48bc1360caSSteven Price * Return: 0 on success, positive RMI result code or negative Linux error code
49bc1360caSSteven Price */
rmi_granule_range_delegate(unsigned long base,unsigned long top,unsigned long * out_top)50bc1360caSSteven Price static long rmi_granule_range_delegate(unsigned long base,
51bc1360caSSteven Price unsigned long top,
52bc1360caSSteven Price unsigned long *out_top)
53bc1360caSSteven Price {
54bc1360caSSteven Price struct arm_smccc_1_2_regs regs = {
55bc1360caSSteven Price SMC_RMI_GRANULE_RANGE_DELEGATE, base, top
56bc1360caSSteven Price };
57bc1360caSSteven Price long ret = rmi_sro_execute(®s);
58bc1360caSSteven Price
59bc1360caSSteven Price if (ret == RMI_SUCCESS && out_top)
60bc1360caSSteven Price *out_top = regs.a1;
61bc1360caSSteven Price
62bc1360caSSteven Price return ret;
63bc1360caSSteven Price }
64bc1360caSSteven Price
65bc1360caSSteven Price /*
66bc1360caSSteven Price * rmi_delegate_range: Delegate a physically contiguous range.
67bc1360caSSteven Price * We iterate over the range until we hit an error. So we may
68bc1360caSSteven Price * return an error, but with a partially delegated range. The
69bc1360caSSteven Price * caller must always look at the @out_phys to figure out, how
70bc1360caSSteven Price * much progress was made.
71bc1360caSSteven Price *
72bc1360caSSteven Price * @phys: Base of the physical address range
73bc1360caSSteven Price * @size: Size of the physical address range
74bc1360caSSteven Price * @out_phys: Top of the range that was completed. This is always
75bc1360caSSteven Price * valid, irrespective of the result.
76bc1360caSSteven Price *
77bc1360caSSteven Price * Returns RMI_SUCCESS on successful completion. Otherwise, returns
78bc1360caSSteven Price * the Linux error number or the RMI status code as described
79bc1360caSSteven Price * by the RMM spec for RMI_GRANULE_DELEGATE_RANGE or RMI_BLOCKED.
80bc1360caSSteven Price */
rmi_delegate_range(phys_addr_t phys,unsigned long size,phys_addr_t * out_phys)81bc1360caSSteven Price int rmi_delegate_range(phys_addr_t phys,
82bc1360caSSteven Price unsigned long size,
83bc1360caSSteven Price phys_addr_t *out_phys)
84bc1360caSSteven Price {
85bc1360caSSteven Price long ret = 0;
86bc1360caSSteven Price unsigned long top = phys + size;
87bc1360caSSteven Price unsigned long out_top;
88bc1360caSSteven Price
89bc1360caSSteven Price while (phys < top) {
90bc1360caSSteven Price ret = rmi_granule_range_delegate(phys, top, &out_top);
91bc1360caSSteven Price
92bc1360caSSteven Price if (ret != RMI_SUCCESS)
93bc1360caSSteven Price break;
94bc1360caSSteven Price /*
95bc1360caSSteven Price * Buggy RMM ? Let the caller handle the failure.
96bc1360caSSteven Price * We can't know how far the RMM delegated in this
97bc1360caSSteven Price * iteration, so we return the best known good limit.
98bc1360caSSteven Price * RMM can deal with granules already in "undelegated"
99bc1360caSSteven Price * in a given range. So, it is fine for the caller to
100bc1360caSSteven Price * try the range we return.
101bc1360caSSteven Price */
102bc1360caSSteven Price if (WARN_ON(out_top <= phys)) {
103bc1360caSSteven Price ret = -ENXIO;
104bc1360caSSteven Price break;
105bc1360caSSteven Price }
106bc1360caSSteven Price phys = out_top;
107bc1360caSSteven Price }
108bc1360caSSteven Price
109bc1360caSSteven Price if (out_phys)
110bc1360caSSteven Price *out_phys = phys;
111bc1360caSSteven Price
112bc1360caSSteven Price return ret;
113bc1360caSSteven Price }
114bc1360caSSteven Price EXPORT_SYMBOL_GPL(rmi_delegate_range);
115bc1360caSSteven Price
116bc1360caSSteven Price /*
117bc1360caSSteven Price * rmi_granule_range_undelegate() - Undelegate a range of granules
118bc1360caSSteven Price * @base: Base PA of the target range
119bc1360caSSteven Price * @top: Top PA of the target range
120bc1360caSSteven Price * @out_top: Returns the top PA of range whose state is undelegated
121bc1360caSSteven Price *
122bc1360caSSteven Price * Undelegate a range of granules to allow use by the normal world. Will fail
123bc1360caSSteven Price * if the granules are in use by RMM. RMM can ignore granules that are already
124bc1360caSSteven Price * undelegated and thus is safe to be called on a range with a mix of delegated
125bc1360caSSteven Price * and undelegated granules.
126bc1360caSSteven Price *
127bc1360caSSteven Price * Return: 0 on success, positive RMI result code or negative Linux error code
128bc1360caSSteven Price */
rmi_granule_range_undelegate(unsigned long base,unsigned long top,unsigned long * out_top)129bc1360caSSteven Price static long rmi_granule_range_undelegate(unsigned long base,
130bc1360caSSteven Price unsigned long top,
131bc1360caSSteven Price unsigned long *out_top)
132bc1360caSSteven Price {
133bc1360caSSteven Price struct arm_smccc_1_2_regs regs = {
134bc1360caSSteven Price SMC_RMI_GRANULE_RANGE_UNDELEGATE, base, top
135bc1360caSSteven Price };
136bc1360caSSteven Price long ret = rmi_sro_execute(®s);
137bc1360caSSteven Price
138bc1360caSSteven Price if (ret == RMI_SUCCESS && out_top)
139bc1360caSSteven Price *out_top = regs.a1;
140bc1360caSSteven Price
141bc1360caSSteven Price return ret;
142bc1360caSSteven Price }
143bc1360caSSteven Price
rmi_undelegate_range(phys_addr_t phys,unsigned long size)144bc1360caSSteven Price int rmi_undelegate_range(phys_addr_t phys,
145bc1360caSSteven Price unsigned long size)
146bc1360caSSteven Price {
147bc1360caSSteven Price long ret = 0;
148bc1360caSSteven Price unsigned long top = phys + size;
149bc1360caSSteven Price unsigned long out_top;
150bc1360caSSteven Price
151bc1360caSSteven Price while (phys < top) {
152bc1360caSSteven Price ret = rmi_granule_range_undelegate(phys, top, &out_top);
153bc1360caSSteven Price
154bc1360caSSteven Price if (ret != RMI_SUCCESS)
155bc1360caSSteven Price break;
156bc1360caSSteven Price /* Buggy RMM ? Let the caller leak the pages */
157bc1360caSSteven Price if (WARN_ON(out_top <= phys))
158bc1360caSSteven Price return -ENXIO;
159bc1360caSSteven Price phys = out_top;
160bc1360caSSteven Price }
161bc1360caSSteven Price
162bc1360caSSteven Price return ret;
163bc1360caSSteven Price }
164bc1360caSSteven Price EXPORT_SYMBOL_GPL(rmi_undelegate_range);
165bc1360caSSteven Price
166bc1360caSSteven Price /*
167bc1360caSSteven Price * rmi_free_delegated_page: Undelegate and free a page that has been previously
168bc1360caSSteven Price * delegated to the Realm world. If we are unable to undelegate it, the page is
169bc1360caSSteven Price * leaked.
170bc1360caSSteven Price * NOTE: Do not use this helper if the page could be concurrently operated by
171bc1360caSSteven Price * another thread, as it may get leaked if the undelegation fails due to RMI_BLOCKED
172bc1360caSSteven Price */
rmi_free_delegated_page(phys_addr_t phys)173bc1360caSSteven Price int rmi_free_delegated_page(phys_addr_t phys)
174bc1360caSSteven Price {
175bc1360caSSteven Price if (WARN_ON_ONCE(rmi_undelegate_page(phys))) {
176bc1360caSSteven Price /* Undelegate failed: leak the page */
177bc1360caSSteven Price return -EBUSY;
178bc1360caSSteven Price }
179bc1360caSSteven Price
180bc1360caSSteven Price free_page((unsigned long)phys_to_virt(phys));
181bc1360caSSteven Price
182bc1360caSSteven Price return 0;
183bc1360caSSteven Price }
184bc1360caSSteven Price EXPORT_SYMBOL_GPL(rmi_free_delegated_page);
185bc1360caSSteven Price
186bc1360caSSteven Price /*
187bc1360caSSteven Price * Convert the RmiAddrBlockSize to actual size. This is used in RmiDonateReq
188bc1360caSSteven Price * and RmiAddrRangeDesc*.
189bc1360caSSteven Price */
rmi_addr_block_size_to_bytes(unsigned long block_size_fld)190bc1360caSSteven Price static unsigned long rmi_addr_block_size_to_bytes(unsigned long block_size_fld)
191bc1360caSSteven Price {
192bc1360caSSteven Price return BIT(ARM64_HW_PGTABLE_LEVEL_SHIFT(3 - block_size_fld));
193bc1360caSSteven Price }
194bc1360caSSteven Price
195bc1360caSSteven Price /*
196bc1360caSSteven Price * free_addr_range: Free memory described by the address range entry, which may
197bc1360caSSteven Price * be partially consumed by RMM.
198bc1360caSSteven Price *
199bc1360caSSteven Price * @entry: RMI_ADDR_RANGE descriptor
200bc1360caSSteven Price * @consumed_size: Page aligned size consumed by the RMM from the address range.
201bc1360caSSteven Price *
202bc1360caSSteven Price * If the state of the address is DELEGATED, undelegate it back, before freeing.
203bc1360caSSteven Price * Leaks the memory if we cannot undelegate the range.
204bc1360caSSteven Price */
free_addr_range(unsigned long entry,unsigned long consumed_size)205bc1360caSSteven Price static void free_addr_range(unsigned long entry, unsigned long consumed_size)
206bc1360caSSteven Price {
207bc1360caSSteven Price unsigned long phys = RMI_ADDR_RANGE_ADDR(entry);
208bc1360caSSteven Price unsigned long block_size_fld = RMI_ADDR_RANGE_BLOCK_SIZE(entry);
209bc1360caSSteven Price unsigned long count = RMI_ADDR_RANGE_COUNT(entry);
210bc1360caSSteven Price unsigned long state = RMI_ADDR_RANGE_STATE(entry);
211bc1360caSSteven Price unsigned long size = rmi_addr_block_size_to_bytes(block_size_fld) * count;
212bc1360caSSteven Price
213bc1360caSSteven Price WARN_ON(!PAGE_ALIGNED(phys) || !PAGE_ALIGNED(consumed_size));
214bc1360caSSteven Price
215bc1360caSSteven Price /* We shouldn't see this in reclaim path, leak it for now */
216bc1360caSSteven Price if (WARN_ON((state != RMI_OP_MEM_DELEGATED) &&
217bc1360caSSteven Price (state != RMI_OP_MEM_UNDELEGATED)))
218bc1360caSSteven Price return;
219bc1360caSSteven Price
220bc1360caSSteven Price /* Adjust the address and size for partially consumed entry */
221bc1360caSSteven Price phys += consumed_size;
222bc1360caSSteven Price size -= consumed_size;
223bc1360caSSteven Price /*
224bc1360caSSteven Price * Undelegate the pages back if required. If we can't
225bc1360caSSteven Price * change them back, leak the pages.
226bc1360caSSteven Price */
227bc1360caSSteven Price if (state == RMI_OP_MEM_DELEGATED &&
228bc1360caSSteven Price WARN_ON(rmi_undelegate_range(phys, size)))
229bc1360caSSteven Price return;
230bc1360caSSteven Price free_pages_exact(phys_to_virt(phys), size);
231bc1360caSSteven Price }
232bc1360caSSteven Price
rmi_op_continue(unsigned long sro_handle,unsigned long flags,struct arm_smccc_1_2_regs * out_regs)233bc1360caSSteven Price static void rmi_op_continue(unsigned long sro_handle, unsigned long flags,
234bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs)
235bc1360caSSteven Price {
236bc1360caSSteven Price *out_regs = (struct arm_smccc_1_2_regs) {
237bc1360caSSteven Price SMC_RMI_OP_CONTINUE, sro_handle, flags
238bc1360caSSteven Price };
239bc1360caSSteven Price
240bc1360caSSteven Price rmi_smccc_invoke(out_regs);
241bc1360caSSteven Price }
242bc1360caSSteven Price
rmi_op_cancel(unsigned long sro_handle,struct arm_smccc_1_2_regs * out_regs)243bc1360caSSteven Price static void rmi_op_cancel(unsigned long sro_handle,
244bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs)
245bc1360caSSteven Price {
246bc1360caSSteven Price *out_regs = (struct arm_smccc_1_2_regs) {
247bc1360caSSteven Price SMC_RMI_OP_CANCEL, sro_handle
248bc1360caSSteven Price };
249bc1360caSSteven Price
250bc1360caSSteven Price rmi_smccc_invoke(out_regs);
251bc1360caSSteven Price }
252bc1360caSSteven Price
rmi_op_mem_donate(unsigned long sro_handle,unsigned long list_addr,unsigned long list_count,unsigned long flags,struct arm_smccc_1_2_regs * out_regs)253bc1360caSSteven Price static void rmi_op_mem_donate(unsigned long sro_handle, unsigned long list_addr,
254bc1360caSSteven Price unsigned long list_count, unsigned long flags,
255bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs)
256bc1360caSSteven Price {
257bc1360caSSteven Price *out_regs = (struct arm_smccc_1_2_regs) {
258bc1360caSSteven Price SMC_RMI_OP_MEM_DONATE, sro_handle, list_addr, list_count, flags
259bc1360caSSteven Price };
260bc1360caSSteven Price
261bc1360caSSteven Price /*
262bc1360caSSteven Price * The output donated count (a1) is always valid, irrespective
263bc1360caSSteven Price * of the return result. i.e., 0 if there was an error
264bc1360caSSteven Price */
265bc1360caSSteven Price rmi_smccc_invoke(out_regs);
266bc1360caSSteven Price }
267bc1360caSSteven Price
rmi_op_mem_reclaim(unsigned long sro_handle,unsigned long list_addr,unsigned long list_count,struct arm_smccc_1_2_regs * out_regs)268bc1360caSSteven Price static void rmi_op_mem_reclaim(unsigned long sro_handle,
269bc1360caSSteven Price unsigned long list_addr,
270bc1360caSSteven Price unsigned long list_count,
271bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs)
272bc1360caSSteven Price {
273bc1360caSSteven Price *out_regs = (struct arm_smccc_1_2_regs) {
274bc1360caSSteven Price SMC_RMI_OP_MEM_RECLAIM, sro_handle, list_addr, list_count
275bc1360caSSteven Price };
276bc1360caSSteven Price
277bc1360caSSteven Price rmi_smccc_invoke(out_regs);
278bc1360caSSteven Price }
279bc1360caSSteven Price
rmi_sro_ensure_capacity(struct rmi_sro_state * sro,unsigned long count)280bc1360caSSteven Price static int rmi_sro_ensure_capacity(struct rmi_sro_state *sro,
281bc1360caSSteven Price unsigned long count)
282bc1360caSSteven Price {
283bc1360caSSteven Price if (WARN_ON_ONCE(sro->addr_count > RMI_MAX_ADDR_LIST))
284bc1360caSSteven Price return -EOVERFLOW;
285bc1360caSSteven Price
286bc1360caSSteven Price if (count > RMI_MAX_ADDR_LIST - sro->addr_count)
287bc1360caSSteven Price return -ENOSPC;
288bc1360caSSteven Price
289bc1360caSSteven Price return 0;
290bc1360caSSteven Price }
291bc1360caSSteven Price
rmi_sro_donate_contig(struct rmi_sro_state * sro,unsigned long sro_handle,unsigned long donatereq,struct arm_smccc_1_2_regs * out_regs,gfp_t gfp)292bc1360caSSteven Price static int rmi_sro_donate_contig(struct rmi_sro_state *sro,
293bc1360caSSteven Price unsigned long sro_handle,
294bc1360caSSteven Price unsigned long donatereq,
295bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs,
296bc1360caSSteven Price gfp_t gfp)
297bc1360caSSteven Price {
298bc1360caSSteven Price unsigned long block_size_fld = RMI_DONATE_BLOCK_SIZE(donatereq);
299bc1360caSSteven Price unsigned long block_size = rmi_addr_block_size_to_bytes(block_size_fld);
300bc1360caSSteven Price unsigned long count = RMI_DONATE_COUNT(donatereq);
301bc1360caSSteven Price unsigned long state = RMI_DONATE_STATE(donatereq);
302bc1360caSSteven Price unsigned long size = block_size * count;
303bc1360caSSteven Price unsigned long addr_range;
304bc1360caSSteven Price unsigned long donated_size;
305bc1360caSSteven Price int ret;
306bc1360caSSteven Price void *virt;
307bc1360caSSteven Price phys_addr_t phys;
308bc1360caSSteven Price
309bc1360caSSteven Price /*
310bc1360caSSteven Price * The RMM specification requires contiguous allocations are always a
311bc1360caSSteven Price * power of 2
312bc1360caSSteven Price */
313bc1360caSSteven Price if (WARN_ON_ONCE(!is_power_of_2(size)))
314bc1360caSSteven Price return -EINVAL;
315bc1360caSSteven Price /*
316bc1360caSSteven Price * RMM clamps the Maximum value of RmiOpMemDonateReq:count to prevent
317bc1360caSSteven Price * overflow in the RMI_ADDR_RANGE_COUNT field.
318bc1360caSSteven Price */
319bc1360caSSteven Price if (WARN_ON_ONCE(count > FIELD_MAX(RMI_ADDR_RANGE_COUNT_MASK)))
320bc1360caSSteven Price return -EINVAL;
321bc1360caSSteven Price
322bc1360caSSteven Price /*
323bc1360caSSteven Price * We can't allocate blocks more than what the buddy allocator can
324bc1360caSSteven Price * satisfy. TODO: Add support for larger allocations.
325bc1360caSSteven Price */
326bc1360caSSteven Price if (get_order(size) > MAX_PAGE_ORDER)
327bc1360caSSteven Price return -ENOMEM;
328bc1360caSSteven Price
329bc1360caSSteven Price /* Reuse the cached address range if we have one */
330bc1360caSSteven Price for (int i = 0; i < sro->addr_count; i++) {
331bc1360caSSteven Price unsigned long entry = sro->addr_list[i];
332bc1360caSSteven Price
333bc1360caSSteven Price if (RMI_ADDR_RANGE_BLOCK_SIZE(entry) == block_size_fld &&
334bc1360caSSteven Price RMI_ADDR_RANGE_COUNT(entry) == count &&
335bc1360caSSteven Price RMI_ADDR_RANGE_STATE(entry) == state &&
336bc1360caSSteven Price IS_ALIGNED(RMI_ADDR_RANGE_ADDR(entry), size)) {
337bc1360caSSteven Price sro->addr_count--;
338bc1360caSSteven Price swap(sro->addr_list[sro->addr_count],
339bc1360caSSteven Price sro->addr_list[i]);
340bc1360caSSteven Price
341bc1360caSSteven Price goto mem_donate;
342bc1360caSSteven Price }
343bc1360caSSteven Price }
344bc1360caSSteven Price
345bc1360caSSteven Price ret = rmi_sro_ensure_capacity(sro, 1);
346bc1360caSSteven Price /* In the odd case we have filled up the cache, free up the entire list */
347bc1360caSSteven Price if (ret)
348bc1360caSSteven Price rmi_sro_free(sro);
349bc1360caSSteven Price
350bc1360caSSteven Price virt = alloc_pages_exact(size, gfp);
351bc1360caSSteven Price if (!virt)
352bc1360caSSteven Price return -ENOMEM;
353bc1360caSSteven Price phys = virt_to_phys(virt);
354bc1360caSSteven Price
355bc1360caSSteven Price if (state == RMI_OP_MEM_DELEGATED) {
356bc1360caSSteven Price phys_addr_t delegated_phys;
357bc1360caSSteven Price
358bc1360caSSteven Price if (rmi_delegate_range(phys, size, &delegated_phys)) {
359bc1360caSSteven Price if (!rmi_undelegate_range(phys, delegated_phys - phys))
360bc1360caSSteven Price free_pages_exact(virt, size);
361bc1360caSSteven Price return -ENXIO;
362bc1360caSSteven Price }
363bc1360caSSteven Price }
364bc1360caSSteven Price
365bc1360caSSteven Price addr_range = phys & RMI_ADDR_RANGE_ADDR_MASK;
366bc1360caSSteven Price FIELD_MODIFY(RMI_ADDR_RANGE_BLOCK_SIZE_MASK, &addr_range, block_size_fld);
367bc1360caSSteven Price FIELD_MODIFY(RMI_ADDR_RANGE_COUNT_MASK, &addr_range, count);
368bc1360caSSteven Price FIELD_MODIFY(RMI_ADDR_RANGE_STATE_MASK, &addr_range, state);
369bc1360caSSteven Price
370bc1360caSSteven Price sro->addr_list[sro->addr_count] = addr_range;
371bc1360caSSteven Price
372bc1360caSSteven Price mem_donate:
373bc1360caSSteven Price rmi_op_mem_donate(sro_handle,
374bc1360caSSteven Price virt_to_phys(&sro->addr_list[sro->addr_count]), 1,
375bc1360caSSteven Price 0, out_regs);
376bc1360caSSteven Price donated_size = out_regs->a1 << PAGE_SHIFT;
377bc1360caSSteven Price
378bc1360caSSteven Price if (WARN_ON(out_regs->a1 > (size >> PAGE_SHIFT)))
379bc1360caSSteven Price donated_size = size;
380bc1360caSSteven Price
381bc1360caSSteven Price /* All granules consumed by the RMM */
382bc1360caSSteven Price if (donated_size == size)
383bc1360caSSteven Price return 0;
384bc1360caSSteven Price /*
385bc1360caSSteven Price * No granules were consumed by the RMM, cache them. This is a valid
386bc1360caSSteven Price * case, where the RMM was donated memory by another competing thread.
387bc1360caSSteven Price */
388bc1360caSSteven Price if (donated_size == 0) {
389bc1360caSSteven Price sro->addr_count++;
390bc1360caSSteven Price return 0;
391bc1360caSSteven Price }
392bc1360caSSteven Price
393bc1360caSSteven Price /* The granules were partially consumed, reclaim the unused ones. */
394bc1360caSSteven Price free_addr_range(sro->addr_list[sro->addr_count], donated_size);
395bc1360caSSteven Price
396bc1360caSSteven Price return 0;
397bc1360caSSteven Price }
398bc1360caSSteven Price
rmi_sro_donate_noncontig(struct rmi_sro_state * sro,unsigned long sro_handle,unsigned long donatereq,struct arm_smccc_1_2_regs * out_regs,gfp_t gfp)399bc1360caSSteven Price static int rmi_sro_donate_noncontig(struct rmi_sro_state *sro,
400bc1360caSSteven Price unsigned long sro_handle,
401bc1360caSSteven Price unsigned long donatereq,
402bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs,
403bc1360caSSteven Price gfp_t gfp)
404bc1360caSSteven Price {
405bc1360caSSteven Price unsigned long block_size_fld = RMI_DONATE_BLOCK_SIZE(donatereq);
406bc1360caSSteven Price unsigned long block_size = rmi_addr_block_size_to_bytes(block_size_fld);
407bc1360caSSteven Price unsigned long count = RMI_DONATE_COUNT(donatereq);
408bc1360caSSteven Price unsigned long state = RMI_DONATE_STATE(donatereq);
409bc1360caSSteven Price unsigned long found = 0;
410bc1360caSSteven Price unsigned long donated_granules;
411bc1360caSSteven Price unsigned long granules_per_block = block_size >> PAGE_SHIFT;
412bc1360caSSteven Price unsigned long consumed_blocks;
413bc1360caSSteven Price int addr_list_start = sro->addr_count;
414bc1360caSSteven Price int ret, i, src;
415bc1360caSSteven Price
416bc1360caSSteven Price /*
417bc1360caSSteven Price * We can't allocate blocks more than what the buddy allocator can
418bc1360caSSteven Price * satisfy. TODO: Add support for larger allocations.
419bc1360caSSteven Price */
420bc1360caSSteven Price if (get_order(block_size) > MAX_PAGE_ORDER)
421bc1360caSSteven Price return -ENOMEM;
422bc1360caSSteven Price /*
423bc1360caSSteven Price * Maximum value of RmiOpMemDonateReq:count is 2^(PAGE_SHIFT-2) - 1.
424bc1360caSSteven Price * But we further clamp it down by the number of entries we can do
425bc1360caSSteven Price * in one go. The RMM can request the remaining in the next iteration.
426bc1360caSSteven Price */
427bc1360caSSteven Price if (count > RMI_MAX_ADDR_LIST)
428bc1360caSSteven Price count = RMI_MAX_ADDR_LIST;
429bc1360caSSteven Price
430bc1360caSSteven Price /* Gather the suitable entries to the end of the list */
431bc1360caSSteven Price i = 0;
432bc1360caSSteven Price while (i < addr_list_start && found < count) {
433bc1360caSSteven Price unsigned long entry = sro->addr_list[i];
434bc1360caSSteven Price
435bc1360caSSteven Price if (RMI_ADDR_RANGE_BLOCK_SIZE(entry) == block_size_fld &&
436bc1360caSSteven Price RMI_ADDR_RANGE_COUNT(entry) == 1 &&
437bc1360caSSteven Price RMI_ADDR_RANGE_STATE(entry) == state) {
438bc1360caSSteven Price addr_list_start--;
439bc1360caSSteven Price swap(sro->addr_list[addr_list_start],
440bc1360caSSteven Price sro->addr_list[i]);
441bc1360caSSteven Price found++;
442bc1360caSSteven Price /* Continue from the swapped in entry */
443bc1360caSSteven Price continue;
444bc1360caSSteven Price }
445bc1360caSSteven Price /* Skip past the entry */
446bc1360caSSteven Price i++;
447bc1360caSSteven Price }
448bc1360caSSteven Price
449bc1360caSSteven Price ret = rmi_sro_ensure_capacity(sro, count - found);
450bc1360caSSteven Price if (ret) {
451bc1360caSSteven Price /* If we have found some entries, donate them and try again */
452bc1360caSSteven Price if (found)
453bc1360caSSteven Price goto mem_donate;
454bc1360caSSteven Price /* Otherwise free up the list and start again */
455bc1360caSSteven Price rmi_sro_free(sro);
456bc1360caSSteven Price /* Reset the addr_list_start to match sro->addr_count */
457bc1360caSSteven Price addr_list_start = 0;
458bc1360caSSteven Price }
459bc1360caSSteven Price
460bc1360caSSteven Price for (; found < count; found++) {
461bc1360caSSteven Price unsigned long addr_range;
462bc1360caSSteven Price void *virt = alloc_pages_exact(block_size, gfp);
463bc1360caSSteven Price phys_addr_t phys;
464bc1360caSSteven Price
465bc1360caSSteven Price if (!virt)
466bc1360caSSteven Price return -ENOMEM;
467bc1360caSSteven Price
468bc1360caSSteven Price phys = virt_to_phys(virt);
469bc1360caSSteven Price
470bc1360caSSteven Price if (state == RMI_OP_MEM_DELEGATED) {
471bc1360caSSteven Price phys_addr_t delegated_phys;
472bc1360caSSteven Price
473bc1360caSSteven Price if (rmi_delegate_range(phys, block_size, &delegated_phys)) {
474bc1360caSSteven Price if (!rmi_undelegate_range(phys, delegated_phys - phys))
475bc1360caSSteven Price free_pages_exact(virt, block_size);
476bc1360caSSteven Price return -ENXIO;
477bc1360caSSteven Price }
478bc1360caSSteven Price }
479bc1360caSSteven Price
480bc1360caSSteven Price addr_range = phys & RMI_ADDR_RANGE_ADDR_MASK;
481bc1360caSSteven Price FIELD_MODIFY(RMI_ADDR_RANGE_BLOCK_SIZE_MASK, &addr_range, block_size_fld);
482bc1360caSSteven Price FIELD_MODIFY(RMI_ADDR_RANGE_COUNT_MASK, &addr_range, 1);
483bc1360caSSteven Price FIELD_MODIFY(RMI_ADDR_RANGE_STATE_MASK, &addr_range, state);
484bc1360caSSteven Price
485bc1360caSSteven Price sro->addr_list[sro->addr_count++] = addr_range;
486bc1360caSSteven Price }
487bc1360caSSteven Price
488bc1360caSSteven Price mem_donate:
489bc1360caSSteven Price rmi_op_mem_donate(sro_handle,
490bc1360caSSteven Price virt_to_phys(&sro->addr_list[addr_list_start]),
491bc1360caSSteven Price found, 0, out_regs);
492bc1360caSSteven Price
493bc1360caSSteven Price donated_granules = out_regs->a1;
494bc1360caSSteven Price /*
495bc1360caSSteven Price * The RMM shouldn't report more granules than we provided, but clamp
496bc1360caSSteven Price * just in case.
497bc1360caSSteven Price */
498bc1360caSSteven Price if (WARN_ON_ONCE(donated_granules > found * granules_per_block))
499bc1360caSSteven Price donated_granules = found * granules_per_block;
500bc1360caSSteven Price
501bc1360caSSteven Price /*
502bc1360caSSteven Price * The RMM reports the consumed memory in terms of granules, but we
503bc1360caSSteven Price * track in the address lists in block-sized ranges. So divide to get
504bc1360caSSteven Price * the number of (complete) consumed blocks.
505bc1360caSSteven Price */
506bc1360caSSteven Price consumed_blocks = donated_granules / granules_per_block;
507bc1360caSSteven Price if (donated_granules % granules_per_block) {
508bc1360caSSteven Price /*
509bc1360caSSteven Price * A block has been partially consumed, the start is owned by
510bc1360caSSteven Price * the RMM, the tail is owned by the host
511bc1360caSSteven Price */
512bc1360caSSteven Price unsigned long entry =
513bc1360caSSteven Price sro->addr_list[addr_list_start + consumed_blocks];
514bc1360caSSteven Price unsigned long donated_size =
515bc1360caSSteven Price (donated_granules % granules_per_block) << PAGE_SHIFT;
516bc1360caSSteven Price
517bc1360caSSteven Price free_addr_range(entry, donated_size);
518bc1360caSSteven Price /*
519bc1360caSSteven Price * This block is now fully 'consumed' (either held by the RMM or
520bc1360caSSteven Price * freed)
521bc1360caSSteven Price */
522bc1360caSSteven Price consumed_blocks++;
523bc1360caSSteven Price }
524bc1360caSSteven Price
525bc1360caSSteven Price /*
526bc1360caSSteven Price * Keep just the blocks the RMM didn't use in addr_list
527bc1360caSSteven Price * RMM claimed consumed_blocks entries from addr_list_start.
528bc1360caSSteven Price * Move the entries left out at the end i.e.,
529bc1360caSSteven Price * [ addr_list_start + consumed_blocks, addr_list_start + found)
530bc1360caSSteven Price * to the rest of the valid entries and adjust the addr_count to
531bc1360caSSteven Price * reflect the available entries.
532bc1360caSSteven Price */
533bc1360caSSteven Price for (i = 0, src = addr_list_start + consumed_blocks;
534bc1360caSSteven Price i < found - consumed_blocks; i++)
535bc1360caSSteven Price sro->addr_list[addr_list_start + i] = sro->addr_list[src + i];
536bc1360caSSteven Price
537bc1360caSSteven Price sro->addr_count -= consumed_blocks;
538bc1360caSSteven Price
539bc1360caSSteven Price return 0;
540bc1360caSSteven Price }
541bc1360caSSteven Price
rmi_sro_donate(struct rmi_sro_state * sro,unsigned long sro_handle,unsigned long donatereq,struct arm_smccc_1_2_regs * regs,gfp_t gfp)542bc1360caSSteven Price static int rmi_sro_donate(struct rmi_sro_state *sro,
543bc1360caSSteven Price unsigned long sro_handle,
544bc1360caSSteven Price unsigned long donatereq,
545bc1360caSSteven Price struct arm_smccc_1_2_regs *regs,
546bc1360caSSteven Price gfp_t gfp)
547bc1360caSSteven Price {
548bc1360caSSteven Price unsigned long state = RMI_DONATE_STATE(donatereq);
549bc1360caSSteven Price
550bc1360caSSteven Price if (WARN_ON_ONCE(!RMI_DONATE_COUNT(donatereq)))
551bc1360caSSteven Price return -EINVAL;
552bc1360caSSteven Price
553bc1360caSSteven Price /*
554bc1360caSSteven Price * We do not support RMI_OP_MEM_CONDITIONAL yet. This is only required
555bc1360caSSteven Price * for use in RMI_GRANULE_TRACKING_SET, which we don't support yet.
556bc1360caSSteven Price */
557bc1360caSSteven Price if (WARN_ON_ONCE((state != RMI_OP_MEM_DELEGATED) &&
558bc1360caSSteven Price (state != RMI_OP_MEM_UNDELEGATED)))
559bc1360caSSteven Price return -EINVAL;
560bc1360caSSteven Price
561bc1360caSSteven Price if (RMI_DONATE_CONTIG(donatereq) == RMI_OP_MEM_CONTIG)
562bc1360caSSteven Price return rmi_sro_donate_contig(sro, sro_handle, donatereq, regs, gfp);
563bc1360caSSteven Price else
564bc1360caSSteven Price return rmi_sro_donate_noncontig(sro, sro_handle, donatereq, regs, gfp);
565bc1360caSSteven Price }
566bc1360caSSteven Price
rmi_sro_reclaim(struct rmi_sro_state * sro,unsigned long sro_handle,struct arm_smccc_1_2_regs * out_regs)567bc1360caSSteven Price static int rmi_sro_reclaim(struct rmi_sro_state *sro,
568bc1360caSSteven Price unsigned long sro_handle,
569bc1360caSSteven Price struct arm_smccc_1_2_regs *out_regs)
570bc1360caSSteven Price {
571bc1360caSSteven Price unsigned long capacity;
572bc1360caSSteven Price
573bc1360caSSteven Price /*
574bc1360caSSteven Price * We don't do a partial free of the entries. So for now free the
575bc1360caSSteven Price * entire address list as we prepare to reclaim more from the RMM.
576bc1360caSSteven Price */
577bc1360caSSteven Price if (rmi_sro_ensure_capacity(sro, 1))
578bc1360caSSteven Price rmi_sro_free(sro);
579bc1360caSSteven Price
580bc1360caSSteven Price capacity = RMI_MAX_ADDR_LIST - sro->addr_count;
581bc1360caSSteven Price
582bc1360caSSteven Price rmi_op_mem_reclaim(sro_handle,
583bc1360caSSteven Price virt_to_phys(&sro->addr_list[sro->addr_count]),
584bc1360caSSteven Price capacity, out_regs);
585bc1360caSSteven Price
586bc1360caSSteven Price /*
587bc1360caSSteven Price * RMI_OP_MEM_RECLAIM always return RMI_INCOMPLETE, except when the
588bc1360caSSteven Price * input parameters were invalid.
589bc1360caSSteven Price */
590bc1360caSSteven Price if (WARN_ON_ONCE(RMI_RESULT_STATUS(out_regs->a0) != RMI_INCOMPLETE))
591bc1360caSSteven Price return -EINVAL;
592bc1360caSSteven Price if (WARN_ON_ONCE(out_regs->a1 > capacity))
593bc1360caSSteven Price out_regs->a1 = capacity;
594bc1360caSSteven Price
595bc1360caSSteven Price sro->addr_count += out_regs->a1;
596bc1360caSSteven Price
597bc1360caSSteven Price return 0;
598bc1360caSSteven Price }
599bc1360caSSteven Price
rmi_sro_free(struct rmi_sro_state * sro)600bc1360caSSteven Price void rmi_sro_free(struct rmi_sro_state *sro)
601bc1360caSSteven Price {
602bc1360caSSteven Price /* Handle the worse */
603bc1360caSSteven Price if (WARN_ON(sro->addr_count < 0))
604bc1360caSSteven Price return;
605bc1360caSSteven Price
606bc1360caSSteven Price if (WARN_ON(sro->addr_count > RMI_MAX_ADDR_LIST))
607bc1360caSSteven Price sro->addr_count = RMI_MAX_ADDR_LIST;
608bc1360caSSteven Price
609bc1360caSSteven Price for (int i = 0; i < sro->addr_count; i++)
610bc1360caSSteven Price free_addr_range(sro->addr_list[i], 0);
611bc1360caSSteven Price
612bc1360caSSteven Price sro->addr_count = 0;
613bc1360caSSteven Price }
614bc1360caSSteven Price EXPORT_SYMBOL_GPL(rmi_sro_free);
615bc1360caSSteven Price
rmi_sro_memxfer_execute(struct rmi_sro_state * sro,gfp_t gfp)616bc1360caSSteven Price long rmi_sro_memxfer_execute(struct rmi_sro_state *sro, gfp_t gfp)
617bc1360caSSteven Price {
618bc1360caSSteven Price struct arm_smccc_1_2_regs *regs = &sro->regs;
619bc1360caSSteven Price bool cancelled = false;
620bc1360caSSteven Price unsigned long sro_handle;
621bc1360caSSteven Price
622bc1360caSSteven Price rmi_smccc_invoke(regs);
623bc1360caSSteven Price
624bc1360caSSteven Price sro_handle = regs->a1;
625bc1360caSSteven Price while (RMI_RESULT_STATUS(regs->a0) == RMI_INCOMPLETE) {
626bc1360caSSteven Price bool can_cancel = RMI_RESULT_CAN_CANCEL(regs->a0) == RMI_OP_CAN_CANCEL;
627bc1360caSSteven Price int ret = 0;
628bc1360caSSteven Price
629bc1360caSSteven Price switch (RMI_RESULT_MEMREQ(regs->a0)) {
630bc1360caSSteven Price case RMI_OP_MEM_REQ_NONE:
631bc1360caSSteven Price rmi_op_continue(sro_handle, RMI_CONTINUE_KEEP_GOING,
632bc1360caSSteven Price regs);
633bc1360caSSteven Price break;
634bc1360caSSteven Price case RMI_OP_MEM_REQ_DONATE:
635bc1360caSSteven Price ret = rmi_sro_donate(sro, sro_handle, regs->a2, regs,
636bc1360caSSteven Price gfp);
637bc1360caSSteven Price break;
638bc1360caSSteven Price case RMI_OP_MEM_REQ_RECLAIM:
639bc1360caSSteven Price ret = rmi_sro_reclaim(sro, sro_handle, regs);
640bc1360caSSteven Price break;
641bc1360caSSteven Price default:
642bc1360caSSteven Price WARN_ON_ONCE(1);
643bc1360caSSteven Price ret = -ENXIO;
644bc1360caSSteven Price }
645bc1360caSSteven Price
646bc1360caSSteven Price if (ret) {
647bc1360caSSteven Price /*
648bc1360caSSteven Price * All memory donating SROs must be cancellable. So a
649bc1360caSSteven Price * failure in memory allocation shouldn't be an issue.
650bc1360caSSteven Price * However, if we encounter a random failure (e.g.,
651bc1360caSSteven Price * buggy RMM), don't loop forever, just give up.
652bc1360caSSteven Price */
653bc1360caSSteven Price if (WARN_ON_ONCE(!can_cancel))
654bc1360caSSteven Price return ret;
655bc1360caSSteven Price /*
656bc1360caSSteven Price * If we have already cancelled, and came back here due
657bc1360caSSteven Price * to an error in MEMREQ, then there is no point
658bc1360caSSteven Price * in going in loops.
659bc1360caSSteven Price */
660bc1360caSSteven Price if (WARN_ON_ONCE(cancelled))
661bc1360caSSteven Price break;
662bc1360caSSteven Price rmi_op_cancel(sro_handle, regs);
663bc1360caSSteven Price cancelled = true;
664bc1360caSSteven Price
665bc1360caSSteven Price if (WARN_ON_ONCE(RMI_RESULT_STATUS(regs->a0) != RMI_INCOMPLETE))
666bc1360caSSteven Price return ret;
667bc1360caSSteven Price }
668bc1360caSSteven Price }
669bc1360caSSteven Price
670bc1360caSSteven Price if (cancelled)
671bc1360caSSteven Price return -ECANCELED;
672bc1360caSSteven Price
673bc1360caSSteven Price return regs->a0;
674bc1360caSSteven Price }
675bc1360caSSteven Price EXPORT_SYMBOL_GPL(rmi_sro_memxfer_execute);
676bc1360caSSteven Price
677bc1360caSSteven Price /*
678bc1360caSSteven Price * rmi_sro_execute: Execute an RMI command that is stateful but not memory
679bc1360caSSteven Price * transferring. Takes regs, filled with the FIDs and the arguments in place.
680bc1360caSSteven Price *
681bc1360caSSteven Price * Returns :
682bc1360caSSteven Price * -ECANCELED - If the operation had to be aborted and SRO was cancellable.
683bc1360caSSteven Price * Otherwise, returns the result of the RMI command.
684bc1360caSSteven Price */
rmi_sro_execute(struct arm_smccc_1_2_regs * regs)685bc1360caSSteven Price long rmi_sro_execute(struct arm_smccc_1_2_regs *regs)
686bc1360caSSteven Price {
687bc1360caSSteven Price bool cancelled = false;
688bc1360caSSteven Price unsigned long sro_handle;
689bc1360caSSteven Price
690bc1360caSSteven Price rmi_smccc_invoke(regs);
691bc1360caSSteven Price
692bc1360caSSteven Price sro_handle = regs->a1;
693bc1360caSSteven Price while (RMI_RESULT_STATUS(regs->a0) == RMI_INCOMPLETE) {
694bc1360caSSteven Price bool can_cancel = RMI_RESULT_CAN_CANCEL(regs->a0) == RMI_OP_CAN_CANCEL;
695bc1360caSSteven Price
696bc1360caSSteven Price switch (RMI_RESULT_MEMREQ(regs->a0)) {
697bc1360caSSteven Price case RMI_OP_MEM_REQ_NONE:
698bc1360caSSteven Price rmi_op_continue(sro_handle, RMI_CONTINUE_KEEP_GOING,
699bc1360caSSteven Price regs);
700bc1360caSSteven Price break;
701bc1360caSSteven Price default:
702bc1360caSSteven Price WARN_ON_ONCE(1);
703bc1360caSSteven Price if (!can_cancel)
704bc1360caSSteven Price return regs->a0;
705bc1360caSSteven Price /*
706bc1360caSSteven Price * We can't get here normally, but handle this anyway
707bc1360caSSteven Price * for a buggy RMM implementation.
708bc1360caSSteven Price */
709bc1360caSSteven Price if (cancelled)
710bc1360caSSteven Price return -ECANCELED;
711bc1360caSSteven Price rmi_op_cancel(sro_handle, regs);
712bc1360caSSteven Price cancelled = true;
713bc1360caSSteven Price }
714bc1360caSSteven Price }
715bc1360caSSteven Price
716bc1360caSSteven Price if (cancelled)
717bc1360caSSteven Price return -ECANCELED;
718bc1360caSSteven Price
719bc1360caSSteven Price return regs->a0;
720bc1360caSSteven Price }
721bc1360caSSteven Price EXPORT_SYMBOL_GPL(rmi_sro_execute);
722bc1360caSSteven Price
rmi_check_version(void)72324657f2cSSteven Price static int rmi_check_version(void)
72424657f2cSSteven Price {
72524657f2cSSteven Price unsigned short version_major, version_minor;
72624657f2cSSteven Price unsigned long host_version = RMI_ABI_VERSION(RMI_ABI_MAJOR_VERSION,
72724657f2cSSteven Price RMI_ABI_MINOR_VERSION);
72824657f2cSSteven Price unsigned long aa64pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
72924657f2cSSteven Price struct arm_smccc_1_2_regs res = {
73024657f2cSSteven Price SMC_RMI_VERSION, host_version,
73124657f2cSSteven Price };
73224657f2cSSteven Price
73324657f2cSSteven Price /* If RME isn't supported, then RMI can't be */
73424657f2cSSteven Price if (cpuid_feature_extract_unsigned_field(aa64pfr0, ID_AA64PFR0_EL1_RME_SHIFT) == 0)
73524657f2cSSteven Price return -ENXIO;
73624657f2cSSteven Price
73724657f2cSSteven Price if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
73824657f2cSSteven Price return -ENXIO;
73924657f2cSSteven Price
74024657f2cSSteven Price rmi_smccc_invoke(&res);
74124657f2cSSteven Price if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
74224657f2cSSteven Price return -ENXIO;
74324657f2cSSteven Price
74424657f2cSSteven Price version_major = RMI_ABI_VERSION_GET_MAJOR(res.a1);
74524657f2cSSteven Price version_minor = RMI_ABI_VERSION_GET_MINOR(res.a1);
74624657f2cSSteven Price
74724657f2cSSteven Price if (res.a0 != RMI_SUCCESS) {
74824657f2cSSteven Price unsigned short high_version_major, high_version_minor;
74924657f2cSSteven Price
75024657f2cSSteven Price high_version_major = RMI_ABI_VERSION_GET_MAJOR(res.a2);
75124657f2cSSteven Price high_version_minor = RMI_ABI_VERSION_GET_MINOR(res.a2);
75224657f2cSSteven Price
75324657f2cSSteven Price pr_err("Unsupported RMI ABI (v%d.%d - v%d.%d) we want v%d.%d\n",
75424657f2cSSteven Price version_major, version_minor,
75524657f2cSSteven Price high_version_major, high_version_minor,
75624657f2cSSteven Price RMI_ABI_MAJOR_VERSION,
75724657f2cSSteven Price RMI_ABI_MINOR_VERSION);
75824657f2cSSteven Price return -ENXIO;
75924657f2cSSteven Price }
76024657f2cSSteven Price
76124657f2cSSteven Price pr_info("RMI ABI version %d.%d\n", version_major, version_minor);
76224657f2cSSteven Price
76324657f2cSSteven Price return 0;
76424657f2cSSteven Price }
76524657f2cSSteven Price
rmi_read_features(void)76624657f2cSSteven Price static int rmi_read_features(void)
76724657f2cSSteven Price {
76824657f2cSSteven Price /*
76924657f2cSSteven Price * Since we've negotiated a compatible version these feature registers
77024657f2cSSteven Price * should always be available
77124657f2cSSteven Price */
77224657f2cSSteven Price for (int i = 0; i < ARRAY_SIZE(rmi_feat_reg_cache); i++) {
77324657f2cSSteven Price struct arm_smccc_1_2_regs args = {
77424657f2cSSteven Price SMC_RMI_FEATURES, i,
77524657f2cSSteven Price };
77624657f2cSSteven Price
77724657f2cSSteven Price rmi_smccc_invoke(&args);
77824657f2cSSteven Price if (WARN_ON(args.a0 != RMI_SUCCESS))
77924657f2cSSteven Price return -EINVAL;
78024657f2cSSteven Price
78124657f2cSSteven Price rmi_feat_reg_cache[i] = args.a1;
78224657f2cSSteven Price }
78324657f2cSSteven Price
78424657f2cSSteven Price return 0;
78524657f2cSSteven Price }
78624657f2cSSteven Price
rmi_feat_reg(unsigned int index)78724657f2cSSteven Price unsigned long rmi_feat_reg(unsigned int index)
78824657f2cSSteven Price {
78924657f2cSSteven Price if (WARN_ON(index >= ARRAY_SIZE(rmi_feat_reg_cache)))
79024657f2cSSteven Price return 0;
79124657f2cSSteven Price
79224657f2cSSteven Price return rmi_feat_reg_cache[index];
79324657f2cSSteven Price }
79424657f2cSSteven Price EXPORT_SYMBOL_GPL(rmi_feat_reg);
79524657f2cSSteven Price
rmi_rmm_config_set(unsigned long cfg_ptr)796a0382431SSteven Price static int rmi_rmm_config_set(unsigned long cfg_ptr)
797a0382431SSteven Price {
798a0382431SSteven Price struct arm_smccc_1_2_regs regs = {
799a0382431SSteven Price SMC_RMI_RMM_CONFIG_SET, cfg_ptr,
800a0382431SSteven Price };
801a0382431SSteven Price
802a0382431SSteven Price rmi_smccc_invoke(®s);
803a0382431SSteven Price
804a0382431SSteven Price return regs.a0;
805a0382431SSteven Price }
806a0382431SSteven Price
rmi_configure(void)807a0382431SSteven Price static int rmi_configure(void)
808a0382431SSteven Price {
809a0382431SSteven Price unsigned long granule_feature;
810a0382431SSteven Price unsigned long granule_size;
811a0382431SSteven Price int ret;
812a0382431SSteven Price
813a0382431SSteven Price switch (PAGE_SIZE) {
814a0382431SSteven Price case SZ_4K:
815a0382431SSteven Price granule_size = RMI_GRANULE_SIZE_4KB;
816a0382431SSteven Price granule_feature = RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_4KB;
817a0382431SSteven Price break;
818a0382431SSteven Price case SZ_16K:
819a0382431SSteven Price granule_size = RMI_GRANULE_SIZE_16KB;
820a0382431SSteven Price granule_feature = RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_16KB;
821a0382431SSteven Price break;
822a0382431SSteven Price case SZ_64K:
823a0382431SSteven Price granule_size = RMI_GRANULE_SIZE_64KB;
824a0382431SSteven Price granule_feature = RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_64KB;
825a0382431SSteven Price break;
826a0382431SSteven Price default:
827a0382431SSteven Price BUILD_BUG();
828a0382431SSteven Price }
829a0382431SSteven Price
830a0382431SSteven Price if (!(rmi_feat_reg(1) & granule_feature)) {
831a0382431SSteven Price pr_err("RMM does not support %luKB granules\n",
832a0382431SSteven Price PAGE_SIZE >> 10);
833a0382431SSteven Price return -ENXIO;
834a0382431SSteven Price }
835a0382431SSteven Price
836a0382431SSteven Price struct rmm_config *config __free(free_page) =
837a0382431SSteven Price (struct rmm_config *)get_zeroed_page(GFP_KERNEL);
838a0382431SSteven Price
839a0382431SSteven Price if (!config) {
840a0382431SSteven Price pr_err("Unable to allocate memory for RMM config\n");
841a0382431SSteven Price return -ENOMEM;
842a0382431SSteven Price }
843a0382431SSteven Price
844a0382431SSteven Price config->rmi_granule_size = granule_size;
845a0382431SSteven Price
846a0382431SSteven Price /*
847a0382431SSteven Price * For now we set the tracking_region_size to 0 which is the only option
848a0382431SSteven Price * for 4KB PAGE_SIZE (1GB for 4KB PAGE_SIZE, 32MB/512MB for 16KB/64KB).
849a0382431SSteven Price * TODO: Support other tracking sizes via Kconfig option for other
850a0382431SSteven Price * PAGE_SIZES
851a0382431SSteven Price */
852a0382431SSteven Price config->tracking_region_size = 0;
853a0382431SSteven Price
854a0382431SSteven Price ret = rmi_rmm_config_set(virt_to_phys(config));
855a0382431SSteven Price if (ret) {
856a0382431SSteven Price pr_err("RMM config set failed (%d)\n", ret);
857a0382431SSteven Price return -EINVAL;
858a0382431SSteven Price }
859a0382431SSteven Price
860a0382431SSteven Price return 0;
861a0382431SSteven Price }
86224657f2cSSteven Price
863c20b65a0SSteven Price /**
864c20b65a0SSteven Price * rmi_granule_tracking_get() - Get configuration of a Granule tracking region
865c20b65a0SSteven Price * @start: Base PA of the tracking region
866c20b65a0SSteven Price * @end: End of the PA region
867c20b65a0SSteven Price * @out_category: Memory category
868c20b65a0SSteven Price * @out_state: Tracking region state
869c20b65a0SSteven Price * @out_top: Top of the memory region
870c20b65a0SSteven Price *
871c20b65a0SSteven Price * Return: RMI return code
872c20b65a0SSteven Price */
rmi_granule_tracking_get(unsigned long start,unsigned long end,unsigned long * out_category,unsigned long * out_state,unsigned long * out_top)873c20b65a0SSteven Price static int rmi_granule_tracking_get(unsigned long start,
874c20b65a0SSteven Price unsigned long end,
875c20b65a0SSteven Price unsigned long *out_category,
876c20b65a0SSteven Price unsigned long *out_state,
877c20b65a0SSteven Price unsigned long *out_top)
878c20b65a0SSteven Price {
879c20b65a0SSteven Price struct arm_smccc_1_2_regs regs = {
880c20b65a0SSteven Price SMC_RMI_GRANULE_TRACKING_GET, start, end,
881c20b65a0SSteven Price };
882c20b65a0SSteven Price
883c20b65a0SSteven Price rmi_smccc_invoke(®s);
884c20b65a0SSteven Price
885c20b65a0SSteven Price if (regs.a0 != RMI_SUCCESS)
886c20b65a0SSteven Price return regs.a0;
887c20b65a0SSteven Price
888c20b65a0SSteven Price if (out_category)
889c20b65a0SSteven Price *out_category = regs.a1;
890c20b65a0SSteven Price if (out_state)
891c20b65a0SSteven Price *out_state = regs.a2;
892c20b65a0SSteven Price if (out_top)
893c20b65a0SSteven Price *out_top = regs.a3;
894c20b65a0SSteven Price
895c20b65a0SSteven Price return RMI_SUCCESS;
896c20b65a0SSteven Price }
897c20b65a0SSteven Price
898c20b65a0SSteven Price /*
899c20b65a0SSteven Price * Make sure the area is tracked by RMM at FINE granularity.
900c20b65a0SSteven Price * We do not support changing the tracking yet.
901c20b65a0SSteven Price */
rmi_verify_memory_tracking(phys_addr_t start,phys_addr_t end)902c20b65a0SSteven Price static int rmi_verify_memory_tracking(phys_addr_t start, phys_addr_t end)
903c20b65a0SSteven Price {
904c20b65a0SSteven Price while (start < end) {
905c20b65a0SSteven Price unsigned long ret, category, state, next;
906c20b65a0SSteven Price
907c20b65a0SSteven Price ret = rmi_granule_tracking_get(start, end, &category, &state, &next);
908c20b65a0SSteven Price if (ret != RMI_SUCCESS) {
909c20b65a0SSteven Price pr_err("RMI_GRANULE_TRACKING_GET failed for %llx-%llx: (%lu)\n",
910c20b65a0SSteven Price start, end, ret);
911c20b65a0SSteven Price return -ENXIO;
912c20b65a0SSteven Price }
913c20b65a0SSteven Price
914c20b65a0SSteven Price if (WARN_ON(next <= start))
915c20b65a0SSteven Price return -ENXIO;
916c20b65a0SSteven Price
917c20b65a0SSteven Price if (state != RMI_TRACKING_FINE ||
918c20b65a0SSteven Price category != RMI_MEM_CATEGORY_CONVENTIONAL) {
919c20b65a0SSteven Price /* TODO: Set granule tracking in this case */
920c20b65a0SSteven Price pr_err("Granule tracking for region isn't fine/conventional: %llx-%lx\n",
921c20b65a0SSteven Price start, next);
922c20b65a0SSteven Price return -ENODEV;
923c20b65a0SSteven Price }
924c20b65a0SSteven Price start = next;
925c20b65a0SSteven Price }
926c20b65a0SSteven Price
927c20b65a0SSteven Price return 0;
928c20b65a0SSteven Price }
929c20b65a0SSteven Price
930c20b65a0SSteven Price /*
931c20b65a0SSteven Price * rmi_gpt_info - Query the GPT info for the given PAR.
932c20b65a0SSteven Price * @start: Base of the physical address region
933c20b65a0SSteven Price * @end: Top of the physical address region
934c20b65a0SSteven Price * @out_top: Top of the physical address region for which the GPT @out_gpt_par_state
935c20b65a0SSteven Price * is valid
936c20b65a0SSteven Price * @out_gpt_par_state: State of the GPT covered by [start, out_top)
937c20b65a0SSteven Price */
rmi_gpt_info(unsigned long start,unsigned long end,unsigned long * out_top,unsigned long * out_gpt_par_state)938c20b65a0SSteven Price static long rmi_gpt_info(unsigned long start, unsigned long end,
939c20b65a0SSteven Price unsigned long *out_top,
940c20b65a0SSteven Price unsigned long *out_gpt_par_state)
941c20b65a0SSteven Price {
942c20b65a0SSteven Price struct arm_smccc_1_2_regs regs = {
943c20b65a0SSteven Price SMC_RMI_GPT_INFO, start, end,
944c20b65a0SSteven Price };
945c20b65a0SSteven Price
946c20b65a0SSteven Price rmi_smccc_invoke(®s);
947c20b65a0SSteven Price if (regs.a0 != RMI_SUCCESS)
948c20b65a0SSteven Price return regs.a0;
949c20b65a0SSteven Price
950c20b65a0SSteven Price if (out_top)
951c20b65a0SSteven Price *out_top = regs.a1;
952c20b65a0SSteven Price if (out_gpt_par_state)
953c20b65a0SSteven Price *out_gpt_par_state = regs.a2;
954c20b65a0SSteven Price
955c20b65a0SSteven Price return RMI_SUCCESS;
956c20b65a0SSteven Price }
957c20b65a0SSteven Price
958c20b65a0SSteven Price /*
959c20b65a0SSteven Price * We do not support creating L1 GPTs yet. So, make sure that all the regions
960c20b65a0SSteven Price * are managed by the firmware.
961c20b65a0SSteven Price */
rmi_verify_gpt_firmware_managed(phys_addr_t start,phys_addr_t end)962c20b65a0SSteven Price static int rmi_verify_gpt_firmware_managed(phys_addr_t start, phys_addr_t end)
963c20b65a0SSteven Price {
964c20b65a0SSteven Price unsigned long l0gpt_sz;
965c20b65a0SSteven Price unsigned long next, par_state;
966c20b65a0SSteven Price
967c20b65a0SSteven Price l0gpt_sz = 1UL << (30 + FIELD_GET(RMI_FEATURE_REGISTER_1_L0GPTSZ,
968c20b65a0SSteven Price rmi_feat_reg(1)));
969c20b65a0SSteven Price start = ALIGN_DOWN(start, l0gpt_sz);
970c20b65a0SSteven Price end = ALIGN(end, l0gpt_sz);
971c20b65a0SSteven Price
972c20b65a0SSteven Price while (start < end) {
973c20b65a0SSteven Price long ret = rmi_gpt_info(start, end, &next, &par_state);
974c20b65a0SSteven Price
975c20b65a0SSteven Price if (ret != RMI_SUCCESS) {
976c20b65a0SSteven Price pr_err("RMI_GPT_INFO failed for %llx-%llx: (%ld)\n",
977c20b65a0SSteven Price start, end, ret);
978c20b65a0SSteven Price return -ENXIO;
979c20b65a0SSteven Price }
980c20b65a0SSteven Price
981c20b65a0SSteven Price if (WARN_ON(next <= start))
982c20b65a0SSteven Price return -ENXIO;
983c20b65a0SSteven Price
984c20b65a0SSteven Price if (par_state != RMI_GPT_PAR_PLAT) {
985c20b65a0SSteven Price pr_err("GPT for the region is not managed by firmware %llx-%lx\n",
986c20b65a0SSteven Price start, next);
987c20b65a0SSteven Price return -ENODEV;
988c20b65a0SSteven Price }
989c20b65a0SSteven Price start = next;
990c20b65a0SSteven Price }
991c20b65a0SSteven Price
992c20b65a0SSteven Price return 0;
993c20b65a0SSteven Price }
994c20b65a0SSteven Price
rmi_prepare_memory(phys_addr_t start,phys_addr_t end)995c20b65a0SSteven Price static int rmi_prepare_memory(phys_addr_t start, phys_addr_t end)
996c20b65a0SSteven Price {
997c20b65a0SSteven Price int ret;
998c20b65a0SSteven Price
999c20b65a0SSteven Price if (start >= end)
1000c20b65a0SSteven Price return -EINVAL;
1001c20b65a0SSteven Price
1002c20b65a0SSteven Price ret = rmi_verify_memory_tracking(start, end);
1003c20b65a0SSteven Price if (ret)
1004c20b65a0SSteven Price return ret;
1005c20b65a0SSteven Price
1006c20b65a0SSteven Price return rmi_verify_gpt_firmware_managed(start, end);
1007c20b65a0SSteven Price }
1008c20b65a0SSteven Price
rmi_init_metadata(void)1009c20b65a0SSteven Price static int rmi_init_metadata(void)
1010c20b65a0SSteven Price {
1011c20b65a0SSteven Price phys_addr_t start, end;
1012c20b65a0SSteven Price struct memblock_region *r;
1013c20b65a0SSteven Price
1014c20b65a0SSteven Price for_each_mem_region(r) {
1015c20b65a0SSteven Price int ret;
1016c20b65a0SSteven Price
1017c20b65a0SSteven Price /* Firmware-reserved NOMAP regions are not usable system RAM */
1018c20b65a0SSteven Price if (memblock_is_nomap(r))
1019c20b65a0SSteven Price continue;
1020c20b65a0SSteven Price
1021c20b65a0SSteven Price start = PAGE_ALIGN(r->base);
1022c20b65a0SSteven Price /*
1023c20b65a0SSteven Price * We always deal with PAGE_SIZE and if in the odd case this
1024c20b65a0SSteven Price * region boundary is not PAGE aligned, we stick to the page
1025c20b65a0SSteven Price * that we can use from the region.
1026c20b65a0SSteven Price */
1027c20b65a0SSteven Price end = PAGE_ALIGN_DOWN(r->base + r->size);
1028c20b65a0SSteven Price /* Too small ? */
1029c20b65a0SSteven Price if (start >= end)
1030c20b65a0SSteven Price continue;
1031c20b65a0SSteven Price
1032c20b65a0SSteven Price ret = rmi_prepare_memory(start, end);
1033c20b65a0SSteven Price if (ret)
1034c20b65a0SSteven Price return ret;
1035c20b65a0SSteven Price }
1036c20b65a0SSteven Price
1037c20b65a0SSteven Price return 0;
1038c20b65a0SSteven Price }
1039c20b65a0SSteven Price
rmi_memory_notifier(struct notifier_block * nb,unsigned long action,void * data)1040c20b65a0SSteven Price static int rmi_memory_notifier(struct notifier_block *nb,
1041c20b65a0SSteven Price unsigned long action, void *data)
1042c20b65a0SSteven Price {
1043c20b65a0SSteven Price struct memory_notify *arg = data;
1044c20b65a0SSteven Price phys_addr_t start, end;
1045c20b65a0SSteven Price int ret;
1046c20b65a0SSteven Price
1047c20b65a0SSteven Price if (action != MEM_GOING_ONLINE)
1048c20b65a0SSteven Price return NOTIFY_DONE;
1049c20b65a0SSteven Price
1050c20b65a0SSteven Price start = PFN_PHYS(arg->start_pfn);
1051c20b65a0SSteven Price end = PFN_PHYS(arg->start_pfn + arg->nr_pages);
1052c20b65a0SSteven Price
1053*06898e53SSuzuki K Poulose /*
1054*06898e53SSuzuki K Poulose * If the hotplugged memory region is in ZONE_MOVABLE, neither the
1055*06898e53SSuzuki K Poulose * guest-memfd nor the kernel allocations can come from there. So we are
1056*06898e53SSuzuki K Poulose * fine to skip this.
1057*06898e53SSuzuki K Poulose * For boot time memory, we don't allow this discount, as the
1058*06898e53SSuzuki K Poulose * decision to move boot memory pages to ZONE_MOVABLE is purely
1059*06898e53SSuzuki K Poulose * a kernel choice and the firmware must have decided what it covers.
1060*06898e53SSuzuki K Poulose */
1061*06898e53SSuzuki K Poulose if (is_zone_movable_page(pfn_to_page(arg->start_pfn)))
1062*06898e53SSuzuki K Poulose return NOTIFY_DONE;
1063*06898e53SSuzuki K Poulose
1064c20b65a0SSteven Price ret = rmi_prepare_memory(start, end);
1065c20b65a0SSteven Price
1066c20b65a0SSteven Price return notifier_from_errno(ret);
1067c20b65a0SSteven Price }
1068c20b65a0SSteven Price
1069c20b65a0SSteven Price static struct notifier_block rmi_memory_nb = {
1070c20b65a0SSteven Price .notifier_call = rmi_memory_notifier,
1071c20b65a0SSteven Price };
1072c20b65a0SSteven Price
rmi_init_memory(void)1073c20b65a0SSteven Price static int rmi_init_memory(void)
1074c20b65a0SSteven Price {
1075c20b65a0SSteven Price int ret;
1076c20b65a0SSteven Price
1077c20b65a0SSteven Price ret = rmi_init_metadata();
1078c20b65a0SSteven Price if (ret)
1079c20b65a0SSteven Price return ret;
1080c20b65a0SSteven Price
1081c20b65a0SSteven Price return register_memory_notifier(&rmi_memory_nb);
1082c20b65a0SSteven Price }
1083c20b65a0SSteven Price
arm64_init_rmi(void)108424657f2cSSteven Price static int __init arm64_init_rmi(void)
108524657f2cSSteven Price {
108624657f2cSSteven Price int ret;
108724657f2cSSteven Price
108824657f2cSSteven Price /* If we can't agree on the RMI ABI version, don't proceed further */
108924657f2cSSteven Price ret = rmi_check_version();
109024657f2cSSteven Price if (ret)
109124657f2cSSteven Price return ret;
109224657f2cSSteven Price
109324657f2cSSteven Price ret = rmi_read_features();
109424657f2cSSteven Price if (ret)
109524657f2cSSteven Price return ret;
109624657f2cSSteven Price
1097a0382431SSteven Price ret = rmi_configure();
1098a0382431SSteven Price if (ret)
1099a0382431SSteven Price return ret;
1100a0382431SSteven Price
1101fa193c50SSteven Price /* Activate the RMM */
1102fa193c50SSteven Price struct rmi_sro_state *sro __free(kfree) = kmalloc_obj(*sro);
1103fa193c50SSteven Price if (!sro)
1104fa193c50SSteven Price return -ENOMEM;
1105fa193c50SSteven Price
1106fa193c50SSteven Price ret = rmi_sro_memxfer_cmd(sro, GFP_KERNEL, SMC_RMI_RMM_ACTIVATE);
1107fa193c50SSteven Price if (ret) {
1108fa193c50SSteven Price pr_err("RMM activate failed (%d)\n", ret);
1109fa193c50SSteven Price ret = ret < 0 ? ret : -ENXIO;
1110c20b65a0SSteven Price return ret;
1111fa193c50SSteven Price }
1112fa193c50SSteven Price
1113c20b65a0SSteven Price WRITE_ONCE(arm64_rmm_active, true);
1114c20b65a0SSteven Price
1115c20b65a0SSteven Price ret = rmi_init_memory();
1116c20b65a0SSteven Price if (ret) {
1117c20b65a0SSteven Price /* Deactivate the RMM */
1118c20b65a0SSteven Price if (!WARN_ON(rmi_sro_memxfer_cmd(sro, GFP_KERNEL, SMC_RMI_RMM_DEACTIVATE)))
1119c20b65a0SSteven Price WRITE_ONCE(arm64_rmm_active, false);
1120fa193c50SSteven Price return ret;
112124657f2cSSteven Price }
112224657f2cSSteven Price
1123c20b65a0SSteven Price /* Mark the RMM is usable */
1124c20b65a0SSteven Price WRITE_ONCE(arm64_rmi_is_available, true);
1125c20b65a0SSteven Price pr_info("RMI configured\n");
1126c20b65a0SSteven Price
1127c20b65a0SSteven Price return 0;
1128c20b65a0SSteven Price }
1129c20b65a0SSteven Price
113024657f2cSSteven Price /*
113124657f2cSSteven Price * Note arm64_init_rmi() must be called before kvm_init_rmi() otherwise KVM
113224657f2cSSteven Price * will not support realm guests. subsys_initcall() is called before
113324657f2cSSteven Price * module_init() (used for KVM) so this is OK.
113424657f2cSSteven Price */
113524657f2cSSteven Price subsys_initcall(arm64_init_rmi);
1136