From 2b8a21e9a417bd331f2f00f667717f7fde2bdd15 Mon Sep 17 00:00:00 2001 From: Stephen Dickey Date: Fri, 14 Jan 2022 10:57:06 -0800 Subject: [PATCH] sched/walt: create conditions for walt-bug and console output Allow for finer grain control over the walt-bug capabilities, such that different walt-bug types can be treated differently, either causing a panic, or simply printing out content. echo 0x4544DEXY > /proc/sys/walt/panic_on_walt_bug Y in the above represents the bitmask for the walt debug class that is enabled. If set, the device will panic on that class of issue. X in the above represents the bitmask for the walt debug class that is enabled, for printing to console. If set, device will printk on that class of issue. X and Y are independent, and maybe configured separately as desired. However, nothing will happen if the most significant 3 bytes of panic_on_walt_bug are not properly set to the SENTINEL value. Change-Id: I01382fdb5717625f42f45eac4151d47578f0b0c6 Signed-off-by: Stephen Dickey --- kernel/sched/walt/sysctl.c | 4 +-- kernel/sched/walt/walt.c | 66 +++++++++++++++++++++--------------- kernel/sched/walt/walt.h | 63 ++++++++++++++++++++++++++-------- kernel/sched/walt/walt_cfs.c | 8 +++-- 4 files changed, 95 insertions(+), 46 deletions(-) diff --git a/kernel/sched/walt/sysctl.c b/kernel/sched/walt/sysctl.c index c6eb6430b15b..f52aa1b90f76 100644 --- a/kernel/sched/walt/sysctl.c +++ b/kernel/sched/walt/sysctl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved. */ #include "walt.h" @@ -62,7 +62,7 @@ const int sched_user_hint_max = 1000; unsigned int sysctl_walt_rtg_cfs_boost_prio = 99; /* disabled by default */ unsigned int sysctl_sched_sync_hint_enable = 1; unsigned int sysctl_sched_bug_on_rt_throttle; -unsigned int sysctl_panic_on_walt_bug; +unsigned int sysctl_panic_on_walt_bug = walt_debug_initial_values(); unsigned int sysctl_sched_suppress_region2; unsigned int sysctl_sched_skip_sp_newly_idle_lb = 1; unsigned int sysctl_sched_hyst_min_coloc_ns = 80000000; diff --git a/kernel/sched/walt/walt.c b/kernel/sched/walt/walt.c index 45e96ac17e00..f313c98b5d21 100644 --- a/kernel/sched/walt/walt.c +++ b/kernel/sched/walt/walt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2022, The Linux Foundation. All rights reserved. */ #include @@ -293,11 +293,11 @@ fixup_cumulative_runnable_avg(struct rq *rq, lockdep_assert_held(&rq->__lock); if (task_rq(p) != rq) - WALT_BUG(p, "on CPU %d task %s(%d) not on rq %d", + WALT_BUG(WALT_BUG_UPSTREAM, p, "on CPU %d task %s(%d) not on rq %d", raw_smp_processor_id(), p->comm, p->pid, rq->cpu); if (cumulative_runnable_avg_scaled < 0) { - WALT_BUG(p, "on CPU %d task ds=%llu is higher than cra=%llu\n", + WALT_BUG(WALT_BUG_WALT, p, "on CPU %d task ds=%llu is higher than cra=%llu\n", raw_smp_processor_id(), wts->demand_scaled, stats->cumulative_runnable_avg_scaled); cumulative_runnable_avg_scaled = 0; @@ -305,7 +305,7 @@ fixup_cumulative_runnable_avg(struct rq *rq, stats->cumulative_runnable_avg_scaled = (u64)cumulative_runnable_avg_scaled; if (pred_demands_sum_scaled < 0) { - WALT_BUG(p, "on CPU %d task pds=%llu is higher than pds_sum=%llu\n", + WALT_BUG(WALT_BUG_WALT, p, "on CPU %d task pds=%llu is higher than pds_sum=%llu\n", raw_smp_processor_id(), wts->pred_demand_scaled, stats->pred_demands_sum_scaled); pred_demands_sum_scaled = 0; @@ -696,22 +696,22 @@ static inline void account_load_subtractions(struct rq *rq) } if ((s64)wrq->prev_runnable_sum < 0) { - WALT_BUG(NULL, "wrq->prev_runnable_sum=%llu < 0", + WALT_BUG(WALT_BUG_WALT, NULL, "wrq->prev_runnable_sum=%llu < 0", (s64)wrq->prev_runnable_sum); wrq->prev_runnable_sum = 0; } if ((s64)wrq->curr_runnable_sum < 0) { - WALT_BUG(NULL, "wrq->curr_runnable_sum=%llu < 0", + WALT_BUG(WALT_BUG_WALT, NULL, "wrq->curr_runnable_sum=%llu < 0", (s64)wrq->curr_runnable_sum); wrq->curr_runnable_sum = 0; } if ((s64)wrq->nt_prev_runnable_sum < 0) { - WALT_BUG(NULL, "wrq->nt_prev_runnable_sum=%llu < 0", + WALT_BUG(WALT_BUG_WALT, NULL, "wrq->nt_prev_runnable_sum=%llu < 0", (s64)wrq->nt_prev_runnable_sum); wrq->nt_prev_runnable_sum = 0; } if ((s64)wrq->nt_curr_runnable_sum < 0) { - WALT_BUG(NULL, "wrq->nt_curr_runnable_sum=%llu < 0", + WALT_BUG(WALT_BUG_WALT, NULL, "wrq->nt_curr_runnable_sum=%llu < 0", (s64)wrq->nt_curr_runnable_sum); wrq->nt_curr_runnable_sum = 0; } @@ -823,7 +823,8 @@ static inline void inter_cluster_migration_fixup dest_wrq->prev_runnable_sum += wts->prev_window; if (src_wrq->curr_runnable_sum < wts->curr_window_cpu[task_cpu]) { - WALT_BUG(p, "pid=%u CPU%d -> CPU%d src_crs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU%d -> CPU%d src_crs=%llu is lesser than task_contrib=%llu", p->pid, src_rq->cpu, dest_rq->cpu, src_wrq->curr_runnable_sum, wts->curr_window_cpu[task_cpu]); @@ -832,7 +833,8 @@ static inline void inter_cluster_migration_fixup src_wrq->curr_runnable_sum -= wts->curr_window_cpu[task_cpu]; if (src_wrq->prev_runnable_sum < wts->prev_window_cpu[task_cpu]) { - WALT_BUG(p, "pid=%u CPU%d -> CPU%d src_prs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU%d -> CPU%d src_prs=%llu is lesser than task_contrib=%llu", p->pid, src_rq->cpu, dest_rq->cpu, src_wrq->prev_runnable_sum, wts->prev_window_cpu[task_cpu]); @@ -845,7 +847,8 @@ static inline void inter_cluster_migration_fixup dest_wrq->nt_prev_runnable_sum += wts->prev_window; if (src_wrq->nt_curr_runnable_sum < wts->curr_window_cpu[task_cpu]) { - WALT_BUG(p, "pid=%u CPU%d -> CPU%d src_nt_crs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU%d -> CPU%d src_nt_crs=%llu is lesser than task_contrib=%llu", p->pid, src_rq->cpu, dest_rq->cpu, src_wrq->nt_curr_runnable_sum, wts->curr_window_cpu[task_cpu]); @@ -855,7 +858,8 @@ static inline void inter_cluster_migration_fixup wts->curr_window_cpu[task_cpu]; if (src_wrq->nt_prev_runnable_sum < wts->prev_window_cpu[task_cpu]) { - WALT_BUG(p, "pid=%u CPU%d -> CPU%d src_nt_prs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU%d -> CPU%d src_nt_prs=%llu is lesser than task_contrib=%llu", p->pid, src_rq->cpu, dest_rq->cpu, src_wrq->nt_prev_runnable_sum, wts->prev_window_cpu[task_cpu]); @@ -982,7 +986,7 @@ static void fixup_busy_time(struct task_struct *p, int new_cpu) lockdep_assert_held(&dest_rq->__lock); if (task_rq(p) != src_rq) - WALT_BUG(p, "on CPU %d task %s(%d) not on src_rq %d", + WALT_BUG(WALT_BUG_UPSTREAM, p, "on CPU %d task %s(%d) not on src_rq %d", raw_smp_processor_id(), p->comm, p->pid, src_rq->cpu); walt_update_task_ravg(task_rq(p)->curr, task_rq(p), @@ -3188,7 +3192,8 @@ static void transfer_busy_time(struct rq *rq, dst_nt_prev_runnable_sum = &cpu_time->nt_prev_runnable_sum; if (*src_curr_runnable_sum < wts->curr_window_cpu[cpu]) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_crs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_crs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_curr_runnable_sum, wts->curr_window_cpu[cpu]); *src_curr_runnable_sum = wts->curr_window_cpu[cpu]; @@ -3196,7 +3201,8 @@ static void transfer_busy_time(struct rq *rq, *src_curr_runnable_sum -= wts->curr_window_cpu[cpu]; if (*src_prev_runnable_sum < wts->prev_window_cpu[cpu]) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_prs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_prs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_prev_runnable_sum, wts->prev_window_cpu[cpu]); *src_prev_runnable_sum = wts->prev_window_cpu[cpu]; @@ -3205,7 +3211,8 @@ static void transfer_busy_time(struct rq *rq, if (new_task) { if (*src_nt_curr_runnable_sum < wts->curr_window_cpu[cpu]) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_nt_crs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_nt_crs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_nt_curr_runnable_sum, wts->curr_window_cpu[cpu]); @@ -3215,7 +3222,8 @@ static void transfer_busy_time(struct rq *rq, wts->curr_window_cpu[cpu]; if (*src_nt_prev_runnable_sum < wts->prev_window_cpu[cpu]) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_nt_prs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_nt_prs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_nt_prev_runnable_sum, wts->prev_window_cpu[cpu]); @@ -3242,7 +3250,8 @@ static void transfer_busy_time(struct rq *rq, dst_nt_prev_runnable_sum = &wrq->nt_prev_runnable_sum; if (*src_curr_runnable_sum < wts->curr_window) { - WALT_BUG(p, "WALT-UG pid=%u CPU=%d event=%d src_crs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "WALT-UG pid=%u CPU=%d event=%d src_crs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_curr_runnable_sum, wts->curr_window); *src_curr_runnable_sum = wts->curr_window; @@ -3250,7 +3259,8 @@ static void transfer_busy_time(struct rq *rq, *src_curr_runnable_sum -= wts->curr_window; if (*src_prev_runnable_sum < wts->prev_window) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_prs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_prs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_prev_runnable_sum, wts->prev_window); *src_prev_runnable_sum = wts->prev_window; @@ -3259,7 +3269,8 @@ static void transfer_busy_time(struct rq *rq, if (new_task) { if (*src_nt_curr_runnable_sum < wts->curr_window) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_nt_crs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_nt_crs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_nt_curr_runnable_sum, wts->curr_window); @@ -3268,7 +3279,8 @@ static void transfer_busy_time(struct rq *rq, *src_nt_curr_runnable_sum -= wts->curr_window; if (*src_nt_prev_runnable_sum < wts->prev_window) { - WALT_BUG(p, "pid=%u CPU=%d event=%d src_nt_prs=%llu is lesser than task_contrib=%llu", + WALT_BUG(WALT_BUG_WALT, p, + "pid=%u CPU=%d event=%d src_nt_prs=%llu is lesser than task_contrib=%llu", p->pid, cpu, event, *src_nt_prev_runnable_sum, wts->prev_window); @@ -3916,18 +3928,18 @@ static void android_rvh_enqueue_task(void *unused, struct rq *rq, struct task_st lockdep_assert_held(&rq->__lock); if (p->cpu != cpu_of(rq)) - WALT_BUG(p, "enqueuing on rq %d when task->cpu is %d\n", + WALT_BUG(WALT_BUG_UPSTREAM, p, "enqueuing on rq %d when task->cpu is %d\n", cpu_of(rq), p->cpu); /* catch double enqueue */ if (wts->prev_on_rq == 1) { - WALT_BUG(p, "double enqueue detected: task_cpu=%d new_cpu=%d\n", + WALT_BUG(WALT_BUG_UPSTREAM, p, "double enqueue detected: task_cpu=%d new_cpu=%d\n", task_cpu(p), cpu_of(rq)); double_enqueue = true; } if (!cpumask_test_cpu(cpu_of(rq), p->cpus_ptr)) - WALT_BUG(p, "enqueueing on rq=%d comm=%s(%d) affinity=0x%x", + WALT_BUG(WALT_BUG_NONCRITICAL, p, "enqueueing on rq=%d comm=%s(%d) affinity=0x%x", cpu_of(rq), p->comm, p->pid, (*(cpumask_bits(p->cpus_ptr)))); wts->prev_on_rq = 1; @@ -3965,7 +3977,7 @@ static void android_rvh_dequeue_task(void *unused, struct rq *rq, struct task_st * an invalid failure. */ if (wts->prev_on_rq_cpu >= 0 && wts->prev_on_rq_cpu != cpu_of(rq)) - WALT_BUG(p, "dequeue cpu %d not same as enqueue %d\n", + WALT_BUG(WALT_BUG_UPSTREAM, p, "dequeue cpu %d not same as enqueue %d\n", cpu_of(rq), wts->prev_on_rq_cpu); /* no longer on a cpu */ @@ -3973,7 +3985,7 @@ static void android_rvh_dequeue_task(void *unused, struct rq *rq, struct task_st /* catch double deq */ if (wts->prev_on_rq == 2) { - WALT_BUG(p, "double dequeue detected: task_cpu=%d new_cpu=%d\n", + WALT_BUG(WALT_BUG_UPSTREAM, p, "double dequeue detected: task_cpu=%d new_cpu=%d\n", task_cpu(p), cpu_of(rq)); double_dequeue = true; } @@ -4123,7 +4135,7 @@ static void android_rvh_schedule(void *unused, struct task_struct *prev, walt_update_task_ravg(prev, rq, PUT_PREV_TASK, wallclock, 0); walt_update_task_ravg(next, rq, PICK_NEXT_TASK, wallclock, 0); if (is_idle_task(next) && wrq->walt_stats.cumulative_runnable_avg_scaled != 0) - WALT_BUG(next, "next=idle cra non zero=%d\n", + WALT_BUG(WALT_BUG_WALT, next, "next=idle cra non zero=%d\n", wrq->walt_stats.cumulative_runnable_avg_scaled); } else { walt_update_task_ravg(prev, rq, TASK_UPDATE, wallclock, 0); diff --git a/kernel/sched/walt/walt.h b/kernel/sched/walt/walt.h index 5792c86de8f2..a5f75363eeb0 100644 --- a/kernel/sched/walt/walt.h +++ b/kernel/sched/walt/walt.h @@ -917,6 +917,16 @@ extern int in_sched_bug; extern struct rq *__migrate_task(struct rq *rq, struct rq_flags *rf, struct task_struct *p, int dest_cpu); +enum WALT_DEBUG_FEAT { + WALT_BUG_UPSTREAM, + WALT_BUG_WALT, + WALT_BUG_NONCRITICAL, + WALT_BUG_UNUSED, + + /* maximum 4 entries allowed */ + WALT_DEBUG_FEAT_NR, +}; + #define WALT_PANIC(condition) \ ({ \ if (unlikely(!!(condition)) && !in_sched_bug) { \ @@ -926,21 +936,46 @@ extern struct rq *__migrate_task(struct rq *rq, struct rq_flags *rf, } \ }) -#define WALT_PANIC_SENTINEL 0x4544DEAD +/* the least signifcant byte is the bitmask for features and printk */ +#define WALT_PANIC_SENTINEL 0x4544DE00 -/* - * crash if walt bugs are fatal, otherwise return immediately. - * output format and arguments to console - */ -#define WALT_BUG(p, format, args...) \ -({ \ - if (unlikely(sysctl_panic_on_walt_bug == WALT_PANIC_SENTINEL)) {\ - printk_deferred("WALT-BUG " format, args); \ - if (p) \ - walt_task_dump(p); \ - WALT_PANIC(1); \ - } \ +#define walt_debug_bitmask_panic(x) (1UL << x) +#define walt_debug_bitmask_print(x) (1UL << (x + WALT_DEBUG_FEAT_NR)) + +/* setup initial values, bug and print on upstream and walt, ignore noncritical */ +#define walt_debug_initial_values() \ + (WALT_PANIC_SENTINEL | \ + walt_debug_bitmask_panic(WALT_BUG_UPSTREAM) | \ + walt_debug_bitmask_print(WALT_BUG_UPSTREAM) | \ + walt_debug_bitmask_panic(WALT_BUG_WALT) | \ + walt_debug_bitmask_print(WALT_BUG_WALT)) + +/* least significant nibble is the bug feature itself */ +#define walt_debug_feat_panic(x) (!!(sysctl_panic_on_walt_bug & (1UL << x))) + +/* 2nd least significant nibble is the print capability */ +#define walt_debug_feat_print(x) (!!(sysctl_panic_on_walt_bug & (1UL << (x + WALT_DEBUG_FEAT_NR)))) + +/* return true if the sentinel is set, regardless of feature set */ +static inline bool is_walt_sentinel(void) +{ + if (unlikely((sysctl_panic_on_walt_bug & 0xFFFFFF00) == WALT_PANIC_SENTINEL)) + return true; + return false; +} + +/* if the sentinel is properly set, print and/or panic as configured */ +#define WALT_BUG(feat, p, format, args...) \ +({ \ + if (is_walt_sentinel()) { \ + if (walt_debug_feat_print(feat)) \ + printk_deferred("WALT-BUG " format, args); \ + if (walt_debug_feat_panic(feat)) { \ + if (p) \ + walt_task_dump(p); \ + WALT_PANIC(1); \ + } \ + } \ }) - #endif /* _WALT_H */ diff --git a/kernel/sched/walt/walt_cfs.c b/kernel/sched/walt/walt_cfs.c index 9cdbe5c59ad5..3b3bafe42f42 100644 --- a/kernel/sched/walt/walt_cfs.c +++ b/kernel/sched/walt/walt_cfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved. */ #include @@ -1268,7 +1268,8 @@ static void walt_cfs_replace_next_task_fair(void *unused, struct rq *rq, struct if ((*p) && (*p) != prev && ((*p)->on_cpu == 1 || (*p)->on_rq == 0 || (*p)->on_rq == TASK_ON_RQ_MIGRATING || (*p)->cpu != cpu_of(rq))) - WALT_BUG(*p, "picked %s(%d) on_cpu=%d on_rq=%d p->cpu=%d cpu_of(rq)=%d kthread=%d\n", + WALT_BUG(WALT_BUG_UPSTREAM, *p, + "picked %s(%d) on_cpu=%d on_rq=%d p->cpu=%d cpu_of(rq)=%d kthread=%d\n", (*p)->comm, (*p)->pid, (*p)->on_cpu, (*p)->on_rq, (*p)->cpu, cpu_of(rq), ((*p)->flags & PF_KTHREAD)); @@ -1287,7 +1288,8 @@ static void walt_cfs_replace_next_task_fair(void *unused, struct rq *rq, struct if ((*p) && (*p) != prev && ((*p)->on_cpu == 1 || (*p)->on_rq == 0 || (*p)->on_rq == TASK_ON_RQ_MIGRATING || (*p)->cpu != cpu_of(rq))) - WALT_BUG(*p, "picked %s(%d) on_cpu=%d on_rq=%d p->cpu=%d cpu_of(rq)=%d kthread=%d\n", + WALT_BUG(WALT_BUG_UPSTREAM, *p, + "picked %s(%d) on_cpu=%d on_rq=%d p->cpu=%d cpu_of(rq)=%d kthread=%d\n", (*p)->comm, (*p)->pid, (*p)->on_cpu, (*p)->on_rq, (*p)->cpu, cpu_of(rq), ((*p)->flags & PF_KTHREAD));