mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Xen PV guests don't allow CPU0 hotplug, so disable it. Signed-off-by: Juergen Gross <jgross@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: boris.ostrovsky@oracle.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/20180912174122.24282-1-jgross@suse.com 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("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);
 |