From 2755f25d0c9ae7bb320880583ab41705f7372d66 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Wed, 28 Feb 2024 17:24:41 +0530 Subject: [PATCH 01/46] UPSTREAM: usb: gadget: ncm: Fix handling of zero block length packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While connecting to a Linux host with CDC_NCM_NTB_DEF_SIZE_TX set to 65536, it has been observed that we receive short packets, which come at interval of 5-10 seconds sometimes and have block length zero but still contain 1-2 valid datagrams present. According to the NCM spec: "If wBlockLength = 0x0000, the block is terminated by a short packet. In this case, the USB transfer must still be shorter than dwNtbInMaxSize or dwNtbOutMaxSize. If exactly dwNtbInMaxSize or dwNtbOutMaxSize bytes are sent, and the size is a multiple of wMaxPacketSize for the given pipe, then no ZLP shall be sent. wBlockLength= 0x0000 must be used with extreme care, because of the possibility that the host and device may get out of sync, and because of test issues. wBlockLength = 0x0000 allows the sender to reduce latency by starting to send a very large NTB, and then shortening it when the sender discovers that there’s not sufficient data to justify sending a large NTB" However, there is a potential issue with the current implementation, as it checks for the occurrence of multiple NTBs in a single giveback by verifying if the leftover bytes to be processed is zero or not. If the block length reads zero, we would process the same NTB infintely because the leftover bytes is never zero and it leads to a crash. Fix this by bailing out if block length reads zero. Cc: stable@vger.kernel.org Fixes: 427694cfaafa ("usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call") Signed-off-by: Krishna Kurapati Reviewed-by: Maciej Żenczykowski Link: https://lore.kernel.org/r/20240228115441.2105585-1-quic_kriskura@quicinc.com Signed-off-by: Greg Kroah-Hartman (cherry picked from commit f90ce1e04cbcc76639d6cba0fdbd820cd80b3c70 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master) Bug: 320608613 Change-Id: I4b60d855f5539e66261e71dc2a29c7d22712e382 Signed-off-by: Krishna Kurapati (cherry picked from commit b493b35d3a52a47d92607a03c257fcb71fcc2ef9) --- drivers/usb/gadget/function/f_ncm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 5e78fcc63e4d..14601a2d2542 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1348,7 +1348,7 @@ parse_ntb: if (to_process == 1 && (*(unsigned char *)(ntb_ptr + block_len) == 0x00)) { to_process--; - } else if (to_process > 0) { + } else if ((to_process > 0) && (block_len != 0)) { ntb_ptr = (unsigned char *)(ntb_ptr + block_len); goto parse_ntb; } From 84574a4ee98a7240ede177bd18cb95eaea8a6f6d Mon Sep 17 00:00:00 2001 From: Kyle Tso Date: Mon, 20 May 2024 23:28:09 +0800 Subject: [PATCH 02/46] FROMLIST: usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state Similar to what fixed in Commit a6fe37f428c1 ("usb: typec: tcpm: Skip hard reset when in error recovery"), the handling of the received Hard Reset has to be skipped during TOGGLING state. [ 4086.021288] VBUS off [ 4086.021295] pending state change SNK_READY -> SNK_UNATTACHED @ 650 ms [rev2 NONE_AMS] [ 4086.022113] VBUS VSAFE0V [ 4086.022117] state change SNK_READY -> SNK_UNATTACHED [rev2 NONE_AMS] [ 4086.022447] VBUS off [ 4086.022450] state change SNK_UNATTACHED -> SNK_UNATTACHED [rev2 NONE_AMS] [ 4086.023060] VBUS VSAFE0V [ 4086.023064] state change SNK_UNATTACHED -> SNK_UNATTACHED [rev2 NONE_AMS] [ 4086.023070] disable BIST MODE TESTDATA [ 4086.023766] disable vbus discharge ret:0 [ 4086.023911] Setting usb_comm capable false [ 4086.028874] Setting voltage/current limit 0 mV 0 mA [ 4086.028888] polarity 0 [ 4086.030305] Requesting mux state 0, usb-role 0, orientation 0 [ 4086.033539] Start toggling [ 4086.038496] state change SNK_UNATTACHED -> TOGGLING [rev2 NONE_AMS] // This Hard Reset is unexpected [ 4086.038499] Received hard reset [ 4086.038501] state change TOGGLING -> HARD_RESET_START [rev2 HARD_RESET] Fixes: f0690a25a140 ("staging: typec: USB Type-C Port Manager (tcpm)") Cc: stable@vger.kernel.org Signed-off-by: Kyle Tso Reviewed-by: Heikki Krogerus Change-Id: Icfa144f370bd87670df1cd71f247a3528ab4c591 Bug: 331356545 Link: https://lore.kernel.org/all/20240520154858.1072347-1-kyletso@google.com/ --- drivers/usb/typec/tcpm/tcpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 34543d2c1f0b..fc89be47a4da 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -5467,6 +5467,7 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port) port->tcpc->set_bist_data(port->tcpc, false); switch (port->state) { + case TOGGLING: case ERROR_RECOVERY: case PORT_RESET: case PORT_RESET_WAIT_OFF: From 68c821783c7688df37f4ac7bb39f3fb606b827c0 Mon Sep 17 00:00:00 2001 From: Qianfeng Rong Date: Tue, 21 May 2024 12:54:16 +0800 Subject: [PATCH 03/46] UPSTREAM: epoll: be better about file lifetimes epoll can call out to vfs_poll() with a file pointer that may race with the last 'fput()'. That would make f_count go down to zero, and while the ep->mtx locking means that the resulting file pointer tear-down will be blocked until the poll returns, it means that f_count is already dead, and any use of it won't actually get a reference to the file any more: it's dead regardless. Make sure we have a valid ref on the file pointer before we call down to vfs_poll() from the epoll routines. Bug: 341834298 Change-Id: Iefa13cd84102ded3e104c030c8d7d0b7a8c1eab2 Link: https://lore.kernel.org/lkml/0000000000002d631f0615918f1e@google.com/ Reported-by: syzbot+045b454ab35fd82a35fb@syzkaller.appspotmail.com Reviewed-by: Jens Axboe Signed-off-by: Linus Torvalds (cherry picked from commit 4efaa5acf0a1d2b5947f98abb3acf8bfd966422b) Signed-off-by: Qianfeng Rong --- fs/eventpoll.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6aec06ec2de6..f2c5a2f7fd41 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -878,6 +878,34 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep return res; } +/* + * The ffd.file pointer may be in the process of being torn down due to + * being closed, but we may not have finished eventpoll_release() yet. + * + * Normally, even with the atomic_long_inc_not_zero, the file may have + * been free'd and then gotten re-allocated to something else (since + * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU). + * + * But for epoll, users hold the ep->mtx mutex, and as such any file in + * the process of being free'd will block in eventpoll_release_file() + * and thus the underlying file allocation will not be free'd, and the + * file re-use cannot happen. + * + * For the same reason we can avoid a rcu_read_lock() around the + * operation - 'ffd.file' cannot go away even if the refcount has + * reached zero (but we must still not call out to ->poll() functions + * etc). + */ +static struct file *epi_fget(const struct epitem *epi) +{ + struct file *file; + + file = epi->ffd.file; + if (!atomic_long_inc_not_zero(&file->f_count)) + file = NULL; + return file; +} + /* * Differs from ep_eventpoll_poll() in that internal callers already have * the ep->mtx so we need to start from depth=1, such that mutex_lock_nested() @@ -886,14 +914,22 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep static __poll_t ep_item_poll(const struct epitem *epi, poll_table *pt, int depth) { - struct file *file = epi->ffd.file; + struct file *file = epi_fget(epi); __poll_t res; + /* + * We could return EPOLLERR | EPOLLHUP or something, but let's + * treat this more as "file doesn't exist, poll didn't happen". + */ + if (!file) + return 0; + pt->_key = epi->event.events; if (!is_file_epoll(file)) res = vfs_poll(file, pt); else res = __ep_eventpoll_poll(file, pt, depth); + fput(file); return res & epi->event.events; } From 47a00e599b5f334815b95c4f8a703f6133b28767 Mon Sep 17 00:00:00 2001 From: Giuliano Procida Date: Thu, 23 May 2024 09:47:16 +0100 Subject: [PATCH 04/46] ANDROID: pahole -J -j1 for reproducible BTF Versions of pahole from 1.22 support multi-threaded operation with separate CUs being processed independently. This results in non-deterministic and effectively non-reproducible output for kernel objects. Later versions of pahole aim to support determinism by retiring CUs in order. We regain determinism by restricting parallelism to 1 at the cost of some performance. The default parallelism of `pahole -J` is the number of online processors * 1.1. Experiments on a workstation with 36 cores reveal that performance is actually worse for `vmlinux` at `-j` (8.9s) than at `-j3` (7.8s) and the optimum is around `-j9` (4.9s). No parallelism is slowest (18.8s), but still acceptable for GKI. Bug: 342094847 Change-Id: Ibd72ac638faa1826f6655b336cc7001591ea70f1 Signed-off-by: Giuliano Procida --- scripts/pahole-flags.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh index 728d55190d97..746e91c86860 100755 --- a/scripts/pahole-flags.sh +++ b/scripts/pahole-flags.sh @@ -17,7 +17,7 @@ if [ "${pahole_ver}" -ge "121" ]; then extra_paholeopt="${extra_paholeopt} --btf_gen_floats" fi if [ "${pahole_ver}" -ge "122" ]; then - extra_paholeopt="${extra_paholeopt} -j" + extra_paholeopt="${extra_paholeopt} -j1" fi if [ "${pahole_ver}" -ge "124" ]; then # see PAHOLE_HAS_LANG_EXCLUDE From 6820762b5e43ccdce6272b583e77dd728143f94c Mon Sep 17 00:00:00 2001 From: Matthias Maennich Date: Tue, 28 May 2024 11:32:43 +0000 Subject: [PATCH 05/46] FROMLIST: kheaders: explicitly define file modes for archived headers Build environments might be running with different umask settings resulting in indeterministic file modes for the files contained in kheaders.tar.xz. The file itself is served with 444, i.e. world readable. Archive the files explicitly with 744,a+X to improve reproducibility across build environments. --mode=0444 is not suitable as directories need to be executable. Also, 444 makes it hard to delete all the readonly files after extraction. Cc: Cc: Cc: Masahiro Yamada Cc: Joel Fernandes Link: https://lore.kernel.org/r/20240528113243.827490-2-maennich@google.com Bug: 342094847 Bug: 342393806 Change-Id: Ib206a6e0abfacf8132bfad8c43a62982062175fa Signed-off-by: Matthias Maennich --- kernel/gen_kheaders.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index bb8945ca53cd..25f958ffa37f 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -85,7 +85,7 @@ find $cpio_dir -type f -print0 | # pre-sorted, as --sort=name might not be available. find $cpio_dir -printf "./%P\n" | LC_ALL=C sort | \ tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ - --owner=0 --group=0 --numeric-owner --no-recursion \ + --owner=0 --group=0 --numeric-owner --no-recursion --mode=u=rw,go=r,a+X \ -I $XZ -cf $tarfile -C $cpio_dir/ -T - > /dev/null echo $headers_md5 > kernel/kheaders.md5 From 29f2af3ce7df16cc916095f53a5128120023780b Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 10 Apr 2024 19:48:02 +0000 Subject: [PATCH 06/46] BACKPORT: FROMGIT: module: allow UNUSED_KSYMS_WHITELIST to be relative against objtree. If UNUSED_KSYMS_WHITELIST is a file generated before Kbuild runs, and the source tree is in a read-only filesystem, the developer must put the file somewhere and specify an absolute path to UNUSED_KSYMS_WHITELIST. This worked, but if IKCONFIG=y, an absolute path is embedded into .config and eventually into vmlinux, causing the build to be less reproducible when building on a different machine. This patch makes the handling of UNUSED_KSYMS_WHITELIST to be similar to MODULE_SIG_KEY. First, check if UNUSED_KSYMS_WHITELIST is an absolute path, just as before this patch. If so, use the path as is. If it is a relative path, use wildcard to check the existence of the file below objtree first. If it does not exist, fall back to the original behavior of adding $(srctree)/ before the value. After this patch, the developer can put the generated file in objtree, then use a relative path against objtree in .config, eradicating any absolute paths that may be evaluated differently on different machines. Signed-off-by: Yifan Hong Reviewed-by: Elliot Berman Signed-off-by: Luis Chamberlain (cherry picked from commit a2e3c811938b4902725e259c03b2d6c539613992 https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next) Bug: 333769605 Change-Id: I0696ac8f686329795034ada5a4587af4ecbb774f [elsk: apply change to gen_autoksyms.sh instead because CONFIG_UNUSED_KSYMS_WHITELIST is parsed there. Revert change to Makefile.modpost.] Bug: 342390208 Signed-off-by: Yifan Hong --- kernel/module/Kconfig | 2 +- scripts/gen_autoksyms.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index 6b5c1175faea..ef66cce84d61 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -311,7 +311,7 @@ config UNUSED_KSYMS_WHITELIST exported at all times, even in absence of in-tree users. The value to set here is the path to a text file containing the list of symbols, one per line. The path can be absolute, or relative to the kernel - source tree. + source or obj tree. config MODULES_TREE_LOOKUP def_bool y diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 653fadbad302..e12178d677e2 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -31,7 +31,7 @@ fi ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) if [ -n "$ksym_wl" ]; then - [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" + [ "${ksym_wl}" != "${ksym_wl#/}" ] || [ -f "$ksym_wl" ] || ksym_wl="$abs_srctree/$ksym_wl" if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 exit 1 From 3f139724700e080489f2249b0bab4d22f633e455 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 28 May 2024 17:12:58 +0000 Subject: [PATCH 07/46] Revert "BACKPORT: FROMGIT: module: allow UNUSED_KSYMS_WHITELIST ..." Revert submission 3101887-android14-ksyms-wl Reason for revert: Restore green in release builds Reverted changes: /q/submissionid:3101887-android14-ksyms-wl Change-Id: If86a1a6c7875bace543381575544590823cd092c --- kernel/module/Kconfig | 2 +- scripts/gen_autoksyms.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index ef66cce84d61..6b5c1175faea 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -311,7 +311,7 @@ config UNUSED_KSYMS_WHITELIST exported at all times, even in absence of in-tree users. The value to set here is the path to a text file containing the list of symbols, one per line. The path can be absolute, or relative to the kernel - source or obj tree. + source tree. config MODULES_TREE_LOOKUP def_bool y diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index e12178d677e2..653fadbad302 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -31,7 +31,7 @@ fi ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) if [ -n "$ksym_wl" ]; then - [ "${ksym_wl}" != "${ksym_wl#/}" ] || [ -f "$ksym_wl" ] || ksym_wl="$abs_srctree/$ksym_wl" + [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 exit 1 From e302f3a21b6554722c72787fddc4780c0280e88b Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Wed, 28 Jun 2023 13:17:03 -0700 Subject: [PATCH 08/46] ANDROID: incremental-fs: Make work with 16k pages Bug: 260919895 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: Ia4fbb6011930b085bc00a36851e9b0e8559d3dc5 (cherry picked from commit 5ac10739bcf2dae9220a7a39392aa41235bc64c2) --- fs/incfs/pseudo_files.c | 10 +++--- fs/incfs/verity.c | 8 ++--- fs/incfs/vfs.c | 67 ++++++++++++++++++++++------------------- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/fs/incfs/pseudo_files.c b/fs/incfs/pseudo_files.c index 814d7063581a..eea115de98c7 100644 --- a/fs/incfs/pseudo_files.c +++ b/fs/incfs/pseudo_files.c @@ -1073,7 +1073,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, int rl_size; ssize_t result = 0; bool report_uid; - unsigned long page = 0; + void *page = 0; struct incfs_pending_read_info *reads_buf = NULL; struct incfs_pending_read_info2 *reads_buf2 = NULL; size_t record_size; @@ -1086,13 +1086,13 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, report_uid = mi->mi_options.report_uid; record_size = report_uid ? sizeof(*reads_buf2) : sizeof(*reads_buf); reads_to_collect = len / record_size; - reads_per_page = PAGE_SIZE / record_size; + reads_per_page = INCFS_DATA_FILE_BLOCK_SIZE / record_size; rl_size = READ_ONCE(mi->mi_log.rl_size); if (rl_size == 0) return 0; - page = __get_free_page(GFP_NOFS); + page = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS); if (!page) return -ENOMEM; @@ -1116,7 +1116,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, reads_collected; goto out; } - if (copy_to_user(buf, (void *)page, + if (copy_to_user(buf, page, reads_collected * record_size)) { result = total_reads_collected ? total_reads_collected * record_size : @@ -1133,7 +1133,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, result = total_reads_collected * record_size; *ppos = 0; out: - free_page(page); + kfree(page); return result; } diff --git a/fs/incfs/verity.c b/fs/incfs/verity.c index 562a8e774178..b49441a146d2 100644 --- a/fs/incfs/verity.c +++ b/fs/incfs/verity.c @@ -303,8 +303,8 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df, struct mem_range buf = {.len = INCFS_DATA_FILE_BLOCK_SIZE}; struct mem_range tmp = {.len = 2 * INCFS_DATA_FILE_BLOCK_SIZE}; - buf.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(buf.len)); - tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len)); + buf.data = (u8 *)kzalloc(buf.len, GFP_NOFS); + tmp.data = (u8 *)kzalloc(tmp.len, GFP_NOFS); if (!buf.data || !tmp.data) { error = -ENOMEM; goto out; @@ -372,8 +372,8 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df, } out: - free_pages((unsigned long)tmp.data, get_order(tmp.len)); - free_pages((unsigned long)buf.data, get_order(buf.len)); + kfree(tmp.data); + kfree(buf.data); return error; } diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index 0c80779e99e9..7086135a4d7f 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -541,13 +541,15 @@ static int read_folio(struct file *f, struct folio *folio) struct page *page = &folio->page; loff_t offset = 0; loff_t size = 0; - ssize_t bytes_to_read = 0; - ssize_t read_result = 0; + ssize_t total_read = 0; struct data_file *df = get_incfs_data_file(f); int result = 0; void *page_start; int block_index; unsigned int delayed_min_us = 0; + struct mem_range tmp = { + .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE + }; if (!df) { SetPageError(page); @@ -561,32 +563,39 @@ static int read_folio(struct file *f, struct folio *folio) INCFS_DATA_FILE_BLOCK_SIZE; size = df->df_size; - if (offset < size) { - struct mem_range tmp = { - .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE - }; - tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len)); - if (!tmp.data) { - read_result = -ENOMEM; - goto err; - } - bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE); - - read_result = read_single_page_timeouts(df, f, block_index, - range(page_start, bytes_to_read), tmp, - &delayed_min_us); - - free_pages((unsigned long)tmp.data, get_order(tmp.len)); - } else { - bytes_to_read = 0; - read_result = 0; + tmp.data = kzalloc(tmp.len, GFP_NOFS); + if (!tmp.data) { + result = -ENOMEM; + goto err; } + while (offset + total_read < size) { + ssize_t bytes_to_read = min_t(loff_t, + size - offset - total_read, + INCFS_DATA_FILE_BLOCK_SIZE); + + result = read_single_page_timeouts(df, f, block_index, + range(page_start + total_read, bytes_to_read), + tmp, &delayed_min_us); + if (result < 0) + break; + + total_read += result; + block_index++; + + if (result < INCFS_DATA_FILE_BLOCK_SIZE) + break; + if (total_read == PAGE_SIZE) + break; + } + kfree(tmp.data); err: - if (read_result < 0) - result = read_result; - else if (read_result < PAGE_SIZE) - zero_user(page, read_result, PAGE_SIZE - read_result); + if (result < 0) + total_read = 0; + else + result = 0; + if (total_read < PAGE_SIZE) + zero_user(page, total_read, PAGE_SIZE - total_read); if (result == 0) SetPageUptodate(page); @@ -770,8 +779,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg) return -EFAULT; usr_fill_block_array = u64_to_user_ptr(fill_blocks.fill_blocks); - data_buf = (u8 *)__get_free_pages(GFP_NOFS | __GFP_COMP, - get_order(data_buf_size)); + data_buf = (u8 *)kzalloc(data_buf_size, GFP_NOFS); if (!data_buf) return -ENOMEM; @@ -806,8 +814,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg) break; } - if (data_buf) - free_pages((unsigned long)data_buf, get_order(data_buf_size)); + kfree(data_buf); if (complete) handle_file_completed(f, df); @@ -1807,8 +1814,6 @@ struct dentry *incfs_mount_fs(struct file_system_type *type, int flags, sb->s_blocksize_bits = blksize_bits(sb->s_blocksize); sb->s_xattr = incfs_xattr_ops; - BUILD_BUG_ON(PAGE_SIZE != INCFS_DATA_FILE_BLOCK_SIZE); - if (!dev_name) { pr_err("incfs: Backing dir is not set, filesystem can't be mounted.\n"); error = -ENOENT; From d3c340f987cb561b7c5991639c362e8c1dcdbbcd Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 9 Apr 2024 13:22:12 -0700 Subject: [PATCH 09/46] UPSTREAM: selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior [ Upstream commit 076361362122a6d8a4c45f172ced5576b2d4a50d ] The struct adjtimex freq field takes a signed value who's units are in shifted (<<16) parts-per-million. Unfortunately for negative adjustments, the straightforward use of: freq = ppm << 16 trips undefined behavior warnings with clang: valid-adjtimex.c:66:6: warning: shifting a negative signed value is undefined [-Wshift-negative-value] -499<<16, ~~~~^ valid-adjtimex.c:67:6: warning: shifting a negative signed value is undefined [-Wshift-negative-value] -450<<16, ~~~~^ .. Fix it by using a multiply by (1 << 16) instead of shifting negative values in the valid-adjtimex test case. Align the values for better readability. Bug: 339526723 Reported-by: Lee Jones Reported-by: Muhammad Usama Anjum Change-Id: Ied611c13a802acf9c7a2427f0a61eb358b571a3d Signed-off-by: John Stultz Signed-off-by: Thomas Gleixner Reviewed-by: Muhammad Usama Anjum Link: https://lore.kernel.org/r/20240409202222.2830476-1-jstultz@google.com Link: https://lore.kernel.org/lkml/0c6d4f0d-2064-4444-986b-1d1ed782135f@collabora.com/ Signed-off-by: Sasha Levin (cherry picked from commit 1f3484dec916a3c4f43c4c44bad398bc24373110) Signed-off-by: Edward Liaw --- .../testing/selftests/timers/valid-adjtimex.c | 73 +++++++++---------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c index 48b9a803235a..d13ebde20322 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c @@ -21,9 +21,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - - - #include #include #include @@ -62,45 +59,47 @@ int clear_time_state(void) #define NUM_FREQ_OUTOFRANGE 4 #define NUM_FREQ_INVALID 2 +#define SHIFTED_PPM (1 << 16) + long valid_freq[NUM_FREQ_VALID] = { - -499<<16, - -450<<16, - -400<<16, - -350<<16, - -300<<16, - -250<<16, - -200<<16, - -150<<16, - -100<<16, - -75<<16, - -50<<16, - -25<<16, - -10<<16, - -5<<16, - -1<<16, + -499 * SHIFTED_PPM, + -450 * SHIFTED_PPM, + -400 * SHIFTED_PPM, + -350 * SHIFTED_PPM, + -300 * SHIFTED_PPM, + -250 * SHIFTED_PPM, + -200 * SHIFTED_PPM, + -150 * SHIFTED_PPM, + -100 * SHIFTED_PPM, + -75 * SHIFTED_PPM, + -50 * SHIFTED_PPM, + -25 * SHIFTED_PPM, + -10 * SHIFTED_PPM, + -5 * SHIFTED_PPM, + -1 * SHIFTED_PPM, -1000, - 1<<16, - 5<<16, - 10<<16, - 25<<16, - 50<<16, - 75<<16, - 100<<16, - 150<<16, - 200<<16, - 250<<16, - 300<<16, - 350<<16, - 400<<16, - 450<<16, - 499<<16, + 1 * SHIFTED_PPM, + 5 * SHIFTED_PPM, + 10 * SHIFTED_PPM, + 25 * SHIFTED_PPM, + 50 * SHIFTED_PPM, + 75 * SHIFTED_PPM, + 100 * SHIFTED_PPM, + 150 * SHIFTED_PPM, + 200 * SHIFTED_PPM, + 250 * SHIFTED_PPM, + 300 * SHIFTED_PPM, + 350 * SHIFTED_PPM, + 400 * SHIFTED_PPM, + 450 * SHIFTED_PPM, + 499 * SHIFTED_PPM, }; long outofrange_freq[NUM_FREQ_OUTOFRANGE] = { - -1000<<16, - -550<<16, - 550<<16, - 1000<<16, + -1000 * SHIFTED_PPM, + -550 * SHIFTED_PPM, + 550 * SHIFTED_PPM, + 1000 * SHIFTED_PPM, }; #define LONG_MAX (~0UL>>1) From dd875b63669a9a0b7b3fbbcd66d9456aa3f73a2d Mon Sep 17 00:00:00 2001 From: Bian Jin chen Date: Wed, 29 May 2024 16:25:00 +0800 Subject: [PATCH 10/46] ANDROID: GKI: Update rockchip symbols for some usb wifi bt. 3 function symbol(s) added 'int usb_anchor_empty(struct usb_anchor*)' 'void usb_disable_autosuspend(struct usb_device*)' 'void usb_reset_endpoint(struct usb_device*, unsigned int)' Bug: 300024866 Signed-off-by: Bian Jin chen Change-Id: Ib1c613e2aca4ab7f4c29f044829505efd4544ef3 --- android/abi_gki_aarch64.stg | 35 ++++++++++++++++++++++++++++++++ android/abi_gki_aarch64_rockchip | 7 +++++++ 2 files changed, 42 insertions(+) diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg index 2072d7f55eaa..69a90ae57fd9 100644 --- a/android/abi_gki_aarch64.stg +++ b/android/abi_gki_aarch64.stg @@ -310386,6 +310386,11 @@ function { parameter_id: 0x4585663f parameter_id: 0x3e10b518 } +function { + id: 0x90953240 + return_type_id: 0x6720d32f + parameter_id: 0x345745bd +} function { id: 0x9095ed8c return_type_id: 0x6720d32f @@ -402213,6 +402218,15 @@ elf_symbol { type_id: 0x10985193 full_name: "usb_amd_quirk_pll_enable" } +elf_symbol { + id: 0x406267f4 + name: "usb_anchor_empty" + is_defined: true + symbol_type: FUNCTION + crc: 0x7e8d8619 + type_id: 0x90953240 + full_name: "usb_anchor_empty" +} elf_symbol { id: 0x73c499cf name: "usb_anchor_urb" @@ -402492,6 +402506,15 @@ elf_symbol { type_id: 0x1c1deea6 full_name: "usb_device_match_id" } +elf_symbol { + id: 0xeedbb4b8 + name: "usb_disable_autosuspend" + is_defined: true + symbol_type: FUNCTION + crc: 0xda80b80f + type_id: 0x13c76860 + full_name: "usb_disable_autosuspend" +} elf_symbol { id: 0xdefa9d60 name: "usb_disabled" @@ -403437,6 +403460,15 @@ elf_symbol { type_id: 0x9edfdadc full_name: "usb_reset_device" } +elf_symbol { + id: 0x80c1324b + name: "usb_reset_endpoint" + is_defined: true + symbol_type: FUNCTION + crc: 0x3e614434 + type_id: 0x12d17df8 + full_name: "usb_reset_endpoint" +} elf_symbol { id: 0xb61e8892 name: "usb_role_string" @@ -415611,6 +415643,7 @@ interface { symbol_id: 0x7da4e281 symbol_id: 0x811fc2f9 symbol_id: 0xaff7b9fa + symbol_id: 0x406267f4 symbol_id: 0x73c499cf symbol_id: 0x1e897b44 symbol_id: 0xdc4939d2 @@ -415642,6 +415675,7 @@ interface { symbol_id: 0x201afca9 symbol_id: 0x3be9765e symbol_id: 0xd75ad246 + symbol_id: 0xeedbb4b8 symbol_id: 0xdefa9d60 symbol_id: 0x905187d4 symbol_id: 0x8483fc3d @@ -415747,6 +415781,7 @@ interface { symbol_id: 0x58937c87 symbol_id: 0xe3f9d54d symbol_id: 0xd80a0cec + symbol_id: 0x80c1324b symbol_id: 0xb61e8892 symbol_id: 0xd5bd73b9 symbol_id: 0x951bfee9 diff --git a/android/abi_gki_aarch64_rockchip b/android/abi_gki_aarch64_rockchip index 1679dba4127d..5c3c52b7b61c 100644 --- a/android/abi_gki_aarch64_rockchip +++ b/android/abi_gki_aarch64_rockchip @@ -2995,3 +2995,10 @@ # required by vl6180.ko iio_read_const_attr + +# required by aic_btusb.ko + usb_disable_autosuspend + +# required by wlan_mt7663_usb.ko + usb_anchor_empty + usb_reset_endpoint From 6c17e786e7dd15d261cac950e8ffc9cd8500bc78 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 28 May 2024 16:32:22 +0000 Subject: [PATCH 11/46] Revert "ANDROID: vendor_hook: rename the the name of hooks" This reverts commit db91c5d31a2a20f3de604ed9354b0efc0462cc55. The alloc->mutex to spinlock_t patches from [1] are being backported into this branch. The vendor hooks will be reapplied on top of these backports in a way that matches the new structure of the code. Link: https://lore.kernel.org/all/20231201172212.1813387-1-cmllamas@google.com/ [1] Change-Id: I39dd50bb58a08f39942322ee014dd08ebbd83168 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 15 +++++++-------- drivers/android/vendor_hooks.c | 2 +- include/trace/hooks/binder.h | 6 +++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index c7ebf14587a6..4325384965e7 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -410,14 +410,13 @@ static struct binder_buffer *binder_alloc_new_buf_locked( } trace_android_vh_binder_alloc_new_buf_locked(size, &alloc->free_async_space, is_async); - trace_android_vh_binder_detect_low_async_space(is_async, &alloc->free_async_space, pid, - &should_fail); - if (should_fail) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd failed, not allowed to alloc more async space\n", - alloc->pid, size); - return ERR_PTR(-EPERM); - } + trace_android_vh_binder_detect_low_async_space_locked(is_async, &alloc->free_async_space, pid, &should_fail); + if (should_fail) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_alloc_buf size %zd failed, not allowed to alloc more async space\n", + alloc->pid, size); + return ERR_PTR(-EPERM); + } /* Pad 0-size buffers so they get assigned unique addresses */ size = max(size, sizeof(void *)); diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index a45022e569e2..c4b14f965ad3 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -391,7 +391,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_ioctl_end); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_looper_exited); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_spawn_new_thread); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_has_special_work_ilocked); -EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_detect_low_async_space); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_detect_low_async_space_locked); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_init); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_tsk_init); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_tsk_free); diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index fa2b762e3401..e67cfc5fee1b 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -83,9 +83,9 @@ DECLARE_HOOK(android_vh_binder_alloc_new_buf_locked, TP_PROTO(size_t size, size_t *free_async_space, int is_async), TP_ARGS(size, free_async_space, is_async)); -DECLARE_HOOK(android_vh_binder_detect_low_async_space, - TP_PROTO(int is_async, size_t *free_async_space, int pid, bool *should_fail), - TP_ARGS(is_async, free_async_space, pid, should_fail)); +DECLARE_HOOK(android_vh_binder_detect_low_async_space_locked, + TP_PROTO(int is_async, size_t *free_async_space, int pid, bool *should_fail), + TP_ARGS(is_async, free_async_space, pid, should_fail)); struct binder_transaction_data; DECLARE_HOOK(android_vh_binder_reply, TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, From 9e2c184da18f8d7093c5d006aa465a47c2041a28 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 28 May 2024 16:34:19 +0000 Subject: [PATCH 12/46] Revert "ANDROID: vendor_hooks: Add hook for binder_detect_low_async_space_locked" This reverts commit 7ce117301e1bd43ff24e0f83d1bf27ec1b77f17e. The alloc->mutex to spinlock_t patches from [1] are being backported into this branch. The vendor hooks will be reapplied on top of these backports in a way that matches the new structure of the code. Link: https://lore.kernel.org/all/20231201172212.1813387-1-cmllamas@google.com/ [1] Change-Id: I7f4aaab31b4462a40881c596abdcbef835a32e4a Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 8 -------- drivers/android/vendor_hooks.c | 1 - include/trace/hooks/binder.h | 4 ---- 3 files changed, 13 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 4325384965e7..aaa07ff5e6d6 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -382,7 +382,6 @@ static struct binder_buffer *binder_alloc_new_buf_locked( void __user *end_page_addr; size_t size, data_offsets_size; int ret; - bool should_fail = false; /* Check binder_alloc is fully initialized */ if (!binder_alloc_get_vma(alloc)) { @@ -410,13 +409,6 @@ static struct binder_buffer *binder_alloc_new_buf_locked( } trace_android_vh_binder_alloc_new_buf_locked(size, &alloc->free_async_space, is_async); - trace_android_vh_binder_detect_low_async_space_locked(is_async, &alloc->free_async_space, pid, &should_fail); - if (should_fail) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd failed, not allowed to alloc more async space\n", - alloc->pid, size); - return ERR_PTR(-EPERM); - } /* Pad 0-size buffers so they get assigned unique addresses */ size = max(size, sizeof(void *)); diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index c4b14f965ad3..31dde279e279 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -391,7 +391,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_ioctl_end); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_looper_exited); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_spawn_new_thread); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_has_special_work_ilocked); -EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_detect_low_async_space_locked); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_init); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_tsk_init); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_tsk_free); diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index e67cfc5fee1b..77bfa4db10e2 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -82,10 +82,6 @@ DECLARE_HOOK(android_vh_binder_select_special_worklist, DECLARE_HOOK(android_vh_binder_alloc_new_buf_locked, TP_PROTO(size_t size, size_t *free_async_space, int is_async), TP_ARGS(size, free_async_space, is_async)); - -DECLARE_HOOK(android_vh_binder_detect_low_async_space_locked, - TP_PROTO(int is_async, size_t *free_async_space, int pid, bool *should_fail), - TP_ARGS(is_async, free_async_space, pid, should_fail)); struct binder_transaction_data; DECLARE_HOOK(android_vh_binder_reply, TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, From 6a29f5fb4b4c0a33791cd5327b9a546b6b9cf885 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 28 May 2024 16:38:30 +0000 Subject: [PATCH 13/46] Revert "ANDROID: Add vendor hooks for binder perf tuning" This reverts commit 17fff41db863f170ebea8b5ae5c99ccd874ac4cd. The alloc->mutex to spinlock_t patches from [1] are being backported into this branch. The vendor hooks will be reapplied on top of these backports in a way that matches the new structure of the code. Link: https://lore.kernel.org/all/20231201172212.1813387-1-cmllamas@google.com/ [1] Change-Id: Ic1acdd3401f985614d2d7383bdaabd6d71bb0c44 Signed-off-by: Carlos Llamas --- drivers/android/binder.c | 2 -- drivers/android/binder_alloc.c | 3 --- drivers/android/vendor_hooks.c | 3 --- include/trace/hooks/binder.h | 13 ------------- 4 files changed, 21 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index dc2a8ba27b4c..9164e3b8b9dd 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3211,7 +3211,6 @@ static void binder_transaction(struct binder_proc *proc, target_proc = target_thread->proc; target_proc->tmp_ref++; binder_inner_proc_unlock(target_thread->proc); - trace_android_vh_binder_reply(target_proc, proc, thread, tr); } else { if (tr->target.handle) { struct binder_ref *ref; @@ -3274,7 +3273,6 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_invalid_target_handle; } - trace_android_vh_binder_trans(target_proc, proc, thread, tr); if (security_binder_transaction(proc->cred, target_proc->cred) < 0) { binder_txn_error("%d:%d transaction credentials failed\n", diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index aaa07ff5e6d6..fcbb750b1ccc 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -25,7 +25,6 @@ #include #include "binder_alloc.h" #include "binder_trace.h" -#include struct list_lru binder_alloc_lru; @@ -408,8 +407,6 @@ static struct binder_buffer *binder_alloc_new_buf_locked( return ERR_PTR(-EINVAL); } - trace_android_vh_binder_alloc_new_buf_locked(size, &alloc->free_async_space, is_async); - /* Pad 0-size buffers so they get assigned unique addresses */ size = max(size, sizeof(void *)); diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 31dde279e279..2fd4d34cf7c9 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -293,9 +293,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_online); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_free); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_alloc); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cpuset_fork); -EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_alloc_new_buf_locked); -EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_reply); -EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_trans); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmap_region); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_try_to_unmap_one); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_slab_bypass); diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index 77bfa4db10e2..e71334f96007 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -78,19 +78,6 @@ DECLARE_HOOK(android_vh_binder_select_special_worklist, TP_PROTO(struct list_head **list, struct binder_thread *thread, struct binder_proc *proc, int wait_for_proc_work, bool *nothing_to_do), TP_ARGS(list, thread, proc, wait_for_proc_work, nothing_to_do)); - -DECLARE_HOOK(android_vh_binder_alloc_new_buf_locked, - TP_PROTO(size_t size, size_t *free_async_space, int is_async), - TP_ARGS(size, free_async_space, is_async)); -struct binder_transaction_data; -DECLARE_HOOK(android_vh_binder_reply, - TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, - struct binder_thread *thread, struct binder_transaction_data *tr), - TP_ARGS(target_proc, proc, thread, tr)); -DECLARE_HOOK(android_vh_binder_trans, - TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, - struct binder_thread *thread, struct binder_transaction_data *tr), - TP_ARGS(target_proc, proc, thread, tr)); DECLARE_HOOK(android_vh_binder_proc_transaction, TP_PROTO(struct task_struct *caller_task, struct task_struct *binder_proc_task, struct task_struct *binder_th_task, int node_debug_id, From 8b2c4f7ab3337d1be62d7f77b4bbe265658eca76 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:37 +0000 Subject: [PATCH 14/46] UPSTREAM: binder: remove extern from function prototypes The kernel coding style does not require 'extern' in function prototypes in .h files, so remove them from drivers/android/binder_alloc.h as they are not needed. No functional changes in this patch. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-9-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit da483f8b390546fbe36abd72f58d612a8032e2a8) Change-Id: I75e4ee9cf08fada7378f448bc5992d125174132f Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.h | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index dc1e2b01dd64..82380febdd85 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -121,27 +121,27 @@ static inline void binder_selftest_alloc(struct binder_alloc *alloc) {} enum lru_status binder_alloc_free_page(struct list_head *item, struct list_lru_one *lru, spinlock_t *lock, void *cb_arg); -extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, - int is_async, - int pid); -extern void binder_alloc_init(struct binder_alloc *alloc); -extern int binder_alloc_shrinker_init(void); -extern void binder_alloc_shrinker_exit(void); -extern void binder_alloc_vma_close(struct binder_alloc *alloc); -extern struct binder_buffer * +struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async, + int pid); +void binder_alloc_init(struct binder_alloc *alloc); +int binder_alloc_shrinker_init(void); +void binder_alloc_shrinker_exit(void); +void binder_alloc_vma_close(struct binder_alloc *alloc); +struct binder_buffer * binder_alloc_prepare_to_free(struct binder_alloc *alloc, uintptr_t user_ptr); -extern void binder_alloc_free_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer); -extern int binder_alloc_mmap_handler(struct binder_alloc *alloc, - struct vm_area_struct *vma); -extern void binder_alloc_deferred_release(struct binder_alloc *alloc); -extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc); -extern void binder_alloc_print_allocated(struct seq_file *m, - struct binder_alloc *alloc); +void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer); +int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma); +void binder_alloc_deferred_release(struct binder_alloc *alloc); +int binder_alloc_get_allocated_count(struct binder_alloc *alloc); +void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc); void binder_alloc_print_pages(struct seq_file *m, struct binder_alloc *alloc); From b66dacff3db81260bda82f588fe00f31fb605051 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:38 +0000 Subject: [PATCH 15/46] UPSTREAM: binder: keep vma addresses type as unsigned long The vma addresses in binder are currently stored as void __user *. This requires casting back and forth between the mm/ api which uses unsigned long. Since we also do internal arithmetic on these addresses we end up having to cast them _again_ to an integer type. Lets stop all the unnecessary casting which kills code readability and store the virtual addresses as the native unsigned long from mm/. Note that this approach is preferred over uintptr_t as Linus explains in [1]. Opportunistically add a few cosmetic touchups. Link: https://lore.kernel.org/all/CAHk-=wj2OHy-5e+srG1fy+ZU00TmZ1NFp6kFLbVLMXHe7A1d-g@mail.gmail.com/ [1] Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-10-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit df9aabead791d7a3d59938abe288720f5c1367f7) Change-Id: Ib2fbaf0ad881973eb77957863f079f986fe0d926 Signed-off-by: Carlos Llamas --- drivers/android/binder.c | 21 +++--- drivers/android/binder_alloc.c | 91 +++++++++++-------------- drivers/android/binder_alloc.h | 6 +- drivers/android/binder_alloc_selftest.c | 6 +- drivers/android/binder_trace.h | 2 +- 5 files changed, 57 insertions(+), 69 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 9164e3b8b9dd..1183e2b945ac 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2276,9 +2276,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, * Convert the address to an offset relative to * the base of the transaction buffer. */ - fda_offset = - (parent->buffer - (uintptr_t)buffer->user_data) + - fda->parent_offset; + fda_offset = parent->buffer - buffer->user_data + + fda->parent_offset; for (fd_index = 0; fd_index < fda->num_fds; fd_index++) { u32 fd; @@ -2796,7 +2795,7 @@ static int binder_translate_fd_array(struct list_head *pf_head, * Convert the address to an offset relative to * the base of the transaction buffer. */ - fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) + + fda_offset = parent->buffer - t->buffer->user_data + fda->parent_offset; sender_ufda_base = (void __user *)(uintptr_t)sender_uparent->buffer + fda->parent_offset; @@ -2871,8 +2870,9 @@ static int binder_fixup_parent(struct list_head *pf_head, proc->pid, thread->pid); return -EINVAL; } - buffer_offset = bp->parent_offset + - (uintptr_t)parent->buffer - (uintptr_t)b->user_data; + + buffer_offset = bp->parent_offset + parent->buffer - b->user_data; + return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0); } @@ -3471,7 +3471,7 @@ static void binder_transaction(struct binder_proc *proc, ALIGN(extra_buffers_size, sizeof(void *)) - ALIGN(secctx_sz, sizeof(u64)); - t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset; + t->security_ctx = t->buffer->user_data + buf_offset; err = binder_alloc_copy_to_buffer(&target_proc->alloc, t->buffer, buf_offset, secctx, secctx_sz); @@ -3749,8 +3749,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_translate_failed; } /* Fixup buffer pointer to target proc address space */ - bp->buffer = (uintptr_t) - t->buffer->user_data + sg_buf_offset; + bp->buffer = t->buffer->user_data + sg_buf_offset; sg_buf_offset += ALIGN(bp->length, sizeof(u64)); num_valid = (buffer_offset - off_start_offset) / @@ -4940,7 +4939,7 @@ skip: } trd->data_size = t->buffer->data_size; trd->offsets_size = t->buffer->offsets_size; - trd->data.ptr.buffer = (uintptr_t)t->buffer->user_data; + trd->data.ptr.buffer = t->buffer->user_data; trd->data.ptr.offsets = trd->data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); @@ -6254,7 +6253,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m, } if (buffer->target_node) seq_printf(m, " node %d", buffer->target_node->debug_id); - seq_printf(m, " size %zd:%zd data %pK\n", + seq_printf(m, " size %zd:%zd data %lx\n", buffer->data_size, buffer->offsets_size, buffer->user_data); } diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index fcbb750b1ccc..305c83da0ee9 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -125,23 +125,20 @@ static void binder_insert_allocated_buffer_locked( static struct binder_buffer *binder_alloc_prepare_to_free_locked( struct binder_alloc *alloc, - uintptr_t user_ptr) + unsigned long user_ptr) { struct rb_node *n = alloc->allocated_buffers.rb_node; struct binder_buffer *buffer; - void __user *uptr; - - uptr = (void __user *)user_ptr; while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); BUG_ON(buffer->free); - if (uptr < buffer->user_data) + if (user_ptr < buffer->user_data) { n = n->rb_left; - else if (uptr > buffer->user_data) + } else if (user_ptr > buffer->user_data) { n = n->rb_right; - else { + } else { /* * Guard against user threads attempting to * free the buffer when in use by kernel or @@ -168,7 +165,7 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( * Return: Pointer to buffer or NULL */ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, - uintptr_t user_ptr) + unsigned long user_ptr) { struct binder_buffer *buffer; @@ -179,18 +176,17 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, } static int binder_update_page_range(struct binder_alloc *alloc, int allocate, - void __user *start, void __user *end) + unsigned long start, unsigned long end) { - void __user *page_addr; - unsigned long user_page_addr; - struct binder_lru_page *page; struct vm_area_struct *vma = NULL; + struct binder_lru_page *page; struct mm_struct *mm = NULL; + unsigned long page_addr; bool need_mm = false; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s pages %pK-%pK\n", alloc->pid, - allocate ? "allocate" : "free", start, end); + "%d: %s allocate pages %lx-%lx\n", alloc->pid, + allocate ? "allocate" : "free", start, end); if (end <= start) return 0; @@ -249,18 +245,17 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, __GFP_HIGHMEM | __GFP_ZERO); if (!page->page_ptr) { - pr_err("%d: binder_alloc_buf failed for page at %pK\n", - alloc->pid, page_addr); + pr_err("%d: binder_alloc_buf failed for page at %lx\n", + alloc->pid, page_addr); goto err_alloc_page_failed; } page->alloc = alloc; INIT_LIST_HEAD(&page->lru); - user_page_addr = (uintptr_t)page_addr; - ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr); + ret = vm_insert_page(vma, page_addr, page->page_ptr); if (ret) { pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", - alloc->pid, user_page_addr); + alloc->pid, page_addr); goto err_vm_insert_page_failed; } @@ -377,9 +372,9 @@ static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_buffer *buffer; size_t buffer_size; struct rb_node *best_fit = NULL; - void __user *has_page_addr; - void __user *end_page_addr; size_t size, data_offsets_size; + unsigned long has_page_addr; + unsigned long end_page_addr; int ret; /* Check binder_alloc is fully initialized */ @@ -477,15 +472,13 @@ static struct binder_buffer *binder_alloc_new_buf_locked( "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", alloc->pid, size, buffer, buffer_size); - has_page_addr = (void __user *) - (((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK); + has_page_addr = (buffer->user_data + buffer_size) & PAGE_MASK; WARN_ON(n && buffer_size != size); - end_page_addr = - (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size); + end_page_addr = PAGE_ALIGN(buffer->user_data + size); if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; - ret = binder_update_page_range(alloc, 1, (void __user *) - PAGE_ALIGN((uintptr_t)buffer->user_data), end_page_addr); + ret = binder_update_page_range(alloc, 1, PAGE_ALIGN(buffer->user_data), + end_page_addr); if (ret) return ERR_PTR(ret); @@ -498,7 +491,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( __func__, alloc->pid); goto err_alloc_buf_struct_failed; } - new_buffer->user_data = (u8 __user *)buffer->user_data + size; + new_buffer->user_data = buffer->user_data + size; list_add(&new_buffer->entry, &buffer->entry); new_buffer->free = 1; binder_insert_free_buffer(alloc, new_buffer); @@ -536,8 +529,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( return buffer; err_alloc_buf_struct_failed: - binder_update_page_range(alloc, 0, (void __user *) - PAGE_ALIGN((uintptr_t)buffer->user_data), + binder_update_page_range(alloc, 0, PAGE_ALIGN(buffer->user_data), end_page_addr); return ERR_PTR(-ENOMEM); } @@ -574,15 +566,14 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, return buffer; } -static void __user *buffer_start_page(struct binder_buffer *buffer) +static unsigned long buffer_start_page(struct binder_buffer *buffer) { - return (void __user *)((uintptr_t)buffer->user_data & PAGE_MASK); + return buffer->user_data & PAGE_MASK; } -static void __user *prev_buffer_end_page(struct binder_buffer *buffer) +static unsigned long prev_buffer_end_page(struct binder_buffer *buffer) { - return (void __user *) - (((uintptr_t)(buffer->user_data) - 1) & PAGE_MASK); + return (buffer->user_data - 1) & PAGE_MASK; } static void binder_delete_free_buffer(struct binder_alloc *alloc, @@ -597,7 +588,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, if (prev_buffer_end_page(prev) == buffer_start_page(buffer)) { to_free = false; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK share page with %pK\n", + "%d: merge free, buffer %lx share page with %lx\n", alloc->pid, buffer->user_data, prev->user_data); } @@ -607,7 +598,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, if (buffer_start_page(next) == buffer_start_page(buffer)) { to_free = false; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK share page with %pK\n", + "%d: merge free, buffer %lx share page with %lx\n", alloc->pid, buffer->user_data, next->user_data); @@ -616,17 +607,17 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, if (PAGE_ALIGNED(buffer->user_data)) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer start %pK is page aligned\n", + "%d: merge free, buffer start %lx is page aligned\n", alloc->pid, buffer->user_data); to_free = false; } if (to_free) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK do not share page with %pK or %pK\n", + "%d: merge free, buffer %lx do not share page with %lx or %lx\n", alloc->pid, buffer->user_data, prev->user_data, - next ? next->user_data : NULL); + next ? next->user_data : 0); binder_update_page_range(alloc, 0, buffer_start_page(buffer), buffer_start_page(buffer) + PAGE_SIZE); } @@ -662,10 +653,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, alloc->pid, size, alloc->free_async_space); } - binder_update_page_range(alloc, 0, - (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data), - (void __user *)(((uintptr_t) - buffer->user_data + buffer_size) & PAGE_MASK)); + binder_update_page_range(alloc, 0, PAGE_ALIGN(buffer->user_data), + (buffer->user_data + buffer_size) & PAGE_MASK); rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1; @@ -754,7 +743,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, SZ_4M); mutex_unlock(&binder_alloc_mmap_lock); - alloc->buffer = (void __user *)vma->vm_start; + alloc->buffer = vma->vm_start; alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE, sizeof(alloc->pages[0]), @@ -787,7 +776,7 @@ err_alloc_buf_struct_failed: kfree(alloc->pages); alloc->pages = NULL; err_alloc_pages_failed: - alloc->buffer = NULL; + alloc->buffer = 0; mutex_lock(&binder_alloc_mmap_lock); alloc->buffer_size = 0; err_already_mapped: @@ -840,7 +829,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) int i; for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { - void __user *page_addr; + unsigned long page_addr; bool on_lru; if (!alloc->pages[i].page_ptr) @@ -850,7 +839,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) &alloc->pages[i].lru); page_addr = alloc->buffer + i * PAGE_SIZE; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %pK %s\n", + "%s: %d: page %d at %lx %s\n", __func__, alloc->pid, i, page_addr, on_lru ? "on lru" : "active"); __free_page(alloc->pages[i].page_ptr); @@ -870,7 +859,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) static void print_binder_buffer(struct seq_file *m, const char *prefix, struct binder_buffer *buffer) { - seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n", + seq_printf(m, "%s %d: %lx size %zd:%zd:%zd %s\n", prefix, buffer->debug_id, buffer->user_data, buffer->data_size, buffer->offsets_size, buffer->extra_buffers_size, @@ -984,7 +973,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, struct binder_lru_page, lru); struct binder_alloc *alloc; - uintptr_t page_addr; + unsigned long page_addr; size_t index; struct vm_area_struct *vma; @@ -996,7 +985,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, goto err_page_already_freed; index = page - alloc->pages; - page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; + page_addr = alloc->buffer + index * PAGE_SIZE; mm = alloc->mm; if (!mmget_not_zero(mm)) diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 82380febdd85..cb19677a5c15 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -56,7 +56,7 @@ struct binder_buffer { size_t data_size; size_t offsets_size; size_t extra_buffers_size; - void __user *user_data; + unsigned long user_data; int pid; }; @@ -101,7 +101,7 @@ struct binder_alloc { struct mutex mutex; struct vm_area_struct *vma; struct mm_struct *mm; - void __user *buffer; + unsigned long buffer; struct list_head buffers; struct rb_root free_buffers; struct rb_root allocated_buffers; @@ -133,7 +133,7 @@ void binder_alloc_shrinker_exit(void); void binder_alloc_vma_close(struct binder_alloc *alloc); struct binder_buffer * binder_alloc_prepare_to_free(struct binder_alloc *alloc, - uintptr_t user_ptr); + unsigned long user_ptr); void binder_alloc_free_buf(struct binder_alloc *alloc, struct binder_buffer *buffer); int binder_alloc_mmap_handler(struct binder_alloc *alloc, diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c index c2b323bc3b3a..341c73b4a807 100644 --- a/drivers/android/binder_alloc_selftest.c +++ b/drivers/android/binder_alloc_selftest.c @@ -93,11 +93,11 @@ static bool check_buffer_pages_allocated(struct binder_alloc *alloc, struct binder_buffer *buffer, size_t size) { - void __user *page_addr; - void __user *end; + unsigned long page_addr; + unsigned long end; int page_index; - end = (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size); + end = PAGE_ALIGN(buffer->user_data + size); page_addr = buffer->user_data; for (; page_addr < end; page_addr += PAGE_SIZE) { page_index = (page_addr - alloc->buffer) / PAGE_SIZE; diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h index 5d82cf8af88b..e90fc3d5eea3 100644 --- a/drivers/android/binder_trace.h +++ b/drivers/android/binder_trace.h @@ -341,7 +341,7 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_update_buffer_release, TRACE_EVENT(binder_update_page_range, TP_PROTO(struct binder_alloc *alloc, bool allocate, - void __user *start, void __user *end), + unsigned long start, unsigned long end), TP_ARGS(alloc, allocate, start, end), TP_STRUCT__entry( __field(int, proc) From e5fae62ffbbb29dfe32bae90e6e77075b81759c8 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:39 +0000 Subject: [PATCH 16/46] UPSTREAM: binder: split up binder_update_page_range() The binder_update_page_range() function performs both allocation and freeing of binder pages. However, these two operations are unrelated and have no common logic. In fact, when a free operation is requested, the allocation logic is skipped entirely. This behavior makes the error path unnecessarily complex. To improve readability of the code, this patch splits the allocation and freeing operations into separate functions. No functional changes are introduced by this patch. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-11-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 0d35bf3bf2da8d43fd12fea7699dc936999bf96e) Change-Id: Iaf64f94564d2017c4633f2421c15b0bdee914738 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 79 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 305c83da0ee9..b76ae29c5b77 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -175,8 +175,32 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, return buffer; } -static int binder_update_page_range(struct binder_alloc *alloc, int allocate, - unsigned long start, unsigned long end) +static void binder_free_page_range(struct binder_alloc *alloc, + unsigned long start, unsigned long end) +{ + struct binder_lru_page *page; + unsigned long page_addr; + + trace_binder_update_page_range(alloc, false, start, end); + + for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { + size_t index; + int ret; + + index = (page_addr - alloc->buffer) / PAGE_SIZE; + page = &alloc->pages[index]; + + trace_binder_free_lru_start(alloc, index); + + ret = list_lru_add(&binder_alloc_lru, &page->lru); + WARN_ON(!ret); + + trace_binder_free_lru_end(alloc, index); + } +} + +static int binder_allocate_page_range(struct binder_alloc *alloc, + unsigned long start, unsigned long end) { struct vm_area_struct *vma = NULL; struct binder_lru_page *page; @@ -185,16 +209,13 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, bool need_mm = false; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s allocate pages %lx-%lx\n", alloc->pid, - allocate ? "allocate" : "free", start, end); + "%d: allocate pages %lx-%lx\n", + alloc->pid, start, end); if (end <= start) return 0; - trace_binder_update_page_range(alloc, allocate, start, end); - - if (allocate == 0) - goto free_range; + trace_binder_update_page_range(alloc, true, start, end); for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; @@ -270,32 +291,12 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, } return 0; -free_range: - for (page_addr = end - PAGE_SIZE; 1; page_addr -= PAGE_SIZE) { - bool ret; - size_t index; - - index = (page_addr - alloc->buffer) / PAGE_SIZE; - page = &alloc->pages[index]; - - trace_binder_free_lru_start(alloc, index); - - ret = list_lru_add(&binder_alloc_lru, &page->lru); - WARN_ON(!ret); - - trace_binder_free_lru_end(alloc, index); - if (page_addr == start) - break; - continue; - err_vm_insert_page_failed: - __free_page(page->page_ptr); - page->page_ptr = NULL; + __free_page(page->page_ptr); + page->page_ptr = NULL; err_alloc_page_failed: err_page_ptr_cleared: - if (page_addr == start) - break; - } + binder_free_page_range(alloc, start, page_addr); err_no_vma: if (mm) { mmap_write_unlock(mm); @@ -477,8 +478,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( end_page_addr = PAGE_ALIGN(buffer->user_data + size); if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; - ret = binder_update_page_range(alloc, 1, PAGE_ALIGN(buffer->user_data), - end_page_addr); + ret = binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), + end_page_addr); if (ret) return ERR_PTR(ret); @@ -529,8 +530,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( return buffer; err_alloc_buf_struct_failed: - binder_update_page_range(alloc, 0, PAGE_ALIGN(buffer->user_data), - end_page_addr); + binder_free_page_range(alloc, PAGE_ALIGN(buffer->user_data), + end_page_addr); return ERR_PTR(-ENOMEM); } @@ -618,8 +619,8 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, alloc->pid, buffer->user_data, prev->user_data, next ? next->user_data : 0); - binder_update_page_range(alloc, 0, buffer_start_page(buffer), - buffer_start_page(buffer) + PAGE_SIZE); + binder_free_page_range(alloc, buffer_start_page(buffer), + buffer_start_page(buffer) + PAGE_SIZE); } list_del(&buffer->entry); kfree(buffer); @@ -653,8 +654,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, alloc->pid, size, alloc->free_async_space); } - binder_update_page_range(alloc, 0, PAGE_ALIGN(buffer->user_data), - (buffer->user_data + buffer_size) & PAGE_MASK); + binder_free_page_range(alloc, PAGE_ALIGN(buffer->user_data), + (buffer->user_data + buffer_size) & PAGE_MASK); rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1; From a880c450b731deda117e4db3e463337b590a009a Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:40 +0000 Subject: [PATCH 17/46] UPSTREAM: binder: do unlocked work in binder_alloc_new_buf() Extract non-critical sections from binder_alloc_new_buf_locked() that don't require holding the alloc->mutex. While we are here, consolidate the checks for size overflow and zero-sized padding into a separate sanitized_size() helper function. Also add a few touchups to follow the coding guidelines. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-12-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 377e1684db7a1e23261f3c3ebf76523c0554d512) Change-Id: I8fc18c06563ad2c26536633034fb3e94b0aaf510 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 95 ++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index b76ae29c5b77..79851d5f6e8e 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -363,9 +363,7 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_alloc *alloc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, + size_t size, int is_async, int pid) { @@ -373,39 +371,10 @@ static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_buffer *buffer; size_t buffer_size; struct rb_node *best_fit = NULL; - size_t size, data_offsets_size; unsigned long has_page_addr; unsigned long end_page_addr; int ret; - /* Check binder_alloc is fully initialized */ - if (!binder_alloc_get_vma(alloc)) { - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%d: binder_alloc_buf, no vma\n", - alloc->pid); - return ERR_PTR(-ESRCH); - } - - data_offsets_size = ALIGN(data_size, sizeof(void *)) + - ALIGN(offsets_size, sizeof(void *)); - - if (data_offsets_size < data_size || data_offsets_size < offsets_size) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: got transaction with invalid size %zd-%zd\n", - alloc->pid, data_size, offsets_size); - return ERR_PTR(-EINVAL); - } - size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *)); - if (size < data_offsets_size || size < extra_buffers_size) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: got transaction with invalid extra_buffers_size %zd\n", - alloc->pid, extra_buffers_size); - return ERR_PTR(-EINVAL); - } - - /* Pad 0-size buffers so they get assigned unique addresses */ - size = max(size, sizeof(void *)); - if (is_async && alloc->free_async_space < size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", @@ -421,13 +390,14 @@ static struct binder_buffer *binder_alloc_new_buf_locked( if (size < buffer_size) { best_fit = n; n = n->rb_left; - } else if (size > buffer_size) + } else if (size > buffer_size) { n = n->rb_right; - else { + } else { best_fit = n; break; } } + if (best_fit == NULL) { size_t allocated_buffers = 0; size_t largest_alloc_size = 0; @@ -505,10 +475,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %pK\n", alloc->pid, size, buffer); - buffer->data_size = data_size; - buffer->offsets_size = offsets_size; buffer->async_transaction = is_async; - buffer->extra_buffers_size = extra_buffers_size; buffer->pid = pid; buffer->oneway_spam_suspect = false; if (is_async) { @@ -527,6 +494,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( alloc->oneway_spam_detected = false; } } + return buffer; err_alloc_buf_struct_failed: @@ -535,6 +503,28 @@ err_alloc_buf_struct_failed: return ERR_PTR(-ENOMEM); } +/* Calculate the sanitized total size, returns 0 for invalid request */ +static inline size_t sanitized_size(size_t data_size, + size_t offsets_size, + size_t extra_buffers_size) +{ + size_t total, tmp; + + /* Align to pointer size and check for overflows */ + tmp = ALIGN(data_size, sizeof(void *)) + + ALIGN(offsets_size, sizeof(void *)); + if (tmp < data_size || tmp < offsets_size) + return 0; + total = tmp + ALIGN(extra_buffers_size, sizeof(void *)); + if (total < tmp || total < extra_buffers_size) + return 0; + + /* Pad 0-sized buffers so they get a unique address */ + total = max(total, sizeof(void *)); + + return total; +} + /** * binder_alloc_new_buf() - Allocate a new binder buffer * @alloc: binder_alloc for this proc @@ -559,11 +549,38 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, int pid) { struct binder_buffer *buffer; + size_t size; + + /* Check binder_alloc is fully initialized */ + if (!binder_alloc_get_vma(alloc)) { + binder_alloc_debug(BINDER_DEBUG_USER_ERROR, + "%d: binder_alloc_buf, no vma\n", + alloc->pid); + return ERR_PTR(-ESRCH); + } + + size = sanitized_size(data_size, offsets_size, extra_buffers_size); + if (unlikely(!size)) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: got transaction with invalid size %zd-%zd-%zd\n", + alloc->pid, data_size, offsets_size, + extra_buffers_size); + return ERR_PTR(-EINVAL); + } mutex_lock(&alloc->mutex); - buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size, - extra_buffers_size, is_async, pid); + buffer = binder_alloc_new_buf_locked(alloc, size, is_async, pid); + if (IS_ERR(buffer)) { + mutex_unlock(&alloc->mutex); + goto out; + } + + buffer->data_size = data_size; + buffer->offsets_size = offsets_size; + buffer->extra_buffers_size = extra_buffers_size; mutex_unlock(&alloc->mutex); + +out: return buffer; } From a37caf8d4c24778de8adb5364582b0efdae2b970 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:41 +0000 Subject: [PATCH 18/46] UPSTREAM: binder: remove pid param in binder_alloc_new_buf() Binder attributes the buffer allocation to the current->tgid everytime. There is no need to pass this as a parameter so drop it. Also add a few touchups to follow the coding guidelines. No functional changes are introduced in this patch. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-13-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 89f71743bf42217dd4092fda703a8e4f6f4e55ac) Change-Id: Ib21fdc5afd7eeb4723b08913ba40ded762421b0b Signed-off-by: Carlos Llamas --- drivers/android/binder.c | 2 +- drivers/android/binder_alloc.c | 18 ++++++++---------- drivers/android/binder_alloc.h | 7 ++----- drivers/android/binder_alloc_selftest.c | 2 +- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 1183e2b945ac..7f20e2ac3593 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3446,7 +3446,7 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size, tr->offsets_size, extra_buffers_size, - !reply && (t->flags & TF_ONE_WAY), current->tgid); + !reply && (t->flags & TF_ONE_WAY)); if (IS_ERR(t->buffer)) { char *s; diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 79851d5f6e8e..052a115e7ef2 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -319,7 +319,7 @@ static inline struct vm_area_struct *binder_alloc_get_vma( return smp_load_acquire(&alloc->vma); } -static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) +static bool debug_low_async_space_locked(struct binder_alloc *alloc) { /* * Find the amount and size of buffers allocated by the current caller; @@ -328,10 +328,11 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) * and at some point we'll catch them in the act. This is more efficient * than keeping a map per pid. */ - struct rb_node *n; struct binder_buffer *buffer; size_t total_alloc_size = 0; + int pid = current->tgid; size_t num_buffers = 0; + struct rb_node *n; for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) { @@ -364,8 +365,7 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_alloc *alloc, size_t size, - int is_async, - int pid) + int is_async) { struct rb_node *n = alloc->free_buffers.rb_node; struct binder_buffer *buffer; @@ -476,7 +476,6 @@ static struct binder_buffer *binder_alloc_new_buf_locked( "%d: binder_alloc_buf size %zd got %pK\n", alloc->pid, size, buffer); buffer->async_transaction = is_async; - buffer->pid = pid; buffer->oneway_spam_suspect = false; if (is_async) { alloc->free_async_space -= size; @@ -489,7 +488,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( * of async space left (which is less than 10% of total * buffer size). */ - buffer->oneway_spam_suspect = debug_low_async_space_locked(alloc, pid); + buffer->oneway_spam_suspect = debug_low_async_space_locked(alloc); } else { alloc->oneway_spam_detected = false; } @@ -532,7 +531,6 @@ static inline size_t sanitized_size(size_t data_size, * @offsets_size: user specified buffer offset * @extra_buffers_size: size of extra space for meta-data (eg, security context) * @is_async: buffer for async transaction - * @pid: pid to attribute allocation to (used for debugging) * * Allocate a new buffer given the requested sizes. Returns * the kernel version of the buffer pointer. The size allocated @@ -545,8 +543,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, size_t data_size, size_t offsets_size, size_t extra_buffers_size, - int is_async, - int pid) + int is_async) { struct binder_buffer *buffer; size_t size; @@ -569,7 +566,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, } mutex_lock(&alloc->mutex); - buffer = binder_alloc_new_buf_locked(alloc, size, is_async, pid); + buffer = binder_alloc_new_buf_locked(alloc, size, is_async); if (IS_ERR(buffer)) { mutex_unlock(&alloc->mutex); goto out; @@ -578,6 +575,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, buffer->data_size = data_size; buffer->offsets_size = offsets_size; buffer->extra_buffers_size = extra_buffers_size; + buffer->pid = current->tgid; mutex_unlock(&alloc->mutex); out: diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index cb19677a5c15..bbc16bc6d5ac 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -49,15 +49,13 @@ struct binder_buffer { unsigned async_transaction:1; unsigned oneway_spam_suspect:1; unsigned debug_id:27; - struct binder_transaction *transaction; - struct binder_node *target_node; size_t data_size; size_t offsets_size; size_t extra_buffers_size; unsigned long user_data; - int pid; + int pid; }; /** @@ -125,8 +123,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, size_t data_size, size_t offsets_size, size_t extra_buffers_size, - int is_async, - int pid); + int is_async); void binder_alloc_init(struct binder_alloc *alloc); int binder_alloc_shrinker_init(void); void binder_alloc_shrinker_exit(void); diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c index 341c73b4a807..ed753747e54c 100644 --- a/drivers/android/binder_alloc_selftest.c +++ b/drivers/android/binder_alloc_selftest.c @@ -119,7 +119,7 @@ static void binder_selftest_alloc_buf(struct binder_alloc *alloc, int i; for (i = 0; i < BUFFER_NUM; i++) { - buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0, 0); + buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0); if (IS_ERR(buffers[i]) || !check_buffer_pages_allocated(alloc, buffers[i], sizes[i])) { From 919daae2b62ce840019e48700d18bb3817119afb Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:42 +0000 Subject: [PATCH 19/46] UPSTREAM: binder: separate the no-space debugging logic Move the no-space debugging logic into a separate function. Lets also mark this branch as unlikely in binder_alloc_new_buf_locked() as most requests will fit without issue. Also add a few cosmetic changes and suggestions from checkpatch. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-14-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 9409af24e4503d14093b27db9425f7c99e64fef4) Change-Id: I4ff8ced5728a63815f7d47df9eb9ac85aa0a362d Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 71 +++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 052a115e7ef2..2410b7810b75 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -319,6 +319,43 @@ static inline struct vm_area_struct *binder_alloc_get_vma( return smp_load_acquire(&alloc->vma); } +static void debug_no_space_locked(struct binder_alloc *alloc) +{ + size_t largest_alloc_size = 0; + struct binder_buffer *buffer; + size_t allocated_buffers = 0; + size_t largest_free_size = 0; + size_t total_alloc_size = 0; + size_t total_free_size = 0; + size_t free_buffers = 0; + size_t buffer_size; + struct rb_node *n; + + for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + allocated_buffers++; + total_alloc_size += buffer_size; + if (buffer_size > largest_alloc_size) + largest_alloc_size = buffer_size; + } + + for (n = rb_first(&alloc->free_buffers); n; n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + free_buffers++; + total_free_size += buffer_size; + if (buffer_size > largest_free_size) + largest_free_size = buffer_size; + } + + binder_alloc_debug(BINDER_DEBUG_USER_ERROR, + "allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n", + total_alloc_size, allocated_buffers, + largest_alloc_size, total_free_size, + free_buffers, largest_free_size); +} + static bool debug_low_async_space_locked(struct binder_alloc *alloc) { /* @@ -398,42 +435,14 @@ static struct binder_buffer *binder_alloc_new_buf_locked( } } - if (best_fit == NULL) { - size_t allocated_buffers = 0; - size_t largest_alloc_size = 0; - size_t total_alloc_size = 0; - size_t free_buffers = 0; - size_t largest_free_size = 0; - size_t total_free_size = 0; - - for (n = rb_first(&alloc->allocated_buffers); n != NULL; - n = rb_next(n)) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - buffer_size = binder_alloc_buffer_size(alloc, buffer); - allocated_buffers++; - total_alloc_size += buffer_size; - if (buffer_size > largest_alloc_size) - largest_alloc_size = buffer_size; - } - for (n = rb_first(&alloc->free_buffers); n != NULL; - n = rb_next(n)) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - buffer_size = binder_alloc_buffer_size(alloc, buffer); - free_buffers++; - total_free_size += buffer_size; - if (buffer_size > largest_free_size) - largest_free_size = buffer_size; - } + if (unlikely(!best_fit)) { binder_alloc_debug(BINDER_DEBUG_USER_ERROR, "%d: binder_alloc_buf size %zd failed, no address space\n", alloc->pid, size); - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n", - total_alloc_size, allocated_buffers, - largest_alloc_size, total_free_size, - free_buffers, largest_free_size); + debug_no_space_locked(alloc); return ERR_PTR(-ENOSPC); } + if (n == NULL) { buffer = rb_entry(best_fit, struct binder_buffer, rb_node); buffer_size = binder_alloc_buffer_size(alloc, buffer); From e4ee73a6826545f1a7a98c6d68e2f880a659d8c7 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:43 +0000 Subject: [PATCH 20/46] UPSTREAM: binder: relocate low space calculation Move the low async space calculation to debug_low_async_space_locked(). This logic not only fits better here but also offloads some of the many tasks currently done in binder_alloc_new_buf_locked(). No functional change in this patch. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-15-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit c13500eaabd2343aa4cbb76b54ec624cb0c0ef8d) Change-Id: I1b396f59f2a5b6640d8664767f2d45a675af7197 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 2410b7810b75..247322d20613 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -371,6 +371,15 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc) size_t num_buffers = 0; struct rb_node *n; + /* + * Only start detecting spammers once we have less than 20% of async + * space left (which is less than 10% of total buffer size). + */ + if (alloc->free_async_space >= alloc->buffer_size / 10) { + alloc->oneway_spam_detected = false; + return false; + } + for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -491,16 +500,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_alloc_buf size %zd async free %zd\n", alloc->pid, size, alloc->free_async_space); - if (alloc->free_async_space < alloc->buffer_size / 10) { - /* - * Start detecting spammers once we have less than 20% - * of async space left (which is less than 10% of total - * buffer size). - */ - buffer->oneway_spam_suspect = debug_low_async_space_locked(alloc); - } else { - alloc->oneway_spam_detected = false; - } + if (debug_low_async_space_locked(alloc)) + buffer->oneway_spam_suspect = true; } return buffer; From 568a63be9a8954a9739fa8e272d194967346706c Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:44 +0000 Subject: [PATCH 21/46] UPSTREAM: binder: relocate binder_alloc_clear_buf() Move this function up along with binder_alloc_get_page() so that their prototypes aren't necessary. No functional change in this patch. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-16-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit cbc174a64b8d0ab542752c167dc1334b52b88624) Change-Id: I0d3c69c9a26c7415308202c4b7868a36b83d089c Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 124 ++++++++++++++++----------------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 247322d20613..5a7c058b78aa 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -704,8 +704,68 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, binder_insert_free_buffer(alloc, buffer); } +/** + * binder_alloc_get_page() - get kernel pointer for given buffer offset + * @alloc: binder_alloc for this proc + * @buffer: binder buffer to be accessed + * @buffer_offset: offset into @buffer data + * @pgoffp: address to copy final page offset to + * + * Lookup the struct page corresponding to the address + * at @buffer_offset into @buffer->user_data. If @pgoffp is not + * NULL, the byte-offset into the page is written there. + * + * The caller is responsible to ensure that the offset points + * to a valid address within the @buffer and that @buffer is + * not freeable by the user. Since it can't be freed, we are + * guaranteed that the corresponding elements of @alloc->pages[] + * cannot change. + * + * Return: struct page + */ +static struct page *binder_alloc_get_page(struct binder_alloc *alloc, + struct binder_buffer *buffer, + binder_size_t buffer_offset, + pgoff_t *pgoffp) +{ + binder_size_t buffer_space_offset = buffer_offset + + (buffer->user_data - alloc->buffer); + pgoff_t pgoff = buffer_space_offset & ~PAGE_MASK; + size_t index = buffer_space_offset >> PAGE_SHIFT; + struct binder_lru_page *lru_page; + + lru_page = &alloc->pages[index]; + *pgoffp = pgoff; + return lru_page->page_ptr; +} + +/** + * binder_alloc_clear_buf() - zero out buffer + * @alloc: binder_alloc for this proc + * @buffer: binder buffer to be cleared + * + * memset the given buffer to 0 + */ static void binder_alloc_clear_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer); + struct binder_buffer *buffer) +{ + size_t bytes = binder_alloc_buffer_size(alloc, buffer); + binder_size_t buffer_offset = 0; + + while (bytes) { + unsigned long size; + struct page *page; + pgoff_t pgoff; + + page = binder_alloc_get_page(alloc, buffer, + buffer_offset, &pgoff); + size = min_t(size_t, bytes, PAGE_SIZE - pgoff); + memset_page(page, pgoff, 0, size); + bytes -= size; + buffer_offset += size; + } +} + /** * binder_alloc_free_buf() - free a binder buffer * @alloc: binder_alloc for this proc @@ -1142,68 +1202,6 @@ static inline bool check_buffer(struct binder_alloc *alloc, (!buffer->allow_user_free || !buffer->transaction); } -/** - * binder_alloc_get_page() - get kernel pointer for given buffer offset - * @alloc: binder_alloc for this proc - * @buffer: binder buffer to be accessed - * @buffer_offset: offset into @buffer data - * @pgoffp: address to copy final page offset to - * - * Lookup the struct page corresponding to the address - * at @buffer_offset into @buffer->user_data. If @pgoffp is not - * NULL, the byte-offset into the page is written there. - * - * The caller is responsible to ensure that the offset points - * to a valid address within the @buffer and that @buffer is - * not freeable by the user. Since it can't be freed, we are - * guaranteed that the corresponding elements of @alloc->pages[] - * cannot change. - * - * Return: struct page - */ -static struct page *binder_alloc_get_page(struct binder_alloc *alloc, - struct binder_buffer *buffer, - binder_size_t buffer_offset, - pgoff_t *pgoffp) -{ - binder_size_t buffer_space_offset = buffer_offset + - (buffer->user_data - alloc->buffer); - pgoff_t pgoff = buffer_space_offset & ~PAGE_MASK; - size_t index = buffer_space_offset >> PAGE_SHIFT; - struct binder_lru_page *lru_page; - - lru_page = &alloc->pages[index]; - *pgoffp = pgoff; - return lru_page->page_ptr; -} - -/** - * binder_alloc_clear_buf() - zero out buffer - * @alloc: binder_alloc for this proc - * @buffer: binder buffer to be cleared - * - * memset the given buffer to 0 - */ -static void binder_alloc_clear_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer) -{ - size_t bytes = binder_alloc_buffer_size(alloc, buffer); - binder_size_t buffer_offset = 0; - - while (bytes) { - unsigned long size; - struct page *page; - pgoff_t pgoff; - - page = binder_alloc_get_page(alloc, buffer, - buffer_offset, &pgoff); - size = min_t(size_t, bytes, PAGE_SIZE - pgoff); - memset_page(page, pgoff, 0, size); - bytes -= size; - buffer_offset += size; - } -} - /** * binder_alloc_copy_user_to_buffer() - copy src user to tgt user * @alloc: binder_alloc for this proc From 796a1cae7bd836d42984497e34ccaa34c56551c0 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:45 +0000 Subject: [PATCH 22/46] UPSTREAM: binder: refactor page range allocation Instead of looping through the page range twice to first determine if the mmap lock is required, simply do it per-page as needed. Split out all this logic into a separate binder_install_single_page() function. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-17-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit ea2735ce19c1c6ce0f6011f813a1eea0272c231d) Change-Id: Ic057e9cfaeb22754f99bdec2a51076cf58c86855 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 107 +++++++++++++++------------------ 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 5a7c058b78aa..5cc9cb4fb9f9 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -199,14 +199,51 @@ static void binder_free_page_range(struct binder_alloc *alloc, } } +static int binder_install_single_page(struct binder_alloc *alloc, + struct binder_lru_page *lru_page, + unsigned long addr) +{ + struct page *page; + int ret = 0; + + if (!mmget_not_zero(alloc->mm)) + return -ESRCH; + + mmap_write_lock(alloc->mm); + if (!alloc->vma) { + pr_err("%d: %s failed, no vma\n", alloc->pid, __func__); + ret = -ESRCH; + goto out; + } + + page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); + if (!page) { + pr_err("%d: failed to allocate page\n", alloc->pid); + ret = -ENOMEM; + goto out; + } + + ret = vm_insert_page(alloc->vma, addr, page); + if (ret) { + pr_err("%d: %s failed to insert page at %lx with %d\n", + alloc->pid, __func__, addr, ret); + __free_page(page); + ret = -ENOMEM; + goto out; + } + + lru_page->page_ptr = page; +out: + mmap_write_unlock(alloc->mm); + mmput_async(alloc->mm); + return ret; +} + static int binder_allocate_page_range(struct binder_alloc *alloc, unsigned long start, unsigned long end) { - struct vm_area_struct *vma = NULL; struct binder_lru_page *page; - struct mm_struct *mm = NULL; unsigned long page_addr; - bool need_mm = false; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: allocate pages %lx-%lx\n", @@ -218,32 +255,9 @@ static int binder_allocate_page_range(struct binder_alloc *alloc, trace_binder_update_page_range(alloc, true, start, end); for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; - if (!page->page_ptr) { - need_mm = true; - break; - } - } - - if (need_mm && mmget_not_zero(alloc->mm)) - mm = alloc->mm; - - if (mm) { - mmap_write_lock(mm); - vma = alloc->vma; - } - - if (!vma && need_mm) { - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%d: binder_alloc_buf failed to map pages in userspace, no vma\n", - alloc->pid); - goto err_no_vma; - } - - for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - int ret; + unsigned long index; bool on_lru; - size_t index; + int ret; index = (page_addr - alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; @@ -258,26 +272,15 @@ static int binder_allocate_page_range(struct binder_alloc *alloc, continue; } - if (WARN_ON(!vma)) - goto err_page_ptr_cleared; - trace_binder_alloc_page_start(alloc, index); - page->page_ptr = alloc_page(GFP_KERNEL | - __GFP_HIGHMEM | - __GFP_ZERO); - if (!page->page_ptr) { - pr_err("%d: binder_alloc_buf failed for page at %lx\n", - alloc->pid, page_addr); - goto err_alloc_page_failed; - } + page->alloc = alloc; INIT_LIST_HEAD(&page->lru); - ret = vm_insert_page(vma, page_addr, page->page_ptr); + ret = binder_install_single_page(alloc, page, page_addr); if (ret) { - pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", - alloc->pid, page_addr); - goto err_vm_insert_page_failed; + binder_free_page_range(alloc, start, page_addr); + return ret; } if (index + 1 > alloc->pages_high) @@ -285,24 +288,8 @@ static int binder_allocate_page_range(struct binder_alloc *alloc, trace_binder_alloc_page_end(alloc, index); } - if (mm) { - mmap_write_unlock(mm); - mmput_async(mm); - } - return 0; -err_vm_insert_page_failed: - __free_page(page->page_ptr); - page->page_ptr = NULL; -err_alloc_page_failed: -err_page_ptr_cleared: - binder_free_page_range(alloc, start, page_addr); -err_no_vma: - if (mm) { - mmap_write_unlock(mm); - mmput_async(mm); - } - return vma ? -ENOMEM : -ESRCH; + return 0; } static inline void binder_alloc_set_vma(struct binder_alloc *alloc, From 48554214a7658e09de8d8a16688f1d3eac37b226 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:46 +0000 Subject: [PATCH 23/46] UPSTREAM: binder: malloc new_buffer outside of locks Preallocate new_buffer before acquiring the alloc->mutex and hand it down to binder_alloc_new_buf_locked(). The new buffer will be used in the vast majority of requests (measured at 98.2% in field data). The buffer is discarded otherwise. This change is required in preparation for transitioning alloc->mutex into a spinlock in subsequent commits. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-18-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit c7ac30fad18231a1637d38aa8a97d6b4788ed8ad) Change-Id: Ib7c8eb3c53e8383694a118fabc776a6a22783c75 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 44 ++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 5cc9cb4fb9f9..f6a5eaf836bb 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -395,24 +395,27 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc) return false; } +/* Callers preallocate @new_buffer, it is freed by this function if unused */ static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_alloc *alloc, + struct binder_buffer *new_buffer, size_t size, int is_async) { struct rb_node *n = alloc->free_buffers.rb_node; - struct binder_buffer *buffer; - size_t buffer_size; struct rb_node *best_fit = NULL; + struct binder_buffer *buffer; unsigned long has_page_addr; unsigned long end_page_addr; + size_t buffer_size; int ret; if (is_async && alloc->free_async_space < size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", alloc->pid, size); - return ERR_PTR(-ENOSPC); + buffer = ERR_PTR(-ENOSPC); + goto out; } while (n) { @@ -436,7 +439,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( "%d: binder_alloc_buf size %zd failed, no address space\n", alloc->pid, size); debug_no_space_locked(alloc); - return ERR_PTR(-ENOSPC); + buffer = ERR_PTR(-ENOSPC); + goto out; } if (n == NULL) { @@ -455,22 +459,17 @@ static struct binder_buffer *binder_alloc_new_buf_locked( end_page_addr = has_page_addr; ret = binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), end_page_addr); - if (ret) - return ERR_PTR(ret); + if (ret) { + buffer = ERR_PTR(ret); + goto out; + } if (buffer_size != size) { - struct binder_buffer *new_buffer; - - new_buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (!new_buffer) { - pr_err("%s: %d failed to alloc new buffer struct\n", - __func__, alloc->pid); - goto err_alloc_buf_struct_failed; - } new_buffer->user_data = buffer->user_data + size; list_add(&new_buffer->entry, &buffer->entry); new_buffer->free = 1; binder_insert_free_buffer(alloc, new_buffer); + new_buffer = NULL; } rb_erase(best_fit, &alloc->free_buffers); @@ -491,12 +490,10 @@ static struct binder_buffer *binder_alloc_new_buf_locked( buffer->oneway_spam_suspect = true; } +out: + /* Discard possibly unused new_buffer */ + kfree(new_buffer); return buffer; - -err_alloc_buf_struct_failed: - binder_free_page_range(alloc, PAGE_ALIGN(buffer->user_data), - end_page_addr); - return ERR_PTR(-ENOMEM); } /* Calculate the sanitized total size, returns 0 for invalid request */ @@ -542,7 +539,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, size_t extra_buffers_size, int is_async) { - struct binder_buffer *buffer; + struct binder_buffer *buffer, *next; size_t size; /* Check binder_alloc is fully initialized */ @@ -562,8 +559,13 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, return ERR_PTR(-EINVAL); } + /* Preallocate the next buffer */ + next = kzalloc(sizeof(*next), GFP_KERNEL); + if (!next) + return ERR_PTR(-ENOMEM); + mutex_lock(&alloc->mutex); - buffer = binder_alloc_new_buf_locked(alloc, size, is_async); + buffer = binder_alloc_new_buf_locked(alloc, next, size, is_async); if (IS_ERR(buffer)) { mutex_unlock(&alloc->mutex); goto out; From 2b6af2f338be89042c5c66d6a0397fdb471b2e57 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:47 +0000 Subject: [PATCH 24/46] UPSTREAM: binder: initialize lru pages in mmap callback Rather than repeatedly initializing some of the binder_lru_page members during binder_alloc_new_buf(), perform this initialization just once in binder_alloc_mmap_handler(), after the pages have been created. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-19-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 68aef12d094e4c96d972790f1620415460a4f3cf) Change-Id: I3197038683f76a5cb98a79d017d1515429df2d73 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index f6a5eaf836bb..9a4ba5434c80 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -274,9 +274,6 @@ static int binder_allocate_page_range(struct binder_alloc *alloc, trace_binder_alloc_page_start(alloc, index); - page->alloc = alloc; - INIT_LIST_HEAD(&page->lru); - ret = binder_install_single_page(alloc, page, page_addr); if (ret) { binder_free_page_range(alloc, start, page_addr); @@ -798,9 +795,9 @@ void binder_alloc_free_buf(struct binder_alloc *alloc, int binder_alloc_mmap_handler(struct binder_alloc *alloc, struct vm_area_struct *vma) { - int ret; - const char *failure_string; struct binder_buffer *buffer; + const char *failure_string; + int ret, i; if (unlikely(vma->vm_mm != alloc->mm)) { ret = -EINVAL; @@ -829,6 +826,11 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_alloc_pages_failed; } + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + alloc->pages[i].alloc = alloc; + INIT_LIST_HEAD(&alloc->pages[i].lru); + } + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) { ret = -ENOMEM; From 78dfa6954720257ae9d507062c33bee53c0231c3 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:48 +0000 Subject: [PATCH 25/46] UPSTREAM: binder: perform page installation outside of locks Split out the insertion of pages to be outside of the alloc->mutex in a separate binder_install_buffer_pages() routine. Since this is no longer serialized, we must look at the full range of pages used by the buffers. The installation is protected with mmap_sem in write mode since multiple tasks might race to install the same page. Besides avoiding unnecessary nested locking this helps in preparation of switching the alloc->mutex into a spinlock_t in subsequent patches. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-20-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 37ebbb4f73a0d299fa0c7dd043932a2f5fbbb779) Change-Id: I7b0684310b8824194d7e4a51a1fd67944f8ec06a Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 101 ++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 9a4ba5434c80..6166e4b22857 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -175,6 +175,21 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, return buffer; } +static inline void +binder_set_installed_page(struct binder_lru_page *lru_page, + struct page *page) +{ + /* Pairs with acquire in binder_get_installed_page() */ + smp_store_release(&lru_page->page_ptr, page); +} + +static inline struct page * +binder_get_installed_page(struct binder_lru_page *lru_page) +{ + /* Pairs with release in binder_set_installed_page() */ + return smp_load_acquire(&lru_page->page_ptr); +} + static void binder_free_page_range(struct binder_alloc *alloc, unsigned long start, unsigned long end) { @@ -190,6 +205,9 @@ static void binder_free_page_range(struct binder_alloc *alloc, index = (page_addr - alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; + if (!binder_get_installed_page(page)) + continue; + trace_binder_free_lru_start(alloc, index); ret = list_lru_add(&binder_alloc_lru, &page->lru); @@ -209,7 +227,14 @@ static int binder_install_single_page(struct binder_alloc *alloc, if (!mmget_not_zero(alloc->mm)) return -ESRCH; + /* + * Protected with mmap_sem in write mode as multiple tasks + * might race to install the same page. + */ mmap_write_lock(alloc->mm); + if (binder_get_installed_page(lru_page)) + goto out; + if (!alloc->vma) { pr_err("%d: %s failed, no vma\n", alloc->pid, __func__); ret = -ESRCH; @@ -232,15 +257,50 @@ static int binder_install_single_page(struct binder_alloc *alloc, goto out; } - lru_page->page_ptr = page; + /* Mark page installation complete and safe to use */ + binder_set_installed_page(lru_page, page); out: mmap_write_unlock(alloc->mm); mmput_async(alloc->mm); return ret; } -static int binder_allocate_page_range(struct binder_alloc *alloc, - unsigned long start, unsigned long end) +static int binder_install_buffer_pages(struct binder_alloc *alloc, + struct binder_buffer *buffer, + size_t size) +{ + struct binder_lru_page *page; + unsigned long start, final; + unsigned long page_addr; + + start = buffer->user_data & PAGE_MASK; + final = PAGE_ALIGN(buffer->user_data + size); + + for (page_addr = start; page_addr < final; page_addr += PAGE_SIZE) { + unsigned long index; + int ret; + + index = (page_addr - alloc->buffer) / PAGE_SIZE; + page = &alloc->pages[index]; + + if (binder_get_installed_page(page)) + continue; + + trace_binder_alloc_page_start(alloc, index); + + ret = binder_install_single_page(alloc, page, page_addr); + if (ret) + return ret; + + trace_binder_alloc_page_end(alloc, index); + } + + return 0; +} + +/* The range of pages should exclude those shared with other buffers */ +static void binder_allocate_page_range(struct binder_alloc *alloc, + unsigned long start, unsigned long end) { struct binder_lru_page *page; unsigned long page_addr; @@ -249,15 +309,11 @@ static int binder_allocate_page_range(struct binder_alloc *alloc, "%d: allocate pages %lx-%lx\n", alloc->pid, start, end); - if (end <= start) - return 0; - trace_binder_update_page_range(alloc, true, start, end); for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { unsigned long index; bool on_lru; - int ret; index = (page_addr - alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; @@ -272,21 +328,9 @@ static int binder_allocate_page_range(struct binder_alloc *alloc, continue; } - trace_binder_alloc_page_start(alloc, index); - - ret = binder_install_single_page(alloc, page, page_addr); - if (ret) { - binder_free_page_range(alloc, start, page_addr); - return ret; - } - if (index + 1 > alloc->pages_high) alloc->pages_high = index + 1; - - trace_binder_alloc_page_end(alloc, index); } - - return 0; } static inline void binder_alloc_set_vma(struct binder_alloc *alloc, @@ -405,7 +449,6 @@ static struct binder_buffer *binder_alloc_new_buf_locked( unsigned long has_page_addr; unsigned long end_page_addr; size_t buffer_size; - int ret; if (is_async && alloc->free_async_space < size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, @@ -449,18 +492,14 @@ static struct binder_buffer *binder_alloc_new_buf_locked( "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", alloc->pid, size, buffer, buffer_size); - has_page_addr = (buffer->user_data + buffer_size) & PAGE_MASK; WARN_ON(n && buffer_size != size); + + has_page_addr = (buffer->user_data + buffer_size) & PAGE_MASK; end_page_addr = PAGE_ALIGN(buffer->user_data + size); if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; - ret = binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), - end_page_addr); - if (ret) { - buffer = ERR_PTR(ret); - goto out; - } - + binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), + end_page_addr); if (buffer_size != size) { new_buffer->user_data = buffer->user_data + size; list_add(&new_buffer->entry, &buffer->entry); @@ -538,6 +577,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, { struct binder_buffer *buffer, *next; size_t size; + int ret; /* Check binder_alloc is fully initialized */ if (!binder_alloc_get_vma(alloc)) { @@ -574,6 +614,11 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, buffer->pid = current->tgid; mutex_unlock(&alloc->mutex); + ret = binder_install_buffer_pages(alloc, buffer, size); + if (ret) { + binder_alloc_free_buf(alloc, buffer); + buffer = ERR_PTR(ret); + } out: return buffer; } From de86cd1e00996f47c8226b5823a9040482bd0daa Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:49 +0000 Subject: [PATCH 26/46] UPSTREAM: binder: remove redundant debug log The debug information in this statement is already logged earlier in the same function. We can get rid of this duplicate log. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-21-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 258ce20ede33c551002705fa1488864fb287752c) Change-Id: Ie533a55ea10b2af927004f1d0e244b386ba25360 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 6166e4b22857..f5b9fc2855be 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -512,9 +512,6 @@ static struct binder_buffer *binder_alloc_new_buf_locked( buffer->free = 0; buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got %pK\n", - alloc->pid, size, buffer); buffer->async_transaction = is_async; buffer->oneway_spam_suspect = false; if (is_async) { From aac2b2c731ac26e17e621062a25115db114f6079 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:50 +0000 Subject: [PATCH 27/46] UPSTREAM: binder: make oversized buffer code more readable The sections in binder_alloc_new_buf_locked() dealing with oversized buffers are scattered which makes them difficult to read. Instead, consolidate this code into a single block to improve readability. No functional change here. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-22-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit de0e6573125f8ea7a01a9b05a45b0c73116c73b2) Change-Id: I62c2cec7341e13d9174b4f0839a1345df7cfd808 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index f5b9fc2855be..184fe7b73cb4 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -483,24 +483,12 @@ static struct binder_buffer *binder_alloc_new_buf_locked( goto out; } - if (n == NULL) { + if (buffer_size != size) { + /* Found an oversized buffer and needs to be split */ buffer = rb_entry(best_fit, struct binder_buffer, rb_node); buffer_size = binder_alloc_buffer_size(alloc, buffer); - } - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", - alloc->pid, size, buffer, buffer_size); - - WARN_ON(n && buffer_size != size); - - has_page_addr = (buffer->user_data + buffer_size) & PAGE_MASK; - end_page_addr = PAGE_ALIGN(buffer->user_data + size); - if (end_page_addr > has_page_addr) - end_page_addr = has_page_addr; - binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), - end_page_addr); - if (buffer_size != size) { + WARN_ON(n || buffer_size == size); new_buffer->user_data = buffer->user_data + size; list_add(&new_buffer->entry, &buffer->entry); new_buffer->free = 1; @@ -508,7 +496,18 @@ static struct binder_buffer *binder_alloc_new_buf_locked( new_buffer = NULL; } - rb_erase(best_fit, &alloc->free_buffers); + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", + alloc->pid, size, buffer, buffer_size); + + has_page_addr = (buffer->user_data + buffer_size) & PAGE_MASK; + end_page_addr = PAGE_ALIGN(buffer->user_data + size); + if (end_page_addr > has_page_addr) + end_page_addr = has_page_addr; + binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), + end_page_addr); + + rb_erase(&buffer->rb_node, &alloc->free_buffers); buffer->free = 0; buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); From 19d966c1c6c3dd9b44ea5f7272e142632e66f4f5 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:51 +0000 Subject: [PATCH 28/46] BACKPORT: UPSTREAM: binder: rename lru shrinker utilities Now that the page allocation step is done separately we should rename the binder_free_page_range() and binder_allocate_page_range() functions to provide a more accurate description of what they do. Lets borrow the freelist concept used in other parts of the kernel for this. No functional change here. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-23-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit ea9cdbf0c7273b55e251b2ed8f85794cfadab5d5) Change-Id: I0d0dfcc6f72d54209da310be2ad5e30f3d722652 [cmllamas: fixed trivial conflicts due to missing commits e33c267ab70d 95a542da5322e] Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 40 ++++++++++++------------- drivers/android/binder_alloc.h | 4 +-- drivers/android/binder_alloc_selftest.c | 6 ++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 184fe7b73cb4..05624c0ff6d5 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -26,7 +26,7 @@ #include "binder_alloc.h" #include "binder_trace.h" -struct list_lru binder_alloc_lru; +struct list_lru binder_freelist; static DEFINE_MUTEX(binder_alloc_mmap_lock); @@ -190,8 +190,8 @@ binder_get_installed_page(struct binder_lru_page *lru_page) return smp_load_acquire(&lru_page->page_ptr); } -static void binder_free_page_range(struct binder_alloc *alloc, - unsigned long start, unsigned long end) +static void binder_lru_freelist_add(struct binder_alloc *alloc, + unsigned long start, unsigned long end) { struct binder_lru_page *page; unsigned long page_addr; @@ -210,7 +210,7 @@ static void binder_free_page_range(struct binder_alloc *alloc, trace_binder_free_lru_start(alloc, index); - ret = list_lru_add(&binder_alloc_lru, &page->lru); + ret = list_lru_add(&binder_freelist, &page->lru); WARN_ON(!ret); trace_binder_free_lru_end(alloc, index); @@ -299,14 +299,14 @@ static int binder_install_buffer_pages(struct binder_alloc *alloc, } /* The range of pages should exclude those shared with other buffers */ -static void binder_allocate_page_range(struct binder_alloc *alloc, - unsigned long start, unsigned long end) +static void binder_lru_freelist_del(struct binder_alloc *alloc, + unsigned long start, unsigned long end) { struct binder_lru_page *page; unsigned long page_addr; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: allocate pages %lx-%lx\n", + "%d: pages %lx-%lx\n", alloc->pid, start, end); trace_binder_update_page_range(alloc, true, start, end); @@ -321,7 +321,7 @@ static void binder_allocate_page_range(struct binder_alloc *alloc, if (page->page_ptr) { trace_binder_alloc_lru_start(alloc, index); - on_lru = list_lru_del(&binder_alloc_lru, &page->lru); + on_lru = list_lru_del(&binder_freelist, &page->lru); WARN_ON(!on_lru); trace_binder_alloc_lru_end(alloc, index); @@ -504,8 +504,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( end_page_addr = PAGE_ALIGN(buffer->user_data + size); if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; - binder_allocate_page_range(alloc, PAGE_ALIGN(buffer->user_data), - end_page_addr); + binder_lru_freelist_del(alloc, PAGE_ALIGN(buffer->user_data), + end_page_addr); rb_erase(&buffer->rb_node, &alloc->free_buffers); buffer->free = 0; @@ -671,8 +671,8 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, alloc->pid, buffer->user_data, prev->user_data, next ? next->user_data : 0); - binder_free_page_range(alloc, buffer_start_page(buffer), - buffer_start_page(buffer) + PAGE_SIZE); + binder_lru_freelist_add(alloc, buffer_start_page(buffer), + buffer_start_page(buffer) + PAGE_SIZE); } list_del(&buffer->entry); kfree(buffer); @@ -706,8 +706,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, alloc->pid, size, alloc->free_async_space); } - binder_free_page_range(alloc, PAGE_ALIGN(buffer->user_data), - (buffer->user_data + buffer_size) & PAGE_MASK); + binder_lru_freelist_add(alloc, PAGE_ALIGN(buffer->user_data), + (buffer->user_data + buffer_size) & PAGE_MASK); rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1; @@ -953,7 +953,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) if (!alloc->pages[i].page_ptr) continue; - on_lru = list_lru_del(&binder_alloc_lru, + on_lru = list_lru_del(&binder_freelist, &alloc->pages[i].lru); page_addr = alloc->buffer + i * PAGE_SIZE; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, @@ -1152,13 +1152,13 @@ err_get_alloc_mutex_failed: static unsigned long binder_shrink_count(struct shrinker *shrink, struct shrink_control *sc) { - return list_lru_count(&binder_alloc_lru); + return list_lru_count(&binder_freelist); } static unsigned long binder_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { - return list_lru_walk(&binder_alloc_lru, binder_alloc_free_page, + return list_lru_walk(&binder_freelist, binder_alloc_free_page, NULL, sc->nr_to_scan); } @@ -1186,12 +1186,12 @@ void binder_alloc_init(struct binder_alloc *alloc) int binder_alloc_shrinker_init(void) { - int ret = list_lru_init(&binder_alloc_lru); + int ret = list_lru_init(&binder_freelist); if (ret == 0) { ret = register_shrinker(&binder_shrinker, "android-binder"); if (ret) - list_lru_destroy(&binder_alloc_lru); + list_lru_destroy(&binder_freelist); } return ret; } @@ -1199,7 +1199,7 @@ int binder_alloc_shrinker_init(void) void binder_alloc_shrinker_exit(void) { unregister_shrinker(&binder_shrinker); - list_lru_destroy(&binder_alloc_lru); + list_lru_destroy(&binder_freelist); } /** diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index bbc16bc6d5ac..a5181916942e 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -15,7 +15,7 @@ #include #include -extern struct list_lru binder_alloc_lru; +extern struct list_lru binder_freelist; struct binder_transaction; /** @@ -61,7 +61,7 @@ struct binder_buffer { /** * struct binder_lru_page - page object used for binder shrinker * @page_ptr: pointer to physical page in mmap'd space - * @lru: entry in binder_alloc_lru + * @lru: entry in binder_freelist * @alloc: binder_alloc for a proc */ struct binder_lru_page { diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c index ed753747e54c..fba7ab6ca451 100644 --- a/drivers/android/binder_alloc_selftest.c +++ b/drivers/android/binder_alloc_selftest.c @@ -158,8 +158,8 @@ static void binder_selftest_free_page(struct binder_alloc *alloc) int i; unsigned long count; - while ((count = list_lru_count(&binder_alloc_lru))) { - list_lru_walk(&binder_alloc_lru, binder_alloc_free_page, + while ((count = list_lru_count(&binder_freelist))) { + list_lru_walk(&binder_freelist, binder_alloc_free_page, NULL, count); } @@ -183,7 +183,7 @@ static void binder_selftest_alloc_free(struct binder_alloc *alloc, /* Allocate from lru. */ binder_selftest_alloc_buf(alloc, buffers, sizes, seq); - if (list_lru_count(&binder_alloc_lru)) + if (list_lru_count(&binder_freelist)) pr_err("lru list should be empty but is not\n"); binder_selftest_free_buf(alloc, buffers, sizes, seq, end); From baef4637fce544e368c4ff90dcf2a712fc718f4f Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:52 +0000 Subject: [PATCH 29/46] UPSTREAM: binder: document the final page calculation The code to determine the page range for binder_lru_freelist_del() is quite obscure. It leverages the buffer_size calculated before doing an oversized buffer split. This is used to figure out if the last page is being shared with another active buffer. If so, the page gets trimmed out of the range as it has been previously removed from the freelist. This would be equivalent to getting the start page of the next in-use buffer explicitly. However, the code for this is much larger as we can see in binder_free_buf_locked() routine. Instead, lets settle on documenting the tricky step and using better names for now. I believe an ideal solution would be to count the binder_page->users to determine when a page should be added or removed from the freelist. However, this is a much bigger change than what I'm willing to risk at this time. Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-24-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 67dcc880780569ec40391cae4d8299adc1e7a44e) Change-Id: Iec2466605fe7f8aa338c8313f586cdb7519a36e7 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 05624c0ff6d5..e4c0c8dce0fe 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -446,8 +446,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( struct rb_node *n = alloc->free_buffers.rb_node; struct rb_node *best_fit = NULL; struct binder_buffer *buffer; - unsigned long has_page_addr; - unsigned long end_page_addr; + unsigned long next_used_page; + unsigned long curr_last_page; size_t buffer_size; if (is_async && alloc->free_async_space < size) { @@ -500,12 +500,16 @@ static struct binder_buffer *binder_alloc_new_buf_locked( "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", alloc->pid, size, buffer, buffer_size); - has_page_addr = (buffer->user_data + buffer_size) & PAGE_MASK; - end_page_addr = PAGE_ALIGN(buffer->user_data + size); - if (end_page_addr > has_page_addr) - end_page_addr = has_page_addr; + /* + * Now we remove the pages from the freelist. A clever calculation + * with buffer_size determines if the last page is shared with an + * adjacent in-use buffer. In such case, the page has been already + * removed from the freelist so we trim our range short. + */ + next_used_page = (buffer->user_data + buffer_size) & PAGE_MASK; + curr_last_page = PAGE_ALIGN(buffer->user_data + size); binder_lru_freelist_del(alloc, PAGE_ALIGN(buffer->user_data), - end_page_addr); + min(next_used_page, curr_last_page)); rb_erase(&buffer->rb_node, &alloc->free_buffers); buffer->free = 0; From aacaa36eaa8b1f818ce17365dfda235171b41322 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:53 +0000 Subject: [PATCH 30/46] UPSTREAM: binder: collapse print_binder_buffer() into caller The code in print_binder_buffer() is quite small so it can be collapsed into its single caller binder_alloc_print_allocated(). No functional change in this patch. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-25-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 8e905217c4543af9cf1754809846157a7dbbb261) Change-Id: Ic3e2522b4702e60e09be3d5940f88ec8252ac793 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index e4c0c8dce0fe..401d19ea6650 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -978,16 +978,6 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) __func__, alloc->pid, buffers, page_count); } -static void print_binder_buffer(struct seq_file *m, const char *prefix, - struct binder_buffer *buffer) -{ - seq_printf(m, "%s %d: %lx size %zd:%zd:%zd %s\n", - prefix, buffer->debug_id, buffer->user_data, - buffer->data_size, buffer->offsets_size, - buffer->extra_buffers_size, - buffer->transaction ? "active" : "delivered"); -} - /** * binder_alloc_print_allocated() - print buffer info * @m: seq_file for output via seq_printf() @@ -999,12 +989,18 @@ static void print_binder_buffer(struct seq_file *m, const char *prefix, void binder_alloc_print_allocated(struct seq_file *m, struct binder_alloc *alloc) { + struct binder_buffer *buffer; struct rb_node *n; mutex_lock(&alloc->mutex); - for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) - print_binder_buffer(m, " buffer", - rb_entry(n, struct binder_buffer, rb_node)); + for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + seq_printf(m, " buffer %d: %lx size %zd:%zd:%zd %s\n", + buffer->debug_id, buffer->user_data, + buffer->data_size, buffer->offsets_size, + buffer->extra_buffers_size, + buffer->transaction ? "active" : "delivered"); + } mutex_unlock(&alloc->mutex); } From 0402339efb29c97d25e7a190474cf30dcd3ac01f Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:54 +0000 Subject: [PATCH 31/46] UPSTREAM: binder: refactor binder_delete_free_buffer() Skip the freelist call immediately as needed, instead of continuing the pointless checks. Also, drop the debug logs that we don't really need. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-26-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit f07b83a48e944c8a1cc1e9f6703fae5e34df2ba4) Change-Id: I035bd6cd5c06ec984cd6eb3c3b53e0958c64df4f Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 44 +++++++++------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 401d19ea6650..9c417e580671 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -636,48 +636,26 @@ static unsigned long prev_buffer_end_page(struct binder_buffer *buffer) static void binder_delete_free_buffer(struct binder_alloc *alloc, struct binder_buffer *buffer) { - struct binder_buffer *prev, *next = NULL; - bool to_free = true; + struct binder_buffer *prev, *next; + + if (PAGE_ALIGNED(buffer->user_data)) + goto skip_freelist; BUG_ON(alloc->buffers.next == &buffer->entry); prev = binder_buffer_prev(buffer); BUG_ON(!prev->free); - if (prev_buffer_end_page(prev) == buffer_start_page(buffer)) { - to_free = false; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %lx share page with %lx\n", - alloc->pid, buffer->user_data, - prev->user_data); - } + if (prev_buffer_end_page(prev) == buffer_start_page(buffer)) + goto skip_freelist; if (!list_is_last(&buffer->entry, &alloc->buffers)) { next = binder_buffer_next(buffer); - if (buffer_start_page(next) == buffer_start_page(buffer)) { - to_free = false; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %lx share page with %lx\n", - alloc->pid, - buffer->user_data, - next->user_data); - } + if (buffer_start_page(next) == buffer_start_page(buffer)) + goto skip_freelist; } - if (PAGE_ALIGNED(buffer->user_data)) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer start %lx is page aligned\n", - alloc->pid, buffer->user_data); - to_free = false; - } - - if (to_free) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %lx do not share page with %lx or %lx\n", - alloc->pid, buffer->user_data, - prev->user_data, - next ? next->user_data : 0); - binder_lru_freelist_add(alloc, buffer_start_page(buffer), - buffer_start_page(buffer) + PAGE_SIZE); - } + binder_lru_freelist_add(alloc, buffer_start_page(buffer), + buffer_start_page(buffer) + PAGE_SIZE); +skip_freelist: list_del(&buffer->entry); kfree(buffer); } From 112ca28d2657361beac34272c4f9551be7a6d3cf Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:55 +0000 Subject: [PATCH 32/46] UPSTREAM: binder: avoid user addresses in debug logs Prefer logging vma offsets instead of addresses or simply drop the debug log altogether if not useful. Note this covers the instances affected by the switch to store addresses as unsigned long. However, there are other sections in the driver that could do the same. Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231201172212.1813387-27-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 162c79731448a5a052e93af7753df579dfe0bf7a) Change-Id: I92b7f409e45d9006492d56302e911ccdd8efc950 Signed-off-by: Carlos Llamas --- drivers/android/binder.c | 4 ++-- drivers/android/binder_alloc.c | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 7f20e2ac3593..425afa2ecb92 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -6253,9 +6253,9 @@ static void print_binder_transaction_ilocked(struct seq_file *m, } if (buffer->target_node) seq_printf(m, " node %d", buffer->target_node->debug_id); - seq_printf(m, " size %zd:%zd data %lx\n", + seq_printf(m, " size %zd:%zd offset %lx\n", buffer->data_size, buffer->offsets_size, - buffer->user_data); + proc->alloc.buffer - buffer->user_data); } static void print_binder_work_ilocked(struct seq_file *m, diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 9c417e580671..c98e212c59fc 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -250,8 +250,8 @@ static int binder_install_single_page(struct binder_alloc *alloc, ret = vm_insert_page(alloc->vma, addr, page); if (ret) { - pr_err("%d: %s failed to insert page at %lx with %d\n", - alloc->pid, __func__, addr, ret); + pr_err("%d: %s failed to insert page at offset %lx with %d\n", + alloc->pid, __func__, addr - alloc->buffer, ret); __free_page(page); ret = -ENOMEM; goto out; @@ -305,10 +305,6 @@ static void binder_lru_freelist_del(struct binder_alloc *alloc, struct binder_lru_page *page; unsigned long page_addr; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: pages %lx-%lx\n", - alloc->pid, start, end); - trace_binder_update_page_range(alloc, true, start, end); for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { @@ -939,8 +935,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) &alloc->pages[i].lru); page_addr = alloc->buffer + i * PAGE_SIZE; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %lx %s\n", - __func__, alloc->pid, i, page_addr, + "%s: %d: page %d %s\n", + __func__, alloc->pid, i, on_lru ? "on lru" : "active"); __free_page(alloc->pages[i].page_ptr); page_count++; @@ -974,7 +970,8 @@ void binder_alloc_print_allocated(struct seq_file *m, for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { buffer = rb_entry(n, struct binder_buffer, rb_node); seq_printf(m, " buffer %d: %lx size %zd:%zd:%zd %s\n", - buffer->debug_id, buffer->user_data, + buffer->debug_id, + buffer->user_data - alloc->buffer, buffer->data_size, buffer->offsets_size, buffer->extra_buffers_size, buffer->transaction ? "active" : "delivered"); From a4abaacdab8a16529f72eeed81f92f7f933590b9 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:56 +0000 Subject: [PATCH 33/46] UPSTREAM: binder: reverse locking order in shrinker callback The locking order currently requires the alloc->mutex to be acquired first followed by the mmap lock. However, the alloc->mutex is converted into a spinlock in subsequent commits so the order needs to be reversed to avoid nesting the sleeping mmap lock under the spinlock. The shrinker's callback binder_alloc_free_page() is the only place that needs to be reordered since other functions have been refactored and no longer nest these locks. Some minor cosmetic changes are also included in this patch. Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-28-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit e50f4e6cc9bfaca655d3b6a3506d27cf2caa1d40) Change-Id: I7f7501945a477ac5571082a5dd2a7934f484b8ab Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 46 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index c98e212c59fc..100145a08f56 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -1061,35 +1061,39 @@ enum lru_status binder_alloc_free_page(struct list_head *item, void *cb_arg) __must_hold(lock) { - struct mm_struct *mm = NULL; - struct binder_lru_page *page = container_of(item, - struct binder_lru_page, - lru); - struct binder_alloc *alloc; + struct binder_lru_page *page = container_of(item, typeof(*page), lru); + struct binder_alloc *alloc = page->alloc; + struct mm_struct *mm = alloc->mm; + struct vm_area_struct *vma; + struct page *page_to_free; unsigned long page_addr; size_t index; - struct vm_area_struct *vma; - alloc = page->alloc; + if (!mmget_not_zero(mm)) + goto err_mmget; + if (!mmap_read_trylock(mm)) + goto err_mmap_read_lock_failed; if (!mutex_trylock(&alloc->mutex)) goto err_get_alloc_mutex_failed; - if (!page->page_ptr) goto err_page_already_freed; index = page - alloc->pages; page_addr = alloc->buffer + index * PAGE_SIZE; - mm = alloc->mm; - if (!mmget_not_zero(mm)) - goto err_mmget; - if (!mmap_read_trylock(mm)) - goto err_mmap_read_lock_failed; vma = vma_lookup(mm, page_addr); if (vma && vma != binder_alloc_get_vma(alloc)) goto err_invalid_vma; + trace_binder_unmap_kernel_start(alloc, index); + + page_to_free = page->page_ptr; + page->page_ptr = NULL; + + trace_binder_unmap_kernel_end(alloc, index); + list_lru_isolate(lru, item); + mutex_unlock(&alloc->mutex); spin_unlock(lock); if (vma) { @@ -1099,28 +1103,22 @@ enum lru_status binder_alloc_free_page(struct list_head *item, trace_binder_unmap_user_end(alloc, index); } + mmap_read_unlock(mm); mmput_async(mm); - - trace_binder_unmap_kernel_start(alloc, index); - - __free_page(page->page_ptr); - page->page_ptr = NULL; - - trace_binder_unmap_kernel_end(alloc, index); + __free_page(page_to_free); spin_lock(lock); - mutex_unlock(&alloc->mutex); return LRU_REMOVED_RETRY; err_invalid_vma: +err_page_already_freed: + mutex_unlock(&alloc->mutex); +err_get_alloc_mutex_failed: mmap_read_unlock(mm); err_mmap_read_lock_failed: mmput_async(mm); err_mmget: -err_page_already_freed: - mutex_unlock(&alloc->mutex); -err_get_alloc_mutex_failed: return LRU_SKIP; } From a091f9709e0342dfb20372703dd55267e6031c65 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 1 Dec 2023 17:21:57 +0000 Subject: [PATCH 34/46] UPSTREAM: binder: switch alloc->mutex to spinlock_t The alloc->mutex is a highly contended lock that causes performance issues on Android devices. When a low-priority task is given this lock and it sleeps, it becomes difficult for the task to wake up and complete its work. This delays other tasks that are also waiting on the mutex. The problem gets worse when there is memory pressure in the system, because this increases the contention on the alloc->mutex while the shrinker reclaims binder pages. Switching to a spinlock helps to keep the waiters running and avoids the overhead of waking up tasks. This significantly improves the transaction latency when the problematic scenario occurs. The performance impact of this patchset was measured by stress-testing the binder alloc contention. In this test, several clients of different priorities send thousands of transactions of different sizes to a single server. In parallel, pages get reclaimed using the shinker's debugfs. The test was run on a Pixel 8, Pixel 6 and qemu machine. The results were similar on all three devices: after: | sched | prio | average | max | min | |--------+------+---------+-----------+---------| | fifo | 99 | 0.135ms | 1.197ms | 0.022ms | | fifo | 01 | 0.136ms | 5.232ms | 0.018ms | | other | -20 | 0.180ms | 7.403ms | 0.019ms | | other | 19 | 0.241ms | 58.094ms | 0.018ms | before: | sched | prio | average | max | min | |--------+------+---------+-----------+---------| | fifo | 99 | 0.350ms | 248.730ms | 0.020ms | | fifo | 01 | 0.357ms | 248.817ms | 0.024ms | | other | -20 | 0.399ms | 249.906ms | 0.020ms | | other | 19 | 0.477ms | 297.756ms | 0.022ms | The key metrics above are the average and max latencies (wall time). These improvements should roughly translate to p95-p99 latencies on real workloads. The response time is up to 200x faster in these scenarios and there is no penalty in the regular path. Note that it is only possible to convert this lock after a series of changes made by previous patches. These mainly include refactoring the sections that might_sleep() and changing the locking order with the mmap_lock amongst others. Reviewed-by: Alice Ryhl Signed-off-by: Carlos Llamas Link: https://lore.kernel.org/r/20231201172212.1813387-29-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman Bug: 254650075 (cherry picked from commit 7710e2cca32e7f3958480e8bd44f50e29d0c2509) Change-Id: I67121be071d5f072ac0e5eb719c95c0f1dee5eb5 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 46 +++++++++++++++++----------------- drivers/android/binder_alloc.h | 10 ++++---- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 100145a08f56..8b3383eaaf2d 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -169,9 +169,9 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, { struct binder_buffer *buffer; - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); buffer = binder_alloc_prepare_to_free_locked(alloc, user_ptr); - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); return buffer; } @@ -597,10 +597,10 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, if (!next) return ERR_PTR(-ENOMEM); - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); buffer = binder_alloc_new_buf_locked(alloc, next, size, is_async); if (IS_ERR(buffer)) { - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); goto out; } @@ -608,7 +608,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, buffer->offsets_size = offsets_size; buffer->extra_buffers_size = extra_buffers_size; buffer->pid = current->tgid; - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); ret = binder_install_buffer_pages(alloc, buffer, size); if (ret) { @@ -785,17 +785,17 @@ void binder_alloc_free_buf(struct binder_alloc *alloc, * We could eliminate the call to binder_alloc_clear_buf() * from binder_alloc_deferred_release() by moving this to * binder_free_buf_locked(). However, that could - * increase contention for the alloc mutex if clear_on_free - * is used frequently for large buffers. The mutex is not + * increase contention for the alloc->lock if clear_on_free + * is used frequently for large buffers. This lock is not * needed for correctness here. */ if (buffer->clear_on_free) { binder_alloc_clear_buf(alloc, buffer); buffer->clear_on_free = false; } - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); binder_free_buf_locked(alloc, buffer); - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); } /** @@ -893,7 +893,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) struct binder_buffer *buffer; buffers = 0; - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); BUG_ON(alloc->vma); while ((n = rb_first(&alloc->allocated_buffers))) { @@ -943,7 +943,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) } kfree(alloc->pages); } - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); if (alloc->mm) mmdrop(alloc->mm); @@ -966,7 +966,7 @@ void binder_alloc_print_allocated(struct seq_file *m, struct binder_buffer *buffer; struct rb_node *n; - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { buffer = rb_entry(n, struct binder_buffer, rb_node); seq_printf(m, " buffer %d: %lx size %zd:%zd:%zd %s\n", @@ -976,7 +976,7 @@ void binder_alloc_print_allocated(struct seq_file *m, buffer->extra_buffers_size, buffer->transaction ? "active" : "delivered"); } - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); } /** @@ -993,7 +993,7 @@ void binder_alloc_print_pages(struct seq_file *m, int lru = 0; int free = 0; - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); /* * Make sure the binder_alloc is fully initialized, otherwise we might * read inconsistent state. @@ -1009,7 +1009,7 @@ void binder_alloc_print_pages(struct seq_file *m, lru++; } } - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); } @@ -1025,10 +1025,10 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc) struct rb_node *n; int count = 0; - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) count++; - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); return count; } @@ -1073,8 +1073,8 @@ enum lru_status binder_alloc_free_page(struct list_head *item, goto err_mmget; if (!mmap_read_trylock(mm)) goto err_mmap_read_lock_failed; - if (!mutex_trylock(&alloc->mutex)) - goto err_get_alloc_mutex_failed; + if (!spin_trylock(&alloc->lock)) + goto err_get_alloc_lock_failed; if (!page->page_ptr) goto err_page_already_freed; @@ -1093,7 +1093,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, trace_binder_unmap_kernel_end(alloc, index); list_lru_isolate(lru, item); - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); spin_unlock(lock); if (vma) { @@ -1113,8 +1113,8 @@ enum lru_status binder_alloc_free_page(struct list_head *item, err_invalid_vma: err_page_already_freed: - mutex_unlock(&alloc->mutex); -err_get_alloc_mutex_failed: + spin_unlock(&alloc->lock); +err_get_alloc_lock_failed: mmap_read_unlock(mm); err_mmap_read_lock_failed: mmput_async(mm); @@ -1153,7 +1153,7 @@ void binder_alloc_init(struct binder_alloc *alloc) alloc->pid = current->group_leader->pid; alloc->mm = current->mm; mmgrab(alloc->mm); - mutex_init(&alloc->mutex); + spin_lock_init(&alloc->lock); INIT_LIST_HEAD(&alloc->buffers); } diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index a5181916942e..70387234477e 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ struct binder_lru_page { /** * struct binder_alloc - per-binder proc state for binder allocator - * @mutex: protects binder_alloc fields + * @lock: protects binder_alloc fields * @vma: vm_area_struct passed to mmap_handler * (invariant after mmap) * @mm: copy of task->mm (invariant after open) @@ -96,7 +96,7 @@ struct binder_lru_page { * struct binder_buffer objects used to track the user buffers */ struct binder_alloc { - struct mutex mutex; + spinlock_t lock; struct vm_area_struct *vma; struct mm_struct *mm; unsigned long buffer; @@ -153,9 +153,9 @@ binder_alloc_get_free_async_space(struct binder_alloc *alloc) { size_t free_async_space; - mutex_lock(&alloc->mutex); + spin_lock(&alloc->lock); free_async_space = alloc->free_async_space; - mutex_unlock(&alloc->mutex); + spin_unlock(&alloc->lock); return free_async_space; } From 7e855d149275d377ba5eabc233a8513a1a9d81d5 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 28 May 2024 16:43:44 +0000 Subject: [PATCH 35/46] Reapply "ANDROID: Add vendor hooks for binder perf tuning" This reverts commit eeb899e9f54bef5286fd5044db481ecc01e417b4. Change-Id: I810727a6872c16ccb484023bfbc587daca8a2515 Signed-off-by: Carlos Llamas --- drivers/android/binder.c | 2 ++ drivers/android/binder_alloc.c | 3 +++ drivers/android/vendor_hooks.c | 3 +++ include/trace/hooks/binder.h | 13 +++++++++++++ 4 files changed, 21 insertions(+) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 425afa2ecb92..8b38bcbdf6ee 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3211,6 +3211,7 @@ static void binder_transaction(struct binder_proc *proc, target_proc = target_thread->proc; target_proc->tmp_ref++; binder_inner_proc_unlock(target_thread->proc); + trace_android_vh_binder_reply(target_proc, proc, thread, tr); } else { if (tr->target.handle) { struct binder_ref *ref; @@ -3273,6 +3274,7 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_invalid_target_handle; } + trace_android_vh_binder_trans(target_proc, proc, thread, tr); if (security_binder_transaction(proc->cred, target_proc->cred) < 0) { binder_txn_error("%d:%d transaction credentials failed\n", diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 8b3383eaaf2d..d729129f3f25 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -25,6 +25,7 @@ #include #include "binder_alloc.h" #include "binder_trace.h" +#include struct list_lru binder_freelist; @@ -446,6 +447,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked( unsigned long curr_last_page; size_t buffer_size; + trace_android_vh_binder_alloc_new_buf_locked(size, &alloc->free_async_space, is_async); + if (is_async && alloc->free_async_space < size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 2fd4d34cf7c9..31dde279e279 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -293,6 +293,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_online); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_free); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_alloc); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cpuset_fork); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_alloc_new_buf_locked); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_reply); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_trans); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmap_region); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_try_to_unmap_one); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_slab_bypass); diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index e71334f96007..77bfa4db10e2 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -78,6 +78,19 @@ DECLARE_HOOK(android_vh_binder_select_special_worklist, TP_PROTO(struct list_head **list, struct binder_thread *thread, struct binder_proc *proc, int wait_for_proc_work, bool *nothing_to_do), TP_ARGS(list, thread, proc, wait_for_proc_work, nothing_to_do)); + +DECLARE_HOOK(android_vh_binder_alloc_new_buf_locked, + TP_PROTO(size_t size, size_t *free_async_space, int is_async), + TP_ARGS(size, free_async_space, is_async)); +struct binder_transaction_data; +DECLARE_HOOK(android_vh_binder_reply, + TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, + struct binder_thread *thread, struct binder_transaction_data *tr), + TP_ARGS(target_proc, proc, thread, tr)); +DECLARE_HOOK(android_vh_binder_trans, + TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, + struct binder_thread *thread, struct binder_transaction_data *tr), + TP_ARGS(target_proc, proc, thread, tr)); DECLARE_HOOK(android_vh_binder_proc_transaction, TP_PROTO(struct task_struct *caller_task, struct task_struct *binder_proc_task, struct task_struct *binder_th_task, int node_debug_id, From 81054a4507e57418d559cafdded4f5086cc7d24a Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 28 May 2024 16:50:12 +0000 Subject: [PATCH 36/46] Reapply "ANDROID: vendor_hooks: Add hook for binder_detect_low_async_space" This reverts commit 637c8e0d372f1dfff53337a5db89f772577828d7. Also squash commit db91c5d31a2a ("ANDROID: vendor_hook: rename the the name of hooks"), which fixes the length of the vendor hook's name. Rework the error return for a goto as this has been refactor too. Finally, also fix spaces vs tabs. Change-Id: I22c495eb81237c51c0f9f4d4f9f4f1cf0c8438a8 Signed-off-by: Carlos Llamas --- drivers/android/binder_alloc.c | 10 ++++++++++ drivers/android/vendor_hooks.c | 1 + include/trace/hooks/binder.h | 3 +++ 3 files changed, 14 insertions(+) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index d729129f3f25..ed5ea094c9d2 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -445,9 +445,19 @@ static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_buffer *buffer; unsigned long next_used_page; unsigned long curr_last_page; + bool should_fail = false; size_t buffer_size; trace_android_vh_binder_alloc_new_buf_locked(size, &alloc->free_async_space, is_async); + trace_android_vh_binder_detect_low_async_space(is_async, &alloc->free_async_space, + current->tgid, &should_fail); + if (should_fail) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_alloc_buf size %zd failed, not allowed to alloc more async space\n", + alloc->pid, size); + buffer = ERR_PTR(-EPERM); + goto out; + } if (is_async && alloc->free_async_space < size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 31dde279e279..a45022e569e2 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -391,6 +391,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_ioctl_end); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_looper_exited); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_spawn_new_thread); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_has_special_work_ilocked); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_detect_low_async_space); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_init); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_tsk_init); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_delayacct_tsk_free); diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index 77bfa4db10e2..93641ce4ed6e 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -82,6 +82,9 @@ DECLARE_HOOK(android_vh_binder_select_special_worklist, DECLARE_HOOK(android_vh_binder_alloc_new_buf_locked, TP_PROTO(size_t size, size_t *free_async_space, int is_async), TP_ARGS(size, free_async_space, is_async)); +DECLARE_HOOK(android_vh_binder_detect_low_async_space, + TP_PROTO(int is_async, size_t *free_async_space, int pid, bool *should_fail), + TP_ARGS(is_async, free_async_space, pid, should_fail)); struct binder_transaction_data; DECLARE_HOOK(android_vh_binder_reply, TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc, From d30de4c7b0d22cc045a011428e778e40d762b5c0 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 5 Dec 2023 02:41:13 +0000 Subject: [PATCH 37/46] ANDROID: binder: fix KMI-break due to address type change In commit ("binder: keep vma addresses type as unsigned long") the vma address type in 'struct binder_alloc' and 'struct binder_buffer' is changed from 'void __user *' to 'unsigned long'. This triggers the following KMI issues: type 'struct binder_buffer' changed member changed from 'void* user_data' to 'unsigned long user_data' type changed from 'void*' to 'unsigned long' type 'struct binder_alloc' changed member changed from 'void* buffer' to 'unsigned long buffer' type changed from 'void*' to 'unsigned long' This offending commit is being backported as part of a larger patchset from upstream in [1]. Lets fix these issues by doing a partial revert that restores the original types and casts to an integer type where necessary. Note this approach is preferred over dropping the single KMI-breaking patch from the backport, as this would have created non-trivial merge conflicts in the subsequent cherry-picks. Bug: 254650075 Bug: 319778300 Link: https://lore.kernel.org/all/20231201172212.1813387-1-cmllamas@google.com/ [1] Change-Id: Ief9de717d0f34642f5954ffa2e306075a5b4e02e Signed-off-by: Carlos Llamas [cmllamas: fixed trivial conflicts] --- drivers/android/binder.c | 19 +++++++------ drivers/android/binder_alloc.c | 37 +++++++++++++------------ drivers/android/binder_alloc.h | 4 +-- drivers/android/binder_alloc_selftest.c | 6 ++-- drivers/android/binder_trace.h | 2 +- 5 files changed, 35 insertions(+), 33 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 8b38bcbdf6ee..783d4e49cf6f 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2276,8 +2276,9 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, * Convert the address to an offset relative to * the base of the transaction buffer. */ - fda_offset = parent->buffer - buffer->user_data + - fda->parent_offset; + fda_offset = + (parent->buffer - (uintptr_t)buffer->user_data) + + fda->parent_offset; for (fd_index = 0; fd_index < fda->num_fds; fd_index++) { u32 fd; @@ -2795,7 +2796,7 @@ static int binder_translate_fd_array(struct list_head *pf_head, * Convert the address to an offset relative to * the base of the transaction buffer. */ - fda_offset = parent->buffer - t->buffer->user_data + + fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) + fda->parent_offset; sender_ufda_base = (void __user *)(uintptr_t)sender_uparent->buffer + fda->parent_offset; @@ -2870,9 +2871,8 @@ static int binder_fixup_parent(struct list_head *pf_head, proc->pid, thread->pid); return -EINVAL; } - - buffer_offset = bp->parent_offset + parent->buffer - b->user_data; - + buffer_offset = bp->parent_offset + + (uintptr_t)parent->buffer - (uintptr_t)b->user_data; return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0); } @@ -3473,7 +3473,7 @@ static void binder_transaction(struct binder_proc *proc, ALIGN(extra_buffers_size, sizeof(void *)) - ALIGN(secctx_sz, sizeof(u64)); - t->security_ctx = t->buffer->user_data + buf_offset; + t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset; err = binder_alloc_copy_to_buffer(&target_proc->alloc, t->buffer, buf_offset, secctx, secctx_sz); @@ -3751,7 +3751,8 @@ static void binder_transaction(struct binder_proc *proc, goto err_translate_failed; } /* Fixup buffer pointer to target proc address space */ - bp->buffer = t->buffer->user_data + sg_buf_offset; + bp->buffer = (uintptr_t) + t->buffer->user_data + sg_buf_offset; sg_buf_offset += ALIGN(bp->length, sizeof(u64)); num_valid = (buffer_offset - off_start_offset) / @@ -4941,7 +4942,7 @@ skip: } trd->data_size = t->buffer->data_size; trd->offsets_size = t->buffer->offsets_size; - trd->data.ptr.buffer = t->buffer->user_data; + trd->data.ptr.buffer = (uintptr_t)t->buffer->user_data; trd->data.ptr.offsets = trd->data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index ed5ea094c9d2..f42f5d62b72c 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -135,9 +135,9 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( buffer = rb_entry(n, struct binder_buffer, rb_node); BUG_ON(buffer->free); - if (user_ptr < buffer->user_data) { + if (user_ptr < (uintptr_t)buffer->user_data) { n = n->rb_left; - } else if (user_ptr > buffer->user_data) { + } else if (user_ptr > (uintptr_t)buffer->user_data) { n = n->rb_right; } else { /* @@ -203,7 +203,7 @@ static void binder_lru_freelist_add(struct binder_alloc *alloc, size_t index; int ret; - index = (page_addr - alloc->buffer) / PAGE_SIZE; + index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; if (!binder_get_installed_page(page)) @@ -252,7 +252,8 @@ static int binder_install_single_page(struct binder_alloc *alloc, ret = vm_insert_page(alloc->vma, addr, page); if (ret) { pr_err("%d: %s failed to insert page at offset %lx with %d\n", - alloc->pid, __func__, addr - alloc->buffer, ret); + alloc->pid, __func__, addr - (uintptr_t)alloc->buffer, + ret); __free_page(page); ret = -ENOMEM; goto out; @@ -274,14 +275,14 @@ static int binder_install_buffer_pages(struct binder_alloc *alloc, unsigned long start, final; unsigned long page_addr; - start = buffer->user_data & PAGE_MASK; - final = PAGE_ALIGN(buffer->user_data + size); + start = (uintptr_t)buffer->user_data & PAGE_MASK; + final = PAGE_ALIGN((uintptr_t)buffer->user_data + size); for (page_addr = start; page_addr < final; page_addr += PAGE_SIZE) { unsigned long index; int ret; - index = (page_addr - alloc->buffer) / PAGE_SIZE; + index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; if (binder_get_installed_page(page)) @@ -312,7 +313,7 @@ static void binder_lru_freelist_del(struct binder_alloc *alloc, unsigned long index; bool on_lru; - index = (page_addr - alloc->buffer) / PAGE_SIZE; + index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; if (page->page_ptr) { @@ -515,9 +516,9 @@ static struct binder_buffer *binder_alloc_new_buf_locked( * adjacent in-use buffer. In such case, the page has been already * removed from the freelist so we trim our range short. */ - next_used_page = (buffer->user_data + buffer_size) & PAGE_MASK; - curr_last_page = PAGE_ALIGN(buffer->user_data + size); - binder_lru_freelist_del(alloc, PAGE_ALIGN(buffer->user_data), + next_used_page = ((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK; + curr_last_page = PAGE_ALIGN((uintptr_t)buffer->user_data + size); + binder_lru_freelist_del(alloc, PAGE_ALIGN((uintptr_t)buffer->user_data), min(next_used_page, curr_last_page)); rb_erase(&buffer->rb_node, &alloc->free_buffers); @@ -634,12 +635,12 @@ out: static unsigned long buffer_start_page(struct binder_buffer *buffer) { - return buffer->user_data & PAGE_MASK; + return (uintptr_t)buffer->user_data & PAGE_MASK; } static unsigned long prev_buffer_end_page(struct binder_buffer *buffer) { - return (buffer->user_data - 1) & PAGE_MASK; + return ((uintptr_t)buffer->user_data - 1) & PAGE_MASK; } static void binder_delete_free_buffer(struct binder_alloc *alloc, @@ -697,8 +698,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, alloc->pid, size, alloc->free_async_space); } - binder_lru_freelist_add(alloc, PAGE_ALIGN(buffer->user_data), - (buffer->user_data + buffer_size) & PAGE_MASK); + binder_lru_freelist_add(alloc, PAGE_ALIGN((uintptr_t)buffer->user_data), + ((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK); rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1; @@ -847,7 +848,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, SZ_4M); mutex_unlock(&binder_alloc_mmap_lock); - alloc->buffer = vma->vm_start; + alloc->buffer = (void __user *)vma->vm_start; alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE, sizeof(alloc->pages[0]), @@ -946,7 +947,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) on_lru = list_lru_del(&binder_freelist, &alloc->pages[i].lru); - page_addr = alloc->buffer + i * PAGE_SIZE; + page_addr = (uintptr_t)alloc->buffer + i * PAGE_SIZE; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%s: %d: page %d %s\n", __func__, alloc->pid, i, @@ -1092,7 +1093,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, goto err_page_already_freed; index = page - alloc->pages; - page_addr = alloc->buffer + index * PAGE_SIZE; + page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; vma = vma_lookup(mm, page_addr); if (vma && vma != binder_alloc_get_vma(alloc)) diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 70387234477e..d883ebd582e8 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -54,7 +54,7 @@ struct binder_buffer { size_t data_size; size_t offsets_size; size_t extra_buffers_size; - unsigned long user_data; + void __user *user_data; int pid; }; @@ -99,7 +99,7 @@ struct binder_alloc { spinlock_t lock; struct vm_area_struct *vma; struct mm_struct *mm; - unsigned long buffer; + void __user *buffer; struct list_head buffers; struct rb_root free_buffers; struct rb_root allocated_buffers; diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c index fba7ab6ca451..f01de0af2a2e 100644 --- a/drivers/android/binder_alloc_selftest.c +++ b/drivers/android/binder_alloc_selftest.c @@ -97,10 +97,10 @@ static bool check_buffer_pages_allocated(struct binder_alloc *alloc, unsigned long end; int page_index; - end = PAGE_ALIGN(buffer->user_data + size); - page_addr = buffer->user_data; + end = PAGE_ALIGN((uintptr_t)buffer->user_data + size); + page_addr = (uintptr_t)buffer->user_data; for (; page_addr < end; page_addr += PAGE_SIZE) { - page_index = (page_addr - alloc->buffer) / PAGE_SIZE; + page_index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; if (!alloc->pages[page_index].page_ptr || !list_empty(&alloc->pages[page_index].lru)) { pr_err("expect alloc but is %s at page index %d\n", diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h index e90fc3d5eea3..618c4cc016c5 100644 --- a/drivers/android/binder_trace.h +++ b/drivers/android/binder_trace.h @@ -352,7 +352,7 @@ TRACE_EVENT(binder_update_page_range, TP_fast_assign( __entry->proc = alloc->pid; __entry->allocate = allocate; - __entry->offset = start - alloc->buffer; + __entry->offset = start - (uintptr_t)alloc->buffer; __entry->size = end - start; ), TP_printk("proc=%d allocate=%d offset=%zu size=%zu", From 1c5fb0ebd8f3c4f669c768860438d2e1f176531a Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 17 May 2024 17:06:20 +0000 Subject: [PATCH 38/46] ANDROID: binder: fix ptrdiff_t printk-format issue The correct printk format specifier when calculating buffer offsets should be "%tx" as it is a pointer difference (a.k.a ptrdiff_t). This fixes some W=1 build warnings reported by the kernel test robot. Bug: 329799092 Fixes: 63f7ddea2e48 ("ANDROID: binder: fix KMI-break due to address type change") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202401100511.A4BKMwoq-lkp@intel.com/ Change-Id: Iaa87433897b507c47fe8601464445cb6de4b61db Signed-off-by: Carlos Llamas --- drivers/android/binder.c | 2 +- drivers/android/binder_alloc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 783d4e49cf6f..0f6b48dc5036 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -6256,7 +6256,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m, } if (buffer->target_node) seq_printf(m, " node %d", buffer->target_node->debug_id); - seq_printf(m, " size %zd:%zd offset %lx\n", + seq_printf(m, " size %zd:%zd offset %tx\n", buffer->data_size, buffer->offsets_size, proc->alloc.buffer - buffer->user_data); } diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index f42f5d62b72c..0efab3a35c38 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -983,7 +983,7 @@ void binder_alloc_print_allocated(struct seq_file *m, spin_lock(&alloc->lock); for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { buffer = rb_entry(n, struct binder_buffer, rb_node); - seq_printf(m, " buffer %d: %lx size %zd:%zd:%zd %s\n", + seq_printf(m, " buffer %d: %tx size %zd:%zd:%zd %s\n", buffer->debug_id, buffer->user_data - alloc->buffer, buffer->data_size, buffer->offsets_size, From a6358098dac5b0cb772a0edfa8fcca98685f30d7 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 5 Dec 2023 03:08:33 +0000 Subject: [PATCH 39/46] ANDROID: binder: fix KMI-break due to alloc->lock Wrap 'struct binder_proc' inside 'struct binder_proc_wrap' to add the alloc->lock equivalent without breaking the KMI. Also, add convenient apis to access/modify this new spinlock. Without this patch, the following KMI issues show up: type 'struct binder_proc' changed byte size changed from 616 to 576 type 'struct binder_alloc' changed byte size changed from 152 to 112 member 'spinlock_t lock' was added member 'struct mutex mutex' was removed Bug: 254650075 Bug: 319778300 Change-Id: Ic31dc39fb82800a3e47be10a7873cd210f7b60be Signed-off-by: Carlos Llamas [cmllamas: fixed trivial conflicts] --- drivers/android/binder.c | 11 ++++-- drivers/android/binder_alloc.c | 40 ++++++++++----------- drivers/android/binder_alloc.h | 21 ++--------- drivers/android/binder_internal.h | 60 +++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 42 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 0f6b48dc5036..4ea9a4dae15f 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -5155,6 +5155,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) static void binder_free_proc(struct binder_proc *proc) { + struct binder_proc_wrap *proc_wrap; struct binder_device *device; BUG_ON(!list_empty(&proc->todo)); @@ -5172,7 +5173,8 @@ static void binder_free_proc(struct binder_proc *proc) put_cred(proc->cred); binder_stats_deleted(BINDER_STAT_PROC); trace_android_vh_binder_free_proc(proc); - kfree(proc); + proc_wrap = binder_proc_wrap_entry(proc); + kfree(proc_wrap); } static void binder_free_thread(struct binder_thread *thread) @@ -5878,6 +5880,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) static int binder_open(struct inode *nodp, struct file *filp) { + struct binder_proc_wrap *proc_wrap; struct binder_proc *proc, *itr; struct binder_device *binder_dev; struct binderfs_info *info; @@ -5887,9 +5890,11 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, current->group_leader->pid, current->pid); - proc = kzalloc(sizeof(*proc), GFP_KERNEL); - if (proc == NULL) + proc_wrap = kzalloc(sizeof(*proc_wrap), GFP_KERNEL); + if (proc_wrap == NULL) return -ENOMEM; + proc = &proc_wrap->proc; + spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 0efab3a35c38..6ce5a0264946 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -23,7 +23,7 @@ #include #include #include -#include "binder_alloc.h" +#include "binder_internal.h" #include "binder_trace.h" #include @@ -170,9 +170,9 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, { struct binder_buffer *buffer; - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); buffer = binder_alloc_prepare_to_free_locked(alloc, user_ptr); - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); return buffer; } @@ -611,10 +611,10 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, if (!next) return ERR_PTR(-ENOMEM); - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); buffer = binder_alloc_new_buf_locked(alloc, next, size, is_async); if (IS_ERR(buffer)) { - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); goto out; } @@ -622,7 +622,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, buffer->offsets_size = offsets_size; buffer->extra_buffers_size = extra_buffers_size; buffer->pid = current->tgid; - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); ret = binder_install_buffer_pages(alloc, buffer, size); if (ret) { @@ -807,9 +807,9 @@ void binder_alloc_free_buf(struct binder_alloc *alloc, binder_alloc_clear_buf(alloc, buffer); buffer->clear_on_free = false; } - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); binder_free_buf_locked(alloc, buffer); - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); } /** @@ -907,7 +907,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) struct binder_buffer *buffer; buffers = 0; - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); BUG_ON(alloc->vma); while ((n = rb_first(&alloc->allocated_buffers))) { @@ -957,7 +957,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) } kfree(alloc->pages); } - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); if (alloc->mm) mmdrop(alloc->mm); @@ -980,7 +980,7 @@ void binder_alloc_print_allocated(struct seq_file *m, struct binder_buffer *buffer; struct rb_node *n; - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { buffer = rb_entry(n, struct binder_buffer, rb_node); seq_printf(m, " buffer %d: %tx size %zd:%zd:%zd %s\n", @@ -990,7 +990,7 @@ void binder_alloc_print_allocated(struct seq_file *m, buffer->extra_buffers_size, buffer->transaction ? "active" : "delivered"); } - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); } /** @@ -1007,7 +1007,7 @@ void binder_alloc_print_pages(struct seq_file *m, int lru = 0; int free = 0; - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); /* * Make sure the binder_alloc is fully initialized, otherwise we might * read inconsistent state. @@ -1023,7 +1023,7 @@ void binder_alloc_print_pages(struct seq_file *m, lru++; } } - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); } @@ -1039,10 +1039,10 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc) struct rb_node *n; int count = 0; - spin_lock(&alloc->lock); + binder_alloc_lock(alloc); for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) count++; - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); return count; } @@ -1087,7 +1087,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, goto err_mmget; if (!mmap_read_trylock(mm)) goto err_mmap_read_lock_failed; - if (!spin_trylock(&alloc->lock)) + if (!binder_alloc_trylock(alloc)) goto err_get_alloc_lock_failed; if (!page->page_ptr) goto err_page_already_freed; @@ -1107,7 +1107,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, trace_binder_unmap_kernel_end(alloc, index); list_lru_isolate(lru, item); - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); spin_unlock(lock); if (vma) { @@ -1127,7 +1127,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, err_invalid_vma: err_page_already_freed: - spin_unlock(&alloc->lock); + binder_alloc_unlock(alloc); err_get_alloc_lock_failed: mmap_read_unlock(mm); err_mmap_read_lock_failed: @@ -1167,7 +1167,7 @@ void binder_alloc_init(struct binder_alloc *alloc) alloc->pid = current->group_leader->pid; alloc->mm = current->mm; mmgrab(alloc->mm); - spin_lock_init(&alloc->lock); + binder_alloc_lock_init(alloc); INIT_LIST_HEAD(&alloc->buffers); } diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index d883ebd582e8..d3ac713744b0 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -96,7 +96,7 @@ struct binder_lru_page { * struct binder_buffer objects used to track the user buffers */ struct binder_alloc { - spinlock_t lock; + struct mutex mutex; struct vm_area_struct *vma; struct mm_struct *mm; void __user *buffer; @@ -142,23 +142,6 @@ void binder_alloc_print_allocated(struct seq_file *m, void binder_alloc_print_pages(struct seq_file *m, struct binder_alloc *alloc); -/** - * binder_alloc_get_free_async_space() - get free space available for async - * @alloc: binder_alloc for this proc - * - * Return: the bytes remaining in the address-space for async transactions - */ -static inline size_t -binder_alloc_get_free_async_space(struct binder_alloc *alloc) -{ - size_t free_async_space; - - spin_lock(&alloc->lock); - free_async_space = alloc->free_async_space; - spin_unlock(&alloc->lock); - return free_async_space; -} - unsigned long binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc, struct binder_buffer *buffer, diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 439c8c2403c3..4164c346b301 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -461,6 +461,66 @@ struct binder_proc { bool oneway_spam_detection_enabled; }; +struct binder_proc_wrap { + struct binder_proc proc; + spinlock_t lock; +}; + +static inline struct binder_proc * +binder_proc_entry(struct binder_alloc *alloc) +{ + return container_of(alloc, struct binder_proc, alloc); +} + +static inline struct binder_proc_wrap * +binder_proc_wrap_entry(struct binder_proc *proc) +{ + return container_of(proc, struct binder_proc_wrap, proc); +} + +static inline struct binder_proc_wrap * +binder_alloc_to_proc_wrap(struct binder_alloc *alloc) +{ + return binder_proc_wrap_entry(binder_proc_entry(alloc)); +} + +static inline void binder_alloc_lock_init(struct binder_alloc *alloc) +{ + spin_lock_init(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +static inline void binder_alloc_lock(struct binder_alloc *alloc) +{ + spin_lock(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +static inline void binder_alloc_unlock(struct binder_alloc *alloc) +{ + spin_unlock(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +static inline int binder_alloc_trylock(struct binder_alloc *alloc) +{ + return spin_trylock(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +/** + * binder_alloc_get_free_async_space() - get free space available for async + * @alloc: binder_alloc for this proc + * + * Return: the bytes remaining in the address-space for async transactions + */ +static inline size_t +binder_alloc_get_free_async_space(struct binder_alloc *alloc) +{ + size_t free_async_space; + + binder_alloc_lock(alloc); + free_async_space = alloc->free_async_space; + binder_alloc_unlock(alloc); + return free_async_space; +} + /** * struct binder_thread - binder thread bookkeeping * @proc: binder process for this thread From c6427490abb170353d23691ac05339e42377f90a Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 29 May 2024 16:52:43 +0000 Subject: [PATCH 40/46] Revert^2 "BACKPORT: FROMGIT: module: allow UNUSED_KSYMS_WHITELIST ..." This reverts commit 3f139724700e080489f2249b0bab4d22f633e455. Reason for revert: relanding change that should be safe to go in on its own. Below is the original commit message. BACKPORT: FROMGIT: module: allow UNUSED_KSYMS_WHITELIST to be relative against objtree. If UNUSED_KSYMS_WHITELIST is a file generated before Kbuild runs, and the source tree is in a read-only filesystem, the developer must put the file somewhere and specify an absolute path to UNUSED_KSYMS_WHITELIST. This worked, but if IKCONFIG=y, an absolute path is embedded into .config and eventually into vmlinux, causing the build to be less reproducible when building on a different machine. This patch makes the handling of UNUSED_KSYMS_WHITELIST to be similar to MODULE_SIG_KEY. First, check if UNUSED_KSYMS_WHITELIST is an absolute path, just as before this patch. If so, use the path as is. If it is a relative path, use wildcard to check the existence of the file below objtree first. If it does not exist, fall back to the original behavior of adding $(srctree)/ before the value. After this patch, the developer can put the generated file in objtree, then use a relative path against objtree in .config, eradicating any absolute paths that may be evaluated differently on different machines. Signed-off-by: Yifan Hong Reviewed-by: Elliot Berman Signed-off-by: Luis Chamberlain (cherry picked from commit a2e3c811938b4902725e259c03b2d6c539613992 https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next) Bug: 333769605 Change-Id: I442bbe5a68fc895619b84b4749f1e97cb88088ea [elsk: apply change to gen_autoksyms.sh instead because CONFIG_UNUSED_KSYMS_WHITELIST is parsed there. Revert change to Makefile.modpost.] Bug: 342390208 Signed-off-by: Yifan Hong --- kernel/module/Kconfig | 2 +- scripts/gen_autoksyms.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index 6b5c1175faea..ef66cce84d61 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -311,7 +311,7 @@ config UNUSED_KSYMS_WHITELIST exported at all times, even in absence of in-tree users. The value to set here is the path to a text file containing the list of symbols, one per line. The path can be absolute, or relative to the kernel - source tree. + source or obj tree. config MODULES_TREE_LOOKUP def_bool y diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 653fadbad302..e12178d677e2 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -31,7 +31,7 @@ fi ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) if [ -n "$ksym_wl" ]; then - [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" + [ "${ksym_wl}" != "${ksym_wl#/}" ] || [ -f "$ksym_wl" ] || ksym_wl="$abs_srctree/$ksym_wl" if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 exit 1 From 6b75fd4835190d845188cbb044858ae49eb2a466 Mon Sep 17 00:00:00 2001 From: Rick Yiu Date: Wed, 29 May 2024 02:30:22 +0000 Subject: [PATCH 41/46] ANDROID: Update the ABI symbol list To use cpumask_parse_user in vendor code, it will call bitmap_parse_user. Adding the following symbols: - bitmap_parse_user Bug: 248621289 Change-Id: I4b24d8b1fba71af7b55c7444963a003d50f6d93c Signed-off-by: Rick Yiu --- android/abi_gki_aarch64.stg | 10 ++++++++++ android/abi_gki_aarch64_pixel | 1 + 2 files changed, 11 insertions(+) diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg index 69a90ae57fd9..87491603dded 100644 --- a/android/abi_gki_aarch64.stg +++ b/android/abi_gki_aarch64.stg @@ -351925,6 +351925,15 @@ elf_symbol { type_id: 0x9312d42a full_name: "bitmap_parse" } +elf_symbol { + id: 0xba7da88a + name: "bitmap_parse_user" + is_defined: true + symbol_type: FUNCTION + crc: 0x9a5a8914 + type_id: 0x9312d42a + full_name: "bitmap_parse_user" +} elf_symbol { id: 0x10425c32 name: "bitmap_parselist" @@ -410056,6 +410065,7 @@ interface { symbol_id: 0xe4dd862f symbol_id: 0x3a1cd883 symbol_id: 0xa1f151cb + symbol_id: 0xba7da88a symbol_id: 0x10425c32 symbol_id: 0xbd9a7739 symbol_id: 0x82c387e4 diff --git a/android/abi_gki_aarch64_pixel b/android/abi_gki_aarch64_pixel index 0d1b0c47954a..3606c97de5ff 100644 --- a/android/abi_gki_aarch64_pixel +++ b/android/abi_gki_aarch64_pixel @@ -82,6 +82,7 @@ __bitmap_or bitmap_parse bitmap_parselist + bitmap_parse_user bitmap_print_to_pagebuf __bitmap_set __bitmap_subset From 974a6f430e0a6ec753f0a95977b12c6f7e632899 Mon Sep 17 00:00:00 2001 From: Ahmad Chaudhry Date: Thu, 18 Apr 2024 18:49:24 +0000 Subject: [PATCH 42/46] ANDROID: gki_defconfig: Enable Tegra SoCs Enable configs required for Tegra SoCs. Bug: 335325897 Change-Id: I74fd9e1b16810ca417f656ed681e01dff8a4efc9 Signed-off-by: Ahmad Chaudhry --- arch/arm64/configs/gki_defconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 502f707b59e6..7b4e76e57af5 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -48,6 +48,7 @@ CONFIG_PROFILING=y CONFIG_ARCH_SUNXI=y CONFIG_ARCH_HISI=y CONFIG_ARCH_QCOM=y +CONFIG_ARCH_TEGRA=y CONFIG_SCHED_MC=y CONFIG_NR_CPUS=32 CONFIG_PARAVIRT_TIME_ACCOUNTING=y @@ -57,6 +58,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_PMEM=y # CONFIG_ARM64_BTI_KERNEL is not set CONFIG_RANDOMIZE_BASE=y # CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set @@ -399,6 +401,7 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_SAMSUNG=y CONFIG_SERIAL_SAMSUNG_CONSOLE=y +CONFIG_SERIAL_TEGRA_TCU=y CONFIG_SERIAL_QCOM_GENI=y CONFIG_SERIAL_QCOM_GENI_CONSOLE=y CONFIG_SERIAL_SPRD=y @@ -569,22 +572,22 @@ CONFIG_COMMON_CLK_SCPI=y # CONFIG_SUNXI_CCU is not set CONFIG_HWSPINLOCK=y # CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set -CONFIG_MAILBOX=y CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y CONFIG_REMOTEPROC=y CONFIG_REMOTEPROC_CDEV=y CONFIG_RPMSG_CHAR=y CONFIG_QCOM_GENI_SE=y +CONFIG_ARCH_TEGRA_234_SOC=y CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y CONFIG_DEVFREQ_GOV_USERSPACE=y CONFIG_DEVFREQ_GOV_PASSIVE=y CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_MEMORY=y CONFIG_IIO=y CONFIG_IIO_BUFFER=y CONFIG_IIO_TRIGGER=y CONFIG_PWM=y -CONFIG_GENERIC_PHY=y CONFIG_POWERCAP=y CONFIG_IDLE_INJECT=y CONFIG_ANDROID_BINDER_IPC=y @@ -593,7 +596,6 @@ CONFIG_ANDROID_DEBUG_SYMBOLS=y CONFIG_ANDROID_VENDOR_HOOKS=y CONFIG_ANDROID_DEBUG_KINFO=y CONFIG_LIBNVDIMM=y -CONFIG_INTERCONNECT=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y From 1e4532a4a32c8fafb3f254c664b981b013785b92 Mon Sep 17 00:00:00 2001 From: Ahmad Chaudhry Date: Wed, 29 May 2024 17:28:47 +0000 Subject: [PATCH 43/46] ANDROID: Build some tegra configs as vendor module Build some configs that are tristate and selected by CONFIG_ARCH_TEGRA as vendor modules rather than built-in. Bug: 335325897 Change-Id: I7ce4cf975fcbc834bc5fc3c90317d9d81162185a Signed-off-by: Ahmad Chaudhry --- drivers/amba/Kconfig | 1 - drivers/gpio/Kconfig | 1 - drivers/i2c/busses/Kconfig | 1 - drivers/tty/serial/8250/Kconfig | 1 - 4 files changed, 4 deletions(-) diff --git a/drivers/amba/Kconfig b/drivers/amba/Kconfig index fb6c7e0b4cce..73f8cd696561 100644 --- a/drivers/amba/Kconfig +++ b/drivers/amba/Kconfig @@ -6,7 +6,6 @@ if ARM_AMBA config TEGRA_AHB bool - default y if ARCH_TEGRA help Adds AHB configuration functionality for NVIDIA Tegra SoCs, which controls AHB bus master arbitration and some performance diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3e8e5f4ffa59..2396585d88a7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -633,7 +633,6 @@ config GPIO_TB10X config GPIO_TEGRA tristate "NVIDIA Tegra GPIO support" - default ARCH_TEGRA depends on ARCH_TEGRA || COMPILE_TEST depends on OF_GPIO select GPIOLIB_IRQCHIP diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e50f9603d189..9789a3f373f3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1121,7 +1121,6 @@ config I2C_TEGRA config I2C_TEGRA_BPMP tristate "NVIDIA Tegra BPMP I2C controller" depends on TEGRA_BPMP || COMPILE_TEST - default y if TEGRA_BPMP help If you say yes to this option, support will be included for the I2C controller embedded in NVIDIA Tegra SoCs accessed via the BPMP. diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 583a340f9934..7bd40a209e9e 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -522,7 +522,6 @@ config SERIAL_8250_PXA config SERIAL_8250_TEGRA tristate "8250 support for Tegra serial ports" - default SERIAL_8250 depends on SERIAL_8250 depends on ARCH_TEGRA || COMPILE_TEST help From 8498700531c224e81b10f3af96bc530373f2d48b Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 14 May 2024 16:54:59 +0000 Subject: [PATCH 44/46] ANDROID: GKI: update symbol list for db845c Enabling configs for Tegra SoCs required these symbols to be included. This change fixes the following build issues: ERROR: modpost: "devm_tegra_memory_controller_get" [drivers/iommu/arm/arm-smmu/arm_smmu.ko] undefined! ERROR: modpost: "tegra_mc_probe_device" [drivers/iommu/arm/arm-smmu/arm_smmu.ko] undefined! Also update the STG file accordingly: 2 function symbol(s) added 'struct tegra_mc* devm_tegra_memory_controller_get(struct device*)' 'int tegra_mc_probe_device(struct tegra_mc*, struct device*)' Bug: 335325897 Change-Id: Ie357116189e074f1dc0e572553b2264abc910bd3 Signed-off-by: Carlos Llamas --- android/abi_gki_aarch64.stg | 884 +++++++++++++++++++++++++++++++++ android/abi_gki_aarch64_db845c | 2 + 2 files changed, 886 insertions(+) diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg index 87491603dded..184a3b5106ba 100644 --- a/android/abi_gki_aarch64.stg +++ b/android/abi_gki_aarch64.stg @@ -5383,6 +5383,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x1d6740b1 } +pointer_reference { + id: 0x0dca21d4 + kind: POINTER + pointee_type_id: 0x1d6861ce +} pointer_reference { id: 0x0dcbeae6 kind: POINTER @@ -10548,6 +10553,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x58912da5 } +pointer_reference { + id: 0x1cba6ba2 + kind: POINTER + pointee_type_id: 0x58a94817 +} pointer_reference { id: 0x1cc18442 kind: POINTER @@ -20048,6 +20058,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x906c53c0 } +pointer_reference { + id: 0x2e8c0d7b + kind: POINTER + pointee_type_id: 0x9070d372 +} pointer_reference { id: 0x2e8c7bd9 kind: POINTER @@ -20068,6 +20083,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x9078a69f } +pointer_reference { + id: 0x2e8e5582 + kind: POINTER + pointee_type_id: 0x9079b097 +} pointer_reference { id: 0x2e8ed696 kind: POINTER @@ -20258,6 +20278,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x9095e0a9 } +pointer_reference { + id: 0x2eb6a848 + kind: POINTER + pointee_type_id: 0x909a47bd +} pointer_reference { id: 0x2eb6ced9 kind: POINTER @@ -23593,6 +23618,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xe32fa2b6 } +pointer_reference { + id: 0x32618dc6 + kind: POINTER + pointee_type_id: 0xe3c6d185 +} pointer_reference { id: 0x326663cd kind: POINTER @@ -23738,6 +23768,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xe08cc03f } +pointer_reference { + id: 0x32b472a5 + kind: POINTER + pointee_type_id: 0xe0912c08 +} pointer_reference { id: 0x32b54b11 kind: POINTER @@ -24443,6 +24478,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xfa0fa371 } +pointer_reference { + id: 0x3417d991 + kind: POINTER + pointee_type_id: 0xfa1f80d8 +} pointer_reference { id: 0x34192ccc kind: POINTER @@ -24713,6 +24753,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf87d4486 } +pointer_reference { + id: 0x348f7ef2 + kind: POINTER + pointee_type_id: 0xf87d1d57 +} pointer_reference { id: 0x348f9528 kind: POINTER @@ -25543,6 +25588,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf34f7202 } +pointer_reference { + id: 0x364a10f4 + kind: POINTER + pointee_type_id: 0xf368a54d +} pointer_reference { id: 0x364efcf0 kind: POINTER @@ -25608,6 +25658,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf39c3f1e } +pointer_reference { + id: 0x367f8642 + kind: POINTER + pointee_type_id: 0xf3beff96 +} pointer_reference { id: 0x36841126 kind: POINTER @@ -26238,6 +26293,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf4a306a1 } +pointer_reference { + id: 0x37c0c175 + kind: POINTER + pointee_type_id: 0xf543e34b +} pointer_reference { id: 0x37c1fe6c kind: POINTER @@ -26443,6 +26503,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xca7029d8 } +pointer_reference { + id: 0x3812c788 + kind: POINTER + pointee_type_id: 0xca0bf8bc +} pointer_reference { id: 0x381472e2 kind: POINTER @@ -26793,6 +26858,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xc94d23ab } +pointer_reference { + id: 0x38c3d772 + kind: POINTER + pointee_type_id: 0xc94fbb56 +} pointer_reference { id: 0x38c5be1f kind: POINTER @@ -27573,6 +27643,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xc035887a } +pointer_reference { + id: 0x3aa533cf + kind: POINTER + pointee_type_id: 0xc0d429a1 +} pointer_reference { id: 0x3aac87ab kind: POINTER @@ -28533,6 +28608,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xd920878f } +pointer_reference { + id: 0x3cdda08b + kind: POINTER + pointee_type_id: 0xd93664b2 +} pointer_reference { id: 0x3ce1bbd3 kind: POINTER @@ -29098,6 +29178,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xd23047c9 } +pointer_reference { + id: 0x3e21070b + kind: POINTER + pointee_type_id: 0xd2c4fab2 +} pointer_reference { id: 0x3e279e0a kind: POINTER @@ -29478,6 +29563,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xd66432be } +pointer_reference { + id: 0x3f09383b + kind: POINTER + pointee_type_id: 0xd6640671 +} pointer_reference { id: 0x3f095459 kind: POINTER @@ -32238,6 +32328,11 @@ qualified { qualifier: CONST qualified_type_id: 0x72ec8660 } +qualified { + id: 0xc0d429a1 + qualifier: CONST + qualified_type_id: 0x7317100c +} qualified { id: 0xc12aa3e6 qualifier: CONST @@ -32658,6 +32753,11 @@ qualified { qualifier: CONST qualified_type_id: 0x55733825 } +qualified { + id: 0xc94fbb56 + qualifier: CONST + qualified_type_id: 0x55795bd3 +} qualified { id: 0xc97bedb7 qualifier: CONST @@ -32673,6 +32773,11 @@ qualified { qualifier: CONST qualified_type_id: 0x5786c646 } +qualified { + id: 0xca0bf8bc + qualifier: CONST + qualified_type_id: 0x58685478 +} qualified { id: 0xca2c0eb3 qualifier: CONST @@ -33208,6 +33313,11 @@ qualified { qualifier: CONST qualified_type_id: 0x399c459b } +qualified { + id: 0xd2c4fab2 + qualifier: CONST + qualified_type_id: 0x3b545c43 +} qualified { id: 0xd2d7132a qualifier: CONST @@ -33368,6 +33478,11 @@ qualified { qualifier: CONST qualified_type_id: 0x29600806 } +qualified { + id: 0xd6640671 + qualifier: CONST + qualified_type_id: 0x29d7af4d +} qualified { id: 0xd66432be qualifier: CONST @@ -33518,6 +33633,11 @@ qualified { qualifier: CONST qualified_type_id: 0x13b5a562 } +qualified { + id: 0xd93664b2 + qualifier: CONST + qualified_type_id: 0x149e2442 +} qualified { id: 0xd957a3fb qualifier: CONST @@ -33978,6 +34098,11 @@ qualified { qualifier: CONST qualified_type_id: 0xf274b676 } +qualified { + id: 0xe0912c08 + qualifier: CONST + qualified_type_id: 0xf20306a8 +} qualified { id: 0xe095cad8 qualifier: CONST @@ -34978,6 +35103,11 @@ qualified { qualifier: CONST qualified_type_id: 0xbd7a7e80 } +qualified { + id: 0xf368a54d + qualifier: CONST + qualified_type_id: 0xbde523bd +} qualified { id: 0xf39072f0 qualifier: CONST @@ -35243,6 +35373,11 @@ qualified { qualifier: CONST qualified_type_id: 0x91b5a647 } +qualified { + id: 0xf87d1d57 + qualifier: CONST + qualified_type_id: 0x91b3c3d5 +} qualified { id: 0xf87f5460 qualifier: CONST @@ -40461,6 +40596,11 @@ member { type_id: 0x56037e9c offset: 1408 } +member { + id: 0x36707bb7 + type_id: 0x56efb9c6 + offset: 128 +} member { id: 0x36752018 type_id: 0x56faddc1 @@ -45484,6 +45624,12 @@ member { type_id: 0x2dd03fae offset: 320 } +member { + id: 0xd7bdfbb1 + name: "aggregate" + type_id: 0x2dd03fae + offset: 64 +} member { id: 0x9b642e7a name: "ah_ip4_spec" @@ -50407,6 +50553,12 @@ member { type_id: 0xe62ebf07 offset: 32 } +member { + id: 0xd3de74cf + name: "atom_size" + type_id: 0x4585663f + offset: 256 +} member { id: 0x176dead7 name: "atomic" @@ -53379,6 +53531,12 @@ member { type_id: 0xe04f9dc7 offset: 704 } +member { + id: 0xbc613338 + name: "bcast_ch_regs" + type_id: 0x18bd6530 + offset: 256 +} member { id: 0x638c2bea name: "bcdCDC" @@ -54427,6 +54585,18 @@ member { type_id: 0x295c7202 offset: 40 } +member { + id: 0x13de4517 + name: "bit" + type_id: 0x4585663f + offset: 224 +} +member { + id: 0x13de4b08 + name: "bit" + type_id: 0x4585663f + offset: 32 +} member { id: 0xdd1aee2e name: "bit_count" @@ -55004,6 +55174,12 @@ member { type_id: 0xe8034002 offset: 13456 } +member { + id: 0x9728511c + name: "block_dma" + type_id: 0x2eb6a848 + offset: 128 +} member { id: 0xecca238a name: "block_h" @@ -60665,6 +60841,12 @@ member { type_id: 0xe62ebf07 offset: 32 } +member { + id: 0x20f935a9 + name: "ch_intmask" + type_id: 0xc9082b19 + offset: 416 +} member { id: 0x2054ca12 name: "ch_mode" @@ -60677,6 +60859,12 @@ member { type_id: 0xe62ebf07 offset: 64 } +member { + id: 0x46f26d43 + name: "ch_regs" + type_id: 0x0cbf60eb + offset: 320 +} member { id: 0x152992ef name: "chain" @@ -62696,6 +62884,12 @@ member { type_id: 0x18bd6530 offset: 3456 } +member { + id: 0x685f31a0 + name: "client_id_mask" + type_id: 0x914dbfdc + offset: 288 +} member { id: 0xf4c5928f name: "client_list" @@ -62720,6 +62914,11 @@ member { type_id: 0xa7c362b0 offset: 2432 } +member { + id: 0x1b57faed + name: "clients" + type_id: 0x38c3d772 +} member { id: 0x1bbcf6b9 name: "clients" @@ -62779,6 +62978,12 @@ member { name: "clk" type_id: 0x3dcee85d } +member { + id: 0xc8e82903 + name: "clk" + type_id: 0x3dcee85d + offset: 384 +} member { id: 0xc8e82c70 name: "clk" @@ -66636,6 +66841,12 @@ member { type_id: 0x0baa70a7 offset: 96 } +member { + id: 0xfc79e947 + name: "control" + type_id: 0x4585663f + offset: 128 +} member { id: 0xfcf56dc8 name: "control" @@ -72778,6 +72989,12 @@ member { type_id: 0x03913382 offset: 62528 } +member { + id: 0x1c1be12d + name: "debugfs" + type_id: 0x3c9f0fa2 + offset: 2368 +} member { id: 0x1c35735f name: "debugfs" @@ -73125,6 +73342,12 @@ member { type_id: 0x4585663f offset: 32 } +member { + id: 0xea7685d3 + name: "def" + type_id: 0x4585663f + offset: 96 +} member { id: 0xffdeb7b9 name: "def_br_lsto" @@ -78953,6 +79176,12 @@ member { type_id: 0xf435685e offset: 19264 } +member { + id: 0x4c6d670f + name: "dma_idling" + type_id: 0x367f8642 + offset: 192 +} member { id: 0xf4c016ce name: "dma_io_tlb_mem" @@ -82950,6 +83179,18 @@ member { type_id: 0x295c7202 offset: 11912 } +member { + id: 0x321ff48e + name: "emem_data" + type_id: 0x38d23361 + offset: 64 +} +member { + id: 0x4ffc68c3 + name: "emem_regs" + type_id: 0x3ea31487 + offset: 128 +} member { id: 0xfcf1c4f6 name: "emin" @@ -89810,6 +90051,12 @@ member { type_id: 0x0e5445cf offset: 640 } +member { + id: 0xf67ca58b + name: "fifo_size" + type_id: 0x4585663f + offset: 160 +} member { id: 0xf67ca8c0 name: "fifo_size" @@ -96167,6 +96414,12 @@ member { type_id: 0x295c7202 offset: 1080 } +member { + id: 0xf5682334 + name: "gart" + type_id: 0x1cba6ba2 + offset: 128 +} member { id: 0x16b7aef5 name: "gate" @@ -98584,6 +98837,12 @@ member { type_id: 0x49a73111 offset: 2304 } +member { + id: 0x7fbcccea + name: "global_intstatus_channel_shift" + type_id: 0xc9082b19 + offset: 448 +} member { id: 0x88f8622b name: "global_l" @@ -99290,6 +99549,12 @@ member { type_id: 0x3776a166 offset: 128 } +member { + id: 0x933b8dad + name: "groups" + type_id: 0x3cdda08b + offset: 256 +} member { id: 0x9342d5c0 name: "groups" @@ -99721,6 +99986,12 @@ member { type_id: 0x2dfb782b offset: 960 } +member { + id: 0x72a70f4f + name: "handle_irq" + type_id: 0x044ba8c8 + offset: 256 +} member { id: 0x33f92e8a name: "handle_kick" @@ -99998,6 +100269,12 @@ member { type_id: 0x2c494e22 offset: 192 } +member { + id: 0x3ec0be10 + name: "has_addr_hi_reg" + type_id: 0x6d7f5ff6 + offset: 480 +} member { id: 0xeee91e70 name: "has_alpha" @@ -102686,6 +102963,17 @@ member { type_id: 0xdba44af3 offset: 26944 } +member { + id: 0x2ff7d481 + name: "hotreset_assert" + type_id: 0x2eb6a848 +} +member { + id: 0xb245cfae + name: "hotreset_deassert" + type_id: 0x2eb6a848 + offset: 64 +} member { id: 0x354661e5 name: "hour" @@ -104620,6 +104908,12 @@ member { offset: 416 bitsize: 1 } +member { + id: 0x0c93d7b1 + name: "icc_ops" + type_id: 0x3e21070b + offset: 704 +} member { id: 0x9dfcef2c name: "icc_paths" @@ -105072,6 +105366,12 @@ member { type_id: 0x37145079 offset: 1608 } +member { + id: 0xcc1c5d14 + name: "id" + type_id: 0x33756485 + offset: 64 +} member { id: 0xcc248bda name: "id" @@ -110149,6 +110449,12 @@ member { type_id: 0x3ae3ff84 offset: 1088 } +member { + id: 0x1b9b6526 + name: "intmask" + type_id: 0xc9082b19 + offset: 384 +} member { id: 0x5dfd62b5 name: "intr_cmd" @@ -111810,6 +112116,12 @@ member { type_id: 0x6720d32f offset: 320 } +member { + id: 0x99159291 + name: "irq" + type_id: 0x6720d32f + offset: 448 +} member { id: 0x99159514 name: "irq" @@ -115398,6 +115710,12 @@ member { type_id: 0xb3e7bac9 offset: 296 } +member { + id: 0x1713d000 + name: "la" + type_id: 0x1ba1b239 + offset: 64 +} member { id: 0xbe79d648 name: "la_mask" @@ -119901,6 +120219,12 @@ member { type_id: 0xf313e71a offset: 320 } +member { + id: 0x2d1feb8e + name: "lock" + type_id: 0xf313e71a + offset: 2304 +} member { id: 0x2d1feb9a name: "lock" @@ -139222,6 +139546,12 @@ member { type_id: 0x33756485 offset: 704 } +member { + id: 0x4b9a0804 + name: "num_address_bits" + type_id: 0x4585663f + offset: 224 +} member { id: 0x4b1eeeac name: "num_agents" @@ -139263,6 +139593,12 @@ member { type_id: 0xc9082b19 offset: 128 } +member { + id: 0x29605801 + name: "num_asids" + type_id: 0x4585663f + offset: 416 +} member { id: 0x4a3e96b6 name: "num_auto_selectable_formats" @@ -139376,6 +139712,12 @@ member { type_id: 0x6720d32f offset: 8384 } +member { + id: 0x5fe2c2d5 + name: "num_channels" + type_id: 0x295c7202 + offset: 304 +} member { id: 0xc21eb7ca name: "num_chans" @@ -139400,6 +139742,12 @@ member { type_id: 0x914dbfdc offset: 7440 } +member { + id: 0xe6531f76 + name: "num_clients" + type_id: 0x4585663f + offset: 64 +} member { id: 0x1c9b1176 name: "num_clips" @@ -139638,6 +139986,12 @@ member { type_id: 0x0baa70a7 offset: 64 } +member { + id: 0x8f1bb1bf + name: "num_emem_regs" + type_id: 0x4585663f + offset: 192 +} member { id: 0x4a422b42 name: "num_encoder" @@ -139799,6 +140153,12 @@ member { type_id: 0x4585663f offset: 448 } +member { + id: 0x1eceb58f + name: "num_groups" + type_id: 0x4585663f + offset: 320 +} member { id: 0x0a575aaf name: "num_h_tile" @@ -140448,6 +140808,12 @@ member { type_id: 0x4585663f offset: 384 } +member { + id: 0xfe804b5a + name: "num_resets" + type_id: 0x4585663f + offset: 640 +} member { id: 0xdc465f86 name: "num_resources" @@ -140658,6 +141024,18 @@ member { type_id: 0x4585663f offset: 192 } +member { + id: 0x3a29648c + name: "num_swgroups" + type_id: 0x4585663f + offset: 192 +} +member { + id: 0x3a296587 + name: "num_swgroups" + type_id: 0x4585663f + offset: 128 +} member { id: 0x313aeebb name: "num_syms" @@ -140724,6 +141102,18 @@ member { name: "num_timings" type_id: 0x4585663f } +member { + id: 0x349422f9 + name: "num_timings" + type_id: 0x4585663f + offset: 704 +} +member { + id: 0xb021dbba + name: "num_tlb_lines" + type_id: 0x4585663f + offset: 384 +} member { id: 0x8026d50a name: "num_total_plane" @@ -143550,6 +143940,12 @@ member { name: "ops" type_id: 0x326a19f7 } +member { + id: 0xafb9bc7f + name: "ops" + type_id: 0x32b472a5 + offset: 768 +} member { id: 0xafb9c47f name: "ops" @@ -144793,6 +145189,11 @@ member { type_id: 0x6720d32f offset: 288 } +member { + id: 0xd2c76e4c + name: "override" + type_id: 0x4585663f +} member { id: 0xb4e4bcf1 name: "override_edid" @@ -155810,6 +156211,11 @@ member { type_id: 0x2e7404d6 offset: 128 } +member { + id: 0xd7788f3a + name: "probe" + type_id: 0x2e8c0d7b +} member { id: 0xd778c72d name: "probe" @@ -155965,6 +156371,12 @@ member { type_id: 0x3daf8dd1 offset: 128 } +member { + id: 0xe5f24cd0 + name: "probe_device" + type_id: 0x2e8e5582 + offset: 320 +} member { id: 0xf6b66ca8 name: "probe_finalize" @@ -157289,6 +157701,12 @@ member { type_id: 0x32c23ae3 offset: 256 } +member { + id: 0x86b9fc17 + name: "provider" + type_id: 0xe1480d10 + offset: 1472 +} member { id: 0xa159a1de name: "provider_data" @@ -163364,6 +163782,12 @@ member { type_id: 0x4585663f offset: 128 } +member { + id: 0x0f050edd + name: "reg" + type_id: 0x4585663f + offset: 96 +} member { id: 0x0f27a2eb name: "reg" @@ -164007,12 +164431,24 @@ member { name: "regs" type_id: 0x34def0b7 } +member { + id: 0x8011b26a + name: "regs" + type_id: 0x2accfd18 + offset: 192 +} member { id: 0x8023c171 name: "regs" type_id: 0x18bd6530 offset: 3456 } +member { + id: 0x8023c3f2 + name: "regs" + type_id: 0x18bd6530 + offset: 192 +} member { id: 0x8023cc24 name: "regs" @@ -164979,6 +165415,12 @@ member { name: "remove" type_id: 0x0dd7b940 } +member { + id: 0xb4ae1e7a + name: "remove" + type_id: 0x0dca21d4 + offset: 64 +} member { id: 0xb4ae4933 name: "remove" @@ -167136,6 +167578,12 @@ member { type_id: 0xb3e7bac9 offset: 216 } +member { + id: 0x621c7011 + name: "reset" + type_id: 0xa1d6f6c0 + offset: 768 +} member { id: 0x6290827d name: "reset" @@ -167265,6 +167713,12 @@ member { type_id: 0x6d7f5ff6 offset: 512 } +member { + id: 0x62f823e6 + name: "reset" + type_id: 0x4585663f + offset: 192 +} member { id: 0x147cd330 name: "reset_assert_delay" @@ -167380,6 +167834,12 @@ member { type_id: 0x0d9c4ffe offset: 256 } +member { + id: 0x69014681 + name: "reset_ops" + type_id: 0x364a10f4 + offset: 512 +} member { id: 0x98c83941 name: "reset_pending" @@ -167441,6 +167901,12 @@ member { type_id: 0x2ced3956 offset: 512 } +member { + id: 0x4d689b1d + name: "reset_status" + type_id: 0x2eb6a848 + offset: 320 +} member { id: 0xf24ab676 name: "reset_system" @@ -167477,6 +167943,12 @@ member { type_id: 0x1f3c8679 offset: 7744 } +member { + id: 0x54c3a704 + name: "resets" + type_id: 0x3aa533cf + offset: 576 +} member { id: 0x4381fffc name: "resetting_device" @@ -168036,6 +168508,12 @@ member { type_id: 0x2ee76b64 offset: 2240 } +member { + id: 0xcab164a8 + name: "resume" + type_id: 0x2e8c0d7b + offset: 192 +} member { id: 0xcab17152 name: "resume" @@ -169245,6 +169723,11 @@ member { type_id: 0x120540d1 offset: 640 } +member { + id: 0x93cd2de4 + name: "root" + type_id: 0x120540d1 +} member { id: 0x93d246f9 name: "root" @@ -174917,6 +175400,12 @@ member { type_id: 0x18bd6530 offset: 7680 } +member { + id: 0xf1c9d4d6 + name: "security" + type_id: 0x4585663f + offset: 32 +} member { id: 0xad84e518 name: "security_cfm" @@ -176281,6 +176770,11 @@ member { type_id: 0x2d1b3b77 offset: 256 } +member { + id: 0x3df35bca + name: "set" + type_id: 0x2d1b3b77 +} member { id: 0x8fd22bb3 name: "set_ackreq_default" @@ -179439,12 +179933,23 @@ member { type_id: 0xd3c80119 offset: 64 } +member { + id: 0x081eac68 + name: "sid" + type_id: 0x2ce1ed3d + offset: 192 +} member { id: 0x086ca956 name: "sid" type_id: 0x5eeb4a25 offset: 1472 } +member { + id: 0x0877c02a + name: "sid" + type_id: 0x4585663f +} member { id: 0x08a308f3 name: "sid" @@ -182014,6 +182519,23 @@ member { type_id: 0x2e0f9112 offset: 384 } +member { + id: 0xca95fcc2 + name: "smmu" + type_id: 0x1ba9f29e +} +member { + id: 0xcab15bcf + name: "smmu" + type_id: 0x3f09383b + offset: 320 +} +member { + id: 0xcabc305c + name: "smmu" + type_id: 0x32618dc6 + offset: 64 +} member { id: 0x0c1eb745 name: "smp" @@ -182273,6 +182795,12 @@ member { type_id: 0xe62ebf07 offset: 32 } +member { + id: 0xb0492744 + name: "soc" + type_id: 0x348f7ef2 + offset: 512 +} member { id: 0x3de92190 name: "soc_dev_num" @@ -186146,6 +186674,12 @@ member { type_id: 0x4585663f offset: 1248 } +member { + id: 0x2022af02 + name: "status" + type_id: 0x4585663f + offset: 160 +} member { id: 0x2027a418 name: "status" @@ -188171,6 +188705,12 @@ member { type_id: 0x3500e23a offset: 64 } +member { + id: 0x009679b8 + name: "supports_request_limit" + type_id: 0x6d7f5ff6 + offset: 360 +} member { id: 0x065dd0db name: "supports_requests" @@ -188178,6 +188718,12 @@ member { offset: 197 bitsize: 1 } +member { + id: 0xe739cbf3 + name: "supports_round_robin_arbitration" + type_id: 0x6d7f5ff6 + offset: 352 +} member { id: 0x505b26be name: "suppress" @@ -188256,6 +188802,12 @@ member { type_id: 0x2e9195ef offset: 192 } +member { + id: 0xf39453f6 + name: "suspend" + type_id: 0x2e8c0d7b + offset: 128 +} member { id: 0xf394d5ee name: "suspend" @@ -188940,6 +189492,29 @@ member { type_id: 0xb914bfab offset: 1600 } +member { + id: 0x005de33e + name: "swgroup" + type_id: 0x4585663f + offset: 64 +} +member { + id: 0x005de7df + name: "swgroup" + type_id: 0x4585663f +} +member { + id: 0x3f043e5d + name: "swgroups" + type_id: 0x3812c788 + offset: 128 +} +member { + id: 0x3f05edad + name: "swgroups" + type_id: 0x39cc14ac + offset: 64 +} member { id: 0x0bc9608d name: "switch_id" @@ -193028,6 +193603,12 @@ member { type_id: 0x3df0a7d3 offset: 128 } +member { + id: 0xe87350be + name: "tick" + type_id: 0x33756485 + offset: 576 +} member { id: 0xe879699b name: "tick" @@ -193953,6 +194534,12 @@ member { type_id: 0x3ebb35fd offset: 1280 } +member { + id: 0x1f6d9836 + name: "timings" + type_id: 0x3417d991 + offset: 640 +} member { id: 0x1fa42388 name: "timings" @@ -200656,6 +201243,12 @@ member { type_id: 0x0eb62dc3 offset: 320 } +member { + id: 0xea5b0b9a + name: "unblock_dma" + type_id: 0x2eb6a848 + offset: 256 +} member { id: 0x5c7ec059 name: "unbound_attrs" @@ -210788,6 +211381,12 @@ member { type_id: 0x01d9df85 offset: 576 } +member { + id: 0x0b59f1cd + name: "xlate_extended" + type_id: 0x01d9df85 + offset: 128 +} member { id: 0xee360321 name: "xlate_tdm_slot_mask" @@ -213434,6 +214033,26 @@ struct_union { member_id: 0xf5eb6708 } } +struct_union { + id: 0x1ba1b239 + kind: STRUCT + definition { + bytesize: 16 + member_id: 0x0f05075e + member_id: 0x3274483b + member_id: 0xa876e8aa + member_id: 0xea7685d3 + } +} +struct_union { + id: 0x1ba9f29e + kind: STRUCT + definition { + bytesize: 8 + member_id: 0x0f05075e + member_id: 0x13de4b08 + } +} struct_union { id: 0x1c07f73e kind: STRUCT @@ -214101,6 +214720,16 @@ struct_union { member_id: 0x642f0821 } } +struct_union { + id: 0x2accfd18 + kind: STRUCT + definition { + bytesize: 32 + member_id: 0xca95fcc2 + member_id: 0x1713d000 + member_id: 0x081eac68 + } +} struct_union { id: 0x2b189f72 kind: STRUCT @@ -214212,6 +214841,15 @@ struct_union { member_id: 0x3e7e5067 } } +struct_union { + id: 0x2ce1ed3d + kind: STRUCT + definition { + bytesize: 8 + member_id: 0xd2c76e4c + member_id: 0xf1c9d4d6 + } +} struct_union { id: 0x2d07e8c3 kind: STRUCT @@ -215047,6 +215685,14 @@ struct_union { member_id: 0xc101e64f } } +struct_union { + id: 0x3c9f0fa2 + kind: STRUCT + definition { + bytesize: 8 + member_id: 0x93cd2de4 + } +} struct_union { id: 0x3ce2dc79 kind: STRUCT @@ -216375,6 +217021,15 @@ struct_union { member_id: 0x4380fca4 } } +struct_union { + id: 0x56efb9c6 + kind: UNION + definition { + bytesize: 4 + member_id: 0x005de7df + member_id: 0x0877c02a + } +} struct_union { id: 0x56faddc1 kind: UNION @@ -234649,6 +235304,11 @@ struct_union { member_id: 0x34fb052c } } +struct_union { + id: 0x58a94817 + kind: STRUCT + name: "gart_device" +} struct_union { id: 0x78ef929d kind: STRUCT @@ -262972,6 +263632,177 @@ struct_union { member_id: 0x08c59955 } } +struct_union { + id: 0xf543e34b + kind: STRUCT + name: "tegra_mc" + definition { + bytesize: 304 + member_id: 0xce3bbab3 + member_id: 0xcabc305c + member_id: 0xf5682334 + member_id: 0x8023c3f2 + member_id: 0xbc613338 + member_id: 0x46f26d43 + member_id: 0xc8e82903 + member_id: 0x99159291 + member_id: 0xb0492744 + member_id: 0xe87350be + member_id: 0x1f6d9836 + member_id: 0x349422f9 + member_id: 0x621c7011 + member_id: 0x86b9fc17 + member_id: 0x2d1feb8e + member_id: 0x1c1be12d + } +} +struct_union { + id: 0x55795bd3 + kind: STRUCT + name: "tegra_mc_client" + definition { + bytesize: 56 + member_id: 0xcc6aa9f7 + member_id: 0x0de57809 + member_id: 0x36707bb7 + member_id: 0xf67ca58b + member_id: 0x8011b26a + } +} +struct_union { + id: 0x3b545c43 + kind: STRUCT + name: "tegra_mc_icc_ops" + definition { + bytesize: 24 + member_id: 0x3df35bca + member_id: 0xd7bdfbb1 + member_id: 0x0b59f1cd + } +} +struct_union { + id: 0xf20306a8 + kind: STRUCT + name: "tegra_mc_ops" + definition { + bytesize: 48 + member_id: 0xd7788f3a + member_id: 0xb4ae1e7a + member_id: 0xf39453f6 + member_id: 0xcab164a8 + member_id: 0x72a70f4f + member_id: 0xe5f24cd0 + } +} +struct_union { + id: 0x7317100c + kind: STRUCT + name: "tegra_mc_reset" + definition { + bytesize: 32 + member_id: 0x0de57ce8 + member_id: 0xcc1c5d14 + member_id: 0xfc79e947 + member_id: 0x2022af02 + member_id: 0x62f823e6 + member_id: 0x13de4517 + } +} +struct_union { + id: 0xbde523bd + kind: STRUCT + name: "tegra_mc_reset_ops" + definition { + bytesize: 48 + member_id: 0x2ff7d481 + member_id: 0xb245cfae + member_id: 0x9728511c + member_id: 0x4c6d670f + member_id: 0xea5b0b9a + member_id: 0x4d689b1d + } +} +struct_union { + id: 0x91b3c3d5 + kind: STRUCT + name: "tegra_mc_soc" + definition { + bytesize: 104 + member_id: 0x1b57faed + member_id: 0xe6531f76 + member_id: 0x4ffc68c3 + member_id: 0x8f1bb1bf + member_id: 0x4b9a0804 + member_id: 0xd3de74cf + member_id: 0x685f31a0 + member_id: 0x5fe2c2d5 + member_id: 0xcab15bcf + member_id: 0x1b9b6526 + member_id: 0x20f935a9 + member_id: 0x7fbcccea + member_id: 0x3ec0be10 + member_id: 0x69014681 + member_id: 0x54c3a704 + member_id: 0xfe804b5a + member_id: 0x0c93d7b1 + member_id: 0xafb9bc7f + } +} +struct_union { + id: 0xfa1f80d8 + kind: STRUCT + name: "tegra_mc_timing" + definition { + bytesize: 16 + member_id: 0x5fe1279a + member_id: 0x321ff48e + } +} +struct_union { + id: 0xe3c6d185 + kind: STRUCT + name: "tegra_smmu" +} +struct_union { + id: 0x149e2442 + kind: STRUCT + name: "tegra_smmu_group_soc" + definition { + bytesize: 24 + member_id: 0x0de57ce8 + member_id: 0x3f05edad + member_id: 0x3a296587 + } +} +struct_union { + id: 0x29d7af4d + kind: STRUCT + name: "tegra_smmu_soc" + definition { + bytesize: 56 + member_id: 0x1b57faed + member_id: 0xe6531f76 + member_id: 0x3f043e5d + member_id: 0x3a29648c + member_id: 0x933b8dad + member_id: 0x1eceb58f + member_id: 0xe739cbf3 + member_id: 0x009679b8 + member_id: 0xb021dbba + member_id: 0x29605801 + } +} +struct_union { + id: 0x58685478 + kind: STRUCT + name: "tegra_smmu_swgroup" + definition { + bytesize: 16 + member_id: 0x0de57ce8 + member_id: 0x005de33e + member_id: 0x0f050edd + } +} struct_union { id: 0x6a268aa0 kind: STRUCT @@ -301359,6 +302190,11 @@ function { parameter_id: 0x1d44326e parameter_id: 0xf1a6dfed } +function { + id: 0x1d6861ce + return_type_id: 0x48b5725f + parameter_id: 0x37c0c175 +} function { id: 0x1d6aeee7 return_type_id: 0x48b5725f @@ -303687,6 +304523,11 @@ function { parameter_id: 0xfc0e1dbd parameter_id: 0x01222f7d } +function { + id: 0x2195423c + return_type_id: 0x37c0c175 + parameter_id: 0x0258f96e +} function { id: 0x21a7fa19 return_type_id: 0x145f7b00 @@ -310235,6 +311076,11 @@ function { parameter_id: 0x36337082 parameter_id: 0x18bd6530 } +function { + id: 0x9070d372 + return_type_id: 0x6720d32f + parameter_id: 0x37c0c175 +} function { id: 0x907109f8 return_type_id: 0x6720d32f @@ -310298,6 +311144,12 @@ function { parameter_id: 0x3aff5796 parameter_id: 0x0258f96e } +function { + id: 0x9079b097 + return_type_id: 0x6720d32f + parameter_id: 0x37c0c175 + parameter_id: 0x0258f96e +} function { id: 0x908495c3 return_type_id: 0x6720d32f @@ -310428,6 +311280,12 @@ function { parameter_id: 0xe8034002 parameter_id: 0xe8034002 } +function { + id: 0x909a47bd + return_type_id: 0x6720d32f + parameter_id: 0x37c0c175 + parameter_id: 0x3aa533cf +} function { id: 0x909bddf8 return_type_id: 0x6720d32f @@ -336643,6 +337501,12 @@ function { return_type_id: 0x6d7f5ff6 parameter_id: 0x347303b4 } +function { + id: 0xf3beff96 + return_type_id: 0x6d7f5ff6 + parameter_id: 0x37c0c175 + parameter_id: 0x3aa533cf +} function { id: 0xf3c9c4ce return_type_id: 0xeb0f6de6 @@ -361025,6 +361889,15 @@ elf_symbol { type_id: 0x9d15ab3e full_name: "devm_spi_register_controller" } +elf_symbol { + id: 0x43a4025b + name: "devm_tegra_memory_controller_get" + is_defined: true + symbol_type: FUNCTION + crc: 0x986b8e36 + type_id: 0x2195423c + full_name: "devm_tegra_memory_controller_get" +} elf_symbol { id: 0x0dd13028 name: "devm_thermal_of_cooling_device_register" @@ -398780,6 +399653,15 @@ elf_symbol { type_id: 0x129c1f38 full_name: "tcpm_vbus_change" } +elf_symbol { + id: 0xa8f0fe44 + name: "tegra_mc_probe_device" + is_defined: true + symbol_type: FUNCTION + crc: 0x3f100eaf + type_id: 0x9079b097 + full_name: "tegra_mc_probe_device" +} elf_symbol { id: 0x7cfd9233 name: "teo_cpu_get_util_threshold" @@ -411077,6 +411959,7 @@ interface { symbol_id: 0xd1252dfa symbol_id: 0xf3c9734f symbol_id: 0x6c9a6915 + symbol_id: 0x43a4025b symbol_id: 0x0dd13028 symbol_id: 0xfc46114a symbol_id: 0x5dc64161 @@ -415270,6 +416153,7 @@ interface { symbol_id: 0xfccd15d1 symbol_id: 0x591431f1 symbol_id: 0x6869c83d + symbol_id: 0xa8f0fe44 symbol_id: 0x7cfd9233 symbol_id: 0xbd25c7d0 symbol_id: 0x5bbd3545 diff --git a/android/abi_gki_aarch64_db845c b/android/abi_gki_aarch64_db845c index 9c68b5d9188b..2345a4ad62c8 100644 --- a/android/abi_gki_aarch64_db845c +++ b/android/abi_gki_aarch64_db845c @@ -864,6 +864,7 @@ device_get_dma_attr device_match_fwnode devm_krealloc + devm_tegra_memory_controller_get driver_find_device generic_device_group iommu_alloc_resv_region @@ -880,6 +881,7 @@ pci_device_group platform_irq_count report_iommu_fault + tegra_mc_probe_device # required by ath10k_core.ko cpu_latency_qos_add_request From 92704e00b599b6bd40fb70adef7f8c1b402a2faf Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Tue, 14 May 2024 17:08:50 +0000 Subject: [PATCH 45/46] ANDROID: GKI: add tegra20-cpufreq.ko to rockpi4 build Enabling configs for Tegra SoCs required this module to be included in the rockpi4 builds. This change fixes the following build issue: ERROR: The following kernel modules are built but not copied. Add these lines to the module_outs attribute of @@//common:rockpi4_no_kgdb: "drivers/cpufreq/tegra20-cpufreq.ko", Bug: 335325897 Change-Id: I898000725287f34956cb977b3b02685f189cd5a0 Signed-off-by: Carlos Llamas --- BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.bazel b/BUILD.bazel index ac91e68acde6..36dd531b3295 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -586,6 +586,7 @@ _ROCKPI4_MODULE_OUTS = [ "drivers/char/hw_random/virtio-rng.ko", "drivers/clk/clk-rk808.ko", "drivers/cpufreq/cpufreq-dt.ko", + "drivers/cpufreq/tegra20-cpufreq.ko", "drivers/dma/pl330.ko", "drivers/gpu/drm/bridge/analogix/analogix_dp.ko", "drivers/gpu/drm/bridge/synopsys/dw-hdmi.ko", From 74c507aab139d670556720134268dc6cdff6daa7 Mon Sep 17 00:00:00 2001 From: Roy Luo Date: Thu, 7 Mar 2024 03:09:22 +0000 Subject: [PATCH 46/46] UPSTREAM: USB: gadget: core: create sysfs link between udc and gadget udc device and gadget device are tightly coupled, yet there's no good way to corelate the two. Add a sysfs link in udc that points to the corresponding gadget device. An example use case: userspace configures a f_midi configfs driver and bind the udc device, then it tries to locate the corresponding midi device, which is a child device of the gadget device. The gadget device that's associated to the udc device has to be identified in order to index the midi device. Having a sysfs link would make things much easier. Signed-off-by: Roy Luo Link: https://lore.kernel.org/r/20240307030922.3573161-1-royluo@google.com Signed-off-by: Greg Kroah-Hartman Bug: 333778731 Change-Id: I9e3f782543eba5e026a65031aaae754daafb69ab (cherry picked from commit 0ef40f399aa2be8c04aee9b7430705612c104ce5) Signed-off-by: Roy Luo --- drivers/usb/gadget/udc/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 1f56b770465e..369767534006 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1392,8 +1392,16 @@ int usb_add_gadget(struct usb_gadget *gadget) if (ret) goto err_free_id; + ret = sysfs_create_link(&udc->dev.kobj, + &gadget->dev.kobj, "gadget"); + if (ret) + goto err_del_gadget; + return 0; + err_del_gadget: + device_del(&gadget->dev); + err_free_id: ida_free(&gadget_id_numbers, gadget->id_number); @@ -1502,6 +1510,7 @@ void usb_del_gadget(struct usb_gadget *gadget) mutex_unlock(&udc_lock); kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); + sysfs_remove_link(&udc->dev.kobj, "gadget"); flush_work(&gadget->work); device_del(&gadget->dev); ida_free(&gadget_id_numbers, gadget->id_number);