]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - kernel/sched/isolation.c
Merge branch 'kvm-insert-lfence' into kvm-master
[mirror_ubuntu-bionic-kernel.git] / kernel / sched / isolation.c
CommitLineData
78634061
FW
1/*
2 * Housekeeping management. Manage the targets for routine code that can run on
3 * any CPU: unbound workqueues, timers, kthreads and any offloadable work.
4 *
5 * Copyright (C) 2017 Red Hat, Inc., Frederic Weisbecker
6 *
7 */
8
9#include <linux/sched/isolation.h>
10#include <linux/tick.h>
11#include <linux/init.h>
12#include <linux/kernel.h>
e179f5a0 13#include <linux/static_key.h>
150dfee9 14#include <linux/ctype.h>
78634061 15
e179f5a0
FW
16DEFINE_STATIC_KEY_FALSE(housekeeping_overriden);
17EXPORT_SYMBOL_GPL(housekeeping_overriden);
7e56a1cf 18static cpumask_var_t housekeeping_mask;
de201559 19static unsigned int housekeeping_flags;
7e56a1cf 20
de201559 21int housekeeping_any_cpu(enum hk_flags flags)
7e56a1cf 22{
e179f5a0 23 if (static_branch_unlikely(&housekeeping_overriden))
de201559
FW
24 if (housekeeping_flags & flags)
25 return cpumask_any_and(housekeeping_mask, cpu_online_mask);
7e56a1cf
FW
26 return smp_processor_id();
27}
28EXPORT_SYMBOL_GPL(housekeeping_any_cpu);
29
de201559 30const struct cpumask *housekeeping_cpumask(enum hk_flags flags)
7e56a1cf 31{
e179f5a0 32 if (static_branch_unlikely(&housekeeping_overriden))
de201559
FW
33 if (housekeeping_flags & flags)
34 return housekeeping_mask;
7e56a1cf
FW
35 return cpu_possible_mask;
36}
37EXPORT_SYMBOL_GPL(housekeeping_cpumask);
38
de201559 39void housekeeping_affine(struct task_struct *t, enum hk_flags flags)
7e56a1cf 40{
e179f5a0 41 if (static_branch_unlikely(&housekeeping_overriden))
de201559
FW
42 if (housekeeping_flags & flags)
43 set_cpus_allowed_ptr(t, housekeeping_mask);
7e56a1cf
FW
44}
45EXPORT_SYMBOL_GPL(housekeeping_affine);
46
de201559 47bool housekeeping_test_cpu(int cpu, enum hk_flags flags)
7e56a1cf 48{
e179f5a0 49 if (static_branch_unlikely(&housekeeping_overriden))
de201559
FW
50 if (housekeeping_flags & flags)
51 return cpumask_test_cpu(cpu, housekeeping_mask);
7e56a1cf
FW
52 return true;
53}
54EXPORT_SYMBOL_GPL(housekeeping_test_cpu);
78634061
FW
55
56void __init housekeeping_init(void)
57{
6f1982fe 58 if (!housekeeping_flags)
78634061
FW
59 return;
60
6f1982fe
FW
61 static_branch_enable(&housekeeping_overriden);
62
63 /* We need at least one CPU to handle housekeeping work */
64 WARN_ON_ONCE(cpumask_empty(housekeeping_mask));
65}
66
edb93821 67static int __init housekeeping_setup(char *str, enum hk_flags flags)
6f1982fe
FW
68{
69 cpumask_var_t non_housekeeping_mask;
edb93821 70 int err;
6f1982fe
FW
71
72 alloc_bootmem_cpumask_var(&non_housekeeping_mask);
edb93821
FW
73 err = cpulist_parse(str, non_housekeeping_mask);
74 if (err < 0 || cpumask_last(non_housekeeping_mask) >= nr_cpu_ids) {
75 pr_warn("Housekeeping: nohz_full= or isolcpus= incorrect CPU range\n");
6f1982fe
FW
76 free_bootmem_cpumask_var(non_housekeeping_mask);
77 return 0;
78634061
FW
78 }
79
edb93821
FW
80 if (!housekeeping_flags) {
81 alloc_bootmem_cpumask_var(&housekeeping_mask);
82 cpumask_andnot(housekeeping_mask,
83 cpu_possible_mask, non_housekeeping_mask);
84 if (cpumask_empty(housekeeping_mask))
85 cpumask_set_cpu(smp_processor_id(), housekeeping_mask);
86 } else {
87 cpumask_var_t tmp;
88
89 alloc_bootmem_cpumask_var(&tmp);
90 cpumask_andnot(tmp, cpu_possible_mask, non_housekeeping_mask);
91 if (!cpumask_equal(tmp, housekeeping_mask)) {
92 pr_warn("Housekeeping: nohz_full= must match isolcpus=\n");
93 free_bootmem_cpumask_var(tmp);
94 free_bootmem_cpumask_var(non_housekeeping_mask);
95 return 0;
96 }
97 free_bootmem_cpumask_var(tmp);
98 }
de201559 99
edb93821
FW
100 if ((flags & HK_FLAG_TICK) && !(housekeeping_flags & HK_FLAG_TICK)) {
101 if (IS_ENABLED(CONFIG_NO_HZ_FULL)) {
102 tick_nohz_full_setup(non_housekeeping_mask);
103 } else {
104 pr_warn("Housekeeping: nohz unsupported."
105 " Build with CONFIG_NO_HZ_FULL\n");
106 free_bootmem_cpumask_var(non_housekeeping_mask);
107 return 0;
108 }
109 }
e179f5a0 110
edb93821 111 housekeeping_flags |= flags;
6f1982fe
FW
112
113 free_bootmem_cpumask_var(non_housekeeping_mask);
114
115 return 1;
78634061 116}
edb93821
FW
117
118static int __init housekeeping_nohz_full_setup(char *str)
119{
120 unsigned int flags;
121
122 flags = HK_FLAG_TICK | HK_FLAG_TIMER | HK_FLAG_RCU | HK_FLAG_MISC;
123
124 return housekeeping_setup(str, flags);
125}
6f1982fe 126__setup("nohz_full=", housekeeping_nohz_full_setup);
edb93821
FW
127
128static int __init housekeeping_isolcpus_setup(char *str)
129{
150dfee9
FW
130 unsigned int flags = 0;
131
132 while (isalpha(*str)) {
133 if (!strncmp(str, "nohz,", 5)) {
134 str += 5;
135 flags |= HK_FLAG_TICK;
136 continue;
137 }
138
139 if (!strncmp(str, "domain,", 7)) {
140 str += 7;
141 flags |= HK_FLAG_DOMAIN;
142 continue;
143 }
144
145 pr_warn("isolcpus: Error, unknown flag\n");
146 return 0;
147 }
148
149 /* Default behaviour for isolcpus without flags */
150 if (!flags)
151 flags |= HK_FLAG_DOMAIN;
152
153 return housekeeping_setup(str, flags);
edb93821
FW
154}
155__setup("isolcpus=", housekeeping_isolcpus_setup);