19c92ab61SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
20c972a05STodd Kjos /*
30c972a05STodd Kjos * Copyright (C) 2017 Google, Inc.
40c972a05STodd Kjos */
50c972a05STodd Kjos
60c972a05STodd Kjos #ifndef _LINUX_BINDER_ALLOC_H
70c972a05STodd Kjos #define _LINUX_BINDER_ALLOC_H
80c972a05STodd Kjos
90c972a05STodd Kjos #include <linux/rbtree.h>
100c972a05STodd Kjos #include <linux/list.h>
110c972a05STodd Kjos #include <linux/mm.h>
120c972a05STodd Kjos #include <linux/rtmutex.h>
130c972a05STodd Kjos #include <linux/vmalloc.h>
140c972a05STodd Kjos #include <linux/slab.h>
15f2517eb7SSherry Yang #include <linux/list_lru.h>
161a7c3d9bSTodd Kjos #include <uapi/linux/android/binder.h>
170c972a05STodd Kjos
18f2517eb7SSherry Yang extern struct list_lru binder_alloc_lru;
190c972a05STodd Kjos struct binder_transaction;
200c972a05STodd Kjos
210c972a05STodd Kjos /**
220c972a05STodd Kjos * struct binder_buffer - buffer used for binder transactions
230c972a05STodd Kjos * @entry: entry alloc->buffers
240c972a05STodd Kjos * @rb_node: node for allocated_buffers/free_buffers rb trees
257a2670a5STodd Kjos * @free: %true if buffer is free
260f966cbaSTodd Kjos * @clear_on_free: %true if buffer must be zeroed after use
277a2670a5STodd Kjos * @allow_user_free: %true if user is allowed to free buffer
287a2670a5STodd Kjos * @async_transaction: %true if buffer is in use for an async txn
29a7dc1e6fSHang Lu * @oneway_spam_suspect: %true if total async allocate size just exceed
30a7dc1e6fSHang Lu * spamming detect threshold
317a2670a5STodd Kjos * @debug_id: unique ID for debugging
327a2670a5STodd Kjos * @transaction: pointer to associated struct binder_transaction
337a2670a5STodd Kjos * @target_node: struct binder_node associated with this buffer
347a2670a5STodd Kjos * @data_size: size of @transaction data
357a2670a5STodd Kjos * @offsets_size: size of array of offsets
367a2670a5STodd Kjos * @extra_buffers_size: size of space for other objects (like sg lists)
37bde4a19fSTodd Kjos * @user_data: user pointer to base of buffer space
38261e7818SMartijn Coenen * @pid: pid to attribute the buffer to (caller)
390c972a05STodd Kjos *
400c972a05STodd Kjos * Bookkeeping structure for binder transaction buffers
410c972a05STodd Kjos */
420c972a05STodd Kjos struct binder_buffer {
430c972a05STodd Kjos struct list_head entry; /* free and allocated entries by address */
440c972a05STodd Kjos struct rb_node rb_node; /* free entry by size or allocated entry */
450c972a05STodd Kjos /* by address */
460c972a05STodd Kjos unsigned free:1;
470f966cbaSTodd Kjos unsigned clear_on_free:1;
480c972a05STodd Kjos unsigned allow_user_free:1;
490c972a05STodd Kjos unsigned async_transaction:1;
50a7dc1e6fSHang Lu unsigned oneway_spam_suspect:1;
51a7dc1e6fSHang Lu unsigned debug_id:27;
520c972a05STodd Kjos
530c972a05STodd Kjos struct binder_transaction *transaction;
540c972a05STodd Kjos
550c972a05STodd Kjos struct binder_node *target_node;
560c972a05STodd Kjos size_t data_size;
570c972a05STodd Kjos size_t offsets_size;
580c972a05STodd Kjos size_t extra_buffers_size;
59bde4a19fSTodd Kjos void __user *user_data;
60261e7818SMartijn Coenen int pid;
610c972a05STodd Kjos };
620c972a05STodd Kjos
630c972a05STodd Kjos /**
64f2517eb7SSherry Yang * struct binder_lru_page - page object used for binder shrinker
65f2517eb7SSherry Yang * @page_ptr: pointer to physical page in mmap'd space
66f2517eb7SSherry Yang * @lru: entry in binder_alloc_lru
67f2517eb7SSherry Yang * @alloc: binder_alloc for a proc
68f2517eb7SSherry Yang */
69f2517eb7SSherry Yang struct binder_lru_page {
70f2517eb7SSherry Yang struct list_head lru;
71f2517eb7SSherry Yang struct page *page_ptr;
72f2517eb7SSherry Yang struct binder_alloc *alloc;
73f2517eb7SSherry Yang };
74f2517eb7SSherry Yang
75f2517eb7SSherry Yang /**
760c972a05STodd Kjos * struct binder_alloc - per-binder proc state for binder allocator
777b0dbd94SCarlos Llamas * @mutex: protects binder_alloc fields
78c0fd2101SCarlos Llamas * @vma: vm_area_struct passed to mmap_handler
7976ff3346SCarlos Llamas * (invariant after mmap)
80e66b77e5SCarlos Llamas * @mm: copy of task->mm (invariant after open)
810c972a05STodd Kjos * @buffer: base of per-proc address space mapped via mmap
820c972a05STodd Kjos * @buffers: list of all buffers for this proc
830c972a05STodd Kjos * @free_buffers: rb tree of buffers available for allocation
840c972a05STodd Kjos * sorted by size
850c972a05STodd Kjos * @allocated_buffers: rb tree of allocated buffers sorted by address
860c972a05STodd Kjos * @free_async_space: VA space available for async buffers. This is
870c972a05STodd Kjos * initialized at mmap time to 1/2 the full VA space
88f2517eb7SSherry Yang * @pages: array of binder_lru_page
890c972a05STodd Kjos * @buffer_size: size of address space specified via mmap
900c972a05STodd Kjos * @pid: pid for associated binder_proc (invariant after init)
918d9a3ab6SMartijn Coenen * @pages_high: high watermark of offset in @pages
92a7dc1e6fSHang Lu * @oneway_spam_detected: %true if oneway spam detection fired, clear that
93a7dc1e6fSHang Lu * flag once the async buffer has returned to a healthy state
940c972a05STodd Kjos *
950c972a05STodd Kjos * Bookkeeping structure for per-proc address space management for binder
960c972a05STodd Kjos * buffers. It is normally initialized during binder_init() and binder_mmap()
970c972a05STodd Kjos * calls. The address space is used for both user-visible buffers and for
980c972a05STodd Kjos * struct binder_buffer objects used to track the user buffers
990c972a05STodd Kjos */
1000c972a05STodd Kjos struct binder_alloc {
1010c972a05STodd Kjos struct mutex mutex;
102c0fd2101SCarlos Llamas struct vm_area_struct *vma;
103e66b77e5SCarlos Llamas struct mm_struct *mm;
104bde4a19fSTodd Kjos void __user *buffer;
1050c972a05STodd Kjos struct list_head buffers;
1060c972a05STodd Kjos struct rb_root free_buffers;
1070c972a05STodd Kjos struct rb_root allocated_buffers;
1080c972a05STodd Kjos size_t free_async_space;
109f2517eb7SSherry Yang struct binder_lru_page *pages;
1100c972a05STodd Kjos size_t buffer_size;
1110c972a05STodd Kjos int pid;
1128d9a3ab6SMartijn Coenen size_t pages_high;
113a7dc1e6fSHang Lu bool oneway_spam_detected;
1140c972a05STodd Kjos };
1150c972a05STodd Kjos
1164175e2b4SSherry Yang #ifdef CONFIG_ANDROID_BINDER_IPC_SELFTEST
1174175e2b4SSherry Yang void binder_selftest_alloc(struct binder_alloc *alloc);
1184175e2b4SSherry Yang #else
binder_selftest_alloc(struct binder_alloc * alloc)1194175e2b4SSherry Yang static inline void binder_selftest_alloc(struct binder_alloc *alloc) {}
1204175e2b4SSherry Yang #endif
121f2517eb7SSherry Yang enum lru_status binder_alloc_free_page(struct list_head *item,
122f2517eb7SSherry Yang struct list_lru_one *lru,
123f2517eb7SSherry Yang spinlock_t *lock, void *cb_arg);
1240c972a05STodd Kjos extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
1250c972a05STodd Kjos size_t data_size,
1260c972a05STodd Kjos size_t offsets_size,
1270c972a05STodd Kjos size_t extra_buffers_size,
128261e7818SMartijn Coenen int is_async,
129261e7818SMartijn Coenen int pid);
1300c972a05STodd Kjos extern void binder_alloc_init(struct binder_alloc *alloc);
131533dfb25STetsuo Handa extern int binder_alloc_shrinker_init(void);
132*adb9743dSQi Zheng extern void binder_alloc_shrinker_exit(void);
1330c972a05STodd Kjos extern void binder_alloc_vma_close(struct binder_alloc *alloc);
1340c972a05STodd Kjos extern struct binder_buffer *
13553d311cfSTodd Kjos binder_alloc_prepare_to_free(struct binder_alloc *alloc,
1360c972a05STodd Kjos uintptr_t user_ptr);
1370c972a05STodd Kjos extern void binder_alloc_free_buf(struct binder_alloc *alloc,
1380c972a05STodd Kjos struct binder_buffer *buffer);
1390c972a05STodd Kjos extern int binder_alloc_mmap_handler(struct binder_alloc *alloc,
1400c972a05STodd Kjos struct vm_area_struct *vma);
1410c972a05STodd Kjos extern void binder_alloc_deferred_release(struct binder_alloc *alloc);
1420c972a05STodd Kjos extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc);
1430c972a05STodd Kjos extern void binder_alloc_print_allocated(struct seq_file *m,
1440c972a05STodd Kjos struct binder_alloc *alloc);
1458ef4665aSSherry Yang void binder_alloc_print_pages(struct seq_file *m,
1468ef4665aSSherry Yang struct binder_alloc *alloc);
1470c972a05STodd Kjos
1480c972a05STodd Kjos /**
1490c972a05STodd Kjos * binder_alloc_get_free_async_space() - get free space available for async
1500c972a05STodd Kjos * @alloc: binder_alloc for this proc
1510c972a05STodd Kjos *
1520c972a05STodd Kjos * Return: the bytes remaining in the address-space for async transactions
1530c972a05STodd Kjos */
1540c972a05STodd Kjos static inline size_t
binder_alloc_get_free_async_space(struct binder_alloc * alloc)1550c972a05STodd Kjos binder_alloc_get_free_async_space(struct binder_alloc *alloc)
1560c972a05STodd Kjos {
1570c972a05STodd Kjos size_t free_async_space;
1580c972a05STodd Kjos
1590c972a05STodd Kjos mutex_lock(&alloc->mutex);
1600c972a05STodd Kjos free_async_space = alloc->free_async_space;
1610c972a05STodd Kjos mutex_unlock(&alloc->mutex);
1620c972a05STodd Kjos return free_async_space;
1630c972a05STodd Kjos }
1640c972a05STodd Kjos
1651a7c3d9bSTodd Kjos unsigned long
1661a7c3d9bSTodd Kjos binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
1671a7c3d9bSTodd Kjos struct binder_buffer *buffer,
1681a7c3d9bSTodd Kjos binder_size_t buffer_offset,
1691a7c3d9bSTodd Kjos const void __user *from,
1701a7c3d9bSTodd Kjos size_t bytes);
1711a7c3d9bSTodd Kjos
172bb4a2e48STodd Kjos int binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
1738ced0c62STodd Kjos struct binder_buffer *buffer,
1748ced0c62STodd Kjos binder_size_t buffer_offset,
1758ced0c62STodd Kjos void *src,
1768ced0c62STodd Kjos size_t bytes);
1778ced0c62STodd Kjos
178bb4a2e48STodd Kjos int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
1798ced0c62STodd Kjos void *dest,
1808ced0c62STodd Kjos struct binder_buffer *buffer,
1818ced0c62STodd Kjos binder_size_t buffer_offset,
1828ced0c62STodd Kjos size_t bytes);
1838ced0c62STodd Kjos
1840c972a05STodd Kjos #endif /* _LINUX_BINDER_ALLOC_H */
1850c972a05STodd Kjos
186