^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Populate sysfs with topology information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Written by: Matthew Dobson, IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2002, IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This program is distributed in the hope that it will be useful, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * NON INFRINGEMENT. See the GNU General Public License for more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * along with this program; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Send feedback to <colpatch@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/nodemask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/mmzone.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/io_apic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static DEFINE_PER_CPU(struct x86_cpu, cpu_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #ifdef CONFIG_BOOTPARAM_HOTPLUG_CPU0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int cpu0_hotpluggable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int cpu0_hotpluggable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int __init enable_cpu0_hotplug(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cpu0_hotpluggable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) __setup("cpu0_hotplug", enable_cpu0_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #ifdef CONFIG_DEBUG_HOTPLUG_CPU0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * This function offlines a CPU as early as possible and allows userspace to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * boot up without the CPU. The CPU can be onlined back by user after boot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * This is only called for debugging CPU offline/online feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int _debug_hotplug_cpu(int cpu, int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!cpu_is_hotpluggable(cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = remove_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pr_info("DEBUG_HOTPLUG_CPU0: CPU %u is now offline\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pr_debug("Can't offline CPU%d.\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = add_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pr_debug("Can't online CPU%d.\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int __init debug_hotplug_cpu(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) _debug_hotplug_cpu(0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) late_initcall_sync(debug_hotplug_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #endif /* CONFIG_DEBUG_HOTPLUG_CPU0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int arch_register_cpu(int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct cpuinfo_x86 *c = &cpu_data(num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * Currently CPU0 is only hotpluggable on Intel platforms. Other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * vendors can add hotplug support later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Xen PV guests don't support CPU0 hotplug at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (c->x86_vendor != X86_VENDOR_INTEL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) boot_cpu_has(X86_FEATURE_XENPV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) cpu0_hotpluggable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Two known BSP/CPU0 dependencies: Resume from suspend/hibernate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * depends on BSP. PIC interrupts depend on BSP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * If the BSP depencies are under control, one can tell kernel to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * enable BSP hotplug. This basically adds a control file and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * one can attempt to offline BSP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (num == 0 && cpu0_hotpluggable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * We won't take down the boot processor on i386 if some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * interrupts only are able to be serviced by the BSP in PIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) for_each_active_irq(irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!IO_APIC_IRQ(irq) && irq_has_action(irq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) cpu0_hotpluggable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (num || cpu0_hotpluggable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) per_cpu(cpu_devices, num).cpu.hotpluggable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EXPORT_SYMBOL(arch_register_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) void arch_unregister_cpu(int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unregister_cpu(&per_cpu(cpu_devices, num).cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) EXPORT_SYMBOL(arch_unregister_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #else /* CONFIG_HOTPLUG_CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int __init arch_register_cpu(int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #endif /* CONFIG_HOTPLUG_CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static int __init topology_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) for_each_online_node(i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) register_one_node(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) for_each_present_cpu(i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) arch_register_cpu(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) subsys_initcall(topology_init);