diff --git a/arch/arm64/configs/vendor/lahaina_debug.config b/arch/arm64/configs/vendor/lahaina_debug.config index 5c4e6997067e..4661a42fb3f7 100644 --- a/arch/arm64/configs/vendor/lahaina_debug.config +++ b/arch/arm64/configs/vendor/lahaina_debug.config @@ -10,6 +10,7 @@ CONFIG_DEBUG_PAGEALLOC=y CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y CONFIG_PAGE_POISONING=y CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y +CONFIG_PAGE_EXTENSION_PAGE_FREE=y # CONFIG_DEBUG_DMA_BUF_REF is not set # CONFIG_PAGE_POISONING_NO_SANITY is not set # CONFIG_PAGE_POISONING_ZERO is not set diff --git a/include/linux/oom.h b/include/linux/oom.h index 40862dd4f223..c880273c6199 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -130,4 +130,6 @@ extern int sysctl_reap_mem_on_sigkill; /* calls for LMK reaper */ extern void add_to_oom_reaper(struct task_struct *p); +extern void check_panic_on_foreground_kill(struct task_struct *p); +#define ULMK_MAGIC "lmkd" #endif /* _INCLUDE_LINUX_OOM_H */ diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h index cfce186f0c4e..e50acd1810c9 100644 --- a/include/linux/page_ext.h +++ b/include/linux/page_ext.h @@ -19,6 +19,9 @@ struct page_ext_operations { enum page_ext_flags { PAGE_EXT_OWNER, PAGE_EXT_OWNER_ALLOCATED, +#ifdef CONFIG_PAGE_EXTENSION_PAGE_FREE + PAGE_EXT_PG_FREE, +#endif #if defined(CONFIG_IDLE_PAGE_TRACKING) && !defined(CONFIG_64BIT) PAGE_EXT_YOUNG, PAGE_EXT_IDLE, diff --git a/kernel/signal.c b/kernel/signal.c index e8f1ce7a7e47..1ae3e276e51b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1406,6 +1406,7 @@ int group_send_sig_info(int sig, struct kernel_siginfo *info, rcu_read_unlock(); if (!ret && sig) { + check_panic_on_foreground_kill(p); ret = do_send_sig_info(sig, info, p, type); if (capable(CAP_KILL) && sig == SIGKILL) add_to_oom_reaper(p); diff --git a/mm/Kconfig b/mm/Kconfig index 4a8b6d55ae4d..2c5a3693e769 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -759,6 +759,17 @@ config PERCPU_STATS information includes global and per chunk statistics, which can be used to help understand percpu memory usage. +config HAVE_USERSPACE_LOW_MEMORY_KILLER + bool "Configure reclaim paths if there is a userspace LMK" + default n + help + Configures parts of the reclaim paths in the kernel when Android + has a userspace memory killer. This configuration is done for + functional (e.g. ensuring the OOM killer doesn't run at certain + points) and performance purposes (e.g. preventing log-spew + when the OOM killer and userspace memory killer both have the + potential to run). + config GUP_BENCHMARK bool "Enable infrastructure for get_user_pages_fast() benchmarking" help diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug index 46615e0bdb35..14e36729c3d6 100644 --- a/mm/Kconfig.debug +++ b/mm/Kconfig.debug @@ -8,6 +8,15 @@ config PAGE_EXTENSION by not allocating this extra memory according to boottime configuration. +config PAGE_EXTENSION_PAGE_FREE + bool "Add a flag in page_ext_flags to indicate if a page is free" + depends on PAGE_EXTENSION && QGKI + help + Add the PAGE_FREE flag in page_ext_flags, in order to indicate + whether a page from the buddy allocator is free or is in + use. This information can aid in debugging buddy allocator + related issues. + config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL diff --git a/mm/oom_kill.c b/mm/oom_kill.c index c19945135938..d0cece9bdd15 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -58,6 +58,9 @@ int sysctl_oom_kill_allocating_task; int sysctl_oom_dump_tasks = 1; int sysctl_reap_mem_on_sigkill = 1; +static int panic_on_adj_zero; +module_param(panic_on_adj_zero, int, 0644); + /* * Serializes oom killer invocations (out_of_memory()) from all contexts to * prevent from over eager oom killing (e.g. when the oom killer is invoked @@ -1155,8 +1158,7 @@ void pagefault_out_of_memory(void) .order = 0, }; - if (IS_ENABLED(CONFIG_HAVE_LOW_MEMORY_KILLER) || - IS_ENABLED(CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER)) + if (IS_ENABLED(CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER)) return; if (mem_cgroup_oom_synchronize(true)) @@ -1197,3 +1199,18 @@ void add_to_oom_reaper(struct task_struct *p) put_task_struct(p); } + +/* + * Should be called prior to sending sigkill. To guarantee that the + * process to-be-killed is still untouched. + */ +void check_panic_on_foreground_kill(struct task_struct *p) +{ + if (unlikely(!strcmp(current->comm, ULMK_MAGIC) + && p->signal->oom_score_adj == 0 + && panic_on_adj_zero)) { + show_mem(SHOW_MEM_FILTER_NODES, NULL); + show_mem_call_notifiers(); + panic("Attempt to kill foreground task: %s", p->comm); + } +} diff --git a/mm/page_owner.c b/mm/page_owner.c index 41a99cfe0b0d..35673f47d8af 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -29,6 +29,7 @@ struct page_owner { depot_stack_handle_t free_handle; int pid; u64 ts_nsec; + u64 free_ts_nsec; }; static bool page_owner_enabled = IS_ENABLED(CONFIG_PAGE_OWNER_ENABLE_DEFAULT); @@ -152,6 +153,7 @@ void __reset_page_owner(struct page *page, unsigned int order) struct page_ext *page_ext; depot_stack_handle_t handle = 0; struct page_owner *page_owner; + u64 free_ts_nsec = local_clock(); handle = save_stack(GFP_NOWAIT | __GFP_NOWARN); @@ -160,8 +162,12 @@ void __reset_page_owner(struct page *page, unsigned int order) return; for (i = 0; i < (1 << order); i++) { __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); +#ifdef CONFIG_PAGE_EXTENSION_PAGE_FREE + __set_bit(PAGE_EXT_PG_FREE, &page_ext->flags); +#endif page_owner = get_page_owner(page_ext); page_owner->free_handle = handle; + page_owner->free_ts_nsec = free_ts_nsec; page_ext = page_ext_next(page_ext); } } @@ -181,8 +187,13 @@ static inline void __set_page_owner_handle(struct page *page, page_owner->last_migrate_reason = -1; page_owner->pid = current->pid; page_owner->ts_nsec = local_clock(); + page_owner->free_ts_nsec = 0; + __set_bit(PAGE_EXT_OWNER, &page_ext->flags); __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); +#ifdef CONFIG_PAGE_EXTENSION_PAGE_FREE + __clear_bit(PAGE_EXT_PG_FREE, &page_ext->flags); +#endif page_ext = page_ext_next(page_ext); } @@ -247,6 +258,7 @@ void __copy_page_owner(struct page *oldpage, struct page *newpage) new_page_owner->handle = old_page_owner->handle; new_page_owner->pid = old_page_owner->pid; new_page_owner->ts_nsec = old_page_owner->ts_nsec; + new_page_owner->free_ts_nsec = old_page_owner->ts_nsec; /* * We don't clear the bit on the oldpage as it's going to be freed