Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'topic/cpu-smt' into next

Merge SMT changes we are sharing with the tip tree.

+196 -85
+1
Documentation/ABI/testing/sysfs-devices-system-cpu
··· 555 555 ================ ========================================= 556 556 "on" SMT is enabled 557 557 "off" SMT is disabled 558 + "<N>" SMT is enabled with N threads per core. 558 559 "forceoff" SMT is force disabled. Cannot be changed. 559 560 "notsupported" SMT is not supported by the CPU 560 561 "notimplemented" SMT runtime toggling is not
+2 -2
Documentation/admin-guide/kernel-parameters.txt
··· 3853 3853 nosmp [SMP] Tells an SMP kernel to act as a UP kernel, 3854 3854 and disable the IO APIC. legacy for "maxcpus=0". 3855 3855 3856 - nosmt [KNL,MIPS,S390] Disable symmetric multithreading (SMT). 3856 + nosmt [KNL,MIPS,PPC,S390] Disable symmetric multithreading (SMT). 3857 3857 Equivalent to smt=1. 3858 3858 3859 - [KNL,X86] Disable symmetric multithreading (SMT). 3859 + [KNL,X86,PPC] Disable symmetric multithreading (SMT). 3860 3860 nosmt=force: Force disable SMT, cannot be undone 3861 3861 via the sysfs control file. 3862 3862
+3
arch/Kconfig
··· 34 34 config HOTPLUG_SMT 35 35 bool 36 36 37 + config SMT_NUM_THREADS_DYNAMIC 38 + bool 39 + 37 40 # Selected by HOTPLUG_CORE_SYNC_DEAD or HOTPLUG_CORE_SYNC_FULL 38 41 config HOTPLUG_CORE_SYNC 39 42 bool
+2
arch/powerpc/Kconfig
··· 272 272 select HAVE_SYSCALL_TRACEPOINTS 273 273 select HAVE_VIRT_CPU_ACCOUNTING 274 274 select HAVE_VIRT_CPU_ACCOUNTING_GEN 275 + select HOTPLUG_SMT if HOTPLUG_CPU 276 + select SMT_NUM_THREADS_DYNAMIC 275 277 select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE 276 278 select IOMMU_HELPER if PPC64 277 279 select IRQ_DOMAIN
+15
arch/powerpc/include/asm/topology.h
··· 143 143 #endif 144 144 #endif 145 145 146 + #ifdef CONFIG_HOTPLUG_SMT 147 + #include <linux/cpu_smt.h> 148 + #include <asm/cputhreads.h> 149 + 150 + static inline bool topology_is_primary_thread(unsigned int cpu) 151 + { 152 + return cpu == cpu_first_thread_sibling(cpu); 153 + } 154 + 155 + static inline bool topology_smt_thread_allowed(unsigned int cpu) 156 + { 157 + return cpu_thread_in_core(cpu) < cpu_smt_num_threads; 158 + } 159 + #endif 160 + 146 161 #endif /* __KERNEL__ */ 147 162 #endif /* _ASM_POWERPC_TOPOLOGY_H */
+7 -1
arch/powerpc/kernel/smp.c
··· 1088 1088 1089 1089 void __init smp_prepare_cpus(unsigned int max_cpus) 1090 1090 { 1091 - unsigned int cpu; 1091 + unsigned int cpu, num_threads; 1092 1092 1093 1093 DBG("smp_prepare_cpus\n"); 1094 1094 ··· 1155 1155 1156 1156 if (smp_ops && smp_ops->probe) 1157 1157 smp_ops->probe(); 1158 + 1159 + // Initalise the generic SMT topology support 1160 + num_threads = 1; 1161 + if (smt_enabled_at_boot) 1162 + num_threads = smt_enabled_at_boot; 1163 + cpu_smt_set_num_threads(num_threads, threads_per_core); 1158 1164 } 1159 1165 1160 1166 void smp_prepare_boot_cpu(void)
+21 -9
arch/powerpc/platforms/pseries/hotplug-cpu.c
··· 398 398 for_each_present_cpu(cpu) { 399 399 if (get_hard_smp_processor_id(cpu) != thread) 400 400 continue; 401 + 402 + if (!topology_is_primary_thread(cpu)) { 403 + if (cpu_smt_control != CPU_SMT_ENABLED) 404 + break; 405 + if (!topology_smt_thread_allowed(cpu)) 406 + break; 407 + } 408 + 401 409 cpu_maps_update_done(); 402 410 find_and_update_cpu_nid(cpu); 403 411 rc = device_online(get_cpu_device(cpu)); ··· 853 845 .notifier_call = pseries_smp_notifier, 854 846 }; 855 847 856 - static int __init pseries_cpu_hotplug_init(void) 848 + void __init pseries_cpu_hotplug_init(void) 857 849 { 858 850 int qcss_tok; 859 - unsigned int node; 860 - 861 - #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 862 - ppc_md.cpu_probe = dlpar_cpu_probe; 863 - ppc_md.cpu_release = dlpar_cpu_release; 864 - #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ 865 851 866 852 rtas_stop_self_token = rtas_function_token(RTAS_FN_STOP_SELF); 867 853 qcss_tok = rtas_function_token(RTAS_FN_QUERY_CPU_STOPPED_STATE); ··· 864 862 qcss_tok == RTAS_UNKNOWN_SERVICE) { 865 863 printk(KERN_INFO "CPU Hotplug not supported by firmware " 866 864 "- disabling.\n"); 867 - return 0; 865 + return; 868 866 } 869 867 870 868 smp_ops->cpu_offline_self = pseries_cpu_offline_self; 871 869 smp_ops->cpu_disable = pseries_cpu_disable; 872 870 smp_ops->cpu_die = pseries_cpu_die; 871 + } 872 + 873 + static int __init pseries_dlpar_init(void) 874 + { 875 + unsigned int node; 876 + 877 + #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 878 + ppc_md.cpu_probe = dlpar_cpu_probe; 879 + ppc_md.cpu_release = dlpar_cpu_release; 880 + #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ 873 881 874 882 /* Processors can be added/removed only on LPAR */ 875 883 if (firmware_has_feature(FW_FEATURE_LPAR)) { ··· 898 886 899 887 return 0; 900 888 } 901 - machine_arch_initcall(pseries, pseries_cpu_hotplug_init); 889 + machine_arch_initcall(pseries, pseries_dlpar_init);
+2
arch/powerpc/platforms/pseries/pseries.h
··· 75 75 76 76 #ifdef CONFIG_HOTPLUG_CPU 77 77 int dlpar_cpu(struct pseries_hp_errorlog *hp_elog); 78 + void pseries_cpu_hotplug_init(void); 78 79 #else 79 80 static inline int dlpar_cpu(struct pseries_hp_errorlog *hp_elog) 80 81 { 81 82 return -EOPNOTSUPP; 82 83 } 84 + static inline void pseries_cpu_hotplug_init(void) { } 83 85 #endif 84 86 85 87 /* PCI root bridge prepare function override for pseries */
+2
arch/powerpc/platforms/pseries/setup.c
··· 816 816 /* Discover PIC type and setup ppc_md accordingly */ 817 817 smp_init_pseries(); 818 818 819 + // Setup CPU hotplug callbacks 820 + pseries_cpu_hotplug_init(); 819 821 820 822 if (radix_enabled() && !mmu_has_feature(MMU_FTR_GTSE)) 821 823 if (!firmware_has_feature(FW_FEATURE_RPT_INVALIDATE))
+2 -2
arch/x86/include/asm/topology.h
··· 136 136 return __max_smt_threads; 137 137 } 138 138 139 + #include <linux/cpu_smt.h> 140 + 139 141 int topology_update_package_map(unsigned int apicid, unsigned int cpu); 140 142 int topology_update_die_map(unsigned int dieid, unsigned int cpu); 141 143 int topology_phys_to_logical_pkg(unsigned int pkg); 142 - bool topology_smt_supported(void); 143 144 144 145 extern struct cpumask __cpu_primary_thread_mask; 145 146 #define cpu_primary_thread_mask ((const struct cpumask *)&__cpu_primary_thread_mask) ··· 163 162 static inline int topology_max_die_per_package(void) { return 1; } 164 163 static inline int topology_max_smt_threads(void) { return 1; } 165 164 static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } 166 - static inline bool topology_smt_supported(void) { return false; } 167 165 #endif /* !CONFIG_SMP */ 168 166 169 167 static inline void arch_fix_phys_package_id(int num, u32 slot)
+1 -1
arch/x86/kernel/cpu/common.c
··· 2317 2317 * identify_boot_cpu() initialized SMT support information, let the 2318 2318 * core code know. 2319 2319 */ 2320 - cpu_smt_check_topology(); 2320 + cpu_smt_set_num_threads(smp_num_siblings, smp_num_siblings); 2321 2321 2322 2322 if (!IS_ENABLED(CONFIG_SMP)) { 2323 2323 pr_info("CPU: ");
-8
arch/x86/kernel/smpboot.c
··· 327 327 } 328 328 329 329 /** 330 - * topology_smt_supported - Check whether SMT is supported by the CPUs 331 - */ 332 - bool topology_smt_supported(void) 333 - { 334 - return smp_num_siblings > 1; 335 - } 336 - 337 - /** 338 330 * topology_phys_to_logical_pkg - Map a physical package id to a logical 339 331 * @phys_pkg: The physical package id to map 340 332 *
+1 -24
include/linux/cpu.h
··· 18 18 #include <linux/compiler.h> 19 19 #include <linux/cpumask.h> 20 20 #include <linux/cpuhotplug.h> 21 + #include <linux/cpu_smt.h> 21 22 22 23 struct device; 23 24 struct device_node; ··· 204 203 #else 205 204 static inline void cpuhp_report_idle_dead(void) { } 206 205 #endif /* #ifdef CONFIG_HOTPLUG_CPU */ 207 - 208 - enum cpuhp_smt_control { 209 - CPU_SMT_ENABLED, 210 - CPU_SMT_DISABLED, 211 - CPU_SMT_FORCE_DISABLED, 212 - CPU_SMT_NOT_SUPPORTED, 213 - CPU_SMT_NOT_IMPLEMENTED, 214 - }; 215 - 216 - #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) 217 - extern enum cpuhp_smt_control cpu_smt_control; 218 - extern void cpu_smt_disable(bool force); 219 - extern void cpu_smt_check_topology(void); 220 - extern bool cpu_smt_possible(void); 221 - extern int cpuhp_smt_enable(void); 222 - extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); 223 - #else 224 - # define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED) 225 - static inline void cpu_smt_disable(bool force) { } 226 - static inline void cpu_smt_check_topology(void) { } 227 - static inline bool cpu_smt_possible(void) { return false; } 228 - static inline int cpuhp_smt_enable(void) { return 0; } 229 - static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } 230 - #endif 231 206 232 207 extern bool cpu_mitigations_off(void); 233 208 extern bool cpu_mitigations_auto_nosmt(void);
+33
include/linux/cpu_smt.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _LINUX_CPU_SMT_H_ 3 + #define _LINUX_CPU_SMT_H_ 4 + 5 + enum cpuhp_smt_control { 6 + CPU_SMT_ENABLED, 7 + CPU_SMT_DISABLED, 8 + CPU_SMT_FORCE_DISABLED, 9 + CPU_SMT_NOT_SUPPORTED, 10 + CPU_SMT_NOT_IMPLEMENTED, 11 + }; 12 + 13 + #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) 14 + extern enum cpuhp_smt_control cpu_smt_control; 15 + extern unsigned int cpu_smt_num_threads; 16 + extern void cpu_smt_disable(bool force); 17 + extern void cpu_smt_set_num_threads(unsigned int num_threads, 18 + unsigned int max_threads); 19 + extern bool cpu_smt_possible(void); 20 + extern int cpuhp_smt_enable(void); 21 + extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); 22 + #else 23 + # define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED) 24 + # define cpu_smt_num_threads 1 25 + static inline void cpu_smt_disable(bool force) { } 26 + static inline void cpu_smt_set_num_threads(unsigned int num_threads, 27 + unsigned int max_threads) { } 28 + static inline bool cpu_smt_possible(void) { return false; } 29 + static inline int cpuhp_smt_enable(void) { return 0; } 30 + static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } 31 + #endif 32 + 33 + #endif /* _LINUX_CPU_SMT_H_ */
+104 -38
kernel/cpu.c
··· 592 592 void __weak arch_smt_update(void) { } 593 593 594 594 #ifdef CONFIG_HOTPLUG_SMT 595 + 595 596 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; 597 + static unsigned int cpu_smt_max_threads __ro_after_init; 598 + unsigned int cpu_smt_num_threads __read_mostly = UINT_MAX; 596 599 597 600 void __init cpu_smt_disable(bool force) 598 601 { ··· 609 606 pr_info("SMT: disabled\n"); 610 607 cpu_smt_control = CPU_SMT_DISABLED; 611 608 } 609 + cpu_smt_num_threads = 1; 612 610 } 613 611 614 612 /* 615 613 * The decision whether SMT is supported can only be done after the full 616 614 * CPU identification. Called from architecture code. 617 615 */ 618 - void __init cpu_smt_check_topology(void) 616 + void __init cpu_smt_set_num_threads(unsigned int num_threads, 617 + unsigned int max_threads) 619 618 { 620 - if (!topology_smt_supported()) 619 + WARN_ON(!num_threads || (num_threads > max_threads)); 620 + 621 + if (max_threads == 1) 621 622 cpu_smt_control = CPU_SMT_NOT_SUPPORTED; 623 + 624 + cpu_smt_max_threads = max_threads; 625 + 626 + /* 627 + * If SMT has been disabled via the kernel command line or SMT is 628 + * not supported, set cpu_smt_num_threads to 1 for consistency. 629 + * If enabled, take the architecture requested number of threads 630 + * to bring up into account. 631 + */ 632 + if (cpu_smt_control != CPU_SMT_ENABLED) 633 + cpu_smt_num_threads = 1; 634 + else if (num_threads < cpu_smt_num_threads) 635 + cpu_smt_num_threads = num_threads; 622 636 } 623 637 624 638 static int __init smt_cmdline_disable(char *str) ··· 645 625 } 646 626 early_param("nosmt", smt_cmdline_disable); 647 627 628 + /* 629 + * For Archicture supporting partial SMT states check if the thread is allowed. 630 + * Otherwise this has already been checked through cpu_smt_max_threads when 631 + * setting the SMT level. 632 + */ 633 + static inline bool cpu_smt_thread_allowed(unsigned int cpu) 634 + { 635 + #ifdef CONFIG_SMT_NUM_THREADS_DYNAMIC 636 + return topology_smt_thread_allowed(cpu); 637 + #else 638 + return true; 639 + #endif 640 + } 641 + 648 642 static inline bool cpu_smt_allowed(unsigned int cpu) 649 643 { 650 - if (cpu_smt_control == CPU_SMT_ENABLED) 644 + if (cpu_smt_control == CPU_SMT_ENABLED && cpu_smt_thread_allowed(cpu)) 651 645 return true; 652 646 653 647 if (topology_is_primary_thread(cpu)) ··· 684 650 } 685 651 EXPORT_SYMBOL_GPL(cpu_smt_possible); 686 652 687 - static inline bool cpuhp_smt_aware(void) 688 - { 689 - return topology_smt_supported(); 690 - } 691 - 692 - static inline const struct cpumask *cpuhp_get_primary_thread_mask(void) 693 - { 694 - return cpu_primary_thread_mask; 695 - } 696 653 #else 697 654 static inline bool cpu_smt_allowed(unsigned int cpu) { return true; } 698 - static inline bool cpuhp_smt_aware(void) { return false; } 699 - static inline const struct cpumask *cpuhp_get_primary_thread_mask(void) 700 - { 701 - return cpu_present_mask; 702 - } 703 655 #endif 704 656 705 657 static inline enum cpuhp_state ··· 1813 1793 } 1814 1794 early_param("cpuhp.parallel", parallel_bringup_parse_param); 1815 1795 1796 + static inline bool cpuhp_smt_aware(void) 1797 + { 1798 + return cpu_smt_max_threads > 1; 1799 + } 1800 + 1801 + static inline const struct cpumask *cpuhp_get_primary_thread_mask(void) 1802 + { 1803 + return cpu_primary_thread_mask; 1804 + } 1805 + 1816 1806 /* 1817 1807 * On architectures which have enabled parallel bringup this invokes all BP 1818 1808 * prepare states for each of the to be onlined APs first. The last state ··· 2656 2626 for_each_online_cpu(cpu) { 2657 2627 if (topology_is_primary_thread(cpu)) 2658 2628 continue; 2629 + /* 2630 + * Disable can be called with CPU_SMT_ENABLED when changing 2631 + * from a higher to lower number of SMT threads per core. 2632 + */ 2633 + if (ctrlval == CPU_SMT_ENABLED && cpu_smt_thread_allowed(cpu)) 2634 + continue; 2659 2635 ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE); 2660 2636 if (ret) 2661 2637 break; ··· 2695 2659 for_each_present_cpu(cpu) { 2696 2660 /* Skip online CPUs and CPUs on offline nodes */ 2697 2661 if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) 2662 + continue; 2663 + if (!cpu_smt_thread_allowed(cpu)) 2698 2664 continue; 2699 2665 ret = _cpu_up(cpu, 0, CPUHP_ONLINE); 2700 2666 if (ret) ··· 2876 2838 2877 2839 #ifdef CONFIG_HOTPLUG_SMT 2878 2840 2841 + static bool cpu_smt_num_threads_valid(unsigned int threads) 2842 + { 2843 + if (IS_ENABLED(CONFIG_SMT_NUM_THREADS_DYNAMIC)) 2844 + return threads >= 1 && threads <= cpu_smt_max_threads; 2845 + return threads == 1 || threads == cpu_smt_max_threads; 2846 + } 2847 + 2879 2848 static ssize_t 2880 2849 __store_smt_control(struct device *dev, struct device_attribute *attr, 2881 2850 const char *buf, size_t count) 2882 2851 { 2883 - int ctrlval, ret; 2884 - 2885 - if (sysfs_streq(buf, "on")) 2886 - ctrlval = CPU_SMT_ENABLED; 2887 - else if (sysfs_streq(buf, "off")) 2888 - ctrlval = CPU_SMT_DISABLED; 2889 - else if (sysfs_streq(buf, "forceoff")) 2890 - ctrlval = CPU_SMT_FORCE_DISABLED; 2891 - else 2892 - return -EINVAL; 2852 + int ctrlval, ret, num_threads, orig_threads; 2853 + bool force_off; 2893 2854 2894 2855 if (cpu_smt_control == CPU_SMT_FORCE_DISABLED) 2895 2856 return -EPERM; ··· 2896 2859 if (cpu_smt_control == CPU_SMT_NOT_SUPPORTED) 2897 2860 return -ENODEV; 2898 2861 2862 + if (sysfs_streq(buf, "on")) { 2863 + ctrlval = CPU_SMT_ENABLED; 2864 + num_threads = cpu_smt_max_threads; 2865 + } else if (sysfs_streq(buf, "off")) { 2866 + ctrlval = CPU_SMT_DISABLED; 2867 + num_threads = 1; 2868 + } else if (sysfs_streq(buf, "forceoff")) { 2869 + ctrlval = CPU_SMT_FORCE_DISABLED; 2870 + num_threads = 1; 2871 + } else if (kstrtoint(buf, 10, &num_threads) == 0) { 2872 + if (num_threads == 1) 2873 + ctrlval = CPU_SMT_DISABLED; 2874 + else if (cpu_smt_num_threads_valid(num_threads)) 2875 + ctrlval = CPU_SMT_ENABLED; 2876 + else 2877 + return -EINVAL; 2878 + } else { 2879 + return -EINVAL; 2880 + } 2881 + 2899 2882 ret = lock_device_hotplug_sysfs(); 2900 2883 if (ret) 2901 2884 return ret; 2902 2885 2903 - if (ctrlval != cpu_smt_control) { 2904 - switch (ctrlval) { 2905 - case CPU_SMT_ENABLED: 2906 - ret = cpuhp_smt_enable(); 2907 - break; 2908 - case CPU_SMT_DISABLED: 2909 - case CPU_SMT_FORCE_DISABLED: 2910 - ret = cpuhp_smt_disable(ctrlval); 2911 - break; 2912 - } 2913 - } 2886 + orig_threads = cpu_smt_num_threads; 2887 + cpu_smt_num_threads = num_threads; 2888 + 2889 + force_off = ctrlval != cpu_smt_control && ctrlval == CPU_SMT_FORCE_DISABLED; 2890 + 2891 + if (num_threads > orig_threads) 2892 + ret = cpuhp_smt_enable(); 2893 + else if (num_threads < orig_threads || force_off) 2894 + ret = cpuhp_smt_disable(ctrlval); 2914 2895 2915 2896 unlock_device_hotplug(); 2916 2897 return ret ? ret : count; ··· 2955 2900 struct device_attribute *attr, char *buf) 2956 2901 { 2957 2902 const char *state = smt_states[cpu_smt_control]; 2903 + 2904 + #ifdef CONFIG_HOTPLUG_SMT 2905 + /* 2906 + * If SMT is enabled but not all threads are enabled then show the 2907 + * number of threads. If all threads are enabled show "on". Otherwise 2908 + * show the state name. 2909 + */ 2910 + if (cpu_smt_control == CPU_SMT_ENABLED && 2911 + cpu_smt_num_threads != cpu_smt_max_threads) 2912 + return sysfs_emit(buf, "%d\n", cpu_smt_num_threads); 2913 + #endif 2958 2914 2959 2915 return snprintf(buf, PAGE_SIZE - 2, "%s\n", state); 2960 2916 }