mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 17:59:32 +00:00
![Juri Lelli](/assets/img/avatar_default.png)
DEBUG_HOTPLUG_CPU0 debug feature offlines a CPU as early as possible allowing userspace to boot up without that CPU (so that it is possible to check for unwanted dependencies towards the offlined CPU). After doing so it emits a "CPU %u is now offline" pr_info, which is not enough descriptive of why the CPU was offlined (e.g., one might be running with a config that triggered some problem, not being aware that CONFIG_DEBUG_ HOTPLUG_CPU0 is set). Add a bit more of informative text to the pr_info, so that it is immediately obvious why a CPU has been offlined in early boot stages. Background: Got to scratch my head a bit while debugging a WARNING splat related to the offlining of CPU0. Without being aware yet of this debug option it wasn't immediately obvious why CPU0 was being offlined by the kernel. Signed-off-by: Juri Lelli <juri.lelli@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: fenghua.yu@intel.com Link: http://lkml.kernel.org/r/20181219151647.15073-1-juri.lelli@redhat.com [ Merge line-broken line. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
175 lines
4.2 KiB
C
175 lines
4.2 KiB
C
/*
|
|
* Populate sysfs with topology information
|
|
*
|
|
* Written by: Matthew Dobson, IBM Corporation
|
|
* Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
|
|
*
|
|
* Copyright (C) 2002, IBM Corp.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* Send feedback to <colpatch@us.ibm.com>
|
|
*/
|
|
#include <linux/nodemask.h>
|
|
#include <linux/export.h>
|
|
#include <linux/mmzone.h>
|
|
#include <linux/init.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/irq.h>
|
|
#include <asm/cpu.h>
|
|
|
|
static DEFINE_PER_CPU(struct x86_cpu, cpu_devices);
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
|
#ifdef CONFIG_BOOTPARAM_HOTPLUG_CPU0
|
|
static int cpu0_hotpluggable = 1;
|
|
#else
|
|
static int cpu0_hotpluggable;
|
|
static int __init enable_cpu0_hotplug(char *str)
|
|
{
|
|
cpu0_hotpluggable = 1;
|
|
return 1;
|
|
}
|
|
|
|
__setup("cpu0_hotplug", enable_cpu0_hotplug);
|
|
#endif
|
|
|
|
#ifdef CONFIG_DEBUG_HOTPLUG_CPU0
|
|
/*
|
|
* This function offlines a CPU as early as possible and allows userspace to
|
|
* boot up without the CPU. The CPU can be onlined back by user after boot.
|
|
*
|
|
* This is only called for debugging CPU offline/online feature.
|
|
*/
|
|
int _debug_hotplug_cpu(int cpu, int action)
|
|
{
|
|
struct device *dev = get_cpu_device(cpu);
|
|
int ret;
|
|
|
|
if (!cpu_is_hotpluggable(cpu))
|
|
return -EINVAL;
|
|
|
|
lock_device_hotplug();
|
|
|
|
switch (action) {
|
|
case 0:
|
|
ret = cpu_down(cpu);
|
|
if (!ret) {
|
|
pr_info("DEBUG_HOTPLUG_CPU0: CPU %u is now offline\n", cpu);
|
|
dev->offline = true;
|
|
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
|
} else
|
|
pr_debug("Can't offline CPU%d.\n", cpu);
|
|
break;
|
|
case 1:
|
|
ret = cpu_up(cpu);
|
|
if (!ret) {
|
|
dev->offline = false;
|
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
|
} else {
|
|
pr_debug("Can't online CPU%d.\n", cpu);
|
|
}
|
|
break;
|
|
default:
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
unlock_device_hotplug();
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int __init debug_hotplug_cpu(void)
|
|
{
|
|
_debug_hotplug_cpu(0, 0);
|
|
return 0;
|
|
}
|
|
|
|
late_initcall_sync(debug_hotplug_cpu);
|
|
#endif /* CONFIG_DEBUG_HOTPLUG_CPU0 */
|
|
|
|
int arch_register_cpu(int num)
|
|
{
|
|
struct cpuinfo_x86 *c = &cpu_data(num);
|
|
|
|
/*
|
|
* Currently CPU0 is only hotpluggable on Intel platforms. Other
|
|
* vendors can add hotplug support later.
|
|
* Xen PV guests don't support CPU0 hotplug at all.
|
|
*/
|
|
if (c->x86_vendor != X86_VENDOR_INTEL ||
|
|
boot_cpu_has(X86_FEATURE_XENPV))
|
|
cpu0_hotpluggable = 0;
|
|
|
|
/*
|
|
* Two known BSP/CPU0 dependencies: Resume from suspend/hibernate
|
|
* depends on BSP. PIC interrupts depend on BSP.
|
|
*
|
|
* If the BSP depencies are under control, one can tell kernel to
|
|
* enable BSP hotplug. This basically adds a control file and
|
|
* one can attempt to offline BSP.
|
|
*/
|
|
if (num == 0 && cpu0_hotpluggable) {
|
|
unsigned int irq;
|
|
/*
|
|
* We won't take down the boot processor on i386 if some
|
|
* interrupts only are able to be serviced by the BSP in PIC.
|
|
*/
|
|
for_each_active_irq(irq) {
|
|
if (!IO_APIC_IRQ(irq) && irq_has_action(irq)) {
|
|
cpu0_hotpluggable = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (num || cpu0_hotpluggable)
|
|
per_cpu(cpu_devices, num).cpu.hotpluggable = 1;
|
|
|
|
return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
|
|
}
|
|
EXPORT_SYMBOL(arch_register_cpu);
|
|
|
|
void arch_unregister_cpu(int num)
|
|
{
|
|
unregister_cpu(&per_cpu(cpu_devices, num).cpu);
|
|
}
|
|
EXPORT_SYMBOL(arch_unregister_cpu);
|
|
#else /* CONFIG_HOTPLUG_CPU */
|
|
|
|
static int __init arch_register_cpu(int num)
|
|
{
|
|
return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
|
|
}
|
|
#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
|
static int __init topology_init(void)
|
|
{
|
|
int i;
|
|
|
|
#ifdef CONFIG_NUMA
|
|
for_each_online_node(i)
|
|
register_one_node(i);
|
|
#endif
|
|
|
|
for_each_present_cpu(i)
|
|
arch_register_cpu(i);
|
|
|
|
return 0;
|
|
}
|
|
subsys_initcall(topology_init);
|