xref: /linux-6.15/drivers/android/binder_alloc.h (revision 0a7bf686)
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