summaryrefslogtreecommitdiff
path: root/mali_kbase/mali_kbase_mem_linux.h
blob: 6dda44b9f128eeb900257cc63aa0e76e28d372c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
 *
 * (C) COPYRIGHT 2010, 2012-2022 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 */

/**
 * DOC: Base kernel memory APIs, Linux implementation.
 */

#ifndef _KBASE_MEM_LINUX_H_
#define _KBASE_MEM_LINUX_H_

/* A HWC dump mapping */
struct kbase_hwc_dma_mapping {
	void       *cpu_va;
	dma_addr_t  dma_pa;
	size_t      size;
};

/**
 * kbase_mem_alloc - Create a new allocation for GPU
 *
 * @kctx:         The kernel context
 * @va_pages:     The number of pages of virtual address space to reserve
 * @commit_pages: The number of physical pages to allocate upfront
 * @extension:       The number of extra pages to allocate on each GPU fault which
 *                grows the region.
 * @flags:        bitmask of BASE_MEM_* flags to convey special requirements &
 *                properties for the new allocation.
 * @gpu_va:       Start address of the memory region which was allocated from GPU
 *                virtual address space. If the BASE_MEM_FLAG_MAP_FIXED is set
 *                then this parameter shall be provided by the caller.
 * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops.
 *
 * Return: 0 on success or error code
 */
struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages, u64 commit_pages,
					u64 extension, u64 *flags, u64 *gpu_va,
					enum kbase_caller_mmu_sync_info mmu_sync_info);

/**
 * kbase_mem_query - Query properties of a GPU memory region
 *
 * @kctx:     The kernel context
 * @gpu_addr: A GPU address contained within the memory region
 * @query:    The type of query, from KBASE_MEM_QUERY_* flags, which could be
 *            regarding the amount of backing physical memory allocated so far
 *            for the region or the size of the region or the flags associated
 *            with the region.
 * @out:      Pointer to the location to store the result of query.
 *
 * Return: 0 on success or error code
 */
int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query,
		u64 *const out);

/**
 * kbase_mem_import - Import the external memory for use by the GPU
 *
 * @kctx:     The kernel context
 * @type:     Type of external memory
 * @phandle:  Handle to the external memory interpreted as per the type.
 * @padding:  Amount of extra VA pages to append to the imported buffer
 * @gpu_va:   GPU address assigned to the imported external memory
 * @va_pages: Size of the memory region reserved from the GPU address space
 * @flags:    bitmask of BASE_MEM_* flags to convey special requirements &
 *            properties for the new allocation representing the external
 *            memory.
 * Return: 0 on success or error code
 */
int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type,
		void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages,
		u64 *flags);

/**
 * kbase_mem_alias - Create a new allocation for GPU, aliasing one or more
 *                   memory regions
 *
 * @kctx:      The kernel context
 * @flags:     bitmask of BASE_MEM_* flags.
 * @stride:    Bytes between start of each memory region
 * @nents:     The number of regions to pack together into the alias
 * @ai:        Pointer to the struct containing the memory aliasing info
 * @num_pages: Number of pages the alias will cover
 *
 * Return: 0 on failure or otherwise the GPU VA for the alias
 */
u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, u64 nents, struct base_mem_aliasing_info *ai, u64 *num_pages);

/**
 * kbase_mem_flags_change - Change the flags for a memory region
 *
 * @kctx:     The kernel context
 * @gpu_addr: A GPU address contained within the memory region to modify.
 * @flags:    The new flags to set
 * @mask:     Mask of the flags, from BASE_MEM_*, to modify.
 *
 * Return: 0 on success or error code
 */
int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned int flags, unsigned int mask);

/**
 * kbase_mem_commit - Change the physical backing size of a region
 *
 * @kctx: The kernel context
 * @gpu_addr: Handle to the memory region
 * @new_pages: Number of physical pages to back the region with
 *
 * Return: 0 on success or error code
 */
int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages);

/**
 * kbase_mem_shrink - Shrink the physical backing size of a region
 *
 * @kctx: The kernel context
 * @reg:  The GPU region
 * @new_pages: Number of physical pages to back the region with
 *
 * Return: 0 on success or error code
 */
