hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/kernel/sched/isolation.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Housekeeping management. Manage the targets for routine code that can run on
34 * any CPU: unbound workqueues, timers, kthreads and any offloadable work.
....@@ -8,23 +9,37 @@
89 */
910 #include "sched.h"
1011
11
-DEFINE_STATIC_KEY_FALSE(housekeeping_overriden);
12
-EXPORT_SYMBOL_GPL(housekeeping_overriden);
12
+DEFINE_STATIC_KEY_FALSE(housekeeping_overridden);
13
+EXPORT_SYMBOL_GPL(housekeeping_overridden);
1314 static cpumask_var_t housekeeping_mask;
1415 static unsigned int housekeeping_flags;
1516
17
+bool housekeeping_enabled(enum hk_flags flags)
18
+{
19
+ return !!(housekeeping_flags & flags);
20
+}
21
+EXPORT_SYMBOL_GPL(housekeeping_enabled);
22
+
1623 int housekeeping_any_cpu(enum hk_flags flags)
1724 {
18
- if (static_branch_unlikely(&housekeeping_overriden))
19
- if (housekeeping_flags & flags)
25
+ int cpu;
26
+
27
+ if (static_branch_unlikely(&housekeeping_overridden)) {
28
+ if (housekeeping_flags & flags) {
29
+ cpu = sched_numa_find_closest(housekeeping_mask, smp_processor_id());
30
+ if (cpu < nr_cpu_ids)
31
+ return cpu;
32
+
2033 return cpumask_any_and(housekeeping_mask, cpu_online_mask);
34
+ }
35
+ }
2136 return smp_processor_id();
2237 }
2338 EXPORT_SYMBOL_GPL(housekeeping_any_cpu);
2439
2540 const struct cpumask *housekeeping_cpumask(enum hk_flags flags)
2641 {
27
- if (static_branch_unlikely(&housekeeping_overriden))
42
+ if (static_branch_unlikely(&housekeeping_overridden))
2843 if (housekeeping_flags & flags)
2944 return housekeeping_mask;
3045 return cpu_possible_mask;
....@@ -33,7 +48,7 @@
3348
3449 void housekeeping_affine(struct task_struct *t, enum hk_flags flags)
3550 {
36
- if (static_branch_unlikely(&housekeeping_overriden))
51
+ if (static_branch_unlikely(&housekeeping_overridden))
3752 if (housekeeping_flags & flags)
3853 set_cpus_allowed_ptr(t, housekeeping_mask);
3954 }
....@@ -41,7 +56,7 @@
4156
4257 bool housekeeping_test_cpu(int cpu, enum hk_flags flags)
4358 {
44
- if (static_branch_unlikely(&housekeeping_overriden))
59
+ if (static_branch_unlikely(&housekeeping_overridden))
4560 if (housekeeping_flags & flags)
4661 return cpumask_test_cpu(cpu, housekeeping_mask);
4762 return true;
....@@ -53,7 +68,7 @@
5368 if (!housekeeping_flags)
5469 return;
5570
56
- static_branch_enable(&housekeeping_overriden);
71
+ static_branch_enable(&housekeeping_overridden);
5772
5873 if (housekeeping_flags & HK_FLAG_TICK)
5974 sched_tick_offload_init();
....@@ -65,6 +80,7 @@
6580 static int __init housekeeping_setup(char *str, enum hk_flags flags)
6681 {
6782 cpumask_var_t non_housekeeping_mask;
83
+ cpumask_var_t tmp;
6884 int err;
6985
7086 alloc_bootmem_cpumask_var(&non_housekeeping_mask);
....@@ -75,16 +91,23 @@
7591 return 0;
7692 }
7793
94
+ alloc_bootmem_cpumask_var(&tmp);
7895 if (!housekeeping_flags) {
7996 alloc_bootmem_cpumask_var(&housekeeping_mask);
8097 cpumask_andnot(housekeeping_mask,
8198 cpu_possible_mask, non_housekeeping_mask);
82
- if (cpumask_empty(housekeeping_mask))
83
- cpumask_set_cpu(smp_processor_id(), housekeeping_mask);
84
- } else {
85
- cpumask_var_t tmp;
8699
87
- alloc_bootmem_cpumask_var(&tmp);
100
+ cpumask_andnot(tmp, cpu_present_mask, non_housekeeping_mask);
101
+ if (cpumask_empty(tmp)) {
102
+ pr_warn("Housekeeping: must include one present CPU, "
103
+ "using boot CPU:%d\n", smp_processor_id());
104
+ __cpumask_set_cpu(smp_processor_id(), housekeeping_mask);
105
+ __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
106
+ }
107
+ } else {
108
+ cpumask_andnot(tmp, cpu_present_mask, non_housekeeping_mask);
109
+ if (cpumask_empty(tmp))
110
+ __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
88111 cpumask_andnot(tmp, cpu_possible_mask, non_housekeeping_mask);
89112 if (!cpumask_equal(tmp, housekeeping_mask)) {
90113 pr_warn("Housekeeping: nohz_full= must match isolcpus=\n");
....@@ -92,8 +115,8 @@
92115 free_bootmem_cpumask_var(non_housekeeping_mask);
93116 return 0;
94117 }
95
- free_bootmem_cpumask_var(tmp);
96118 }
119
+ free_bootmem_cpumask_var(tmp);
97120
98121 if ((flags & HK_FLAG_TICK) && !(housekeeping_flags & HK_FLAG_TICK)) {
99122 if (IS_ENABLED(CONFIG_NO_HZ_FULL)) {
....@@ -117,7 +140,8 @@
117140 {
118141 unsigned int flags;
119142
120
- flags = HK_FLAG_TICK | HK_FLAG_WQ | HK_FLAG_TIMER | HK_FLAG_RCU | HK_FLAG_MISC;
143
+ flags = HK_FLAG_TICK | HK_FLAG_WQ | HK_FLAG_TIMER | HK_FLAG_RCU |
144
+ HK_FLAG_MISC | HK_FLAG_KTHREAD;
121145
122146 return housekeeping_setup(str, flags);
123147 }
....@@ -126,6 +150,9 @@
126150 static int __init housekeeping_isolcpus_setup(char *str)
127151 {
128152 unsigned int flags = 0;
153
+ bool illegal = false;
154
+ char *par;
155
+ int len;
129156
130157 while (isalpha(*str)) {
131158 if (!strncmp(str, "nohz,", 5)) {
....@@ -140,8 +167,28 @@
140167 continue;
141168 }
142169
143
- pr_warn("isolcpus: Error, unknown flag\n");
144
- return 0;
170
+ if (!strncmp(str, "managed_irq,", 12)) {
171
+ str += 12;
172
+ flags |= HK_FLAG_MANAGED_IRQ;
173
+ continue;
174
+ }
175
+
176
+ /*
177
+ * Skip unknown sub-parameter and validate that it is not
178
+ * containing an invalid character.
179
+ */
180
+ for (par = str, len = 0; *str && *str != ','; str++, len++) {
181
+ if (!isalpha(*str) && *str != '_')
182
+ illegal = true;
183
+ }
184
+
185
+ if (illegal) {
186
+ pr_warn("isolcpus: Invalid flag %.*s\n", len, par);
187
+ return 0;
188
+ }
189
+
190
+ pr_info("isolcpus: Skipped unknown flag %.*s\n", len, par);
191
+ str++;
145192 }
146193
147194 /* Default behaviour for isolcpus without flags */