Pull scheduler fixes from Borislav Petkov: - Avoid touching ~100 config files in order to be able to select the preemption model - clear cluster CPU masks too, on the CPU unplug path - prevent use-after-free in cfs - Prevent a race condition when updating CPU cache domains - Factor out common shared part of smp_prepare_cpus() into a common helper which can be called by both baremetal and Xen, in order to fix a booting of Xen PV guests * tag 'sched_urgent_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: preempt: Restore preemption model selection configs arch_topology: Fix missing clear cluster_cpumask in remove_cpu_topology() sched/fair: Prevent dead task groups from regaining cfs_rq's sched/core: Mitigate race cpus_share_cache()/update_top_cache_domain() x86/smp: Factor out parts of native_smp_prepare_cpus()
Unified · Split
| @@ -126,6 +126,7 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) · 125 unmodified lines | ||
| 126 | 126 | |
| 127 | 127 | void cpu_disable_common(void); |
| 128 | 128 | void native_smp_prepare_boot_cpu(void); |
| 129 | +void smp_prepare_cpus_common(void); | |
| 129 | 130 | void native_smp_prepare_cpus(unsigned int max_cpus); |
| 130 | 131 | void calculate_max_logical_packages(void); |
| 131 | 132 | void native_smp_cpus_done(unsigned int max_cpus); |
| @@ -1350,12 +1350,7 @@ static void __init smp_get_logical_apicid(void) · 1349 unmodified lines | ||
| 1350 | 1350 | cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); |
| 1351 | 1351 | } |
| 1352 | 1352 | |
| 1353 | −/* | |
| 1354 | − * Prepare for SMP bootup. | |
| 1355 | − * @max_cpus: configured maximum number of CPUs, It is a legacy parameter | |
| 1356 | − * for common interface support. | |
| 1357 | − */ | |
| 1358 | −void __init native_smp_prepare_cpus(unsigned int max_cpus) | |
| 1353 | +void __init smp_prepare_cpus_common(void) | |
| 1359 | 1354 | { |
| 1360 | 1355 | unsigned int i; |
| 1361 | 1356 | |
| @@ -1386,6 +1381,17 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) · 24 unmodified lines | ||
| 1386 | 1381 | set_sched_topology(x86_topology); |
| 1387 | 1382 | |
| 1388 | 1383 | set_cpu_sibling_map(0); |
| 1384 | +} | |
| 1385 | + | |
| 1386 | +/* | |
| 1387 | + * Prepare for SMP bootup. | |
| 1388 | + * @max_cpus: configured maximum number of CPUs, It is a legacy parameter | |
| 1389 | + * for common interface support. | |
| 1390 | + */ | |
| 1391 | +void __init native_smp_prepare_cpus(unsigned int max_cpus) | |
| 1392 | +{ | |
| 1393 | + smp_prepare_cpus_common(); | |
| 1394 | + | |
| 1389 | 1395 | init_freq_invariance(false, false); |
| 1390 | 1396 | smp_sanity_check(); |
| 1391 | 1397 | |
| @@ -225,7 +225,6 @@ static void __init xen_pv_smp_prepare_boot_cpu(void) · 224 unmodified lines | ||
| 225 | 225 | static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus) |
| 226 | 226 | { |
| 227 | 227 | unsigned cpu; |
| 228 | − unsigned int i; | |
| 229 | 228 | |
| 230 | 229 | if (skip_ioapic_setup) { |
| 231 | 230 | char *m = (max_cpus == 0) ? |
| @@ -238,16 +237,9 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus) · 6 unmodified lines | ||
| 238 | 237 | } |
| 239 | 238 | xen_init_lock_cpu(0); |
| 240 | 239 | |
| 241 | − smp_store_boot_cpu_info(); | |
| 242 | − cpu_data(0).x86_max_cores = 1; | |
| 240 | + smp_prepare_cpus_common(); | |
| 243 | 241 | |
| 244 | − for_each_possible_cpu(i) { | |
| 245 | − zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); | |
| 246 | − zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); | |
| 247 | − zalloc_cpumask_var(&per_cpu(cpu_die_map, i), GFP_KERNEL); | |
| 248 | − zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL); | |
| 249 | − } | |
| 250 | − set_cpu_sibling_map(0); | |
| 242 | + cpu_data(0).x86_max_cores = 1; | |
| 251 | 243 | |
| 252 | 244 | speculative_store_bypass_ht_init(); |
| 253 | 245 | |
| @@ -677,6 +677,8 @@ void remove_cpu_topology(unsigned int cpu) · 676 unmodified lines | ||
| 677 | 677 | cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); |
| 678 | 678 | for_each_cpu(sibling, topology_sibling_cpumask(cpu)) |
| 679 | 679 | cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); |
| 680 | + for_each_cpu(sibling, topology_cluster_cpumask(cpu)) | |
| 681 | + cpumask_clear_cpu(cpu, topology_cluster_cpumask(sibling)); | |
| 680 | 682 | for_each_cpu(sibling, topology_llc_cpumask(cpu)) |
| 681 | 683 | cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); |
| 682 | 684 | |
| @@ -85,7 +85,7 @@ · 84 unmodified lines | ||
| 85 | 85 | struct completion; |
| 86 | 86 | struct user; |
| 87 | 87 | |
| 88 | −#ifdef CONFIG_PREEMPT_VOLUNTARY | |
| 88 | +#ifdef CONFIG_PREEMPT_VOLUNTARY_BUILD | |
| 89 | 89 | |
| 90 | 90 | extern int __cond_resched(void); |
| 91 | 91 | # define might_resched() __cond_resched() |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #else |
| 16 | 16 | #define MODULE_VERMAGIC_SMP "" |
| 17 | 17 | #endif |
| 18 | −#ifdef CONFIG_PREEMPT | |
| 18 | +#ifdef CONFIG_PREEMPT_BUILD | |
| 19 | 19 | #define MODULE_VERMAGIC_PREEMPT "preempt " |
| 20 | 20 | #elif defined(CONFIG_PREEMPT_RT) |
| 21 | 21 | #define MODULE_VERMAGIC_PREEMPT "preempt_rt " |
| @@ -30,7 +30,7 @@ $(obj)/version.o: include/generated/compile.h · 29 unmodified lines | ||
| 30 | 30 | quiet_cmd_compile.h = CHK $@ |
| 31 | 31 | cmd_compile.h = \ |
| 32 | 32 | $(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \ |
| 33 | − "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" \ | |
| 33 | + "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT_BUILD)" \ | |
| 34 | 34 | "$(CONFIG_PREEMPT_RT)" $(CONFIG_CC_VERSION_TEXT) "$(LD)" |
| 35 | 35 | |
| 36 | 36 | include/generated/compile.h: FORCE |
| @@ -1,12 +1,23 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | |
| 3 | +config PREEMPT_NONE_BUILD | |
| 4 | + bool | |
| 5 | + | |
| 6 | +config PREEMPT_VOLUNTARY_BUILD | |
| 7 | + bool | |
| 8 | + | |
| 9 | +config PREEMPT_BUILD | |
| 10 | + bool | |
| 11 | + select PREEMPTION | |
| 12 | + select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK | |
| 13 | + | |
| 3 | 14 | choice |
| 4 | 15 | prompt "Preemption Model" |
| 5 | − default PREEMPT_NONE_BEHAVIOUR | |
| 16 | + default PREEMPT_NONE | |
| 6 | 17 | |
| 7 | −config PREEMPT_NONE_BEHAVIOUR | |
| 18 | +config PREEMPT_NONE | |
| 8 | 19 | bool "No Forced Preemption (Server)" |
| 9 | − select PREEMPT_NONE if !PREEMPT_DYNAMIC | |
| 20 | + select PREEMPT_NONE_BUILD if !PREEMPT_DYNAMIC | |
| 10 | 21 | help |
| 11 | 22 | This is the traditional Linux preemption model, geared towards |
| 12 | 23 | throughput. It will still provide good latencies most of the |
| @@ -18,10 +29,10 @@ config PREEMPT_NONE_BEHAVIOUR · 5 unmodified lines | ||
| 18 | 29 | raw processing power of the kernel, irrespective of scheduling |
| 19 | 30 | latencies. |
| 20 | 31 | |
| 21 | −config PREEMPT_VOLUNTARY_BEHAVIOUR | |
| 32 | +config PREEMPT_VOLUNTARY | |
| 22 | 33 | bool "Voluntary Kernel Preemption (Desktop)" |
| 23 | 34 | depends on !ARCH_NO_PREEMPT |
| 24 | − select PREEMPT_VOLUNTARY if !PREEMPT_DYNAMIC | |
| 35 | + select PREEMPT_VOLUNTARY_BUILD if !PREEMPT_DYNAMIC | |
| 25 | 36 | help |
| 26 | 37 | This option reduces the latency of the kernel by adding more |
| 27 | 38 | "explicit preemption points" to the kernel code. These new |
| @@ -37,10 +48,10 @@ config PREEMPT_VOLUNTARY_BEHAVIOUR · 9 unmodified lines | ||
| 37 | 48 | |
| 38 | 49 | Select this if you are building a kernel for a desktop system. |
| 39 | 50 | |
| 40 | −config PREEMPT_BEHAVIOUR | |
| 51 | +config PREEMPT | |
| 41 | 52 | bool "Preemptible Kernel (Low-Latency Desktop)" |
| 42 | 53 | depends on !ARCH_NO_PREEMPT |
| 43 | − select PREEMPT | |
| 54 | + select PREEMPT_BUILD | |
| 44 | 55 | help |
| 45 | 56 | This option reduces the latency of the kernel by making |
| 46 | 57 | all kernel code (that is not executing in a critical section) |
| @@ -58,7 +69,7 @@ config PREEMPT_BEHAVIOUR · 11 unmodified lines | ||
| 58 | 69 | |
| 59 | 70 | config PREEMPT_RT |
| 60 | 71 | bool "Fully Preemptible Kernel (Real-Time)" |
| 61 | − depends on EXPERT && ARCH_SUPPORTS_RT && !PREEMPT_DYNAMIC | |
| 72 | + depends on EXPERT && ARCH_SUPPORTS_RT | |
| 62 | 73 | select PREEMPTION |
| 63 | 74 | help |
| 64 | 75 | This option turns the kernel into a real-time kernel by replacing |
| @@ -75,17 +86,6 @@ config PREEMPT_RT · 10 unmodified lines | ||
| 75 | 86 | |
| 76 | 87 | endchoice |
| 77 | 88 | |
| 78 | −config PREEMPT_NONE | |
| 79 | − bool | |
| 80 | − | |
| 81 | −config PREEMPT_VOLUNTARY | |
| 82 | − bool | |
| 83 | − | |
| 84 | −config PREEMPT | |
| 85 | − bool | |
| 86 | − select PREEMPTION | |
| 87 | − select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK | |
| 88 | − | |
| 89 | 89 | config PREEMPT_COUNT |
| 90 | 90 | bool |
| 91 | 91 | |
| @@ -95,8 +95,8 @@ config PREEMPTION · 3 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | config PREEMPT_DYNAMIC |
| 97 | 97 | bool "Preemption behaviour defined on boot" |
| 98 | − depends on HAVE_PREEMPT_DYNAMIC | |
| 99 | − select PREEMPT | |
| 98 | + depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT | |
| 99 | + select PREEMPT_BUILD | |
| 100 | 100 | default y |
| 101 | 101 | help |
| 102 | 102 | This option allows to define the preemption model on the kernel |
| @@ -31,7 +31,7 @@ static inline void autogroup_destroy(struct kref *kref) · 30 unmodified lines | ||
| 31 | 31 | ag->tg->rt_se = NULL; |
| 32 | 32 | ag->tg->rt_rq = NULL; |
| 33 | 33 | #endif |
| 34 | − sched_offline_group(ag->tg); | |
| 34 | + sched_release_group(ag->tg); | |
| 35 | 35 | sched_destroy_group(ag->tg); |
| 36 | 36 | } |
| 37 | 37 | |
| @@ -3726,6 +3726,9 @@ out: · 3725 unmodified lines | ||
| 3726 | 3726 | |
| 3727 | 3727 | bool cpus_share_cache(int this_cpu, int that_cpu) |
| 3728 | 3728 | { |
| 3729 | + if (this_cpu == that_cpu) | |
| 3730 | + return true; | |
| 3731 | + | |
| 3729 | 3732 | return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); |
| 3730 | 3733 | } |
| 3731 | 3734 | |
| @@ -6625,13 +6628,13 @@ __setup("preempt=", setup_preempt_mode); · 2893 unmodified lines | ||
| 6625 | 6628 | static void __init preempt_dynamic_init(void) |
| 6626 | 6629 | { |
| 6627 | 6630 | if (preempt_dynamic_mode == preempt_dynamic_undefined) { |
| 6628 | − if (IS_ENABLED(CONFIG_PREEMPT_NONE_BEHAVIOUR)) { | |
| 6631 | + if (IS_ENABLED(CONFIG_PREEMPT_NONE)) { | |
| 6629 | 6632 | sched_dynamic_update(preempt_dynamic_none); |
| 6630 | − } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY_BEHAVIOUR)) { | |
| 6633 | + } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY)) { | |
| 6631 | 6634 | sched_dynamic_update(preempt_dynamic_voluntary); |
| 6632 | 6635 | } else { |
| 6633 | 6636 | /* Default static call setting, nothing to do */ |
| 6634 | − WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT_BEHAVIOUR)); | |
| 6637 | + WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT)); | |
| 6635 | 6638 | preempt_dynamic_mode = preempt_dynamic_full; |
| 6636 | 6639 | pr_info("Dynamic Preempt: full\n"); |
| 6637 | 6640 | } |
| @@ -9716,6 +9719,22 @@ static void sched_free_group(struct task_group *tg) · 3078 unmodified lines | ||
| 9716 | 9719 | kmem_cache_free(task_group_cache, tg); |
| 9717 | 9720 | } |
| 9718 | 9721 | |
| 9722 | +static void sched_free_group_rcu(struct rcu_head *rcu) | |
| 9723 | +{ | |
| 9724 | + sched_free_group(container_of(rcu, struct task_group, rcu)); | |
| 9725 | +} | |
| 9726 | + | |
| 9727 | +static void sched_unregister_group(struct task_group *tg) | |
| 9728 | +{ | |
| 9729 | + unregister_fair_sched_group(tg); | |
| 9730 | + unregister_rt_sched_group(tg); | |
| 9731 | + /* | |
| 9732 | + * We have to wait for yet another RCU grace period to expire, as | |
| 9733 | + * print_cfs_stats() might run concurrently. | |
| 9734 | + */ | |
| 9735 | + call_rcu(&tg->rcu, sched_free_group_rcu); | |
| 9736 | +} | |
| 9737 | + | |
| 9719 | 9738 | /* allocate runqueue etc for a new task group */ |
| 9720 | 9739 | struct task_group *sched_create_group(struct task_group *parent) |
| 9721 | 9740 | { |
| @@ -9759,25 +9778,35 @@ void sched_online_group(struct task_group *tg, struct task_group *parent) · 37 unmodified lines | ||
| 9759 | 9778 | } |
| 9760 | 9779 | |
| 9761 | 9780 | /* rcu callback to free various structures associated with a task group */ |
| 9762 | −static void sched_free_group_rcu(struct rcu_head *rhp) | |
| 9781 | +static void sched_unregister_group_rcu(struct rcu_head *rhp) | |
| 9763 | 9782 | { |
| 9764 | 9783 | /* Now it should be safe to free those cfs_rqs: */ |
| 9765 | − sched_free_group(container_of(rhp, struct task_group, rcu)); | |
| 9784 | + sched_unregister_group(container_of(rhp, struct task_group, rcu)); | |
| 9766 | 9785 | } |
| 9767 | 9786 | |
| 9768 | 9787 | void sched_destroy_group(struct task_group *tg) |
| 9769 | 9788 | { |
| 9770 | 9789 | /* Wait for possible concurrent references to cfs_rqs complete: */ |
| 9771 | − call_rcu(&tg->rcu, sched_free_group_rcu); | |
| 9790 | + call_rcu(&tg->rcu, sched_unregister_group_rcu); | |
| 9772 | 9791 | } |
| 9773 | 9792 | |
| 9774 | −void sched_offline_group(struct task_group *tg) | |
| 9793 | +void sched_release_group(struct task_group *tg) | |
| 9775 | 9794 | { |
| 9776 | 9795 | unsigned long flags; |
| 9777 | 9796 | |
| 9778 | − /* End participation in shares distribution: */ | |
| 9779 | − unregister_fair_sched_group(tg); | |
| 9780 | − | |
| 9797 | + /* | |
| 9798 | + * Unlink first, to avoid walk_tg_tree_from() from finding us (via | |
| 9799 | + * sched_cfs_period_timer()). | |
| 9800 | + * | |
| 9801 | + * For this to be effective, we have to wait for all pending users of | |
| 9802 | + * this task group to leave their RCU critical section to ensure no new | |
| 9803 | + * user will see our dying task group any more. Specifically ensure | |
| 9804 | + * that tg_unthrottle_up() won't add decayed cfs_rq's to it. | |
| 9805 | + * | |
| 9806 | + * We therefore defer calling unregister_fair_sched_group() to | |
| 9807 | + * sched_unregister_group() which is guarantied to get called only after the | |
| 9808 | + * current RCU grace period has expired. | |
| 9809 | + */ | |
| 9781 | 9810 | spin_lock_irqsave(&task_group_lock, flags); |
| 9782 | 9811 | list_del_rcu(&tg->list); |
| 9783 | 9812 | list_del_rcu(&tg->siblings); |
| @@ -9896,7 +9925,7 @@ static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) · 112 unmodified lines | ||
| 9896 | 9925 | { |
| 9897 | 9926 | struct task_group *tg = css_tg(css); |
| 9898 | 9927 | |
| 9899 | − sched_offline_group(tg); | |
| 9928 | + sched_release_group(tg); | |
| 9900 | 9929 | } |
| 9901 | 9930 | |
| 9902 | 9931 | static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) |
| @@ -9906,7 +9935,7 @@ static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) · 3 unmodified lines | ||
| 9906 | 9935 | /* |
| 9907 | 9936 | * Relies on the RCU grace period between css_released() and this. |
| 9908 | 9937 | */ |
| 9909 | − sched_free_group(tg); | |
| 9938 | + sched_unregister_group(tg); | |
| 9910 | 9939 | } |
| 9911 | 9940 | |
| 9912 | 9941 | /* |
| @@ -11456,8 +11456,6 @@ void free_fair_sched_group(struct task_group *tg) · 11455 unmodified lines | ||
| 11456 | 11456 | { |
| 11457 | 11457 | int i; |
| 11458 | 11458 | |
| 11459 | − destroy_cfs_bandwidth(tg_cfs_bandwidth(tg)); | |
| 11460 | − | |
| 11461 | 11459 | for_each_possible_cpu(i) { |
| 11462 | 11460 | if (tg->cfs_rq) |
| 11463 | 11461 | kfree(tg->cfs_rq[i]); |
| @@ -11534,6 +11532,8 @@ void unregister_fair_sched_group(struct task_group *tg) · 70 unmodified lines | ||
| 11534 | 11532 | struct rq *rq; |
| 11535 | 11533 | int cpu; |
| 11536 | 11534 | |
| 11535 | + destroy_cfs_bandwidth(tg_cfs_bandwidth(tg)); | |
| 11536 | + | |
| 11537 | 11537 | for_each_possible_cpu(cpu) { |
| 11538 | 11538 | if (tg->se[cpu]) |
| 11539 | 11539 | remove_entity_load_avg(tg->se[cpu]); |
| @@ -137,13 +137,17 @@ static inline struct rq *rq_of_rt_se(struct sched_rt_entity *rt_se) · 136 unmodified lines | ||
| 137 | 137 | return rt_rq->rq; |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | −void free_rt_sched_group(struct task_group *tg) | |
| 140 | +void unregister_rt_sched_group(struct task_group *tg) | |
| 141 | 141 | { |
| 142 | − int i; | |
| 143 | − | |
| 144 | 142 | if (tg->rt_se) |
| 145 | 143 | destroy_rt_bandwidth(&tg->rt_bandwidth); |
| 146 | 144 | |
| 145 | +} | |
| 146 | + | |
| 147 | +void free_rt_sched_group(struct task_group *tg) | |
| 148 | +{ | |
| 149 | + int i; | |
| 150 | + | |
| 147 | 151 | for_each_possible_cpu(i) { |
| 148 | 152 | if (tg->rt_rq) |
| 149 | 153 | kfree(tg->rt_rq[i]); |
| @@ -250,6 +254,8 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) · 100 unmodified lines | ||
| 250 | 254 | return &rq->rt; |
| 251 | 255 | } |
| 252 | 256 | |
| 257 | +void unregister_rt_sched_group(struct task_group *tg) { } | |
| 258 | + | |
| 253 | 259 | void free_rt_sched_group(struct task_group *tg) { } |
| 254 | 260 | |
| 255 | 261 | int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) |
| @@ -488,6 +488,7 @@ extern void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b); · 487 unmodified lines | ||
| 488 | 488 | extern void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b); |
| 489 | 489 | extern void unthrottle_cfs_rq(struct cfs_rq *cfs_rq); |
| 490 | 490 | |
| 491 | +extern void unregister_rt_sched_group(struct task_group *tg); | |
| 491 | 492 | extern void free_rt_sched_group(struct task_group *tg); |
| 492 | 493 | extern int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent); |
| 493 | 494 | extern void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, |
| @@ -503,7 +504,7 @@ extern struct task_group *sched_create_group(struct task_group *parent); · 9 unmodified lines | ||
| 503 | 504 | extern void sched_online_group(struct task_group *tg, |
| 504 | 505 | struct task_group *parent); |
| 505 | 506 | extern void sched_destroy_group(struct task_group *tg); |
| 506 | −extern void sched_offline_group(struct task_group *tg); | |
| 507 | +extern void sched_release_group(struct task_group *tg); | |
| 507 | 508 | |
| 508 | 509 | extern void sched_move_task(struct task_struct *tsk); |
| 509 | 510 | |