int kbase_mem_shrink(struct kbase_context *kctx,
		struct kbase_va_region *reg, u64 new_pages);

/**
 * kbase_context_mmap - Memory map method, gets invoked when mmap system call is
 *                      issued on device file /dev/malixx.
 * @kctx: The kernel context
 * @vma:  Pointer to the struct containing the info where the GPU allocation
 *        will be mapped in virtual address space of CPU.
 *
 * Return: 0 on success or error code
 */
int kbase_context_mmap(struct kbase_context *kctx, struct vm_area_struct *vma);

/**
 * kbase_mem_evictable_init - Initialize the Ephemeral memory eviction
 * mechanism.
 * @kctx: The kbase context to initialize.
 *
 * Return: Zero on success or -errno on failure.
 */
int kbase_mem_evictable_init(struct kbase_context *kctx);

/**
 * kbase_mem_evictable_deinit - De-initialize the Ephemeral memory eviction
 * mechanism.
 * @kctx: The kbase context to de-initialize.
 */
void kbase_mem_evictable_deinit(struct kbase_context *kctx);

/**
 * kbase_mem_grow_gpu_mapping - Grow the GPU mapping of an allocation
 * @kctx:      Context the region belongs to
 * @reg:       The GPU region
 * @new_pages: The number of pages after the grow
 * @old_pages: The number of pages before the grow
 * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops.
 *
 * Return: 0 on success, -errno on error.
 *
 * Expand the GPU mapping to encompass the new psychical pages which have
 * been added to the allocation.
 *
 * Note: Caller must be holding the region lock.
 */
int kbase_mem_grow_gpu_mapping(struct kbase_context *kctx,
			       struct kbase_va_region *reg, u64 new_pages,
			       u64 old_pages,
			       enum kbase_caller_mmu_sync_info mmu_sync_info);

/**
 * kbase_mem_evictable_make - Make a physical allocation eligible for eviction
 * @gpu_alloc: The physical allocation to make evictable
 *
 * Return: 0 on success, -errno on error.
 *
 * Take the provided region and make all the physical pages within it
 * reclaimable by the kernel, updating the per-process VM stats as well.
 * Remove any CPU mappings (as these can't be removed in the shrinker callback
 * as mmap_sem/mmap_lock might already be taken) but leave the GPU mapping
 * intact as and until the shrinker reclaims the allocation.
 *
 * Note: Must be called with the region lock of the containing context.
 */
int kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc);

/**
 * kbase_mem_evictable_unmake - Remove a physical allocations eligibility for
 * eviction.
 * @alloc: The physical allocation to remove eviction eligibility from.
 *
 * Return: True if the allocation had its backing restored and false if
 * it hasn't.
 *
 * Make the physical pages in the region no longer reclaimable and update the
 * per-process stats, if the shrinker has already evicted the memory then
 * re-allocate it if the region is still alive.
 *
 * Note: Must be called with the region lock of the containing context.
 */
bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *alloc);

typedef unsigned int kbase_vmap_flag;

/* Sync operations are needed on beginning and ending of access to kernel-mapped GPU memory.
 *
 * This is internal to the struct kbase_vmap_struct and should not be passed in by callers of
 * kbase_vmap-related functions.
 */
#define KBASE_VMAP_FLAG_SYNC_NEEDED (((kbase_vmap_flag)1) << 0)

/* Permanently mapped memory accounting (including enforcing limits) should be done on the
 * kernel-mapped GPU memory.
 *
 * This should be used if the kernel mapping is going to live for a potentially long time, for
 * example if it will persist after the caller has returned.
 */
#define KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING (((kbase_vmap_flag)1) << 1)

/* Set of flags that can be passed into kbase_vmap-related functions */
#define KBASE_VMAP_INPUT_FLAGS (KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING)

struct kbase_vmap_struct {
	off_t offset_in_page;
	struct kbase_mem_phy_alloc *cpu_alloc;
	struct kbase_mem_phy_alloc *gpu_alloc;
	struct tagged_addr *cpu_pages;
	struct tagged_addr *gpu_pages;
	void *addr;
	size_t size;
	kbase_vmap_flag flags;
};

