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>
128b52c726SCarlos Llamas #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
18ea9cdbf0SCarlos Llamas extern struct list_lru binder_freelist;
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 struct binder_transaction *transaction;
530c972a05STodd Kjos struct binder_node *target_node;
540c972a05STodd Kjos size_t data_size;
550c972a05STodd Kjos size_t offsets_size;
560c972a05STodd Kjos size_t extra_buffers_size;
57df9aabeaSCarlos Llamas unsigned long user_data;
58261e7818SMartijn Coenen int pid;
590c972a05STodd Kjos };
600c972a05STodd Kjos
610c972a05STodd Kjos /**
62f909f030SCarlos Llamas * struct binder_shrinker_mdata - binder metadata used to reclaim pages
63f909f030SCarlos Llamas * @lru: LRU entry in binder_freelist
64f909f030SCarlos Llamas * @alloc: binder_alloc owning the page to reclaim
65f909f030SCarlos Llamas * @page_index: offset in @alloc->pages[] into the page to reclaim
66f2517eb7SSherry Yang */
67f909f030SCarlos Llamas struct binder_shrinker_mdata {
68f2517eb7SSherry Yang struct list_head lru;
69f2517eb7SSherry Yang struct binder_alloc *alloc;
70f909f030SCarlos Llamas unsigned long page_index;
71f2517eb7SSherry Yang };
72f2517eb7SSherry Yang
page_to_lru(struct page * p)73f909f030SCarlos Llamas static inline struct list_head *page_to_lru(struct page *p)
74f909f030SCarlos Llamas {
75f909f030SCarlos Llamas struct binder_shrinker_mdata *mdata;
76f909f030SCarlos Llamas
77f909f030SCarlos Llamas mdata = (struct binder_shrinker_mdata *)page_private(p);
78f909f030SCarlos Llamas
79f909f030SCarlos Llamas return &mdata->lru;
80f909f030SCarlos Llamas }
81f909f030SCarlos Llamas
82f2517eb7SSherry Yang /**
830c972a05STodd Kjos * struct binder_alloc - per-binder proc state for binder allocator
848b52c726SCarlos Llamas * @mutex: protects binder_alloc fields
85e66b77e5SCarlos Llamas * @mm: copy of task->mm (invariant after open)
86*0a7bf686SCarlos Llamas * @vm_start: base of per-proc address space mapped via mmap
870c972a05STodd Kjos * @buffers: list of all buffers for this proc
880c972a05STodd Kjos * @free_buffers: rb tree of buffers available for allocation
890c972a05STodd Kjos * sorted by size
900c972a05STodd Kjos * @allocated_buffers: rb tree of allocated buffers sorted by address
910c972a05STodd Kjos * @free_async_space: VA space available for async buffers. This is
920c972a05STodd Kjos * initialized at mmap time to 1/2 the full VA space
93f909f030SCarlos Llamas * @pages: array of struct page *
940c972a05STodd Kjos * @buffer_size: size of address space specified via mmap
950c972a05STodd Kjos * @pid: pid for associated binder_proc (invariant after init)
968d9a3ab6SMartijn Coenen * @pages_high: high watermark of offset in @pages
97072010abSCarlos Llamas * @mapped: whether the vm area is mapped, each binder instance is
98072010abSCarlos Llamas * allowed a single mapping throughout its lifetime
99a7dc1e6fSHang Lu * @oneway_spam_detected: %true if oneway spam detection fired, clear that
100a7dc1e6fSHang Lu * flag once the async buffer has returned to a healthy state
1010c972a05STodd Kjos *
1020c972a05STodd Kjos * Bookkeeping structure for per-proc address space management for binder
1030c972a05STodd Kjos * buffers. It is normally initialized during binder_init() and binder_mmap()
1040c972a05STodd Kjos * calls. The address space is used for both user-visible buffers and for
1050c972a05STodd Kjos * struct binder_buffer objects used to track the user buffers
1060c972a05STodd Kjos */
1070c972a05STodd Kjos struct binder_alloc {
1088b52c726SCarlos Llamas struct mutex mutex;
109e66b77e5SCarlos Llamas struct mm_struct *mm;
110*0a7bf686SCarlos Llamas unsigned long vm_start;
1110c972a05STodd Kjos struct list_head buffers;
1120c972a05STodd Kjos struct rb_root free_buffers;
1130c972a05STodd Kjos struct rb_root allocated_buffers;
1140c972a05STodd Kjos size_t free_async_space;
115f909f030SCarlos Llamas struct page **pages;
1160c972a05STodd Kjos size_t buffer_size;
1170c972a05STodd Kjos int pid;
1188d9a3ab6SMartijn Coenen size_t pages_high;
119072010abSCarlos Llamas bool mapped;
120a7dc1e6fSHang Lu bool oneway_spam_detected;
1210c972a05STodd Kjos };
1220c972a05STodd Kjos
1234175e2b4SSherry Yang #ifdef CONFIG_ANDROID_BINDER_IPC_SELFTEST
1244175e2b4SSherry Yang void binder_selftest_alloc(struct binder_alloc *alloc);
1254175e2b4SSherry Yang #else
binder_selftest_alloc(struct binder_alloc * alloc)1264175e2b4SSherry Yang static inline void binder_selftest_alloc(struct binder_alloc *alloc) {}
1274175e2b4SSherry Yang #endif
128f2517eb7SSherry Yang enum lru_status binder_alloc_free_page(struct list_head *item,
129f2517eb7SSherry Yang struct list_lru_one *lru,
130da0c0251SKairui Song void *cb_arg);
131da483f8bSCarlos Llamas struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
1320c972a05STodd Kjos size_t data_size,
1330c972a05STodd Kjos size_t offsets_size,
1340c972a05STodd Kjos size_t extra_buffers_size,
13589f71743SCarlos Llamas int is_async);
136da483f8bSCarlos Llamas void binder_alloc_init(struct binder_alloc *alloc);
137da483f8bSCarlos Llamas int binder_alloc_shrinker_init(void);
138da483f8bSCarlos Llamas void binder_alloc_shrinker_exit(void);
139da483f8bSCarlos Llamas void binder_alloc_vma_close(struct binder_alloc *alloc);
140da483f8bSCarlos Llamas struct binder_buffer *
14153d311cfSTodd Kjos binder_alloc_prepare_to_free(struct binder_alloc *alloc,
142df9aabeaSCarlos Llamas unsigned long user_ptr);
143da483f8bSCarlos Llamas void binder_alloc_free_buf(struct binder_alloc *alloc,
1440c972a05STodd Kjos struct binder_buffer *buffer);
145da483f8bSCarlos Llamas int binder_alloc_mmap_handler(struct binder_alloc *alloc,
1460c972a05STodd Kjos struct vm_area_struct *vma);
147da483f8bSCarlos Llamas void binder_alloc_deferred_release(struct binder_alloc *alloc);
148da483f8bSCarlos Llamas int binder_alloc_get_allocated_count(struct binder_alloc *alloc);
149da483f8bSCarlos Llamas void binder_alloc_print_allocated(struct seq_file *m,
1500c972a05STodd Kjos struct binder_alloc *alloc);
1518ef4665aSSherry Yang void binder_alloc_print_pages(struct seq_file *m,
1528ef4665aSSherry Yang struct binder_alloc *alloc);
1530c972a05STodd Kjos
1540c972a05STodd Kjos /**
1550c972a05STodd Kjos * binder_alloc_get_free_async_space() - get free space available for async
1560c972a05STodd Kjos * @alloc: binder_alloc for this proc
1570c972a05STodd Kjos *
1580c972a05STodd Kjos * Return: the bytes remaining in the address-space for async transactions
1590c972a05STodd Kjos */
1600c972a05STodd Kjos static inline size_t
binder_alloc_get_free_async_space(struct binder_alloc * alloc)1610c972a05STodd Kjos binder_alloc_get_free_async_space(struct binder_alloc *alloc)
1620c972a05STodd Kjos {
1630c972a05STodd Kjos size_t free_async_space;
1640c972a05STodd Kjos
1658b52c726SCarlos Llamas mutex_lock(&alloc->mutex);
1660c972a05STodd Kjos free_async_space = alloc->free_async_space;
1678b52c726SCarlos Llamas mutex_unlock(&alloc->mutex);
1680c972a05STodd Kjos return free_async_space;
1690c972a05STodd Kjos }
1700c972a05STodd Kjos
1711a7c3d9bSTodd Kjos unsigned long
1721a7c3d9bSTodd Kjos binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
1731a7c3d9bSTodd Kjos struct binder_buffer *buffer,
1741a7c3d9bSTodd Kjos binder_size_t buffer_offset,
1751a7c3d9bSTodd Kjos const void __user *from,
1761a7c3d9bSTodd Kjos size_t bytes);
1771a7c3d9bSTodd Kjos
178bb4a2e48STodd Kjos int binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
1798ced0c62STodd Kjos struct binder_buffer *buffer,
1808ced0c62STodd Kjos binder_size_t buffer_offset,
1818ced0c62STodd Kjos void *src,
1828ced0c62STodd Kjos size_t bytes);
1838ced0c62STodd Kjos
184bb4a2e48STodd Kjos int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
1858ced0c62STodd Kjos void *dest,
1868ced0c62STodd Kjos struct binder_buffer *buffer,
1878ced0c62STodd Kjos binder_size_t buffer_offset,
1888ced0c62STodd Kjos size_t bytes);
1898ced0c62STodd Kjos
1900c972a05STodd Kjos #endif /* _LINUX_BINDER_ALLOC_H */
1910c972a05STodd Kjos
192