1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This program is free software and is provided to you under the terms of the
6*4882a593Smuzhiyun * GNU General Public License version 2 as published by the Free Software
7*4882a593Smuzhiyun * Foundation, and any use by you of this program is subject to the terms
8*4882a593Smuzhiyun * of such GNU licence.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * A copy of the licence is included with the program, and can also be obtained
11*4882a593Smuzhiyun * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12*4882a593Smuzhiyun * Boston, MA 02110-1301, USA.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /**
21*4882a593Smuzhiyun * @file mali_kbase_mem.c
22*4882a593Smuzhiyun * Base kernel memory APIs
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun #ifdef CONFIG_DMA_SHARED_BUFFER
25*4882a593Smuzhiyun #include <linux/dma-buf.h>
26*4882a593Smuzhiyun #endif /* CONFIG_DMA_SHARED_BUFFER */
27*4882a593Smuzhiyun #ifdef CONFIG_UMP
28*4882a593Smuzhiyun #include <linux/ump.h>
29*4882a593Smuzhiyun #endif /* CONFIG_UMP */
30*4882a593Smuzhiyun #include <linux/kernel.h>
31*4882a593Smuzhiyun #include <linux/bug.h>
32*4882a593Smuzhiyun #include <linux/compat.h>
33*4882a593Smuzhiyun #include <linux/version.h>
34*4882a593Smuzhiyun #include <linux/sched/mm.h>
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include <mali_kbase_config.h>
37*4882a593Smuzhiyun #include <mali_kbase.h>
38*4882a593Smuzhiyun #include <mali_midg_regmap.h>
39*4882a593Smuzhiyun #include <mali_kbase_cache_policy.h>
40*4882a593Smuzhiyun #include <mali_kbase_hw.h>
41*4882a593Smuzhiyun #include <mali_kbase_hwaccess_time.h>
42*4882a593Smuzhiyun #include <mali_kbase_tlstream.h>
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* This function finds out which RB tree the given GPU VA region belongs to
45*4882a593Smuzhiyun * based on the region zone */
kbase_reg_flags_to_rbtree(struct kbase_context * kctx,struct kbase_va_region * reg)46*4882a593Smuzhiyun static struct rb_root *kbase_reg_flags_to_rbtree(struct kbase_context *kctx,
47*4882a593Smuzhiyun struct kbase_va_region *reg)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun switch (reg->flags & KBASE_REG_ZONE_MASK) {
52*4882a593Smuzhiyun case KBASE_REG_ZONE_CUSTOM_VA:
53*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_custom;
54*4882a593Smuzhiyun break;
55*4882a593Smuzhiyun case KBASE_REG_ZONE_EXEC:
56*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_exec;
57*4882a593Smuzhiyun break;
58*4882a593Smuzhiyun case KBASE_REG_ZONE_SAME_VA:
59*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_same;
60*4882a593Smuzhiyun /* fall through */
61*4882a593Smuzhiyun default:
62*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_same;
63*4882a593Smuzhiyun break;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun return rbtree;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /* This function finds out which RB tree the given pfn from the GPU VA belongs
70*4882a593Smuzhiyun * to based on the memory zone the pfn refers to */
kbase_gpu_va_to_rbtree(struct kbase_context * kctx,u64 gpu_pfn)71*4882a593Smuzhiyun static struct rb_root *kbase_gpu_va_to_rbtree(struct kbase_context *kctx,
72*4882a593Smuzhiyun u64 gpu_pfn)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #ifdef CONFIG_64BIT
77*4882a593Smuzhiyun if (kbase_ctx_flag(kctx, KCTX_COMPAT)) {
78*4882a593Smuzhiyun #endif /* CONFIG_64BIT */
79*4882a593Smuzhiyun if (gpu_pfn >= KBASE_REG_ZONE_CUSTOM_VA_BASE)
80*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_custom;
81*4882a593Smuzhiyun else if (gpu_pfn >= KBASE_REG_ZONE_EXEC_BASE)
82*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_exec;
83*4882a593Smuzhiyun else
84*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_same;
85*4882a593Smuzhiyun #ifdef CONFIG_64BIT
86*4882a593Smuzhiyun } else {
87*4882a593Smuzhiyun if (gpu_pfn >= kctx->same_va_end)
88*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_custom;
89*4882a593Smuzhiyun else
90*4882a593Smuzhiyun rbtree = &kctx->reg_rbtree_same;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun #endif /* CONFIG_64BIT */
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return rbtree;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* This function inserts a region into the tree. */
kbase_region_tracker_insert(struct kbase_context * kctx,struct kbase_va_region * new_reg)98*4882a593Smuzhiyun static void kbase_region_tracker_insert(struct kbase_context *kctx,
99*4882a593Smuzhiyun struct kbase_va_region *new_reg)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun u64 start_pfn = new_reg->start_pfn;
102*4882a593Smuzhiyun struct rb_node **link = NULL;
103*4882a593Smuzhiyun struct rb_node *parent = NULL;
104*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun rbtree = kbase_reg_flags_to_rbtree(kctx, new_reg);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun link = &(rbtree->rb_node);
109*4882a593Smuzhiyun /* Find the right place in the tree using tree search */
110*4882a593Smuzhiyun while (*link) {
111*4882a593Smuzhiyun struct kbase_va_region *old_reg;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun parent = *link;
114*4882a593Smuzhiyun old_reg = rb_entry(parent, struct kbase_va_region, rblink);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /* RBTree requires no duplicate entries. */
117*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(old_reg->start_pfn != start_pfn);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (old_reg->start_pfn > start_pfn)
120*4882a593Smuzhiyun link = &(*link)->rb_left;
121*4882a593Smuzhiyun else
122*4882a593Smuzhiyun link = &(*link)->rb_right;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /* Put the new node there, and rebalance tree */
126*4882a593Smuzhiyun rb_link_node(&(new_reg->rblink), parent, link);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun rb_insert_color(&(new_reg->rblink), rbtree);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* Find allocated region enclosing free range. */
kbase_region_tracker_find_region_enclosing_range_free(struct kbase_context * kctx,u64 start_pfn,size_t nr_pages)132*4882a593Smuzhiyun static struct kbase_va_region *kbase_region_tracker_find_region_enclosing_range_free(
133*4882a593Smuzhiyun struct kbase_context *kctx, u64 start_pfn, size_t nr_pages)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun struct rb_node *rbnode = NULL;
136*4882a593Smuzhiyun struct kbase_va_region *reg = NULL;
137*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun u64 end_pfn = start_pfn + nr_pages;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun rbtree = kbase_gpu_va_to_rbtree(kctx, start_pfn);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun rbnode = rbtree->rb_node;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun while (rbnode) {
146*4882a593Smuzhiyun u64 tmp_start_pfn, tmp_end_pfn;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun reg = rb_entry(rbnode, struct kbase_va_region, rblink);
149*4882a593Smuzhiyun tmp_start_pfn = reg->start_pfn;
150*4882a593Smuzhiyun tmp_end_pfn = reg->start_pfn + reg->nr_pages;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* If start is lower than this, go left. */
153*4882a593Smuzhiyun if (start_pfn < tmp_start_pfn)
154*4882a593Smuzhiyun rbnode = rbnode->rb_left;
155*4882a593Smuzhiyun /* If end is higher than this, then go right. */
156*4882a593Smuzhiyun else if (end_pfn > tmp_end_pfn)
157*4882a593Smuzhiyun rbnode = rbnode->rb_right;
158*4882a593Smuzhiyun else /* Enclosing */
159*4882a593Smuzhiyun return reg;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun return NULL;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* Find region enclosing given address. */
kbase_region_tracker_find_region_enclosing_address(struct kbase_context * kctx,u64 gpu_addr)166*4882a593Smuzhiyun struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, u64 gpu_addr)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun struct rb_node *rbnode;
169*4882a593Smuzhiyun struct kbase_va_region *reg;
170*4882a593Smuzhiyun u64 gpu_pfn = gpu_addr >> PAGE_SHIFT;
171*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != kctx);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun rbtree = kbase_gpu_va_to_rbtree(kctx, gpu_pfn);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun rbnode = rbtree->rb_node;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun while (rbnode) {
182*4882a593Smuzhiyun u64 tmp_start_pfn, tmp_end_pfn;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun reg = rb_entry(rbnode, struct kbase_va_region, rblink);
185*4882a593Smuzhiyun tmp_start_pfn = reg->start_pfn;
186*4882a593Smuzhiyun tmp_end_pfn = reg->start_pfn + reg->nr_pages;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* If start is lower than this, go left. */
189*4882a593Smuzhiyun if (gpu_pfn < tmp_start_pfn)
190*4882a593Smuzhiyun rbnode = rbnode->rb_left;
191*4882a593Smuzhiyun /* If end is higher than this, then go right. */
192*4882a593Smuzhiyun else if (gpu_pfn >= tmp_end_pfn)
193*4882a593Smuzhiyun rbnode = rbnode->rb_right;
194*4882a593Smuzhiyun else /* Enclosing */
195*4882a593Smuzhiyun return reg;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun return NULL;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_enclosing_address);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* Find region with given base address */
kbase_region_tracker_find_region_base_address(struct kbase_context * kctx,u64 gpu_addr)204*4882a593Smuzhiyun struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, u64 gpu_addr)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun u64 gpu_pfn = gpu_addr >> PAGE_SHIFT;
207*4882a593Smuzhiyun struct rb_node *rbnode = NULL;
208*4882a593Smuzhiyun struct kbase_va_region *reg = NULL;
209*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != kctx);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun rbtree = kbase_gpu_va_to_rbtree(kctx, gpu_pfn);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun rbnode = rbtree->rb_node;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun while (rbnode) {
220*4882a593Smuzhiyun reg = rb_entry(rbnode, struct kbase_va_region, rblink);
221*4882a593Smuzhiyun if (reg->start_pfn > gpu_pfn)
222*4882a593Smuzhiyun rbnode = rbnode->rb_left;
223*4882a593Smuzhiyun else if (reg->start_pfn < gpu_pfn)
224*4882a593Smuzhiyun rbnode = rbnode->rb_right;
225*4882a593Smuzhiyun else
226*4882a593Smuzhiyun return reg;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun return NULL;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_base_address);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /* Find region meeting given requirements */
kbase_region_tracker_find_region_meeting_reqs(struct kbase_context * kctx,struct kbase_va_region * reg_reqs,size_t nr_pages,size_t align)236*4882a593Smuzhiyun static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(struct kbase_context *kctx, struct kbase_va_region *reg_reqs, size_t nr_pages, size_t align)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun struct rb_node *rbnode = NULL;
239*4882a593Smuzhiyun struct kbase_va_region *reg = NULL;
240*4882a593Smuzhiyun struct rb_root *rbtree = NULL;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* Note that this search is a linear search, as we do not have a target
243*4882a593Smuzhiyun address in mind, so does not benefit from the rbtree search */
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun rbtree = kbase_reg_flags_to_rbtree(kctx, reg_reqs);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun rbnode = rb_first(rbtree);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun while (rbnode) {
250*4882a593Smuzhiyun reg = rb_entry(rbnode, struct kbase_va_region, rblink);
251*4882a593Smuzhiyun if ((reg->nr_pages >= nr_pages) &&
252*4882a593Smuzhiyun (reg->flags & KBASE_REG_FREE)) {
253*4882a593Smuzhiyun /* Check alignment */
254*4882a593Smuzhiyun u64 start_pfn = (reg->start_pfn + align - 1) & ~(align - 1);
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if ((start_pfn >= reg->start_pfn) &&
257*4882a593Smuzhiyun (start_pfn <= (reg->start_pfn + reg->nr_pages - 1)) &&
258*4882a593Smuzhiyun ((start_pfn + nr_pages - 1) <= (reg->start_pfn + reg->nr_pages - 1)))
259*4882a593Smuzhiyun return reg;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun rbnode = rb_next(rbnode);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun return NULL;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun * @brief Remove a region object from the global list.
269*4882a593Smuzhiyun *
270*4882a593Smuzhiyun * The region reg is removed, possibly by merging with other free and
271*4882a593Smuzhiyun * compatible adjacent regions. It must be called with the context
272*4882a593Smuzhiyun * region lock held. The associated memory is not released (see
273*4882a593Smuzhiyun * kbase_free_alloced_region). Internal use only.
274*4882a593Smuzhiyun */
kbase_remove_va_region(struct kbase_context * kctx,struct kbase_va_region * reg)275*4882a593Smuzhiyun static int kbase_remove_va_region(struct kbase_context *kctx, struct kbase_va_region *reg)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct rb_node *rbprev;
278*4882a593Smuzhiyun struct kbase_va_region *prev = NULL;
279*4882a593Smuzhiyun struct rb_node *rbnext;
280*4882a593Smuzhiyun struct kbase_va_region *next = NULL;
281*4882a593Smuzhiyun struct rb_root *reg_rbtree = NULL;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun int merged_front = 0;
284*4882a593Smuzhiyun int merged_back = 0;
285*4882a593Smuzhiyun int err = 0;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun reg_rbtree = kbase_reg_flags_to_rbtree(kctx, reg);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* Try to merge with the previous block first */
290*4882a593Smuzhiyun rbprev = rb_prev(&(reg->rblink));
291*4882a593Smuzhiyun if (rbprev) {
292*4882a593Smuzhiyun prev = rb_entry(rbprev, struct kbase_va_region, rblink);
293*4882a593Smuzhiyun if (prev->flags & KBASE_REG_FREE) {
294*4882a593Smuzhiyun /* We're compatible with the previous VMA,
295*4882a593Smuzhiyun * merge with it */
296*4882a593Smuzhiyun WARN_ON((prev->flags & KBASE_REG_ZONE_MASK) !=
297*4882a593Smuzhiyun (reg->flags & KBASE_REG_ZONE_MASK));
298*4882a593Smuzhiyun prev->nr_pages += reg->nr_pages;
299*4882a593Smuzhiyun rb_erase(&(reg->rblink), reg_rbtree);
300*4882a593Smuzhiyun reg = prev;
301*4882a593Smuzhiyun merged_front = 1;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /* Try to merge with the next block second */
306*4882a593Smuzhiyun /* Note we do the lookup here as the tree may have been rebalanced. */
307*4882a593Smuzhiyun rbnext = rb_next(&(reg->rblink));
308*4882a593Smuzhiyun if (rbnext) {
309*4882a593Smuzhiyun /* We're compatible with the next VMA, merge with it */
310*4882a593Smuzhiyun next = rb_entry(rbnext, struct kbase_va_region, rblink);
311*4882a593Smuzhiyun if (next->flags & KBASE_REG_FREE) {
312*4882a593Smuzhiyun WARN_ON((next->flags & KBASE_REG_ZONE_MASK) !=
313*4882a593Smuzhiyun (reg->flags & KBASE_REG_ZONE_MASK));
314*4882a593Smuzhiyun next->start_pfn = reg->start_pfn;
315*4882a593Smuzhiyun next->nr_pages += reg->nr_pages;
316*4882a593Smuzhiyun rb_erase(&(reg->rblink), reg_rbtree);
317*4882a593Smuzhiyun merged_back = 1;
318*4882a593Smuzhiyun if (merged_front) {
319*4882a593Smuzhiyun /* We already merged with prev, free it */
320*4882a593Smuzhiyun kbase_free_alloced_region(reg);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun /* If we failed to merge then we need to add a new block */
326*4882a593Smuzhiyun if (!(merged_front || merged_back)) {
327*4882a593Smuzhiyun /*
328*4882a593Smuzhiyun * We didn't merge anything. Add a new free
329*4882a593Smuzhiyun * placeholder and remove the original one.
330*4882a593Smuzhiyun */
331*4882a593Smuzhiyun struct kbase_va_region *free_reg;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun free_reg = kbase_alloc_free_region(kctx, reg->start_pfn, reg->nr_pages, reg->flags & KBASE_REG_ZONE_MASK);
334*4882a593Smuzhiyun if (!free_reg) {
335*4882a593Smuzhiyun err = -ENOMEM;
336*4882a593Smuzhiyun goto out;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun rb_replace_node(&(reg->rblink), &(free_reg->rblink), reg_rbtree);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun out:
342*4882a593Smuzhiyun return err;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_remove_va_region);
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun /**
348*4882a593Smuzhiyun * @brief Insert a VA region to the list, replacing the current at_reg.
349*4882a593Smuzhiyun */
kbase_insert_va_region_nolock(struct kbase_context * kctx,struct kbase_va_region * new_reg,struct kbase_va_region * at_reg,u64 start_pfn,size_t nr_pages)350*4882a593Smuzhiyun static int kbase_insert_va_region_nolock(struct kbase_context *kctx, struct kbase_va_region *new_reg, struct kbase_va_region *at_reg, u64 start_pfn, size_t nr_pages)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun struct rb_root *reg_rbtree = NULL;
353*4882a593Smuzhiyun int err = 0;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun reg_rbtree = kbase_reg_flags_to_rbtree(kctx, at_reg);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /* Must be a free region */
358*4882a593Smuzhiyun KBASE_DEBUG_ASSERT((at_reg->flags & KBASE_REG_FREE) != 0);
359*4882a593Smuzhiyun /* start_pfn should be contained within at_reg */
360*4882a593Smuzhiyun KBASE_DEBUG_ASSERT((start_pfn >= at_reg->start_pfn) && (start_pfn < at_reg->start_pfn + at_reg->nr_pages));
361*4882a593Smuzhiyun /* at least nr_pages from start_pfn should be contained within at_reg */
362*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= at_reg->start_pfn + at_reg->nr_pages);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun new_reg->start_pfn = start_pfn;
365*4882a593Smuzhiyun new_reg->nr_pages = nr_pages;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /* Regions are a whole use, so swap and delete old one. */
368*4882a593Smuzhiyun if (at_reg->start_pfn == start_pfn && at_reg->nr_pages == nr_pages) {
369*4882a593Smuzhiyun rb_replace_node(&(at_reg->rblink), &(new_reg->rblink),
370*4882a593Smuzhiyun reg_rbtree);
371*4882a593Smuzhiyun kbase_free_alloced_region(at_reg);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun /* New region replaces the start of the old one, so insert before. */
374*4882a593Smuzhiyun else if (at_reg->start_pfn == start_pfn) {
375*4882a593Smuzhiyun at_reg->start_pfn += nr_pages;
376*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(at_reg->nr_pages >= nr_pages);
377*4882a593Smuzhiyun at_reg->nr_pages -= nr_pages;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, new_reg);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun /* New region replaces the end of the old one, so insert after. */
382*4882a593Smuzhiyun else if ((at_reg->start_pfn + at_reg->nr_pages) == (start_pfn + nr_pages)) {
383*4882a593Smuzhiyun at_reg->nr_pages -= nr_pages;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, new_reg);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun /* New region splits the old one, so insert and create new */
388*4882a593Smuzhiyun else {
389*4882a593Smuzhiyun struct kbase_va_region *new_front_reg;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun new_front_reg = kbase_alloc_free_region(kctx,
392*4882a593Smuzhiyun at_reg->start_pfn,
393*4882a593Smuzhiyun start_pfn - at_reg->start_pfn,
394*4882a593Smuzhiyun at_reg->flags & KBASE_REG_ZONE_MASK);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun if (new_front_reg) {
397*4882a593Smuzhiyun at_reg->nr_pages -= nr_pages + new_front_reg->nr_pages;
398*4882a593Smuzhiyun at_reg->start_pfn = start_pfn + nr_pages;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, new_front_reg);
401*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, new_reg);
402*4882a593Smuzhiyun } else {
403*4882a593Smuzhiyun err = -ENOMEM;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun return err;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun /**
411*4882a593Smuzhiyun * @brief Add a VA region to the list.
412*4882a593Smuzhiyun */
kbase_add_va_region(struct kbase_context * kctx,struct kbase_va_region * reg,u64 addr,size_t nr_pages,size_t align)413*4882a593Smuzhiyun int kbase_add_va_region(struct kbase_context *kctx,
414*4882a593Smuzhiyun struct kbase_va_region *reg, u64 addr,
415*4882a593Smuzhiyun size_t nr_pages, size_t align)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun struct kbase_va_region *tmp;
418*4882a593Smuzhiyun u64 gpu_pfn = addr >> PAGE_SHIFT;
419*4882a593Smuzhiyun int err = 0;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != kctx);
422*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != reg);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (!align)
427*4882a593Smuzhiyun align = 1;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun /* must be a power of 2 */
430*4882a593Smuzhiyun KBASE_DEBUG_ASSERT((align & (align - 1)) == 0);
431*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(nr_pages > 0);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun /* Path 1: Map a specific address. Find the enclosing region, which *must* be free. */
434*4882a593Smuzhiyun if (gpu_pfn) {
435*4882a593Smuzhiyun struct device *dev = kctx->kbdev->dev;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(!(gpu_pfn & (align - 1)));
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun tmp = kbase_region_tracker_find_region_enclosing_range_free(kctx, gpu_pfn, nr_pages);
440*4882a593Smuzhiyun if (!tmp) {
441*4882a593Smuzhiyun dev_warn(dev, "Enclosing region not found: 0x%08llx gpu_pfn, %zu nr_pages", gpu_pfn, nr_pages);
442*4882a593Smuzhiyun err = -ENOMEM;
443*4882a593Smuzhiyun goto exit;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun if (!(tmp->flags & KBASE_REG_FREE)) {
446*4882a593Smuzhiyun dev_warn(dev, "Zone mismatch: %lu != %lu", tmp->flags & KBASE_REG_ZONE_MASK, reg->flags & KBASE_REG_ZONE_MASK);
447*4882a593Smuzhiyun dev_warn(dev, "!(tmp->flags & KBASE_REG_FREE): tmp->start_pfn=0x%llx tmp->flags=0x%lx tmp->nr_pages=0x%zx gpu_pfn=0x%llx nr_pages=0x%zx\n", tmp->start_pfn, tmp->flags, tmp->nr_pages, gpu_pfn, nr_pages);
448*4882a593Smuzhiyun dev_warn(dev, "in function %s (%p, %p, 0x%llx, 0x%zx, 0x%zx)\n", __func__, kctx, reg, addr, nr_pages, align);
449*4882a593Smuzhiyun err = -ENOMEM;
450*4882a593Smuzhiyun goto exit;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun err = kbase_insert_va_region_nolock(kctx, reg, tmp, gpu_pfn, nr_pages);
454*4882a593Smuzhiyun if (err) {
455*4882a593Smuzhiyun dev_warn(dev, "Failed to insert va region");
456*4882a593Smuzhiyun err = -ENOMEM;
457*4882a593Smuzhiyun goto exit;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun goto exit;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /* Path 2: Map any free address which meets the requirements. */
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun u64 start_pfn;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun /*
468*4882a593Smuzhiyun * Depending on the zone the allocation request is for
469*4882a593Smuzhiyun * we might need to retry it.
470*4882a593Smuzhiyun */
471*4882a593Smuzhiyun do {
472*4882a593Smuzhiyun tmp = kbase_region_tracker_find_region_meeting_reqs(
473*4882a593Smuzhiyun kctx, reg, nr_pages, align);
474*4882a593Smuzhiyun if (tmp) {
475*4882a593Smuzhiyun start_pfn = (tmp->start_pfn + align - 1) &
476*4882a593Smuzhiyun ~(align - 1);
477*4882a593Smuzhiyun err = kbase_insert_va_region_nolock(kctx, reg,
478*4882a593Smuzhiyun tmp, start_pfn, nr_pages);
479*4882a593Smuzhiyun break;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun * If the allocation is not from the same zone as JIT
484*4882a593Smuzhiyun * then don't retry, we're out of VA and there is
485*4882a593Smuzhiyun * nothing which can be done about it.
486*4882a593Smuzhiyun */
487*4882a593Smuzhiyun if ((reg->flags & KBASE_REG_ZONE_MASK) !=
488*4882a593Smuzhiyun KBASE_REG_ZONE_CUSTOM_VA)
489*4882a593Smuzhiyun break;
490*4882a593Smuzhiyun } while (kbase_jit_evict(kctx));
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun if (!tmp)
493*4882a593Smuzhiyun err = -ENOMEM;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun exit:
497*4882a593Smuzhiyun return err;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_add_va_region);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /**
503*4882a593Smuzhiyun * @brief Initialize the internal region tracker data structure.
504*4882a593Smuzhiyun */
kbase_region_tracker_ds_init(struct kbase_context * kctx,struct kbase_va_region * same_va_reg,struct kbase_va_region * exec_reg,struct kbase_va_region * custom_va_reg)505*4882a593Smuzhiyun static void kbase_region_tracker_ds_init(struct kbase_context *kctx,
506*4882a593Smuzhiyun struct kbase_va_region *same_va_reg,
507*4882a593Smuzhiyun struct kbase_va_region *exec_reg,
508*4882a593Smuzhiyun struct kbase_va_region *custom_va_reg)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun kctx->reg_rbtree_same = RB_ROOT;
511*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, same_va_reg);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /* Although exec and custom_va_reg don't always exist,
514*4882a593Smuzhiyun * initialize unconditionally because of the mem_view debugfs
515*4882a593Smuzhiyun * implementation which relies on these being empty */
516*4882a593Smuzhiyun kctx->reg_rbtree_exec = RB_ROOT;
517*4882a593Smuzhiyun kctx->reg_rbtree_custom = RB_ROOT;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun if (exec_reg)
520*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, exec_reg);
521*4882a593Smuzhiyun if (custom_va_reg)
522*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, custom_va_reg);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
kbase_region_tracker_erase_rbtree(struct rb_root * rbtree)525*4882a593Smuzhiyun static void kbase_region_tracker_erase_rbtree(struct rb_root *rbtree)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun struct rb_node *rbnode;
528*4882a593Smuzhiyun struct kbase_va_region *reg;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun do {
531*4882a593Smuzhiyun rbnode = rb_first(rbtree);
532*4882a593Smuzhiyun if (rbnode) {
533*4882a593Smuzhiyun rb_erase(rbnode, rbtree);
534*4882a593Smuzhiyun reg = rb_entry(rbnode, struct kbase_va_region, rblink);
535*4882a593Smuzhiyun kbase_free_alloced_region(reg);
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun } while (rbnode);
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
kbase_region_tracker_term(struct kbase_context * kctx)540*4882a593Smuzhiyun void kbase_region_tracker_term(struct kbase_context *kctx)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_same);
543*4882a593Smuzhiyun kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_exec);
544*4882a593Smuzhiyun kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_custom);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /**
548*4882a593Smuzhiyun * Initialize the region tracker data structure.
549*4882a593Smuzhiyun */
kbase_region_tracker_init(struct kbase_context * kctx)550*4882a593Smuzhiyun int kbase_region_tracker_init(struct kbase_context *kctx)
551*4882a593Smuzhiyun {
552*4882a593Smuzhiyun struct kbase_va_region *same_va_reg;
553*4882a593Smuzhiyun struct kbase_va_region *exec_reg = NULL;
554*4882a593Smuzhiyun struct kbase_va_region *custom_va_reg = NULL;
555*4882a593Smuzhiyun size_t same_va_bits = sizeof(void *) * BITS_PER_BYTE;
556*4882a593Smuzhiyun u64 custom_va_size = KBASE_REG_ZONE_CUSTOM_VA_SIZE;
557*4882a593Smuzhiyun u64 gpu_va_limit = (1ULL << kctx->kbdev->gpu_props.mmu.va_bits) >> PAGE_SHIFT;
558*4882a593Smuzhiyun u64 same_va_pages;
559*4882a593Smuzhiyun int err;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun /* Take the lock as kbase_free_alloced_region requires it */
562*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun #if defined(CONFIG_ARM64)
565*4882a593Smuzhiyun same_va_bits = VA_BITS;
566*4882a593Smuzhiyun #elif defined(CONFIG_X86_64)
567*4882a593Smuzhiyun same_va_bits = 47;
568*4882a593Smuzhiyun #elif defined(CONFIG_64BIT)
569*4882a593Smuzhiyun #error Unsupported 64-bit architecture
570*4882a593Smuzhiyun #endif
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun #ifdef CONFIG_64BIT
573*4882a593Smuzhiyun if (kbase_ctx_flag(kctx, KCTX_COMPAT))
574*4882a593Smuzhiyun same_va_bits = 32;
575*4882a593Smuzhiyun else if (kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA))
576*4882a593Smuzhiyun same_va_bits = 33;
577*4882a593Smuzhiyun #endif
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun if (kctx->kbdev->gpu_props.mmu.va_bits < same_va_bits) {
580*4882a593Smuzhiyun err = -EINVAL;
581*4882a593Smuzhiyun goto fail_unlock;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun same_va_pages = (1ULL << (same_va_bits - PAGE_SHIFT)) - 1;
585*4882a593Smuzhiyun /* all have SAME_VA */
586*4882a593Smuzhiyun same_va_reg = kbase_alloc_free_region(kctx, 1,
587*4882a593Smuzhiyun same_va_pages,
588*4882a593Smuzhiyun KBASE_REG_ZONE_SAME_VA);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun if (!same_va_reg) {
591*4882a593Smuzhiyun err = -ENOMEM;
592*4882a593Smuzhiyun goto fail_unlock;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun #ifdef CONFIG_64BIT
596*4882a593Smuzhiyun /* 32-bit clients have exec and custom VA zones */
597*4882a593Smuzhiyun if (kbase_ctx_flag(kctx, KCTX_COMPAT)) {
598*4882a593Smuzhiyun #endif
599*4882a593Smuzhiyun if (gpu_va_limit <= KBASE_REG_ZONE_CUSTOM_VA_BASE) {
600*4882a593Smuzhiyun err = -EINVAL;
601*4882a593Smuzhiyun goto fail_free_same_va;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun /* If the current size of TMEM is out of range of the
604*4882a593Smuzhiyun * virtual address space addressable by the MMU then
605*4882a593Smuzhiyun * we should shrink it to fit
606*4882a593Smuzhiyun */
607*4882a593Smuzhiyun if ((KBASE_REG_ZONE_CUSTOM_VA_BASE + KBASE_REG_ZONE_CUSTOM_VA_SIZE) >= gpu_va_limit)
608*4882a593Smuzhiyun custom_va_size = gpu_va_limit - KBASE_REG_ZONE_CUSTOM_VA_BASE;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun exec_reg = kbase_alloc_free_region(kctx,
611*4882a593Smuzhiyun KBASE_REG_ZONE_EXEC_BASE,
612*4882a593Smuzhiyun KBASE_REG_ZONE_EXEC_SIZE,
613*4882a593Smuzhiyun KBASE_REG_ZONE_EXEC);
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (!exec_reg) {
616*4882a593Smuzhiyun err = -ENOMEM;
617*4882a593Smuzhiyun goto fail_free_same_va;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun custom_va_reg = kbase_alloc_free_region(kctx,
621*4882a593Smuzhiyun KBASE_REG_ZONE_CUSTOM_VA_BASE,
622*4882a593Smuzhiyun custom_va_size, KBASE_REG_ZONE_CUSTOM_VA);
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun if (!custom_va_reg) {
625*4882a593Smuzhiyun err = -ENOMEM;
626*4882a593Smuzhiyun goto fail_free_exec;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun #ifdef CONFIG_64BIT
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun #endif
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun kbase_region_tracker_ds_init(kctx, same_va_reg, exec_reg, custom_va_reg);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun kctx->same_va_end = same_va_pages + 1;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
637*4882a593Smuzhiyun return 0;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun fail_free_exec:
640*4882a593Smuzhiyun kbase_free_alloced_region(exec_reg);
641*4882a593Smuzhiyun fail_free_same_va:
642*4882a593Smuzhiyun kbase_free_alloced_region(same_va_reg);
643*4882a593Smuzhiyun fail_unlock:
644*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
645*4882a593Smuzhiyun return err;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun
kbase_region_tracker_init_jit(struct kbase_context * kctx,u64 jit_va_pages)648*4882a593Smuzhiyun int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun #ifdef CONFIG_64BIT
651*4882a593Smuzhiyun struct kbase_va_region *same_va;
652*4882a593Smuzhiyun struct kbase_va_region *custom_va_reg;
653*4882a593Smuzhiyun u64 same_va_bits;
654*4882a593Smuzhiyun u64 total_va_size;
655*4882a593Smuzhiyun int err;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /*
658*4882a593Smuzhiyun * Nothing to do for 32-bit clients, JIT uses the existing
659*4882a593Smuzhiyun * custom VA zone.
660*4882a593Smuzhiyun */
661*4882a593Smuzhiyun if (kbase_ctx_flag(kctx, KCTX_COMPAT))
662*4882a593Smuzhiyun return 0;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun #if defined(CONFIG_ARM64)
665*4882a593Smuzhiyun same_va_bits = VA_BITS;
666*4882a593Smuzhiyun #elif defined(CONFIG_X86_64)
667*4882a593Smuzhiyun same_va_bits = 47;
668*4882a593Smuzhiyun #elif defined(CONFIG_64BIT)
669*4882a593Smuzhiyun #error Unsupported 64-bit architecture
670*4882a593Smuzhiyun #endif
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun if (kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA))
673*4882a593Smuzhiyun same_va_bits = 33;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun total_va_size = (1ULL << (same_va_bits - PAGE_SHIFT)) - 1;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun /*
680*4882a593Smuzhiyun * Modify the same VA free region after creation. Be careful to ensure
681*4882a593Smuzhiyun * that allocations haven't been made as they could cause an overlap
682*4882a593Smuzhiyun * to happen with existing same VA allocations and the custom VA zone.
683*4882a593Smuzhiyun */
684*4882a593Smuzhiyun same_va = kbase_region_tracker_find_region_base_address(kctx,
685*4882a593Smuzhiyun PAGE_SIZE);
686*4882a593Smuzhiyun if (!same_va) {
687*4882a593Smuzhiyun err = -ENOMEM;
688*4882a593Smuzhiyun goto fail_unlock;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun /* The region flag or region size has changed since creation so bail. */
692*4882a593Smuzhiyun if ((!(same_va->flags & KBASE_REG_FREE)) ||
693*4882a593Smuzhiyun (same_va->nr_pages != total_va_size)) {
694*4882a593Smuzhiyun err = -ENOMEM;
695*4882a593Smuzhiyun goto fail_unlock;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (same_va->nr_pages < jit_va_pages ||
699*4882a593Smuzhiyun kctx->same_va_end < jit_va_pages) {
700*4882a593Smuzhiyun err = -ENOMEM;
701*4882a593Smuzhiyun goto fail_unlock;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun /* It's safe to adjust the same VA zone now */
705*4882a593Smuzhiyun same_va->nr_pages -= jit_va_pages;
706*4882a593Smuzhiyun kctx->same_va_end -= jit_va_pages;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun /*
709*4882a593Smuzhiyun * Create a custom VA zone at the end of the VA for allocations which
710*4882a593Smuzhiyun * JIT can use so it doesn't have to allocate VA from the kernel.
711*4882a593Smuzhiyun */
712*4882a593Smuzhiyun custom_va_reg = kbase_alloc_free_region(kctx,
713*4882a593Smuzhiyun kctx->same_va_end,
714*4882a593Smuzhiyun jit_va_pages,
715*4882a593Smuzhiyun KBASE_REG_ZONE_CUSTOM_VA);
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun if (!custom_va_reg) {
718*4882a593Smuzhiyun /*
719*4882a593Smuzhiyun * The context will be destroyed if we fail here so no point
720*4882a593Smuzhiyun * reverting the change we made to same_va.
721*4882a593Smuzhiyun */
722*4882a593Smuzhiyun err = -ENOMEM;
723*4882a593Smuzhiyun goto fail_unlock;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun kbase_region_tracker_insert(kctx, custom_va_reg);
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
729*4882a593Smuzhiyun return 0;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun fail_unlock:
732*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
733*4882a593Smuzhiyun return err;
734*4882a593Smuzhiyun #else
735*4882a593Smuzhiyun return 0;
736*4882a593Smuzhiyun #endif
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun
kbase_mem_init(struct kbase_device * kbdev)739*4882a593Smuzhiyun int kbase_mem_init(struct kbase_device *kbdev)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun struct kbasep_mem_device *memdev;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kbdev);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun memdev = &kbdev->memdev;
746*4882a593Smuzhiyun kbdev->mem_pool_max_size_default = KBASE_MEM_POOL_MAX_SIZE_KCTX;
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun /* Initialize memory usage */
749*4882a593Smuzhiyun atomic_set(&memdev->used_pages, 0);
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun return kbase_mem_pool_init(&kbdev->mem_pool,
752*4882a593Smuzhiyun KBASE_MEM_POOL_MAX_SIZE_KBDEV, kbdev, NULL);
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun
kbase_mem_halt(struct kbase_device * kbdev)755*4882a593Smuzhiyun void kbase_mem_halt(struct kbase_device *kbdev)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun CSTD_UNUSED(kbdev);
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
kbase_mem_term(struct kbase_device * kbdev)760*4882a593Smuzhiyun void kbase_mem_term(struct kbase_device *kbdev)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun struct kbasep_mem_device *memdev;
763*4882a593Smuzhiyun int pages;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kbdev);
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun memdev = &kbdev->memdev;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun pages = atomic_read(&memdev->used_pages);
770*4882a593Smuzhiyun if (pages != 0)
771*4882a593Smuzhiyun dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun kbase_mem_pool_term(&kbdev->mem_pool);
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_mem_term);
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun /**
782*4882a593Smuzhiyun * @brief Allocate a free region object.
783*4882a593Smuzhiyun *
784*4882a593Smuzhiyun * The allocated object is not part of any list yet, and is flagged as
785*4882a593Smuzhiyun * KBASE_REG_FREE. No mapping is allocated yet.
786*4882a593Smuzhiyun *
787*4882a593Smuzhiyun * zone is KBASE_REG_ZONE_CUSTOM_VA, KBASE_REG_ZONE_SAME_VA, or KBASE_REG_ZONE_EXEC
788*4882a593Smuzhiyun *
789*4882a593Smuzhiyun */
kbase_alloc_free_region(struct kbase_context * kctx,u64 start_pfn,size_t nr_pages,int zone)790*4882a593Smuzhiyun struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone)
791*4882a593Smuzhiyun {
792*4882a593Smuzhiyun struct kbase_va_region *new_reg;
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kctx != NULL);
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun /* zone argument should only contain zone related region flags */
797*4882a593Smuzhiyun KBASE_DEBUG_ASSERT((zone & ~KBASE_REG_ZONE_MASK) == 0);
798*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(nr_pages > 0);
799*4882a593Smuzhiyun /* 64-bit address range is the max */
800*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= (U64_MAX / PAGE_SIZE));
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun new_reg = kzalloc(sizeof(*new_reg), GFP_KERNEL);
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun if (!new_reg)
805*4882a593Smuzhiyun return NULL;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun new_reg->cpu_alloc = NULL; /* no alloc bound yet */
808*4882a593Smuzhiyun new_reg->gpu_alloc = NULL; /* no alloc bound yet */
809*4882a593Smuzhiyun new_reg->kctx = kctx;
810*4882a593Smuzhiyun new_reg->flags = zone | KBASE_REG_FREE;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun new_reg->flags |= KBASE_REG_GROWABLE;
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun new_reg->start_pfn = start_pfn;
815*4882a593Smuzhiyun new_reg->nr_pages = nr_pages;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun return new_reg;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_alloc_free_region);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun /**
823*4882a593Smuzhiyun * @brief Free a region object.
824*4882a593Smuzhiyun *
825*4882a593Smuzhiyun * The described region must be freed of any mapping.
826*4882a593Smuzhiyun *
827*4882a593Smuzhiyun * If the region is not flagged as KBASE_REG_FREE, the region's
828*4882a593Smuzhiyun * alloc object will be released.
829*4882a593Smuzhiyun * It is a bug if no alloc object exists for non-free regions.
830*4882a593Smuzhiyun *
831*4882a593Smuzhiyun */
kbase_free_alloced_region(struct kbase_va_region * reg)832*4882a593Smuzhiyun void kbase_free_alloced_region(struct kbase_va_region *reg)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun if (!(reg->flags & KBASE_REG_FREE)) {
835*4882a593Smuzhiyun /*
836*4882a593Smuzhiyun * The physical allocation should have been removed from the
837*4882a593Smuzhiyun * eviction list before this function is called. However, in the
838*4882a593Smuzhiyun * case of abnormal process termination or the app leaking the
839*4882a593Smuzhiyun * memory kbase_mem_free_region is not called so it can still be
840*4882a593Smuzhiyun * on the list at termination time of the region tracker.
841*4882a593Smuzhiyun */
842*4882a593Smuzhiyun if (!list_empty(®->gpu_alloc->evict_node)) {
843*4882a593Smuzhiyun /*
844*4882a593Smuzhiyun * Unlink the physical allocation before unmaking it
845*4882a593Smuzhiyun * evictable so that the allocation isn't grown back to
846*4882a593Smuzhiyun * its last backed size as we're going to unmap it
847*4882a593Smuzhiyun * anyway.
848*4882a593Smuzhiyun */
849*4882a593Smuzhiyun reg->cpu_alloc->reg = NULL;
850*4882a593Smuzhiyun if (reg->cpu_alloc != reg->gpu_alloc)
851*4882a593Smuzhiyun reg->gpu_alloc->reg = NULL;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun /*
854*4882a593Smuzhiyun * If a region has been made evictable then we must
855*4882a593Smuzhiyun * unmake it before trying to free it.
856*4882a593Smuzhiyun * If the memory hasn't been reclaimed it will be
857*4882a593Smuzhiyun * unmapped and freed below, if it has been reclaimed
858*4882a593Smuzhiyun * then the operations below are no-ops.
859*4882a593Smuzhiyun */
860*4882a593Smuzhiyun if (reg->flags & KBASE_REG_DONT_NEED) {
861*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(reg->cpu_alloc->type ==
862*4882a593Smuzhiyun KBASE_MEM_TYPE_NATIVE);
863*4882a593Smuzhiyun kbase_mem_evictable_unmake(reg->gpu_alloc);
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun /*
868*4882a593Smuzhiyun * Remove the region from the sticky resource metadata
869*4882a593Smuzhiyun * list should it be there.
870*4882a593Smuzhiyun */
871*4882a593Smuzhiyun kbase_sticky_resource_release(reg->kctx, NULL,
872*4882a593Smuzhiyun reg->start_pfn << PAGE_SHIFT);
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun kbase_mem_phy_alloc_put(reg->cpu_alloc);
875*4882a593Smuzhiyun kbase_mem_phy_alloc_put(reg->gpu_alloc);
876*4882a593Smuzhiyun /* To detect use-after-free in debug builds */
877*4882a593Smuzhiyun KBASE_DEBUG_CODE(reg->flags |= KBASE_REG_FREE);
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun kfree(reg);
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_free_alloced_region);
883*4882a593Smuzhiyun
kbase_gpu_mmap(struct kbase_context * kctx,struct kbase_va_region * reg,u64 addr,size_t nr_pages,size_t align)884*4882a593Smuzhiyun int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, u64 addr, size_t nr_pages, size_t align)
885*4882a593Smuzhiyun {
886*4882a593Smuzhiyun int err;
887*4882a593Smuzhiyun size_t i = 0;
888*4882a593Smuzhiyun unsigned long attr;
889*4882a593Smuzhiyun unsigned long mask = ~KBASE_REG_MEMATTR_MASK;
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun if ((kctx->kbdev->system_coherency == COHERENCY_ACE) &&
892*4882a593Smuzhiyun (reg->flags & KBASE_REG_SHARE_BOTH))
893*4882a593Smuzhiyun attr = KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_OUTER_WA);
894*4882a593Smuzhiyun else
895*4882a593Smuzhiyun attr = KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_WRITE_ALLOC);
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != kctx);
898*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != reg);
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun err = kbase_add_va_region(kctx, reg, addr, nr_pages, align);
901*4882a593Smuzhiyun if (err)
902*4882a593Smuzhiyun return err;
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun if (reg->gpu_alloc->type == KBASE_MEM_TYPE_ALIAS) {
905*4882a593Smuzhiyun u64 stride;
906*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun alloc = reg->gpu_alloc;
909*4882a593Smuzhiyun stride = alloc->imported.alias.stride;
910*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->imported.alias.aliased);
911*4882a593Smuzhiyun for (i = 0; i < alloc->imported.alias.nents; i++) {
912*4882a593Smuzhiyun if (alloc->imported.alias.aliased[i].alloc) {
913*4882a593Smuzhiyun err = kbase_mmu_insert_pages(kctx,
914*4882a593Smuzhiyun reg->start_pfn + (i * stride),
915*4882a593Smuzhiyun alloc->imported.alias.aliased[i].alloc->pages + alloc->imported.alias.aliased[i].offset,
916*4882a593Smuzhiyun alloc->imported.alias.aliased[i].length,
917*4882a593Smuzhiyun reg->flags);
918*4882a593Smuzhiyun if (err)
919*4882a593Smuzhiyun goto bad_insert;
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun kbase_mem_phy_alloc_gpu_mapped(alloc->imported.alias.aliased[i].alloc);
922*4882a593Smuzhiyun } else {
923*4882a593Smuzhiyun err = kbase_mmu_insert_single_page(kctx,
924*4882a593Smuzhiyun reg->start_pfn + i * stride,
925*4882a593Smuzhiyun page_to_phys(kctx->aliasing_sink_page),
926*4882a593Smuzhiyun alloc->imported.alias.aliased[i].length,
927*4882a593Smuzhiyun (reg->flags & mask) | attr);
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun if (err)
930*4882a593Smuzhiyun goto bad_insert;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun } else {
934*4882a593Smuzhiyun err = kbase_mmu_insert_pages(kctx, reg->start_pfn,
935*4882a593Smuzhiyun kbase_get_gpu_phy_pages(reg),
936*4882a593Smuzhiyun kbase_reg_current_backed_size(reg),
937*4882a593Smuzhiyun reg->flags);
938*4882a593Smuzhiyun if (err)
939*4882a593Smuzhiyun goto bad_insert;
940*4882a593Smuzhiyun kbase_mem_phy_alloc_gpu_mapped(reg->gpu_alloc);
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun return err;
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun bad_insert:
946*4882a593Smuzhiyun if (reg->gpu_alloc->type == KBASE_MEM_TYPE_ALIAS) {
947*4882a593Smuzhiyun u64 stride;
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun stride = reg->gpu_alloc->imported.alias.stride;
950*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(reg->gpu_alloc->imported.alias.aliased);
951*4882a593Smuzhiyun while (i--)
952*4882a593Smuzhiyun if (reg->gpu_alloc->imported.alias.aliased[i].alloc) {
953*4882a593Smuzhiyun kbase_mmu_teardown_pages(kctx, reg->start_pfn + (i * stride), reg->gpu_alloc->imported.alias.aliased[i].length);
954*4882a593Smuzhiyun kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc->imported.alias.aliased[i].alloc);
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun kbase_remove_va_region(kctx, reg);
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun return err;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_gpu_mmap);
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun static void kbase_jd_user_buf_unmap(struct kbase_context *kctx,
966*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc, bool writeable);
967*4882a593Smuzhiyun
kbase_gpu_munmap(struct kbase_context * kctx,struct kbase_va_region * reg)968*4882a593Smuzhiyun int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg)
969*4882a593Smuzhiyun {
970*4882a593Smuzhiyun int err;
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun if (reg->start_pfn == 0)
973*4882a593Smuzhiyun return 0;
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun if (reg->gpu_alloc && reg->gpu_alloc->type == KBASE_MEM_TYPE_ALIAS) {
976*4882a593Smuzhiyun size_t i;
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, reg->nr_pages);
979*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(reg->gpu_alloc->imported.alias.aliased);
980*4882a593Smuzhiyun for (i = 0; i < reg->gpu_alloc->imported.alias.nents; i++)
981*4882a593Smuzhiyun if (reg->gpu_alloc->imported.alias.aliased[i].alloc)
982*4882a593Smuzhiyun kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc->imported.alias.aliased[i].alloc);
983*4882a593Smuzhiyun } else {
984*4882a593Smuzhiyun err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, kbase_reg_current_backed_size(reg));
985*4882a593Smuzhiyun kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc);
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (reg->gpu_alloc && reg->gpu_alloc->type ==
989*4882a593Smuzhiyun KBASE_MEM_TYPE_IMPORTED_USER_BUF) {
990*4882a593Smuzhiyun struct kbase_alloc_import_user_buf *user_buf =
991*4882a593Smuzhiyun ®->gpu_alloc->imported.user_buf;
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun if (user_buf->current_mapping_usage_count & PINNED_ON_IMPORT) {
994*4882a593Smuzhiyun user_buf->current_mapping_usage_count &=
995*4882a593Smuzhiyun ~PINNED_ON_IMPORT;
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun kbase_jd_user_buf_unmap(kctx, reg->gpu_alloc,
998*4882a593Smuzhiyun (reg->flags & KBASE_REG_GPU_WR));
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun }
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun if (err)
1003*4882a593Smuzhiyun return err;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun err = kbase_remove_va_region(kctx, reg);
1006*4882a593Smuzhiyun return err;
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun
kbasep_find_enclosing_cpu_mapping(struct kbase_context * kctx,unsigned long uaddr,size_t size,u64 * offset)1009*4882a593Smuzhiyun static struct kbase_cpu_mapping *kbasep_find_enclosing_cpu_mapping(
1010*4882a593Smuzhiyun struct kbase_context *kctx,
1011*4882a593Smuzhiyun unsigned long uaddr, size_t size, u64 *offset)
1012*4882a593Smuzhiyun {
1013*4882a593Smuzhiyun struct vm_area_struct *vma;
1014*4882a593Smuzhiyun struct kbase_cpu_mapping *map;
1015*4882a593Smuzhiyun unsigned long vm_pgoff_in_region;
1016*4882a593Smuzhiyun unsigned long vm_off_in_region;
1017*4882a593Smuzhiyun unsigned long map_start;
1018*4882a593Smuzhiyun size_t map_size;
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun lockdep_assert_held(¤t->mm->mmap_lock);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun if ((uintptr_t) uaddr + size < (uintptr_t) uaddr) /* overflow check */
1023*4882a593Smuzhiyun return NULL;
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun vma = find_vma_intersection(current->mm, uaddr, uaddr+size);
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun if (!vma || vma->vm_start > uaddr)
1028*4882a593Smuzhiyun return NULL;
1029*4882a593Smuzhiyun if (vma->vm_ops != &kbase_vm_ops)
1030*4882a593Smuzhiyun /* Not ours! */
1031*4882a593Smuzhiyun return NULL;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun map = vma->vm_private_data;
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun if (map->kctx != kctx)
1036*4882a593Smuzhiyun /* Not from this context! */
1037*4882a593Smuzhiyun return NULL;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun vm_pgoff_in_region = vma->vm_pgoff - map->region->start_pfn;
1040*4882a593Smuzhiyun vm_off_in_region = vm_pgoff_in_region << PAGE_SHIFT;
1041*4882a593Smuzhiyun map_start = vma->vm_start - vm_off_in_region;
1042*4882a593Smuzhiyun map_size = map->region->nr_pages << PAGE_SHIFT;
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun if ((uaddr + size) > (map_start + map_size))
1045*4882a593Smuzhiyun /* Not within the CPU mapping */
1046*4882a593Smuzhiyun return NULL;
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun *offset = (uaddr - vma->vm_start) + vm_off_in_region;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun return map;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
kbasep_find_enclosing_cpu_mapping_offset(struct kbase_context * kctx,unsigned long uaddr,size_t size,u64 * offset)1053*4882a593Smuzhiyun int kbasep_find_enclosing_cpu_mapping_offset(
1054*4882a593Smuzhiyun struct kbase_context *kctx,
1055*4882a593Smuzhiyun unsigned long uaddr, size_t size, u64 *offset)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun struct kbase_cpu_mapping *map;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun kbase_os_mem_map_lock(kctx);
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun map = kbasep_find_enclosing_cpu_mapping(kctx, uaddr, size, offset);
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun kbase_os_mem_map_unlock(kctx);
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun if (!map)
1066*4882a593Smuzhiyun return -EINVAL;
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun return 0;
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbasep_find_enclosing_cpu_mapping_offset);
1072*4882a593Smuzhiyun
kbase_sync_single(struct kbase_context * kctx,phys_addr_t cpu_pa,phys_addr_t gpu_pa,off_t offset,size_t size,enum kbase_sync_type sync_fn)1073*4882a593Smuzhiyun void kbase_sync_single(struct kbase_context *kctx,
1074*4882a593Smuzhiyun phys_addr_t cpu_pa, phys_addr_t gpu_pa,
1075*4882a593Smuzhiyun off_t offset, size_t size, enum kbase_sync_type sync_fn)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun struct page *cpu_page;
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun cpu_page = pfn_to_page(PFN_DOWN(cpu_pa));
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun if (likely(cpu_pa == gpu_pa)) {
1082*4882a593Smuzhiyun dma_addr_t dma_addr;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun BUG_ON(!cpu_page);
1085*4882a593Smuzhiyun BUG_ON(offset + size > PAGE_SIZE);
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun dma_addr = kbase_dma_addr(cpu_page) + offset;
1088*4882a593Smuzhiyun if (sync_fn == KBASE_SYNC_TO_CPU)
1089*4882a593Smuzhiyun dma_sync_single_for_cpu(kctx->kbdev->dev, dma_addr,
1090*4882a593Smuzhiyun size, DMA_BIDIRECTIONAL);
1091*4882a593Smuzhiyun else if (sync_fn == KBASE_SYNC_TO_DEVICE)
1092*4882a593Smuzhiyun dma_sync_single_for_device(kctx->kbdev->dev, dma_addr,
1093*4882a593Smuzhiyun size, DMA_BIDIRECTIONAL);
1094*4882a593Smuzhiyun } else {
1095*4882a593Smuzhiyun void *src = NULL;
1096*4882a593Smuzhiyun void *dst = NULL;
1097*4882a593Smuzhiyun struct page *gpu_page;
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun if (WARN(!gpu_pa, "No GPU PA found for infinite cache op"))
1100*4882a593Smuzhiyun return;
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun gpu_page = pfn_to_page(PFN_DOWN(gpu_pa));
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun if (sync_fn == KBASE_SYNC_TO_DEVICE) {
1105*4882a593Smuzhiyun src = ((unsigned char *)kmap(cpu_page)) + offset;
1106*4882a593Smuzhiyun dst = ((unsigned char *)kmap(gpu_page)) + offset;
1107*4882a593Smuzhiyun } else if (sync_fn == KBASE_SYNC_TO_CPU) {
1108*4882a593Smuzhiyun dma_sync_single_for_cpu(kctx->kbdev->dev,
1109*4882a593Smuzhiyun kbase_dma_addr(gpu_page) + offset,
1110*4882a593Smuzhiyun size, DMA_BIDIRECTIONAL);
1111*4882a593Smuzhiyun src = ((unsigned char *)kmap(gpu_page)) + offset;
1112*4882a593Smuzhiyun dst = ((unsigned char *)kmap(cpu_page)) + offset;
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun memcpy(dst, src, size);
1115*4882a593Smuzhiyun kunmap(gpu_page);
1116*4882a593Smuzhiyun kunmap(cpu_page);
1117*4882a593Smuzhiyun if (sync_fn == KBASE_SYNC_TO_DEVICE)
1118*4882a593Smuzhiyun dma_sync_single_for_device(kctx->kbdev->dev,
1119*4882a593Smuzhiyun kbase_dma_addr(gpu_page) + offset,
1120*4882a593Smuzhiyun size, DMA_BIDIRECTIONAL);
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun
kbase_do_syncset(struct kbase_context * kctx,struct basep_syncset * sset,enum kbase_sync_type sync_fn)1124*4882a593Smuzhiyun static int kbase_do_syncset(struct kbase_context *kctx,
1125*4882a593Smuzhiyun struct basep_syncset *sset, enum kbase_sync_type sync_fn)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun int err = 0;
1128*4882a593Smuzhiyun struct kbase_va_region *reg;
1129*4882a593Smuzhiyun struct kbase_cpu_mapping *map;
1130*4882a593Smuzhiyun unsigned long start;
1131*4882a593Smuzhiyun size_t size;
1132*4882a593Smuzhiyun phys_addr_t *cpu_pa;
1133*4882a593Smuzhiyun phys_addr_t *gpu_pa;
1134*4882a593Smuzhiyun u64 page_off, page_count;
1135*4882a593Smuzhiyun u64 i;
1136*4882a593Smuzhiyun u64 offset;
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun kbase_os_mem_map_lock(kctx);
1139*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun /* find the region where the virtual address is contained */
1142*4882a593Smuzhiyun reg = kbase_region_tracker_find_region_enclosing_address(kctx,
1143*4882a593Smuzhiyun sset->mem_handle.basep.handle);
1144*4882a593Smuzhiyun if (!reg) {
1145*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "Can't find region at VA 0x%016llX",
1146*4882a593Smuzhiyun sset->mem_handle.basep.handle);
1147*4882a593Smuzhiyun err = -EINVAL;
1148*4882a593Smuzhiyun goto out_unlock;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun if (!(reg->flags & KBASE_REG_CPU_CACHED))
1152*4882a593Smuzhiyun goto out_unlock;
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun start = (uintptr_t)sset->user_addr;
1155*4882a593Smuzhiyun size = (size_t)sset->size;
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun map = kbasep_find_enclosing_cpu_mapping(kctx, start, size, &offset);
1158*4882a593Smuzhiyun if (!map) {
1159*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "Can't find CPU mapping 0x%016lX for VA 0x%016llX",
1160*4882a593Smuzhiyun start, sset->mem_handle.basep.handle);
1161*4882a593Smuzhiyun err = -EINVAL;
1162*4882a593Smuzhiyun goto out_unlock;
1163*4882a593Smuzhiyun }
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun page_off = offset >> PAGE_SHIFT;
1166*4882a593Smuzhiyun offset &= ~PAGE_MASK;
1167*4882a593Smuzhiyun page_count = (size + offset + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
1168*4882a593Smuzhiyun cpu_pa = kbase_get_cpu_phy_pages(reg);
1169*4882a593Smuzhiyun gpu_pa = kbase_get_gpu_phy_pages(reg);
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun if (page_off > reg->nr_pages ||
1172*4882a593Smuzhiyun page_off + page_count > reg->nr_pages) {
1173*4882a593Smuzhiyun /* Sync overflows the region */
1174*4882a593Smuzhiyun err = -EINVAL;
1175*4882a593Smuzhiyun goto out_unlock;
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun /* Sync first page */
1179*4882a593Smuzhiyun if (cpu_pa[page_off]) {
1180*4882a593Smuzhiyun size_t sz = MIN(((size_t) PAGE_SIZE - offset), size);
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun kbase_sync_single(kctx, cpu_pa[page_off], gpu_pa[page_off],
1183*4882a593Smuzhiyun offset, sz, sync_fn);
1184*4882a593Smuzhiyun }
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun /* Sync middle pages (if any) */
1187*4882a593Smuzhiyun for (i = 1; page_count > 2 && i < page_count - 1; i++) {
1188*4882a593Smuzhiyun /* we grow upwards, so bail on first non-present page */
1189*4882a593Smuzhiyun if (!cpu_pa[page_off + i])
1190*4882a593Smuzhiyun break;
1191*4882a593Smuzhiyun
1192*4882a593Smuzhiyun kbase_sync_single(kctx, cpu_pa[page_off + i],
1193*4882a593Smuzhiyun gpu_pa[page_off + i], 0, PAGE_SIZE, sync_fn);
1194*4882a593Smuzhiyun }
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun /* Sync last page (if any) */
1197*4882a593Smuzhiyun if (page_count > 1 && cpu_pa[page_off + page_count - 1]) {
1198*4882a593Smuzhiyun size_t sz = ((start + size - 1) & ~PAGE_MASK) + 1;
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun kbase_sync_single(kctx, cpu_pa[page_off + page_count - 1],
1201*4882a593Smuzhiyun gpu_pa[page_off + page_count - 1], 0, sz,
1202*4882a593Smuzhiyun sync_fn);
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun out_unlock:
1206*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
1207*4882a593Smuzhiyun kbase_os_mem_map_unlock(kctx);
1208*4882a593Smuzhiyun return err;
1209*4882a593Smuzhiyun }
1210*4882a593Smuzhiyun
kbase_sync_now(struct kbase_context * kctx,struct basep_syncset * sset)1211*4882a593Smuzhiyun int kbase_sync_now(struct kbase_context *kctx, struct basep_syncset *sset)
1212*4882a593Smuzhiyun {
1213*4882a593Smuzhiyun int err = -EINVAL;
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kctx != NULL);
1216*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(sset != NULL);
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun if (sset->mem_handle.basep.handle & ~PAGE_MASK) {
1219*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev,
1220*4882a593Smuzhiyun "mem_handle: passed parameter is invalid");
1221*4882a593Smuzhiyun return -EINVAL;
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun switch (sset->type) {
1225*4882a593Smuzhiyun case BASE_SYNCSET_OP_MSYNC:
1226*4882a593Smuzhiyun err = kbase_do_syncset(kctx, sset, KBASE_SYNC_TO_DEVICE);
1227*4882a593Smuzhiyun break;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun case BASE_SYNCSET_OP_CSYNC:
1230*4882a593Smuzhiyun err = kbase_do_syncset(kctx, sset, KBASE_SYNC_TO_CPU);
1231*4882a593Smuzhiyun break;
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun default:
1234*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "Unknown msync op %d\n", sset->type);
1235*4882a593Smuzhiyun break;
1236*4882a593Smuzhiyun }
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun return err;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_sync_now);
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun /* vm lock must be held */
kbase_mem_free_region(struct kbase_context * kctx,struct kbase_va_region * reg)1244*4882a593Smuzhiyun int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg)
1245*4882a593Smuzhiyun {
1246*4882a593Smuzhiyun int err;
1247*4882a593Smuzhiyun
1248*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != kctx);
1249*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != reg);
1250*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
1251*4882a593Smuzhiyun
1252*4882a593Smuzhiyun /*
1253*4882a593Smuzhiyun * Unlink the physical allocation before unmaking it evictable so
1254*4882a593Smuzhiyun * that the allocation isn't grown back to its last backed size
1255*4882a593Smuzhiyun * as we're going to unmap it anyway.
1256*4882a593Smuzhiyun */
1257*4882a593Smuzhiyun reg->cpu_alloc->reg = NULL;
1258*4882a593Smuzhiyun if (reg->cpu_alloc != reg->gpu_alloc)
1259*4882a593Smuzhiyun reg->gpu_alloc->reg = NULL;
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun /*
1262*4882a593Smuzhiyun * If a region has been made evictable then we must unmake it
1263*4882a593Smuzhiyun * before trying to free it.
1264*4882a593Smuzhiyun * If the memory hasn't been reclaimed it will be unmapped and freed
1265*4882a593Smuzhiyun * below, if it has been reclaimed then the operations below are no-ops.
1266*4882a593Smuzhiyun */
1267*4882a593Smuzhiyun if (reg->flags & KBASE_REG_DONT_NEED) {
1268*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(reg->cpu_alloc->type ==
1269*4882a593Smuzhiyun KBASE_MEM_TYPE_NATIVE);
1270*4882a593Smuzhiyun kbase_mem_evictable_unmake(reg->gpu_alloc);
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun err = kbase_gpu_munmap(kctx, reg);
1274*4882a593Smuzhiyun if (err) {
1275*4882a593Smuzhiyun dev_warn(reg->kctx->kbdev->dev, "Could not unmap from the GPU...\n");
1276*4882a593Smuzhiyun goto out;
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun
1279*4882a593Smuzhiyun /* This will also free the physical pages */
1280*4882a593Smuzhiyun kbase_free_alloced_region(reg);
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun out:
1283*4882a593Smuzhiyun return err;
1284*4882a593Smuzhiyun }
1285*4882a593Smuzhiyun
1286*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_mem_free_region);
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun /**
1289*4882a593Smuzhiyun * @brief Free the region from the GPU and unregister it.
1290*4882a593Smuzhiyun *
1291*4882a593Smuzhiyun * This function implements the free operation on a memory segment.
1292*4882a593Smuzhiyun * It will loudly fail if called with outstanding mappings.
1293*4882a593Smuzhiyun */
kbase_mem_free(struct kbase_context * kctx,u64 gpu_addr)1294*4882a593Smuzhiyun int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
1295*4882a593Smuzhiyun {
1296*4882a593Smuzhiyun int err = 0;
1297*4882a593Smuzhiyun struct kbase_va_region *reg;
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kctx != NULL);
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun if ((gpu_addr & ~PAGE_MASK) && (gpu_addr >= PAGE_SIZE)) {
1302*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "kbase_mem_free: gpu_addr parameter is invalid");
1303*4882a593Smuzhiyun return -EINVAL;
1304*4882a593Smuzhiyun }
1305*4882a593Smuzhiyun
1306*4882a593Smuzhiyun if (0 == gpu_addr) {
1307*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using kbase_mem_free\n");
1308*4882a593Smuzhiyun return -EINVAL;
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
1311*4882a593Smuzhiyun
1312*4882a593Smuzhiyun if (gpu_addr >= BASE_MEM_COOKIE_BASE &&
1313*4882a593Smuzhiyun gpu_addr < BASE_MEM_FIRST_FREE_ADDRESS) {
1314*4882a593Smuzhiyun int cookie = PFN_DOWN(gpu_addr - BASE_MEM_COOKIE_BASE);
1315*4882a593Smuzhiyun
1316*4882a593Smuzhiyun reg = kctx->pending_regions[cookie];
1317*4882a593Smuzhiyun if (!reg) {
1318*4882a593Smuzhiyun err = -EINVAL;
1319*4882a593Smuzhiyun goto out_unlock;
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun /* ask to unlink the cookie as we'll free it */
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun kctx->pending_regions[cookie] = NULL;
1325*4882a593Smuzhiyun kctx->cookies |= (1UL << cookie);
1326*4882a593Smuzhiyun
1327*4882a593Smuzhiyun kbase_free_alloced_region(reg);
1328*4882a593Smuzhiyun } else {
1329*4882a593Smuzhiyun /* A real GPU va */
1330*4882a593Smuzhiyun /* Validate the region */
1331*4882a593Smuzhiyun reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr);
1332*4882a593Smuzhiyun if (!reg || (reg->flags & KBASE_REG_FREE)) {
1333*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "kbase_mem_free called with nonexistent gpu_addr 0x%llX",
1334*4882a593Smuzhiyun gpu_addr);
1335*4882a593Smuzhiyun err = -EINVAL;
1336*4882a593Smuzhiyun goto out_unlock;
1337*4882a593Smuzhiyun }
1338*4882a593Smuzhiyun
1339*4882a593Smuzhiyun if ((reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_SAME_VA) {
1340*4882a593Smuzhiyun /* SAME_VA must be freed through munmap */
1341*4882a593Smuzhiyun dev_warn(kctx->kbdev->dev, "%s called on SAME_VA memory 0x%llX", __func__,
1342*4882a593Smuzhiyun gpu_addr);
1343*4882a593Smuzhiyun err = -EINVAL;
1344*4882a593Smuzhiyun goto out_unlock;
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun err = kbase_mem_free_region(kctx, reg);
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun out_unlock:
1350*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
1351*4882a593Smuzhiyun return err;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_mem_free);
1355*4882a593Smuzhiyun
kbase_update_region_flags(struct kbase_context * kctx,struct kbase_va_region * reg,unsigned long flags)1356*4882a593Smuzhiyun int kbase_update_region_flags(struct kbase_context *kctx,
1357*4882a593Smuzhiyun struct kbase_va_region *reg, unsigned long flags)
1358*4882a593Smuzhiyun {
1359*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != reg);
1360*4882a593Smuzhiyun KBASE_DEBUG_ASSERT((flags & ~((1ul << BASE_MEM_FLAGS_NR_BITS) - 1)) == 0);
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun reg->flags |= kbase_cache_enabled(flags, reg->nr_pages);
1363*4882a593Smuzhiyun /* all memory is now growable */
1364*4882a593Smuzhiyun reg->flags |= KBASE_REG_GROWABLE;
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun if (flags & BASE_MEM_GROW_ON_GPF)
1367*4882a593Smuzhiyun reg->flags |= KBASE_REG_PF_GROW;
1368*4882a593Smuzhiyun
1369*4882a593Smuzhiyun if (flags & BASE_MEM_PROT_CPU_WR)
1370*4882a593Smuzhiyun reg->flags |= KBASE_REG_CPU_WR;
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun if (flags & BASE_MEM_PROT_CPU_RD)
1373*4882a593Smuzhiyun reg->flags |= KBASE_REG_CPU_RD;
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun if (flags & BASE_MEM_PROT_GPU_WR)
1376*4882a593Smuzhiyun reg->flags |= KBASE_REG_GPU_WR;
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun if (flags & BASE_MEM_PROT_GPU_RD)
1379*4882a593Smuzhiyun reg->flags |= KBASE_REG_GPU_RD;
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun if (0 == (flags & BASE_MEM_PROT_GPU_EX))
1382*4882a593Smuzhiyun reg->flags |= KBASE_REG_GPU_NX;
1383*4882a593Smuzhiyun
1384*4882a593Smuzhiyun if (!kbase_device_is_cpu_coherent(kctx->kbdev)) {
1385*4882a593Smuzhiyun if (flags & BASE_MEM_COHERENT_SYSTEM_REQUIRED)
1386*4882a593Smuzhiyun return -EINVAL;
1387*4882a593Smuzhiyun } else if (flags & (BASE_MEM_COHERENT_SYSTEM |
1388*4882a593Smuzhiyun BASE_MEM_COHERENT_SYSTEM_REQUIRED)) {
1389*4882a593Smuzhiyun reg->flags |= KBASE_REG_SHARE_BOTH;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun if (!(reg->flags & KBASE_REG_SHARE_BOTH) &&
1393*4882a593Smuzhiyun flags & BASE_MEM_COHERENT_LOCAL) {
1394*4882a593Smuzhiyun reg->flags |= KBASE_REG_SHARE_IN;
1395*4882a593Smuzhiyun }
1396*4882a593Smuzhiyun
1397*4882a593Smuzhiyun /* Set up default MEMATTR usage */
1398*4882a593Smuzhiyun if (kctx->kbdev->system_coherency == COHERENCY_ACE &&
1399*4882a593Smuzhiyun (reg->flags & KBASE_REG_SHARE_BOTH)) {
1400*4882a593Smuzhiyun reg->flags |=
1401*4882a593Smuzhiyun KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT_ACE);
1402*4882a593Smuzhiyun } else {
1403*4882a593Smuzhiyun reg->flags |=
1404*4882a593Smuzhiyun KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT);
1405*4882a593Smuzhiyun }
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun return 0;
1408*4882a593Smuzhiyun }
1409*4882a593Smuzhiyun
kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc * alloc,size_t nr_pages_requested)1410*4882a593Smuzhiyun int kbase_alloc_phy_pages_helper(
1411*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc,
1412*4882a593Smuzhiyun size_t nr_pages_requested)
1413*4882a593Smuzhiyun {
1414*4882a593Smuzhiyun int new_page_count __maybe_unused;
1415*4882a593Smuzhiyun size_t old_page_count = alloc->nents;
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE);
1418*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->imported.kctx);
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun if (nr_pages_requested == 0)
1421*4882a593Smuzhiyun goto done; /*nothing to do*/
1422*4882a593Smuzhiyun
1423*4882a593Smuzhiyun new_page_count = kbase_atomic_add_pages(
1424*4882a593Smuzhiyun nr_pages_requested, &alloc->imported.kctx->used_pages);
1425*4882a593Smuzhiyun kbase_atomic_add_pages(nr_pages_requested, &alloc->imported.kctx->kbdev->memdev.used_pages);
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun /* Increase mm counters before we allocate pages so that this
1428*4882a593Smuzhiyun * allocation is visible to the OOM killer */
1429*4882a593Smuzhiyun kbase_process_page_usage_inc(alloc->imported.kctx, nr_pages_requested);
1430*4882a593Smuzhiyun
1431*4882a593Smuzhiyun if (kbase_mem_pool_alloc_pages(&alloc->imported.kctx->mem_pool,
1432*4882a593Smuzhiyun nr_pages_requested, alloc->pages + old_page_count) != 0)
1433*4882a593Smuzhiyun goto no_alloc;
1434*4882a593Smuzhiyun
1435*4882a593Smuzhiyun KBASE_TLSTREAM_AUX_PAGESALLOC(
1436*4882a593Smuzhiyun (u32)alloc->imported.kctx->id,
1437*4882a593Smuzhiyun (u64)new_page_count);
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun alloc->nents += nr_pages_requested;
1440*4882a593Smuzhiyun done:
1441*4882a593Smuzhiyun return 0;
1442*4882a593Smuzhiyun
1443*4882a593Smuzhiyun no_alloc:
1444*4882a593Smuzhiyun kbase_process_page_usage_dec(alloc->imported.kctx, nr_pages_requested);
1445*4882a593Smuzhiyun kbase_atomic_sub_pages(nr_pages_requested, &alloc->imported.kctx->used_pages);
1446*4882a593Smuzhiyun kbase_atomic_sub_pages(nr_pages_requested, &alloc->imported.kctx->kbdev->memdev.used_pages);
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun return -ENOMEM;
1449*4882a593Smuzhiyun }
1450*4882a593Smuzhiyun
kbase_free_phy_pages_helper(struct kbase_mem_phy_alloc * alloc,size_t nr_pages_to_free)1451*4882a593Smuzhiyun int kbase_free_phy_pages_helper(
1452*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc,
1453*4882a593Smuzhiyun size_t nr_pages_to_free)
1454*4882a593Smuzhiyun {
1455*4882a593Smuzhiyun struct kbase_context *kctx = alloc->imported.kctx;
1456*4882a593Smuzhiyun bool syncback;
1457*4882a593Smuzhiyun bool reclaimed = (alloc->evicted != 0);
1458*4882a593Smuzhiyun phys_addr_t *start_free;
1459*4882a593Smuzhiyun int new_page_count __maybe_unused;
1460*4882a593Smuzhiyun
1461*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE);
1462*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->imported.kctx);
1463*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->nents >= nr_pages_to_free);
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun /* early out if nothing to do */
1466*4882a593Smuzhiyun if (0 == nr_pages_to_free)
1467*4882a593Smuzhiyun return 0;
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun start_free = alloc->pages + alloc->nents - nr_pages_to_free;
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun syncback = alloc->properties & KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED;
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun kbase_mem_pool_free_pages(&kctx->mem_pool,
1474*4882a593Smuzhiyun nr_pages_to_free,
1475*4882a593Smuzhiyun start_free,
1476*4882a593Smuzhiyun syncback,
1477*4882a593Smuzhiyun reclaimed);
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun alloc->nents -= nr_pages_to_free;
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun /*
1482*4882a593Smuzhiyun * If the allocation was not evicted (i.e. evicted == 0) then
1483*4882a593Smuzhiyun * the page accounting needs to be done.
1484*4882a593Smuzhiyun */
1485*4882a593Smuzhiyun if (!reclaimed) {
1486*4882a593Smuzhiyun kbase_process_page_usage_dec(kctx, nr_pages_to_free);
1487*4882a593Smuzhiyun new_page_count = kbase_atomic_sub_pages(nr_pages_to_free,
1488*4882a593Smuzhiyun &kctx->used_pages);
1489*4882a593Smuzhiyun kbase_atomic_sub_pages(nr_pages_to_free,
1490*4882a593Smuzhiyun &kctx->kbdev->memdev.used_pages);
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun KBASE_TLSTREAM_AUX_PAGESALLOC(
1493*4882a593Smuzhiyun (u32)kctx->id,
1494*4882a593Smuzhiyun (u64)new_page_count);
1495*4882a593Smuzhiyun }
1496*4882a593Smuzhiyun
1497*4882a593Smuzhiyun return 0;
1498*4882a593Smuzhiyun }
1499*4882a593Smuzhiyun
kbase_mem_kref_free(struct kref * kref)1500*4882a593Smuzhiyun void kbase_mem_kref_free(struct kref *kref)
1501*4882a593Smuzhiyun {
1502*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc;
1503*4882a593Smuzhiyun
1504*4882a593Smuzhiyun alloc = container_of(kref, struct kbase_mem_phy_alloc, kref);
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun switch (alloc->type) {
1507*4882a593Smuzhiyun case KBASE_MEM_TYPE_NATIVE: {
1508*4882a593Smuzhiyun WARN_ON(!alloc->imported.kctx);
1509*4882a593Smuzhiyun /*
1510*4882a593Smuzhiyun * The physical allocation must have been removed from the
1511*4882a593Smuzhiyun * eviction list before trying to free it.
1512*4882a593Smuzhiyun */
1513*4882a593Smuzhiyun WARN_ON(!list_empty(&alloc->evict_node));
1514*4882a593Smuzhiyun kbase_free_phy_pages_helper(alloc, alloc->nents);
1515*4882a593Smuzhiyun break;
1516*4882a593Smuzhiyun }
1517*4882a593Smuzhiyun case KBASE_MEM_TYPE_ALIAS: {
1518*4882a593Smuzhiyun /* just call put on the underlying phy allocs */
1519*4882a593Smuzhiyun size_t i;
1520*4882a593Smuzhiyun struct kbase_aliased *aliased;
1521*4882a593Smuzhiyun
1522*4882a593Smuzhiyun aliased = alloc->imported.alias.aliased;
1523*4882a593Smuzhiyun if (aliased) {
1524*4882a593Smuzhiyun for (i = 0; i < alloc->imported.alias.nents; i++)
1525*4882a593Smuzhiyun if (aliased[i].alloc)
1526*4882a593Smuzhiyun kbase_mem_phy_alloc_put(aliased[i].alloc);
1527*4882a593Smuzhiyun vfree(aliased);
1528*4882a593Smuzhiyun }
1529*4882a593Smuzhiyun break;
1530*4882a593Smuzhiyun }
1531*4882a593Smuzhiyun case KBASE_MEM_TYPE_RAW:
1532*4882a593Smuzhiyun /* raw pages, external cleanup */
1533*4882a593Smuzhiyun break;
1534*4882a593Smuzhiyun #ifdef CONFIG_UMP
1535*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_UMP:
1536*4882a593Smuzhiyun ump_dd_release(alloc->imported.ump_handle);
1537*4882a593Smuzhiyun break;
1538*4882a593Smuzhiyun #endif
1539*4882a593Smuzhiyun #ifdef CONFIG_DMA_SHARED_BUFFER
1540*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_UMM:
1541*4882a593Smuzhiyun dma_buf_detach(alloc->imported.umm.dma_buf,
1542*4882a593Smuzhiyun alloc->imported.umm.dma_attachment);
1543*4882a593Smuzhiyun dma_buf_put(alloc->imported.umm.dma_buf);
1544*4882a593Smuzhiyun break;
1545*4882a593Smuzhiyun #endif
1546*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_USER_BUF:
1547*4882a593Smuzhiyun if (alloc->imported.user_buf.mm)
1548*4882a593Smuzhiyun mmdrop(alloc->imported.user_buf.mm);
1549*4882a593Smuzhiyun kfree(alloc->imported.user_buf.pages);
1550*4882a593Smuzhiyun break;
1551*4882a593Smuzhiyun case KBASE_MEM_TYPE_TB:{
1552*4882a593Smuzhiyun void *tb;
1553*4882a593Smuzhiyun
1554*4882a593Smuzhiyun tb = alloc->imported.kctx->jctx.tb;
1555*4882a593Smuzhiyun kbase_device_trace_buffer_uninstall(alloc->imported.kctx);
1556*4882a593Smuzhiyun vfree(tb);
1557*4882a593Smuzhiyun break;
1558*4882a593Smuzhiyun }
1559*4882a593Smuzhiyun default:
1560*4882a593Smuzhiyun WARN(1, "Unexecpted free of type %d\n", alloc->type);
1561*4882a593Smuzhiyun break;
1562*4882a593Smuzhiyun }
1563*4882a593Smuzhiyun
1564*4882a593Smuzhiyun /* Free based on allocation type */
1565*4882a593Smuzhiyun if (alloc->properties & KBASE_MEM_PHY_ALLOC_LARGE)
1566*4882a593Smuzhiyun vfree(alloc);
1567*4882a593Smuzhiyun else
1568*4882a593Smuzhiyun kfree(alloc);
1569*4882a593Smuzhiyun }
1570*4882a593Smuzhiyun
1571*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_mem_kref_free);
1572*4882a593Smuzhiyun
kbase_alloc_phy_pages(struct kbase_va_region * reg,size_t vsize,size_t size)1573*4882a593Smuzhiyun int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size)
1574*4882a593Smuzhiyun {
1575*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL != reg);
1576*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(vsize > 0);
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun /* validate user provided arguments */
1579*4882a593Smuzhiyun if (size > vsize || vsize > reg->nr_pages)
1580*4882a593Smuzhiyun goto out_term;
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun /* Prevent vsize*sizeof from wrapping around.
1583*4882a593Smuzhiyun * For instance, if vsize is 2**29+1, we'll allocate 1 byte and the alloc won't fail.
1584*4882a593Smuzhiyun */
1585*4882a593Smuzhiyun if ((size_t) vsize > ((size_t) -1 / sizeof(*reg->cpu_alloc->pages)))
1586*4882a593Smuzhiyun goto out_term;
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(0 != vsize);
1589*4882a593Smuzhiyun
1590*4882a593Smuzhiyun if (kbase_alloc_phy_pages_helper(reg->cpu_alloc, size) != 0)
1591*4882a593Smuzhiyun goto out_term;
1592*4882a593Smuzhiyun
1593*4882a593Smuzhiyun reg->cpu_alloc->reg = reg;
1594*4882a593Smuzhiyun if (reg->cpu_alloc != reg->gpu_alloc) {
1595*4882a593Smuzhiyun if (kbase_alloc_phy_pages_helper(reg->gpu_alloc, size) != 0)
1596*4882a593Smuzhiyun goto out_rollback;
1597*4882a593Smuzhiyun reg->gpu_alloc->reg = reg;
1598*4882a593Smuzhiyun }
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun return 0;
1601*4882a593Smuzhiyun
1602*4882a593Smuzhiyun out_rollback:
1603*4882a593Smuzhiyun kbase_free_phy_pages_helper(reg->cpu_alloc, size);
1604*4882a593Smuzhiyun out_term:
1605*4882a593Smuzhiyun return -1;
1606*4882a593Smuzhiyun }
1607*4882a593Smuzhiyun
1608*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_alloc_phy_pages);
1609*4882a593Smuzhiyun
kbase_check_alloc_flags(unsigned long flags)1610*4882a593Smuzhiyun bool kbase_check_alloc_flags(unsigned long flags)
1611*4882a593Smuzhiyun {
1612*4882a593Smuzhiyun /* Only known input flags should be set. */
1613*4882a593Smuzhiyun if (flags & ~BASE_MEM_FLAGS_INPUT_MASK)
1614*4882a593Smuzhiyun return false;
1615*4882a593Smuzhiyun
1616*4882a593Smuzhiyun /* At least one flag should be set */
1617*4882a593Smuzhiyun if (flags == 0)
1618*4882a593Smuzhiyun return false;
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun /* Either the GPU or CPU must be reading from the allocated memory */
1621*4882a593Smuzhiyun if ((flags & (BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD)) == 0)
1622*4882a593Smuzhiyun return false;
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun /* Either the GPU or CPU must be writing to the allocated memory */
1625*4882a593Smuzhiyun if ((flags & (BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR)) == 0)
1626*4882a593Smuzhiyun return false;
1627*4882a593Smuzhiyun
1628*4882a593Smuzhiyun /* GPU cannot be writing to GPU executable memory and cannot grow the memory on page fault. */
1629*4882a593Smuzhiyun if ((flags & BASE_MEM_PROT_GPU_EX) && (flags & (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF)))
1630*4882a593Smuzhiyun return false;
1631*4882a593Smuzhiyun
1632*4882a593Smuzhiyun /* GPU should have at least read or write access otherwise there is no
1633*4882a593Smuzhiyun reason for allocating. */
1634*4882a593Smuzhiyun if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0)
1635*4882a593Smuzhiyun return false;
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun /* BASE_MEM_IMPORT_SHARED is only valid for imported memory */
1638*4882a593Smuzhiyun if ((flags & BASE_MEM_IMPORT_SHARED) == BASE_MEM_IMPORT_SHARED)
1639*4882a593Smuzhiyun return false;
1640*4882a593Smuzhiyun
1641*4882a593Smuzhiyun return true;
1642*4882a593Smuzhiyun }
1643*4882a593Smuzhiyun
kbase_check_import_flags(unsigned long flags)1644*4882a593Smuzhiyun bool kbase_check_import_flags(unsigned long flags)
1645*4882a593Smuzhiyun {
1646*4882a593Smuzhiyun /* Only known input flags should be set. */
1647*4882a593Smuzhiyun if (flags & ~BASE_MEM_FLAGS_INPUT_MASK)
1648*4882a593Smuzhiyun return false;
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun /* At least one flag should be set */
1651*4882a593Smuzhiyun if (flags == 0)
1652*4882a593Smuzhiyun return false;
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun /* Imported memory cannot be GPU executable */
1655*4882a593Smuzhiyun if (flags & BASE_MEM_PROT_GPU_EX)
1656*4882a593Smuzhiyun return false;
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun /* Imported memory cannot grow on page fault */
1659*4882a593Smuzhiyun if (flags & BASE_MEM_GROW_ON_GPF)
1660*4882a593Smuzhiyun return false;
1661*4882a593Smuzhiyun
1662*4882a593Smuzhiyun /* GPU should have at least read or write access otherwise there is no
1663*4882a593Smuzhiyun reason for importing. */
1664*4882a593Smuzhiyun if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0)
1665*4882a593Smuzhiyun return false;
1666*4882a593Smuzhiyun
1667*4882a593Smuzhiyun /* Secure memory cannot be read by the CPU */
1668*4882a593Smuzhiyun if ((flags & BASE_MEM_SECURE) && (flags & BASE_MEM_PROT_CPU_RD))
1669*4882a593Smuzhiyun return false;
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun return true;
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun /**
1675*4882a593Smuzhiyun * @brief Acquire the per-context region list lock
1676*4882a593Smuzhiyun */
kbase_gpu_vm_lock(struct kbase_context * kctx)1677*4882a593Smuzhiyun void kbase_gpu_vm_lock(struct kbase_context *kctx)
1678*4882a593Smuzhiyun {
1679*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kctx != NULL);
1680*4882a593Smuzhiyun mutex_lock(&kctx->reg_lock);
1681*4882a593Smuzhiyun }
1682*4882a593Smuzhiyun
1683*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock);
1684*4882a593Smuzhiyun
1685*4882a593Smuzhiyun /**
1686*4882a593Smuzhiyun * @brief Release the per-context region list lock
1687*4882a593Smuzhiyun */
kbase_gpu_vm_unlock(struct kbase_context * kctx)1688*4882a593Smuzhiyun void kbase_gpu_vm_unlock(struct kbase_context *kctx)
1689*4882a593Smuzhiyun {
1690*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kctx != NULL);
1691*4882a593Smuzhiyun mutex_unlock(&kctx->reg_lock);
1692*4882a593Smuzhiyun }
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock);
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
1697*4882a593Smuzhiyun struct kbase_jit_debugfs_data {
1698*4882a593Smuzhiyun int (*func)(struct kbase_jit_debugfs_data *);
1699*4882a593Smuzhiyun struct mutex lock;
1700*4882a593Smuzhiyun struct kbase_context *kctx;
1701*4882a593Smuzhiyun u64 active_value;
1702*4882a593Smuzhiyun u64 pool_value;
1703*4882a593Smuzhiyun u64 destroy_value;
1704*4882a593Smuzhiyun char buffer[50];
1705*4882a593Smuzhiyun };
1706*4882a593Smuzhiyun
kbase_jit_debugfs_common_open(struct inode * inode,struct file * file,int (* func)(struct kbase_jit_debugfs_data *))1707*4882a593Smuzhiyun static int kbase_jit_debugfs_common_open(struct inode *inode,
1708*4882a593Smuzhiyun struct file *file, int (*func)(struct kbase_jit_debugfs_data *))
1709*4882a593Smuzhiyun {
1710*4882a593Smuzhiyun struct kbase_jit_debugfs_data *data;
1711*4882a593Smuzhiyun
1712*4882a593Smuzhiyun data = kzalloc(sizeof(*data), GFP_KERNEL);
1713*4882a593Smuzhiyun if (!data)
1714*4882a593Smuzhiyun return -ENOMEM;
1715*4882a593Smuzhiyun
1716*4882a593Smuzhiyun data->func = func;
1717*4882a593Smuzhiyun mutex_init(&data->lock);
1718*4882a593Smuzhiyun data->kctx = (struct kbase_context *) inode->i_private;
1719*4882a593Smuzhiyun
1720*4882a593Smuzhiyun file->private_data = data;
1721*4882a593Smuzhiyun
1722*4882a593Smuzhiyun return nonseekable_open(inode, file);
1723*4882a593Smuzhiyun }
1724*4882a593Smuzhiyun
kbase_jit_debugfs_common_read(struct file * file,char __user * buf,size_t len,loff_t * ppos)1725*4882a593Smuzhiyun static ssize_t kbase_jit_debugfs_common_read(struct file *file,
1726*4882a593Smuzhiyun char __user *buf, size_t len, loff_t *ppos)
1727*4882a593Smuzhiyun {
1728*4882a593Smuzhiyun struct kbase_jit_debugfs_data *data;
1729*4882a593Smuzhiyun size_t size;
1730*4882a593Smuzhiyun int ret;
1731*4882a593Smuzhiyun
1732*4882a593Smuzhiyun data = (struct kbase_jit_debugfs_data *) file->private_data;
1733*4882a593Smuzhiyun mutex_lock(&data->lock);
1734*4882a593Smuzhiyun
1735*4882a593Smuzhiyun if (*ppos) {
1736*4882a593Smuzhiyun size = strnlen(data->buffer, sizeof(data->buffer));
1737*4882a593Smuzhiyun } else {
1738*4882a593Smuzhiyun if (!data->func) {
1739*4882a593Smuzhiyun ret = -EACCES;
1740*4882a593Smuzhiyun goto out_unlock;
1741*4882a593Smuzhiyun }
1742*4882a593Smuzhiyun
1743*4882a593Smuzhiyun if (data->func(data)) {
1744*4882a593Smuzhiyun ret = -EACCES;
1745*4882a593Smuzhiyun goto out_unlock;
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun
1748*4882a593Smuzhiyun size = scnprintf(data->buffer, sizeof(data->buffer),
1749*4882a593Smuzhiyun "%llu,%llu,%llu", data->active_value,
1750*4882a593Smuzhiyun data->pool_value, data->destroy_value);
1751*4882a593Smuzhiyun }
1752*4882a593Smuzhiyun
1753*4882a593Smuzhiyun ret = simple_read_from_buffer(buf, len, ppos, data->buffer, size);
1754*4882a593Smuzhiyun
1755*4882a593Smuzhiyun out_unlock:
1756*4882a593Smuzhiyun mutex_unlock(&data->lock);
1757*4882a593Smuzhiyun return ret;
1758*4882a593Smuzhiyun }
1759*4882a593Smuzhiyun
kbase_jit_debugfs_common_release(struct inode * inode,struct file * file)1760*4882a593Smuzhiyun static int kbase_jit_debugfs_common_release(struct inode *inode,
1761*4882a593Smuzhiyun struct file *file)
1762*4882a593Smuzhiyun {
1763*4882a593Smuzhiyun kfree(file->private_data);
1764*4882a593Smuzhiyun return 0;
1765*4882a593Smuzhiyun }
1766*4882a593Smuzhiyun
1767*4882a593Smuzhiyun #define KBASE_JIT_DEBUGFS_DECLARE(__fops, __func) \
1768*4882a593Smuzhiyun static int __fops ## _open(struct inode *inode, struct file *file) \
1769*4882a593Smuzhiyun { \
1770*4882a593Smuzhiyun return kbase_jit_debugfs_common_open(inode, file, __func); \
1771*4882a593Smuzhiyun } \
1772*4882a593Smuzhiyun static const struct file_operations __fops = { \
1773*4882a593Smuzhiyun .owner = THIS_MODULE, \
1774*4882a593Smuzhiyun .open = __fops ## _open, \
1775*4882a593Smuzhiyun .release = kbase_jit_debugfs_common_release, \
1776*4882a593Smuzhiyun .read = kbase_jit_debugfs_common_read, \
1777*4882a593Smuzhiyun .write = NULL, \
1778*4882a593Smuzhiyun .llseek = generic_file_llseek, \
1779*4882a593Smuzhiyun }
1780*4882a593Smuzhiyun
kbase_jit_debugfs_count_get(struct kbase_jit_debugfs_data * data)1781*4882a593Smuzhiyun static int kbase_jit_debugfs_count_get(struct kbase_jit_debugfs_data *data)
1782*4882a593Smuzhiyun {
1783*4882a593Smuzhiyun struct kbase_context *kctx = data->kctx;
1784*4882a593Smuzhiyun struct list_head *tmp;
1785*4882a593Smuzhiyun
1786*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
1787*4882a593Smuzhiyun list_for_each(tmp, &kctx->jit_active_head) {
1788*4882a593Smuzhiyun data->active_value++;
1789*4882a593Smuzhiyun }
1790*4882a593Smuzhiyun
1791*4882a593Smuzhiyun list_for_each(tmp, &kctx->jit_pool_head) {
1792*4882a593Smuzhiyun data->pool_value++;
1793*4882a593Smuzhiyun }
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun list_for_each(tmp, &kctx->jit_destroy_head) {
1796*4882a593Smuzhiyun data->destroy_value++;
1797*4882a593Smuzhiyun }
1798*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
1799*4882a593Smuzhiyun
1800*4882a593Smuzhiyun return 0;
1801*4882a593Smuzhiyun }
1802*4882a593Smuzhiyun KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_count_fops,
1803*4882a593Smuzhiyun kbase_jit_debugfs_count_get);
1804*4882a593Smuzhiyun
kbase_jit_debugfs_vm_get(struct kbase_jit_debugfs_data * data)1805*4882a593Smuzhiyun static int kbase_jit_debugfs_vm_get(struct kbase_jit_debugfs_data *data)
1806*4882a593Smuzhiyun {
1807*4882a593Smuzhiyun struct kbase_context *kctx = data->kctx;
1808*4882a593Smuzhiyun struct kbase_va_region *reg;
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
1811*4882a593Smuzhiyun list_for_each_entry(reg, &kctx->jit_active_head, jit_node) {
1812*4882a593Smuzhiyun data->active_value += reg->nr_pages;
1813*4882a593Smuzhiyun }
1814*4882a593Smuzhiyun
1815*4882a593Smuzhiyun list_for_each_entry(reg, &kctx->jit_pool_head, jit_node) {
1816*4882a593Smuzhiyun data->pool_value += reg->nr_pages;
1817*4882a593Smuzhiyun }
1818*4882a593Smuzhiyun
1819*4882a593Smuzhiyun list_for_each_entry(reg, &kctx->jit_destroy_head, jit_node) {
1820*4882a593Smuzhiyun data->destroy_value += reg->nr_pages;
1821*4882a593Smuzhiyun }
1822*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
1823*4882a593Smuzhiyun
1824*4882a593Smuzhiyun return 0;
1825*4882a593Smuzhiyun }
1826*4882a593Smuzhiyun KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_vm_fops,
1827*4882a593Smuzhiyun kbase_jit_debugfs_vm_get);
1828*4882a593Smuzhiyun
kbase_jit_debugfs_phys_get(struct kbase_jit_debugfs_data * data)1829*4882a593Smuzhiyun static int kbase_jit_debugfs_phys_get(struct kbase_jit_debugfs_data *data)
1830*4882a593Smuzhiyun {
1831*4882a593Smuzhiyun struct kbase_context *kctx = data->kctx;
1832*4882a593Smuzhiyun struct kbase_va_region *reg;
1833*4882a593Smuzhiyun
1834*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
1835*4882a593Smuzhiyun list_for_each_entry(reg, &kctx->jit_active_head, jit_node) {
1836*4882a593Smuzhiyun data->active_value += reg->gpu_alloc->nents;
1837*4882a593Smuzhiyun }
1838*4882a593Smuzhiyun
1839*4882a593Smuzhiyun list_for_each_entry(reg, &kctx->jit_pool_head, jit_node) {
1840*4882a593Smuzhiyun data->pool_value += reg->gpu_alloc->nents;
1841*4882a593Smuzhiyun }
1842*4882a593Smuzhiyun
1843*4882a593Smuzhiyun list_for_each_entry(reg, &kctx->jit_destroy_head, jit_node) {
1844*4882a593Smuzhiyun data->destroy_value += reg->gpu_alloc->nents;
1845*4882a593Smuzhiyun }
1846*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
1847*4882a593Smuzhiyun
1848*4882a593Smuzhiyun return 0;
1849*4882a593Smuzhiyun }
1850*4882a593Smuzhiyun KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_phys_fops,
1851*4882a593Smuzhiyun kbase_jit_debugfs_phys_get);
1852*4882a593Smuzhiyun
kbase_jit_debugfs_init(struct kbase_context * kctx)1853*4882a593Smuzhiyun void kbase_jit_debugfs_init(struct kbase_context *kctx)
1854*4882a593Smuzhiyun {
1855*4882a593Smuzhiyun /* Debugfs entry for getting the number of JIT allocations. */
1856*4882a593Smuzhiyun debugfs_create_file("mem_jit_count", S_IRUGO, kctx->kctx_dentry,
1857*4882a593Smuzhiyun kctx, &kbase_jit_debugfs_count_fops);
1858*4882a593Smuzhiyun
1859*4882a593Smuzhiyun /*
1860*4882a593Smuzhiyun * Debugfs entry for getting the total number of virtual pages
1861*4882a593Smuzhiyun * used by JIT allocations.
1862*4882a593Smuzhiyun */
1863*4882a593Smuzhiyun debugfs_create_file("mem_jit_vm", S_IRUGO, kctx->kctx_dentry,
1864*4882a593Smuzhiyun kctx, &kbase_jit_debugfs_vm_fops);
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun /*
1867*4882a593Smuzhiyun * Debugfs entry for getting the number of physical pages used
1868*4882a593Smuzhiyun * by JIT allocations.
1869*4882a593Smuzhiyun */
1870*4882a593Smuzhiyun debugfs_create_file("mem_jit_phys", S_IRUGO, kctx->kctx_dentry,
1871*4882a593Smuzhiyun kctx, &kbase_jit_debugfs_phys_fops);
1872*4882a593Smuzhiyun }
1873*4882a593Smuzhiyun #endif /* CONFIG_DEBUG_FS */
1874*4882a593Smuzhiyun
1875*4882a593Smuzhiyun /**
1876*4882a593Smuzhiyun * kbase_jit_destroy_worker - Deferred worker which frees JIT allocations
1877*4882a593Smuzhiyun * @work: Work item
1878*4882a593Smuzhiyun *
1879*4882a593Smuzhiyun * This function does the work of freeing JIT allocations whose physical
1880*4882a593Smuzhiyun * backing has been released.
1881*4882a593Smuzhiyun */
kbase_jit_destroy_worker(struct work_struct * work)1882*4882a593Smuzhiyun static void kbase_jit_destroy_worker(struct work_struct *work)
1883*4882a593Smuzhiyun {
1884*4882a593Smuzhiyun struct kbase_context *kctx;
1885*4882a593Smuzhiyun struct kbase_va_region *reg;
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun kctx = container_of(work, struct kbase_context, jit_work);
1888*4882a593Smuzhiyun do {
1889*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
1890*4882a593Smuzhiyun if (list_empty(&kctx->jit_destroy_head)) {
1891*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
1892*4882a593Smuzhiyun break;
1893*4882a593Smuzhiyun }
1894*4882a593Smuzhiyun
1895*4882a593Smuzhiyun reg = list_first_entry(&kctx->jit_destroy_head,
1896*4882a593Smuzhiyun struct kbase_va_region, jit_node);
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun list_del(®->jit_node);
1899*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
1900*4882a593Smuzhiyun
1901*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
1902*4882a593Smuzhiyun kbase_mem_free_region(kctx, reg);
1903*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
1904*4882a593Smuzhiyun } while (1);
1905*4882a593Smuzhiyun }
1906*4882a593Smuzhiyun
kbase_jit_init(struct kbase_context * kctx)1907*4882a593Smuzhiyun int kbase_jit_init(struct kbase_context *kctx)
1908*4882a593Smuzhiyun {
1909*4882a593Smuzhiyun INIT_LIST_HEAD(&kctx->jit_active_head);
1910*4882a593Smuzhiyun INIT_LIST_HEAD(&kctx->jit_pool_head);
1911*4882a593Smuzhiyun INIT_LIST_HEAD(&kctx->jit_destroy_head);
1912*4882a593Smuzhiyun INIT_WORK(&kctx->jit_work, kbase_jit_destroy_worker);
1913*4882a593Smuzhiyun
1914*4882a593Smuzhiyun INIT_LIST_HEAD(&kctx->jit_pending_alloc);
1915*4882a593Smuzhiyun INIT_LIST_HEAD(&kctx->jit_atoms_head);
1916*4882a593Smuzhiyun
1917*4882a593Smuzhiyun return 0;
1918*4882a593Smuzhiyun }
1919*4882a593Smuzhiyun
kbase_jit_allocate(struct kbase_context * kctx,struct base_jit_alloc_info * info)1920*4882a593Smuzhiyun struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
1921*4882a593Smuzhiyun struct base_jit_alloc_info *info)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun struct kbase_va_region *reg = NULL;
1924*4882a593Smuzhiyun struct kbase_va_region *walker;
1925*4882a593Smuzhiyun struct kbase_va_region *temp;
1926*4882a593Smuzhiyun size_t current_diff = SIZE_MAX;
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun int ret;
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
1931*4882a593Smuzhiyun /*
1932*4882a593Smuzhiyun * Scan the pool for an existing allocation which meets our
1933*4882a593Smuzhiyun * requirements and remove it.
1934*4882a593Smuzhiyun */
1935*4882a593Smuzhiyun list_for_each_entry_safe(walker, temp, &kctx->jit_pool_head, jit_node) {
1936*4882a593Smuzhiyun
1937*4882a593Smuzhiyun if (walker->nr_pages >= info->va_pages) {
1938*4882a593Smuzhiyun size_t min_size, max_size, diff;
1939*4882a593Smuzhiyun
1940*4882a593Smuzhiyun /*
1941*4882a593Smuzhiyun * The JIT allocations VA requirements have been
1942*4882a593Smuzhiyun * meet, it's suitable but other allocations
1943*4882a593Smuzhiyun * might be a better fit.
1944*4882a593Smuzhiyun */
1945*4882a593Smuzhiyun min_size = min_t(size_t, walker->gpu_alloc->nents,
1946*4882a593Smuzhiyun info->commit_pages);
1947*4882a593Smuzhiyun max_size = max_t(size_t, walker->gpu_alloc->nents,
1948*4882a593Smuzhiyun info->commit_pages);
1949*4882a593Smuzhiyun diff = max_size - min_size;
1950*4882a593Smuzhiyun
1951*4882a593Smuzhiyun if (current_diff > diff) {
1952*4882a593Smuzhiyun current_diff = diff;
1953*4882a593Smuzhiyun reg = walker;
1954*4882a593Smuzhiyun }
1955*4882a593Smuzhiyun
1956*4882a593Smuzhiyun /* The allocation is an exact match, stop looking */
1957*4882a593Smuzhiyun if (current_diff == 0)
1958*4882a593Smuzhiyun break;
1959*4882a593Smuzhiyun }
1960*4882a593Smuzhiyun }
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun if (reg) {
1963*4882a593Smuzhiyun /*
1964*4882a593Smuzhiyun * Remove the found region from the pool and add it to the
1965*4882a593Smuzhiyun * active list.
1966*4882a593Smuzhiyun */
1967*4882a593Smuzhiyun list_move(®->jit_node, &kctx->jit_active_head);
1968*4882a593Smuzhiyun
1969*4882a593Smuzhiyun /*
1970*4882a593Smuzhiyun * Remove the allocation from the eviction list as it's no
1971*4882a593Smuzhiyun * longer eligible for eviction. This must be done before
1972*4882a593Smuzhiyun * dropping the jit_evict_lock
1973*4882a593Smuzhiyun */
1974*4882a593Smuzhiyun list_del_init(®->gpu_alloc->evict_node);
1975*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
1978*4882a593Smuzhiyun
1979*4882a593Smuzhiyun /* Make the physical backing no longer reclaimable */
1980*4882a593Smuzhiyun if (!kbase_mem_evictable_unmake(reg->gpu_alloc))
1981*4882a593Smuzhiyun goto update_failed;
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun /* Grow the backing if required */
1984*4882a593Smuzhiyun if (reg->gpu_alloc->nents < info->commit_pages) {
1985*4882a593Smuzhiyun size_t delta;
1986*4882a593Smuzhiyun size_t old_size = reg->gpu_alloc->nents;
1987*4882a593Smuzhiyun
1988*4882a593Smuzhiyun /* Allocate some more pages */
1989*4882a593Smuzhiyun delta = info->commit_pages - reg->gpu_alloc->nents;
1990*4882a593Smuzhiyun if (kbase_alloc_phy_pages_helper(reg->gpu_alloc, delta)
1991*4882a593Smuzhiyun != 0)
1992*4882a593Smuzhiyun goto update_failed;
1993*4882a593Smuzhiyun
1994*4882a593Smuzhiyun if (reg->cpu_alloc != reg->gpu_alloc) {
1995*4882a593Smuzhiyun if (kbase_alloc_phy_pages_helper(
1996*4882a593Smuzhiyun reg->cpu_alloc, delta) != 0) {
1997*4882a593Smuzhiyun kbase_free_phy_pages_helper(
1998*4882a593Smuzhiyun reg->gpu_alloc, delta);
1999*4882a593Smuzhiyun goto update_failed;
2000*4882a593Smuzhiyun }
2001*4882a593Smuzhiyun }
2002*4882a593Smuzhiyun
2003*4882a593Smuzhiyun ret = kbase_mem_grow_gpu_mapping(kctx, reg,
2004*4882a593Smuzhiyun info->commit_pages, old_size);
2005*4882a593Smuzhiyun /*
2006*4882a593Smuzhiyun * The grow failed so put the allocation back in the
2007*4882a593Smuzhiyun * pool and return failure.
2008*4882a593Smuzhiyun */
2009*4882a593Smuzhiyun if (ret)
2010*4882a593Smuzhiyun goto update_failed;
2011*4882a593Smuzhiyun }
2012*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
2013*4882a593Smuzhiyun } else {
2014*4882a593Smuzhiyun /* No suitable JIT allocation was found so create a new one */
2015*4882a593Smuzhiyun u64 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD |
2016*4882a593Smuzhiyun BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF |
2017*4882a593Smuzhiyun BASE_MEM_COHERENT_LOCAL;
2018*4882a593Smuzhiyun u64 gpu_addr;
2019*4882a593Smuzhiyun
2020*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun reg = kbase_mem_alloc(kctx, info->va_pages, info->commit_pages,
2023*4882a593Smuzhiyun info->extent, &flags, &gpu_addr);
2024*4882a593Smuzhiyun if (!reg)
2025*4882a593Smuzhiyun goto out_unlocked;
2026*4882a593Smuzhiyun
2027*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2028*4882a593Smuzhiyun list_add(®->jit_node, &kctx->jit_active_head);
2029*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2030*4882a593Smuzhiyun }
2031*4882a593Smuzhiyun
2032*4882a593Smuzhiyun return reg;
2033*4882a593Smuzhiyun
2034*4882a593Smuzhiyun update_failed:
2035*4882a593Smuzhiyun /*
2036*4882a593Smuzhiyun * An update to an allocation from the pool failed, chances
2037*4882a593Smuzhiyun * are slim a new allocation would fair any better so return
2038*4882a593Smuzhiyun * the allocation to the pool and return the function with failure.
2039*4882a593Smuzhiyun */
2040*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
2041*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2042*4882a593Smuzhiyun list_move(®->jit_node, &kctx->jit_pool_head);
2043*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2044*4882a593Smuzhiyun out_unlocked:
2045*4882a593Smuzhiyun return NULL;
2046*4882a593Smuzhiyun }
2047*4882a593Smuzhiyun
kbase_jit_free(struct kbase_context * kctx,struct kbase_va_region * reg)2048*4882a593Smuzhiyun void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
2049*4882a593Smuzhiyun {
2050*4882a593Smuzhiyun /* The physical backing of memory in the pool is always reclaimable */
2051*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
2052*4882a593Smuzhiyun kbase_mem_evictable_make(reg->gpu_alloc);
2053*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2056*4882a593Smuzhiyun list_move(®->jit_node, &kctx->jit_pool_head);
2057*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2058*4882a593Smuzhiyun }
2059*4882a593Smuzhiyun
kbase_jit_backing_lost(struct kbase_va_region * reg)2060*4882a593Smuzhiyun void kbase_jit_backing_lost(struct kbase_va_region *reg)
2061*4882a593Smuzhiyun {
2062*4882a593Smuzhiyun struct kbase_context *kctx = reg->kctx;
2063*4882a593Smuzhiyun
2064*4882a593Smuzhiyun lockdep_assert_held(&kctx->jit_evict_lock);
2065*4882a593Smuzhiyun
2066*4882a593Smuzhiyun /*
2067*4882a593Smuzhiyun * JIT allocations will always be on a list, if the region
2068*4882a593Smuzhiyun * is not on a list then it's not a JIT allocation.
2069*4882a593Smuzhiyun */
2070*4882a593Smuzhiyun if (list_empty(®->jit_node))
2071*4882a593Smuzhiyun return;
2072*4882a593Smuzhiyun
2073*4882a593Smuzhiyun /*
2074*4882a593Smuzhiyun * Freeing the allocation requires locks we might not be able
2075*4882a593Smuzhiyun * to take now, so move the allocation to the free list and kick
2076*4882a593Smuzhiyun * the worker which will do the freeing.
2077*4882a593Smuzhiyun */
2078*4882a593Smuzhiyun list_move(®->jit_node, &kctx->jit_destroy_head);
2079*4882a593Smuzhiyun
2080*4882a593Smuzhiyun schedule_work(&kctx->jit_work);
2081*4882a593Smuzhiyun }
2082*4882a593Smuzhiyun
kbase_jit_evict(struct kbase_context * kctx)2083*4882a593Smuzhiyun bool kbase_jit_evict(struct kbase_context *kctx)
2084*4882a593Smuzhiyun {
2085*4882a593Smuzhiyun struct kbase_va_region *reg = NULL;
2086*4882a593Smuzhiyun
2087*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun /* Free the oldest allocation from the pool */
2090*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2091*4882a593Smuzhiyun if (!list_empty(&kctx->jit_pool_head)) {
2092*4882a593Smuzhiyun reg = list_entry(kctx->jit_pool_head.prev,
2093*4882a593Smuzhiyun struct kbase_va_region, jit_node);
2094*4882a593Smuzhiyun list_del(®->jit_node);
2095*4882a593Smuzhiyun }
2096*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2097*4882a593Smuzhiyun
2098*4882a593Smuzhiyun if (reg)
2099*4882a593Smuzhiyun kbase_mem_free_region(kctx, reg);
2100*4882a593Smuzhiyun
2101*4882a593Smuzhiyun return (reg != NULL);
2102*4882a593Smuzhiyun }
2103*4882a593Smuzhiyun
kbase_jit_term(struct kbase_context * kctx)2104*4882a593Smuzhiyun void kbase_jit_term(struct kbase_context *kctx)
2105*4882a593Smuzhiyun {
2106*4882a593Smuzhiyun struct kbase_va_region *walker;
2107*4882a593Smuzhiyun
2108*4882a593Smuzhiyun /* Free all allocations for this context */
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun /*
2111*4882a593Smuzhiyun * Flush the freeing of allocations whose backing has been freed
2112*4882a593Smuzhiyun * (i.e. everything in jit_destroy_head).
2113*4882a593Smuzhiyun */
2114*4882a593Smuzhiyun cancel_work_sync(&kctx->jit_work);
2115*4882a593Smuzhiyun
2116*4882a593Smuzhiyun kbase_gpu_vm_lock(kctx);
2117*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2118*4882a593Smuzhiyun /* Free all allocations from the pool */
2119*4882a593Smuzhiyun while (!list_empty(&kctx->jit_pool_head)) {
2120*4882a593Smuzhiyun walker = list_first_entry(&kctx->jit_pool_head,
2121*4882a593Smuzhiyun struct kbase_va_region, jit_node);
2122*4882a593Smuzhiyun list_del(&walker->jit_node);
2123*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2124*4882a593Smuzhiyun kbase_mem_free_region(kctx, walker);
2125*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2126*4882a593Smuzhiyun }
2127*4882a593Smuzhiyun
2128*4882a593Smuzhiyun /* Free all allocations from active list */
2129*4882a593Smuzhiyun while (!list_empty(&kctx->jit_active_head)) {
2130*4882a593Smuzhiyun walker = list_first_entry(&kctx->jit_active_head,
2131*4882a593Smuzhiyun struct kbase_va_region, jit_node);
2132*4882a593Smuzhiyun list_del(&walker->jit_node);
2133*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2134*4882a593Smuzhiyun kbase_mem_free_region(kctx, walker);
2135*4882a593Smuzhiyun mutex_lock(&kctx->jit_evict_lock);
2136*4882a593Smuzhiyun }
2137*4882a593Smuzhiyun mutex_unlock(&kctx->jit_evict_lock);
2138*4882a593Smuzhiyun kbase_gpu_vm_unlock(kctx);
2139*4882a593Smuzhiyun }
2140*4882a593Smuzhiyun
kbase_jd_user_buf_map(struct kbase_context * kctx,struct kbase_va_region * reg)2141*4882a593Smuzhiyun static int kbase_jd_user_buf_map(struct kbase_context *kctx,
2142*4882a593Smuzhiyun struct kbase_va_region *reg)
2143*4882a593Smuzhiyun {
2144*4882a593Smuzhiyun long pinned_pages;
2145*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc;
2146*4882a593Smuzhiyun struct page **pages;
2147*4882a593Smuzhiyun phys_addr_t *pa;
2148*4882a593Smuzhiyun long i;
2149*4882a593Smuzhiyun int err = -ENOMEM;
2150*4882a593Smuzhiyun unsigned long address;
2151*4882a593Smuzhiyun struct mm_struct *mm;
2152*4882a593Smuzhiyun struct device *dev;
2153*4882a593Smuzhiyun unsigned long offset;
2154*4882a593Smuzhiyun unsigned long local_size;
2155*4882a593Smuzhiyun
2156*4882a593Smuzhiyun alloc = reg->gpu_alloc;
2157*4882a593Smuzhiyun pa = kbase_get_gpu_phy_pages(reg);
2158*4882a593Smuzhiyun address = alloc->imported.user_buf.address;
2159*4882a593Smuzhiyun mm = alloc->imported.user_buf.mm;
2160*4882a593Smuzhiyun
2161*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF);
2162*4882a593Smuzhiyun
2163*4882a593Smuzhiyun pages = alloc->imported.user_buf.pages;
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
2166*4882a593Smuzhiyun pinned_pages = get_user_pages(NULL, mm,
2167*4882a593Smuzhiyun address,
2168*4882a593Smuzhiyun alloc->imported.user_buf.nr_pages,
2169*4882a593Smuzhiyun reg->flags & KBASE_REG_GPU_WR,
2170*4882a593Smuzhiyun 0, pages, NULL);
2171*4882a593Smuzhiyun #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
2172*4882a593Smuzhiyun pinned_pages = get_user_pages_remote(NULL, mm,
2173*4882a593Smuzhiyun address,
2174*4882a593Smuzhiyun alloc->imported.user_buf.nr_pages,
2175*4882a593Smuzhiyun reg->flags & KBASE_REG_GPU_WR,
2176*4882a593Smuzhiyun 0, pages, NULL);
2177*4882a593Smuzhiyun #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
2178*4882a593Smuzhiyun pinned_pages = get_user_pages_remote(NULL, mm,
2179*4882a593Smuzhiyun address,
2180*4882a593Smuzhiyun alloc->imported.user_buf.nr_pages,
2181*4882a593Smuzhiyun reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
2182*4882a593Smuzhiyun pages, NULL);
2183*4882a593Smuzhiyun #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
2184*4882a593Smuzhiyun pinned_pages = get_user_pages_remote(NULL, mm,
2185*4882a593Smuzhiyun address,
2186*4882a593Smuzhiyun alloc->imported.user_buf.nr_pages,
2187*4882a593Smuzhiyun reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
2188*4882a593Smuzhiyun pages, NULL, NULL);
2189*4882a593Smuzhiyun #else
2190*4882a593Smuzhiyun pinned_pages = get_user_pages_remote(mm,
2191*4882a593Smuzhiyun address,
2192*4882a593Smuzhiyun alloc->imported.user_buf.nr_pages,
2193*4882a593Smuzhiyun reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
2194*4882a593Smuzhiyun pages, NULL, NULL);
2195*4882a593Smuzhiyun #endif
2196*4882a593Smuzhiyun
2197*4882a593Smuzhiyun if (pinned_pages <= 0)
2198*4882a593Smuzhiyun return pinned_pages;
2199*4882a593Smuzhiyun
2200*4882a593Smuzhiyun if (pinned_pages != alloc->imported.user_buf.nr_pages) {
2201*4882a593Smuzhiyun for (i = 0; i < pinned_pages; i++)
2202*4882a593Smuzhiyun put_page(pages[i]);
2203*4882a593Smuzhiyun return -ENOMEM;
2204*4882a593Smuzhiyun }
2205*4882a593Smuzhiyun
2206*4882a593Smuzhiyun dev = kctx->kbdev->dev;
2207*4882a593Smuzhiyun offset = address & ~PAGE_MASK;
2208*4882a593Smuzhiyun local_size = alloc->imported.user_buf.size;
2209*4882a593Smuzhiyun
2210*4882a593Smuzhiyun for (i = 0; i < pinned_pages; i++) {
2211*4882a593Smuzhiyun dma_addr_t dma_addr;
2212*4882a593Smuzhiyun unsigned long min;
2213*4882a593Smuzhiyun
2214*4882a593Smuzhiyun min = MIN(PAGE_SIZE - offset, local_size);
2215*4882a593Smuzhiyun dma_addr = dma_map_page(dev, pages[i],
2216*4882a593Smuzhiyun offset, min,
2217*4882a593Smuzhiyun DMA_BIDIRECTIONAL);
2218*4882a593Smuzhiyun if (dma_mapping_error(dev, dma_addr))
2219*4882a593Smuzhiyun goto unwind;
2220*4882a593Smuzhiyun
2221*4882a593Smuzhiyun alloc->imported.user_buf.dma_addrs[i] = dma_addr;
2222*4882a593Smuzhiyun pa[i] = page_to_phys(pages[i]);
2223*4882a593Smuzhiyun
2224*4882a593Smuzhiyun local_size -= min;
2225*4882a593Smuzhiyun offset = 0;
2226*4882a593Smuzhiyun }
2227*4882a593Smuzhiyun
2228*4882a593Smuzhiyun alloc->nents = pinned_pages;
2229*4882a593Smuzhiyun
2230*4882a593Smuzhiyun err = kbase_mmu_insert_pages(kctx, reg->start_pfn, pa,
2231*4882a593Smuzhiyun kbase_reg_current_backed_size(reg),
2232*4882a593Smuzhiyun reg->flags);
2233*4882a593Smuzhiyun if (err == 0)
2234*4882a593Smuzhiyun return 0;
2235*4882a593Smuzhiyun
2236*4882a593Smuzhiyun alloc->nents = 0;
2237*4882a593Smuzhiyun /* fall down */
2238*4882a593Smuzhiyun unwind:
2239*4882a593Smuzhiyun while (i--) {
2240*4882a593Smuzhiyun dma_unmap_page(kctx->kbdev->dev,
2241*4882a593Smuzhiyun alloc->imported.user_buf.dma_addrs[i],
2242*4882a593Smuzhiyun PAGE_SIZE, DMA_BIDIRECTIONAL);
2243*4882a593Smuzhiyun put_page(pages[i]);
2244*4882a593Smuzhiyun pages[i] = NULL;
2245*4882a593Smuzhiyun }
2246*4882a593Smuzhiyun
2247*4882a593Smuzhiyun return err;
2248*4882a593Smuzhiyun }
2249*4882a593Smuzhiyun
kbase_jd_user_buf_unmap(struct kbase_context * kctx,struct kbase_mem_phy_alloc * alloc,bool writeable)2250*4882a593Smuzhiyun static void kbase_jd_user_buf_unmap(struct kbase_context *kctx,
2251*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc, bool writeable)
2252*4882a593Smuzhiyun {
2253*4882a593Smuzhiyun long i;
2254*4882a593Smuzhiyun struct page **pages;
2255*4882a593Smuzhiyun unsigned long size = alloc->imported.user_buf.size;
2256*4882a593Smuzhiyun
2257*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF);
2258*4882a593Smuzhiyun pages = alloc->imported.user_buf.pages;
2259*4882a593Smuzhiyun for (i = 0; i < alloc->imported.user_buf.nr_pages; i++) {
2260*4882a593Smuzhiyun unsigned long local_size;
2261*4882a593Smuzhiyun dma_addr_t dma_addr = alloc->imported.user_buf.dma_addrs[i];
2262*4882a593Smuzhiyun
2263*4882a593Smuzhiyun local_size = MIN(size, PAGE_SIZE - (dma_addr & ~PAGE_MASK));
2264*4882a593Smuzhiyun dma_unmap_page(kctx->kbdev->dev, dma_addr, local_size,
2265*4882a593Smuzhiyun DMA_BIDIRECTIONAL);
2266*4882a593Smuzhiyun if (writeable)
2267*4882a593Smuzhiyun set_page_dirty_lock(pages[i]);
2268*4882a593Smuzhiyun put_page(pages[i]);
2269*4882a593Smuzhiyun pages[i] = NULL;
2270*4882a593Smuzhiyun
2271*4882a593Smuzhiyun size -= local_size;
2272*4882a593Smuzhiyun }
2273*4882a593Smuzhiyun alloc->nents = 0;
2274*4882a593Smuzhiyun }
2275*4882a593Smuzhiyun
2276*4882a593Smuzhiyun
2277*4882a593Smuzhiyun /* to replace sg_dma_len. */
2278*4882a593Smuzhiyun #define MALI_SG_DMA_LEN(sg) ((sg)->length)
2279*4882a593Smuzhiyun
2280*4882a593Smuzhiyun #ifdef CONFIG_DMA_SHARED_BUFFER
kbase_jd_umm_map(struct kbase_context * kctx,struct kbase_va_region * reg)2281*4882a593Smuzhiyun static int kbase_jd_umm_map(struct kbase_context *kctx,
2282*4882a593Smuzhiyun struct kbase_va_region *reg)
2283*4882a593Smuzhiyun {
2284*4882a593Smuzhiyun struct sg_table *sgt;
2285*4882a593Smuzhiyun struct scatterlist *s;
2286*4882a593Smuzhiyun int i;
2287*4882a593Smuzhiyun phys_addr_t *pa;
2288*4882a593Smuzhiyun int err;
2289*4882a593Smuzhiyun size_t count = 0;
2290*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc;
2291*4882a593Smuzhiyun
2292*4882a593Smuzhiyun alloc = reg->gpu_alloc;
2293*4882a593Smuzhiyun
2294*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM);
2295*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(NULL == alloc->imported.umm.sgt);
2296*4882a593Smuzhiyun sgt = dma_buf_map_attachment(alloc->imported.umm.dma_attachment,
2297*4882a593Smuzhiyun DMA_BIDIRECTIONAL);
2298*4882a593Smuzhiyun
2299*4882a593Smuzhiyun if (IS_ERR_OR_NULL(sgt))
2300*4882a593Smuzhiyun return -EINVAL;
2301*4882a593Smuzhiyun
2302*4882a593Smuzhiyun /* save for later */
2303*4882a593Smuzhiyun alloc->imported.umm.sgt = sgt;
2304*4882a593Smuzhiyun
2305*4882a593Smuzhiyun pa = kbase_get_gpu_phy_pages(reg);
2306*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(pa);
2307*4882a593Smuzhiyun
2308*4882a593Smuzhiyun for_each_sg(sgt->sgl, s, sgt->nents, i) {
2309*4882a593Smuzhiyun int j;
2310*4882a593Smuzhiyun size_t pages = PFN_UP(MALI_SG_DMA_LEN(s));
2311*4882a593Smuzhiyun
2312*4882a593Smuzhiyun WARN_ONCE(MALI_SG_DMA_LEN(s) & (PAGE_SIZE-1),
2313*4882a593Smuzhiyun "MALI_SG_DMA_LEN(s)=%u is not a multiple of PAGE_SIZE\n",
2314*4882a593Smuzhiyun MALI_SG_DMA_LEN(s));
2315*4882a593Smuzhiyun
2316*4882a593Smuzhiyun WARN_ONCE(sg_dma_address(s) & (PAGE_SIZE-1),
2317*4882a593Smuzhiyun "sg_dma_address(s)=%llx is not aligned to PAGE_SIZE\n",
2318*4882a593Smuzhiyun (unsigned long long) sg_dma_address(s));
2319*4882a593Smuzhiyun
2320*4882a593Smuzhiyun for (j = 0; (j < pages) && (count < reg->nr_pages); j++,
2321*4882a593Smuzhiyun count++)
2322*4882a593Smuzhiyun *pa++ = sg_dma_address(s) + (j << PAGE_SHIFT);
2323*4882a593Smuzhiyun WARN_ONCE(j < pages,
2324*4882a593Smuzhiyun "sg list from dma_buf_map_attachment > dma_buf->size=%zu\n",
2325*4882a593Smuzhiyun alloc->imported.umm.dma_buf->size);
2326*4882a593Smuzhiyun }
2327*4882a593Smuzhiyun
2328*4882a593Smuzhiyun if (!(reg->flags & KBASE_REG_IMPORT_PAD) &&
2329*4882a593Smuzhiyun WARN_ONCE(count < reg->nr_pages,
2330*4882a593Smuzhiyun "sg list from dma_buf_map_attachment < dma_buf->size=%zu\n",
2331*4882a593Smuzhiyun alloc->imported.umm.dma_buf->size)) {
2332*4882a593Smuzhiyun err = -EINVAL;
2333*4882a593Smuzhiyun goto err_unmap_attachment;
2334*4882a593Smuzhiyun }
2335*4882a593Smuzhiyun
2336*4882a593Smuzhiyun /* Update nents as we now have pages to map */
2337*4882a593Smuzhiyun alloc->nents = reg->nr_pages;
2338*4882a593Smuzhiyun
2339*4882a593Smuzhiyun err = kbase_mmu_insert_pages(kctx, reg->start_pfn,
2340*4882a593Smuzhiyun kbase_get_gpu_phy_pages(reg),
2341*4882a593Smuzhiyun count,
2342*4882a593Smuzhiyun reg->flags | KBASE_REG_GPU_WR | KBASE_REG_GPU_RD);
2343*4882a593Smuzhiyun if (err)
2344*4882a593Smuzhiyun goto err_unmap_attachment;
2345*4882a593Smuzhiyun
2346*4882a593Smuzhiyun if (reg->flags & KBASE_REG_IMPORT_PAD) {
2347*4882a593Smuzhiyun err = kbase_mmu_insert_single_page(kctx,
2348*4882a593Smuzhiyun reg->start_pfn + count,
2349*4882a593Smuzhiyun page_to_phys(kctx->aliasing_sink_page),
2350*4882a593Smuzhiyun reg->nr_pages - count,
2351*4882a593Smuzhiyun (reg->flags | KBASE_REG_GPU_RD) &
2352*4882a593Smuzhiyun ~KBASE_REG_GPU_WR);
2353*4882a593Smuzhiyun if (err)
2354*4882a593Smuzhiyun goto err_teardown_orig_pages;
2355*4882a593Smuzhiyun }
2356*4882a593Smuzhiyun
2357*4882a593Smuzhiyun return 0;
2358*4882a593Smuzhiyun
2359*4882a593Smuzhiyun err_teardown_orig_pages:
2360*4882a593Smuzhiyun kbase_mmu_teardown_pages(kctx, reg->start_pfn, count);
2361*4882a593Smuzhiyun err_unmap_attachment:
2362*4882a593Smuzhiyun dma_buf_unmap_attachment(alloc->imported.umm.dma_attachment,
2363*4882a593Smuzhiyun alloc->imported.umm.sgt, DMA_BIDIRECTIONAL);
2364*4882a593Smuzhiyun alloc->imported.umm.sgt = NULL;
2365*4882a593Smuzhiyun
2366*4882a593Smuzhiyun return err;
2367*4882a593Smuzhiyun }
2368*4882a593Smuzhiyun
kbase_jd_umm_unmap(struct kbase_context * kctx,struct kbase_mem_phy_alloc * alloc)2369*4882a593Smuzhiyun static void kbase_jd_umm_unmap(struct kbase_context *kctx,
2370*4882a593Smuzhiyun struct kbase_mem_phy_alloc *alloc)
2371*4882a593Smuzhiyun {
2372*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(kctx);
2373*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc);
2374*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->imported.umm.dma_attachment);
2375*4882a593Smuzhiyun KBASE_DEBUG_ASSERT(alloc->imported.umm.sgt);
2376*4882a593Smuzhiyun dma_buf_unmap_attachment(alloc->imported.umm.dma_attachment,
2377*4882a593Smuzhiyun alloc->imported.umm.sgt, DMA_BIDIRECTIONAL);
2378*4882a593Smuzhiyun alloc->imported.umm.sgt = NULL;
2379*4882a593Smuzhiyun alloc->nents = 0;
2380*4882a593Smuzhiyun }
2381*4882a593Smuzhiyun #endif /* CONFIG_DMA_SHARED_BUFFER */
2382*4882a593Smuzhiyun
2383*4882a593Smuzhiyun #if (defined(CONFIG_KDS) && defined(CONFIG_UMP)) \
2384*4882a593Smuzhiyun || defined(CONFIG_DMA_SHARED_BUFFER_USES_KDS)
add_kds_resource(struct kds_resource * kds_res,struct kds_resource ** kds_resources,u32 * kds_res_count,unsigned long * kds_access_bitmap,bool exclusive)2385*4882a593Smuzhiyun static void add_kds_resource(struct kds_resource *kds_res,
2386*4882a593Smuzhiyun struct kds_resource **kds_resources, u32 *kds_res_count,
2387*4882a593Smuzhiyun unsigned long *kds_access_bitmap, bool exclusive)
2388*4882a593Smuzhiyun {
2389*4882a593Smuzhiyun u32 i;
2390*4882a593Smuzhiyun
2391*4882a593Smuzhiyun for (i = 0; i < *kds_res_count; i++) {
2392*4882a593Smuzhiyun /* Duplicate resource, ignore */
2393*4882a593Smuzhiyun if (kds_resources[i] == kds_res)
2394*4882a593Smuzhiyun return;
2395*4882a593Smuzhiyun }
2396*4882a593Smuzhiyun
2397*4882a593Smuzhiyun kds_resources[*kds_res_count] = kds_res;
2398*4882a593Smuzhiyun if (exclusive)
2399*4882a593Smuzhiyun set_bit(*kds_res_count, kds_access_bitmap);
2400*4882a593Smuzhiyun (*kds_res_count)++;
2401*4882a593Smuzhiyun }
2402*4882a593Smuzhiyun #endif
2403*4882a593Smuzhiyun
kbase_map_external_resource(struct kbase_context * kctx,struct kbase_va_region * reg,struct mm_struct * locked_mm,u32 * kds_res_count,struct kds_resource ** kds_resources,unsigned long * kds_access_bitmap,bool exclusive)2404*4882a593Smuzhiyun struct kbase_mem_phy_alloc *kbase_map_external_resource(
2405*4882a593Smuzhiyun struct kbase_context *kctx, struct kbase_va_region *reg,
2406*4882a593Smuzhiyun struct mm_struct *locked_mm
2407*4882a593Smuzhiyun #ifdef CONFIG_KDS
2408*4882a593Smuzhiyun , u32 *kds_res_count, struct kds_resource **kds_resources,
2409*4882a593Smuzhiyun unsigned long *kds_access_bitmap, bool exclusive
2410*4882a593Smuzhiyun #endif
2411*4882a593Smuzhiyun )
2412*4882a593Smuzhiyun {
2413*4882a593Smuzhiyun int err;
2414*4882a593Smuzhiyun
2415*4882a593Smuzhiyun /* decide what needs to happen for this resource */
2416*4882a593Smuzhiyun switch (reg->gpu_alloc->type) {
2417*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_USER_BUF: {
2418*4882a593Smuzhiyun if (reg->gpu_alloc->imported.user_buf.mm != locked_mm)
2419*4882a593Smuzhiyun goto exit;
2420*4882a593Smuzhiyun
2421*4882a593Smuzhiyun reg->gpu_alloc->imported.user_buf.current_mapping_usage_count++;
2422*4882a593Smuzhiyun if (1 == reg->gpu_alloc->imported.user_buf.current_mapping_usage_count) {
2423*4882a593Smuzhiyun err = kbase_jd_user_buf_map(kctx, reg);
2424*4882a593Smuzhiyun if (err) {
2425*4882a593Smuzhiyun reg->gpu_alloc->imported.user_buf.current_mapping_usage_count--;
2426*4882a593Smuzhiyun goto exit;
2427*4882a593Smuzhiyun }
2428*4882a593Smuzhiyun }
2429*4882a593Smuzhiyun }
2430*4882a593Smuzhiyun break;
2431*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_UMP: {
2432*4882a593Smuzhiyun #if defined(CONFIG_KDS) && defined(CONFIG_UMP)
2433*4882a593Smuzhiyun if (kds_res_count) {
2434*4882a593Smuzhiyun struct kds_resource *kds_res;
2435*4882a593Smuzhiyun
2436*4882a593Smuzhiyun kds_res = ump_dd_kds_resource_get(
2437*4882a593Smuzhiyun reg->gpu_alloc->imported.ump_handle);
2438*4882a593Smuzhiyun if (kds_res)
2439*4882a593Smuzhiyun add_kds_resource(kds_res, kds_resources,
2440*4882a593Smuzhiyun kds_res_count,
2441*4882a593Smuzhiyun kds_access_bitmap, exclusive);
2442*4882a593Smuzhiyun }
2443*4882a593Smuzhiyun #endif /*defined(CONFIG_KDS) && defined(CONFIG_UMP) */
2444*4882a593Smuzhiyun break;
2445*4882a593Smuzhiyun }
2446*4882a593Smuzhiyun #ifdef CONFIG_DMA_SHARED_BUFFER
2447*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_UMM: {
2448*4882a593Smuzhiyun #ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
2449*4882a593Smuzhiyun if (kds_res_count) {
2450*4882a593Smuzhiyun struct kds_resource *kds_res;
2451*4882a593Smuzhiyun
2452*4882a593Smuzhiyun kds_res = get_dma_buf_kds_resource(
2453*4882a593Smuzhiyun reg->gpu_alloc->imported.umm.dma_buf);
2454*4882a593Smuzhiyun if (kds_res)
2455*4882a593Smuzhiyun add_kds_resource(kds_res, kds_resources,
2456*4882a593Smuzhiyun kds_res_count,
2457*4882a593Smuzhiyun kds_access_bitmap, exclusive);
2458*4882a593Smuzhiyun }
2459*4882a593Smuzhiyun #endif
2460*4882a593Smuzhiyun reg->gpu_alloc->imported.umm.current_mapping_usage_count++;
2461*4882a593Smuzhiyun if (1 == reg->gpu_alloc->imported.umm.current_mapping_usage_count) {
2462*4882a593Smuzhiyun err = kbase_jd_umm_map(kctx, reg);
2463*4882a593Smuzhiyun if (err) {
2464*4882a593Smuzhiyun reg->gpu_alloc->imported.umm.current_mapping_usage_count--;
2465*4882a593Smuzhiyun goto exit;
2466*4882a593Smuzhiyun }
2467*4882a593Smuzhiyun }
2468*4882a593Smuzhiyun break;
2469*4882a593Smuzhiyun }
2470*4882a593Smuzhiyun #endif
2471*4882a593Smuzhiyun default:
2472*4882a593Smuzhiyun goto exit;
2473*4882a593Smuzhiyun }
2474*4882a593Smuzhiyun
2475*4882a593Smuzhiyun return kbase_mem_phy_alloc_get(reg->gpu_alloc);
2476*4882a593Smuzhiyun exit:
2477*4882a593Smuzhiyun return NULL;
2478*4882a593Smuzhiyun }
2479*4882a593Smuzhiyun
kbase_unmap_external_resource(struct kbase_context * kctx,struct kbase_va_region * reg,struct kbase_mem_phy_alloc * alloc)2480*4882a593Smuzhiyun void kbase_unmap_external_resource(struct kbase_context *kctx,
2481*4882a593Smuzhiyun struct kbase_va_region *reg, struct kbase_mem_phy_alloc *alloc)
2482*4882a593Smuzhiyun {
2483*4882a593Smuzhiyun switch (alloc->type) {
2484*4882a593Smuzhiyun #ifdef CONFIG_DMA_SHARED_BUFFER
2485*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_UMM: {
2486*4882a593Smuzhiyun alloc->imported.umm.current_mapping_usage_count--;
2487*4882a593Smuzhiyun
2488*4882a593Smuzhiyun if (0 == alloc->imported.umm.current_mapping_usage_count) {
2489*4882a593Smuzhiyun if (reg && reg->gpu_alloc == alloc) {
2490*4882a593Smuzhiyun int err;
2491*4882a593Smuzhiyun
2492*4882a593Smuzhiyun err = kbase_mmu_teardown_pages(
2493*4882a593Smuzhiyun kctx,
2494*4882a593Smuzhiyun reg->start_pfn,
2495*4882a593Smuzhiyun alloc->nents);
2496*4882a593Smuzhiyun WARN_ON(err);
2497*4882a593Smuzhiyun }
2498*4882a593Smuzhiyun
2499*4882a593Smuzhiyun kbase_jd_umm_unmap(kctx, alloc);
2500*4882a593Smuzhiyun }
2501*4882a593Smuzhiyun }
2502*4882a593Smuzhiyun break;
2503*4882a593Smuzhiyun #endif /* CONFIG_DMA_SHARED_BUFFER */
2504*4882a593Smuzhiyun case KBASE_MEM_TYPE_IMPORTED_USER_BUF: {
2505*4882a593Smuzhiyun alloc->imported.user_buf.current_mapping_usage_count--;
2506*4882a593Smuzhiyun
2507*4882a593Smuzhiyun if (0 == alloc->imported.user_buf.current_mapping_usage_count) {
2508*4882a593Smuzhiyun bool writeable = true;
2509*4882a593Smuzhiyun
2510*4882a593Smuzhiyun if (reg && reg->gpu_alloc == alloc)
2511*4882a593Smuzhiyun kbase_mmu_teardown_pages(
2512*4882a593Smuzhiyun kctx,
2513*4882a593Smuzhiyun reg->start_pfn,
2514*4882a593Smuzhiyun kbase_reg_current_backed_size(reg));
2515*4882a593Smuzhiyun
2516*4882a593Smuzhiyun if (reg && ((reg->flags & KBASE_REG_GPU_WR) == 0))
2517*4882a593Smuzhiyun writeable = false;
2518*4882a593Smuzhiyun
2519*4882a593Smuzhiyun kbase_jd_user_buf_unmap(kctx, alloc, writeable);
2520*4882a593Smuzhiyun }
2521*4882a593Smuzhiyun }
2522*4882a593Smuzhiyun break;
2523*4882a593Smuzhiyun default:
2524*4882a593Smuzhiyun break;
2525*4882a593Smuzhiyun }
2526*4882a593Smuzhiyun kbase_mem_phy_alloc_put(alloc);
2527*4882a593Smuzhiyun }
2528*4882a593Smuzhiyun
kbase_sticky_resource_acquire(struct kbase_context * kctx,u64 gpu_addr)2529*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire(
2530*4882a593Smuzhiyun struct kbase_context *kctx, u64 gpu_addr)
2531*4882a593Smuzhiyun {
2532*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta *meta = NULL;
2533*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta *walker;
2534*4882a593Smuzhiyun
2535*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
2536*4882a593Smuzhiyun
2537*4882a593Smuzhiyun /*
2538*4882a593Smuzhiyun * Walk the per context external resource metadata list for the
2539*4882a593Smuzhiyun * metadata which matches the region which is being acquired.
2540*4882a593Smuzhiyun */
2541*4882a593Smuzhiyun list_for_each_entry(walker, &kctx->ext_res_meta_head, ext_res_node) {
2542*4882a593Smuzhiyun if (walker->gpu_addr == gpu_addr) {
2543*4882a593Smuzhiyun meta = walker;
2544*4882a593Smuzhiyun break;
2545*4882a593Smuzhiyun }
2546*4882a593Smuzhiyun }
2547*4882a593Smuzhiyun
2548*4882a593Smuzhiyun /* No metadata exists so create one. */
2549*4882a593Smuzhiyun if (!meta) {
2550*4882a593Smuzhiyun struct kbase_va_region *reg;
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun /* Find the region */
2553*4882a593Smuzhiyun reg = kbase_region_tracker_find_region_enclosing_address(
2554*4882a593Smuzhiyun kctx, gpu_addr);
2555*4882a593Smuzhiyun if (NULL == reg || (reg->flags & KBASE_REG_FREE))
2556*4882a593Smuzhiyun goto failed;
2557*4882a593Smuzhiyun
2558*4882a593Smuzhiyun /* Allocate the metadata object */
2559*4882a593Smuzhiyun meta = kzalloc(sizeof(*meta), GFP_KERNEL);
2560*4882a593Smuzhiyun if (!meta)
2561*4882a593Smuzhiyun goto failed;
2562*4882a593Smuzhiyun
2563*4882a593Smuzhiyun /*
2564*4882a593Smuzhiyun * Fill in the metadata object and acquire a reference
2565*4882a593Smuzhiyun * for the physical resource.
2566*4882a593Smuzhiyun */
2567*4882a593Smuzhiyun meta->alloc = kbase_map_external_resource(kctx, reg, NULL
2568*4882a593Smuzhiyun #ifdef CONFIG_KDS
2569*4882a593Smuzhiyun , NULL, NULL,
2570*4882a593Smuzhiyun NULL, false
2571*4882a593Smuzhiyun #endif
2572*4882a593Smuzhiyun );
2573*4882a593Smuzhiyun
2574*4882a593Smuzhiyun if (!meta->alloc)
2575*4882a593Smuzhiyun goto fail_map;
2576*4882a593Smuzhiyun
2577*4882a593Smuzhiyun meta->gpu_addr = reg->start_pfn << PAGE_SHIFT;
2578*4882a593Smuzhiyun
2579*4882a593Smuzhiyun list_add(&meta->ext_res_node, &kctx->ext_res_meta_head);
2580*4882a593Smuzhiyun }
2581*4882a593Smuzhiyun
2582*4882a593Smuzhiyun return meta;
2583*4882a593Smuzhiyun
2584*4882a593Smuzhiyun fail_map:
2585*4882a593Smuzhiyun kfree(meta);
2586*4882a593Smuzhiyun failed:
2587*4882a593Smuzhiyun return NULL;
2588*4882a593Smuzhiyun }
2589*4882a593Smuzhiyun
kbase_sticky_resource_release(struct kbase_context * kctx,struct kbase_ctx_ext_res_meta * meta,u64 gpu_addr)2590*4882a593Smuzhiyun bool kbase_sticky_resource_release(struct kbase_context *kctx,
2591*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta *meta, u64 gpu_addr)
2592*4882a593Smuzhiyun {
2593*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta *walker;
2594*4882a593Smuzhiyun struct kbase_va_region *reg;
2595*4882a593Smuzhiyun
2596*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
2597*4882a593Smuzhiyun
2598*4882a593Smuzhiyun /* Search of the metadata if one isn't provided. */
2599*4882a593Smuzhiyun if (!meta) {
2600*4882a593Smuzhiyun /*
2601*4882a593Smuzhiyun * Walk the per context external resource metadata list for the
2602*4882a593Smuzhiyun * metadata which matches the region which is being released.
2603*4882a593Smuzhiyun */
2604*4882a593Smuzhiyun list_for_each_entry(walker, &kctx->ext_res_meta_head,
2605*4882a593Smuzhiyun ext_res_node) {
2606*4882a593Smuzhiyun if (walker->gpu_addr == gpu_addr) {
2607*4882a593Smuzhiyun meta = walker;
2608*4882a593Smuzhiyun break;
2609*4882a593Smuzhiyun }
2610*4882a593Smuzhiyun }
2611*4882a593Smuzhiyun }
2612*4882a593Smuzhiyun
2613*4882a593Smuzhiyun /* No metadata so just return. */
2614*4882a593Smuzhiyun if (!meta)
2615*4882a593Smuzhiyun return false;
2616*4882a593Smuzhiyun
2617*4882a593Smuzhiyun /* Drop the physical memory reference and free the metadata. */
2618*4882a593Smuzhiyun reg = kbase_region_tracker_find_region_enclosing_address(
2619*4882a593Smuzhiyun kctx,
2620*4882a593Smuzhiyun meta->gpu_addr);
2621*4882a593Smuzhiyun
2622*4882a593Smuzhiyun kbase_unmap_external_resource(kctx, reg, meta->alloc);
2623*4882a593Smuzhiyun list_del(&meta->ext_res_node);
2624*4882a593Smuzhiyun kfree(meta);
2625*4882a593Smuzhiyun
2626*4882a593Smuzhiyun return true;
2627*4882a593Smuzhiyun }
2628*4882a593Smuzhiyun
kbase_sticky_resource_init(struct kbase_context * kctx)2629*4882a593Smuzhiyun int kbase_sticky_resource_init(struct kbase_context *kctx)
2630*4882a593Smuzhiyun {
2631*4882a593Smuzhiyun INIT_LIST_HEAD(&kctx->ext_res_meta_head);
2632*4882a593Smuzhiyun
2633*4882a593Smuzhiyun return 0;
2634*4882a593Smuzhiyun }
2635*4882a593Smuzhiyun
kbase_sticky_resource_term(struct kbase_context * kctx)2636*4882a593Smuzhiyun void kbase_sticky_resource_term(struct kbase_context *kctx)
2637*4882a593Smuzhiyun {
2638*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta *walker;
2639*4882a593Smuzhiyun
2640*4882a593Smuzhiyun lockdep_assert_held(&kctx->reg_lock);
2641*4882a593Smuzhiyun
2642*4882a593Smuzhiyun /*
2643*4882a593Smuzhiyun * Free any sticky resources which haven't been unmapped.
2644*4882a593Smuzhiyun *
2645*4882a593Smuzhiyun * Note:
2646*4882a593Smuzhiyun * We don't care about refcounts at this point as no future
2647*4882a593Smuzhiyun * references to the meta data will be made.
2648*4882a593Smuzhiyun * Region termination would find these if we didn't free them
2649*4882a593Smuzhiyun * here, but it's more efficient if we do the clean up here.
2650*4882a593Smuzhiyun */
2651*4882a593Smuzhiyun while (!list_empty(&kctx->ext_res_meta_head)) {
2652*4882a593Smuzhiyun walker = list_first_entry(&kctx->ext_res_meta_head,
2653*4882a593Smuzhiyun struct kbase_ctx_ext_res_meta, ext_res_node);
2654*4882a593Smuzhiyun
2655*4882a593Smuzhiyun kbase_sticky_resource_release(kctx, walker, 0);
2656*4882a593Smuzhiyun }
2657*4882a593Smuzhiyun }
2658