/**
 * kbase_mem_shrink_gpu_mapping - Shrink the GPU mapping of an allocation
 * @kctx:      Context the region belongs to
 * @reg:       The GPU region or NULL if there isn't one
 * @new_pages: The number of pages after the shrink
 * @old_pages: The number of pages before the shrink
 *
 * Return: 0 on success, negative -errno on error
 *
 * Unmap the shrunk pages from the GPU mapping. Note that the size of the region
 * itself is unmodified as we still need to reserve the VA, only the page tables
 * will be modified by this function.
 */
int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx, struct kbase_va_region *reg,
				 u64 new_pages, u64 old_pages);

/**
 * kbase_vmap_reg - Map part of an existing region into the kernel safely, only if the requested
 *                  access permissions are supported
 * @kctx:         Context @reg belongs to
 * @reg:          The GPU region to map part of
 * @gpu_addr:     Start address of VA range to map, which must be within @reg
 * @size:         Size of VA range, which when added to @gpu_addr must be within @reg
 * @prot_request: Flags indicating how the caller will then access the memory
 * @map:          Structure to be given to kbase_vunmap() on freeing
 * @vmap_flags:   Flags of type kbase_vmap_flag
 *
 * Return: Kernel-accessible CPU pointer to the VA range, or NULL on error
 *
 * Variant of kbase_vmap_prot() that can be used given an existing region.
 *
 * The caller must satisfy one of the following for @reg:
 * * It must have been obtained by finding it on the region tracker, and the region lock must not
 *   have been released in the mean time.
 * * Or, it must have been refcounted with a call to kbase_va_region_alloc_get(), and the region
 *   lock is now held again.
 * * Or, @reg has had NO_USER_FREE set at creation time or under the region lock, and the
 *   region lock is now held again.
 *
 * The acceptable @vmap_flags are those in %KBASE_VMAP_INPUT_FLAGS.
 *
 * Refer to kbase_vmap_prot() for more information on the operation of this function.
 */
void *kbase_vmap_reg(struct kbase_context *kctx, struct kbase_va_region *reg, u64 gpu_addr,
		     size_t size, unsigned long prot_request, struct kbase_vmap_struct *map,
		     kbase_vmap_flag vmap_flags);

/**
 * kbase_vmap_prot - Map a GPU VA range into the kernel safely, only if the
 * requested access permissions are supported
 * @kctx:         Context the VA range belongs to
 * @gpu_addr:     Start address of VA range
 * @size:         Size of VA range
 * @prot_request: Flags indicating how the caller will then access the memory
 * @map:          Structure to be given to kbase_vunmap() on freeing
 *
 * Return: Kernel-accessible CPU pointer to the VA range, or NULL on error
 *
 * Map a GPU VA Range into the kernel. The VA range must be contained within a
 * GPU memory region. Appropriate CPU cache-flushing operations are made as
 * required, dependent on the CPU mapping for the memory region.
 *
 * This is safer than using kmap() on the pages directly,
 * because the pages here are refcounted to prevent freeing (and hence reuse
 * elsewhere in the system) until an kbase_vunmap()
 *
 * The flags in @prot_request should use KBASE_REG_{CPU,GPU}_{RD,WR}, to check
 * whether the region should allow the intended access, and return an error if
 * disallowed. This is essential for security of imported memory, particularly
 * a user buf from SHM mapped into the process as RO. In that case, write
 * access must be checked if the intention is for kernel to write to the
 * memory.
 *
 * The checks are also there to help catch access errors on memory where
 * security is not a concern: imported memory that is always RW, and memory
 * that was allocated and owned by the process attached to @kctx. In this case,
 * it helps to identify memory that was mapped with the wrong access type.
 *
 * Note: KBASE_REG_GPU_{RD,WR} flags are currently supported for legacy cases
 * where either the security of memory is solely dependent on those flags, or
 * when userspace code was expecting only the GPU to access the memory (e.g. HW
 * workarounds).
 *
 * All cache maintenance operations shall be ignored if the
 * memory region has been imported.
 *
 */
void *kbase_vmap_prot(struct kbase_context *kctx, u64 gpu_addr, size_t size,
		      unsigned long prot_request, struct kbase_vmap_struct *map);

/**
 * kbase_vmap - Map a GPU VA range into the kernel safely
 * @kctx:     Context the VA range belongs to
 * @gpu_addr: Start address of VA range
 * @size:     Size of VA range
 * @map:      Structure to be given to kbase_vunmap() on freeing
 *
 * Return: Kernel-accessible CPU pointer to the VA range, or NULL on error
 *
 * Map a GPU VA Range into the kernel. The VA range must be contained within a
 * GPU memory region. Appropriate CPU cache-flushing operations are made as
 * required, dependent on the CPU mapping for the memory region.
 *
 * This is safer than using kmap() on the pages directly,
 * because the pages here are refcounted to prevent freeing (and hence reuse
 * elsewhere in the system) until an kbase_vunmap()
 *
 * kbase_vmap_prot() should be used in preference, since kbase_vmap() makes no
 * checks to ensure the security of e.g. imported user bufs from RO SHM.
 *
 * Note: All cache maintenance operations shall be ignored if the memory region
 * has been imported.
 */
void *kbase_vmap(struct kbase_context *kctx, u64 gpu_addr, size_t size,
		struct kbase_vmap_struct *map);

/**
 * kbase_vunmap - Unmap a GPU VA range from the kernel
 * @kctx: Context the VA range belongs to
 * @map:  Structure describing the mapping from the corresponding kbase_vmap()
 *        call
 *
 * Unmaps a GPU VA range from the kernel, given its @map structure obtained
 * from kbase_vmap(). Appropriate CPU cache-flushing operations are made as
 * required, dependent on the CPU mapping for the memory region.
 *
 * The reference taken on pages during kbase_vmap() is released.
 *
 * Note: All cache maintenance operations shall be ignored if the memory region
 * has been imported.
 */
void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map);

extern const struct vm_operations_struct kbase_vm_ops;

/**
 * kbase_sync_mem_regions - Perform the cache maintenance for the kernel mode
 *                          CPU mapping.
 * @kctx: Context the CPU mapping belongs to.
 * @map:  Structure describing the CPU mapping, setup previously by the
 *        kbase_vmap() call.
 * @dest: Indicates the type of maintenance required (i.e. flush or invalidate)
 *
 * Note: The caller shall ensure that CPU mapping is not revoked & remains
 * active whilst the maintenance is in progress.
 */
void kbase_sync_mem_regions(struct kbase_context *kctx,
		struct kbase_vmap_struct *map, enum kbase_sync_type dest);

/**
 * kbase_mem_shrink_cpu_mapping - Shrink the CPU mapping(s) of an allocation
 * @kctx:      Context the region belongs to
 * @reg:       The GPU region
 * @new_pages: The number of pages after the shrink
 * @old_pages: The number of pages before the shrink
 *
 * Shrink (or completely remove) all CPU mappings which reference the shrunk
 * part of the allocation.
 */
void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx,
		struct kbase_va_region *reg,
		u64 new_pages, u64 old_pages);

/**
 * kbase_phy_alloc_mapping_term - Terminate the kernel side mapping of a
 *                                physical allocation
 * @kctx:  The kernel base context associated with the mapping
 * @alloc: Pointer to the allocation to terminate
 *
 * This function will unmap the kernel mapping, and free any structures used to
 * track it.
 */
void kbase_phy_alloc_mapping_term(struct kbase_context *kctx,
		struct kbase_mem_phy_alloc *alloc);

/**
 * kbase_phy_alloc_mapping_get - Get a kernel-side CPU pointer to the permanent
 *                               mapping of a physical allocation
 * @kctx:             The kernel base context @gpu_addr will be looked up in
 * @gpu_addr:         The gpu address to lookup for the kernel-side CPU mapping
 * @out_kern_mapping: Pointer to storage for a struct kbase_vmap_struct pointer
 *                    which will be used for a call to
 *                    kbase_phy_alloc_mapping_put()
 *
 * Return: Pointer to a kernel-side accessible location that directly
 *         corresponds to @gpu_addr, or NULL on failure
 *
 * Looks up @gpu_addr to retrieve the CPU pointer that can be used to access
 * that location kernel-side. Only certain kinds of memory have a permanent
 * kernel mapping, refer to the internal functions
 * kbase_reg_needs_kernel_mapping() and kbase_phy_alloc_mapping_init() for more
 * information.
 *
 * If this function succeeds, a CPU access to the returned pointer will access
 * the actual location represented by @gpu_addr. That is, the return value does
 * not require any offset added to it to access the location specified in
 * @gpu_addr
 *
 * The client must take care to either apply any necessary sync operations when
 * accessing the data, or ensure that the enclosing region was coherent with
 * the GPU, or uncached in the CPU.
 *
 * The refcount on the physical allocations backing the region are taken, so
 * that they do not disappear whilst the client is accessing it. Once the
 * client has finished accessing the memory, it must be released with a call to
 * kbase_phy_alloc_mapping_put()
 *
 * Whilst this is expected to execute quickly (the mapping was already setup
 * when the physical allocation was created), the call is not IRQ-safe due to
 * the region lookup involved.
 *
 * An error code may indicate that:
 * - a userside process has freed the allocation, and so @gpu_addr is no longer
 *   valid
 * - the region containing @gpu_addr does not support a permanent kernel mapping
 */
void *kbase_phy_alloc_mapping_get(struct kbase_context *kctx, u64 gpu_addr,
		struct kbase_vmap_struct **out_kern_mapping);

/**
 * kbase_phy_alloc_mapping_put - Put a reference to the kernel-side mapping of a
 *                               physical allocation
 * @kctx:         The kernel base context associated with the mapping
 * @kern_mapping: Pointer to a struct kbase_phy_alloc_mapping pointer obtained
 *                from a call to kbase_phy_alloc_mapping_get()
 *
 * Releases the reference to the allocations backing @kern_mapping that was
 * obtained through a call to kbase_phy_alloc_mapping_get(). This must be used
 * when the client no longer needs to access the kernel-side CPU pointer.
 *
 * If this was the last reference on the underlying physical allocations, they
 * will go through the normal allocation free steps, which also includes an
 * unmap of the permanent kernel mapping for those allocations.
 *
 * Due to these operations, the function is not IRQ-safe. However it is
 * expected to execute quickly in the normal case, i.e. when the region holding
 * the physical allocation is still present.
 */
void kbase_phy_alloc_mapping_put(struct kbase_context *kctx,
		struct kbase_vmap_struct *kern_mapping);

/**
 * kbase_get_cache_line_alignment - Return cache line alignment
 *
 * @kbdev: Device pointer.
 *
 * Helper function to return the maximum cache line alignment considering
 * both CPU and GPU cache sizes.
 *
 * Return: CPU and GPU cache line alignment, in bytes.
 */
u32 kbase_get_cache_line_alignment(struct kbase_device *kbdev);

#if (KERNEL_VERSION(4, 20, 0) > LINUX_VERSION_CODE)
static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma,
			unsigned long addr, unsigned long pfn, pgprot_t pgprot)
{
	int err = vm_insert_pfn_prot(vma, addr, pfn, pgprot);

	if (unlikely(err == -ENOMEM))
		return VM_FAULT_OOM;
	if (unlikely(err < 0 && err != -EBUSY))
		return VM_FAULT_SIGBUS;

	return VM_FAULT_NOPAGE;
}
#endif

/**
 * kbase_mem_get_process_mmap_lock - Return the mmap lock for the current process
 *
 * Return: the mmap lock for the current process
 */
static inline struct rw_semaphore *kbase_mem_get_process_mmap_lock(void)
{
#if KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE
	return &current->mm->mmap_sem;
#else /* KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE */
	return &current->mm->mmap_lock;
#endif /* KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE */
}

#endif				/* _KBASE_MEM_LINUX_H_ */