2005-04-17 02:20:36 +04:00
/*
2017-09-21 22:55:01 +03:00
* arch / parisc / kernel / topology . c
2005-04-17 02:20:36 +04:00
*
2017-09-21 22:55:01 +03:00
* Copyright ( C ) 2017 Helge Deller < deller @ gmx . de >
2005-04-17 02:20:36 +04:00
*
2017-09-21 22:55:01 +03:00
* based on arch / arm / kernel / topology . c
2005-04-17 02:20:36 +04:00
*
2017-09-21 22:55:01 +03:00
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
2005-04-17 02:20:36 +04:00
*/
2017-09-21 22:55:01 +03:00
# include <linux/percpu.h>
# include <linux/sched.h>
# include <linux/sched/topology.h>
2022-03-24 21:46:50 +03:00
# include <linux/cpu.h>
2005-04-17 02:20:36 +04:00
2017-09-21 22:55:01 +03:00
# include <asm/topology.h>
2022-03-25 14:50:13 +03:00
# include <asm/sections.h>
2005-04-17 02:20:36 +04:00
2022-03-24 21:46:50 +03:00
static DEFINE_PER_CPU ( struct cpu , cpu_devices ) ;
2017-09-21 22:55:01 +03:00
/*
* store_cpu_topology is called at boot when only one cpu is running
* and with the mutex cpu_hotplug . lock locked , when several cpus have booted ,
* which prevents simultaneous write access to cpu_topology array
*/
2022-03-25 14:50:13 +03:00
void store_cpu_topology ( unsigned int cpuid )
2017-09-21 22:55:01 +03:00
{
2022-03-24 21:46:50 +03:00
struct cpu_topology * cpuid_topo = & cpu_topology [ cpuid ] ;
2017-09-21 22:55:01 +03:00
struct cpuinfo_parisc * p ;
int max_socket = - 1 ;
unsigned long cpu ;
/* If the cpu topology has been already set, just return */
if ( cpuid_topo - > core_id ! = - 1 )
return ;
2005-04-17 02:20:36 +04:00
2022-03-24 21:46:50 +03:00
# ifdef CONFIG_HOTPLUG_CPU
per_cpu ( cpu_devices , cpuid ) . hotpluggable = 1 ;
# endif
if ( register_cpu ( & per_cpu ( cpu_devices , cpuid ) , cpuid ) )
pr_warn ( " Failed to register CPU%d device " , cpuid ) ;
2017-09-21 22:55:01 +03:00
/* create cpu topology mapping */
cpuid_topo - > thread_id = - 1 ;
cpuid_topo - > core_id = 0 ;
p = & per_cpu ( cpu_data , cpuid ) ;
for_each_online_cpu ( cpu ) {
const struct cpuinfo_parisc * cpuinfo = & per_cpu ( cpu_data , cpu ) ;
if ( cpu = = cpuid ) /* ignore current cpu */
continue ;
if ( cpuinfo - > cpu_loc = = p - > cpu_loc ) {
cpuid_topo - > core_id = cpu_topology [ cpu ] . core_id ;
if ( p - > cpu_loc ) {
cpuid_topo - > core_id + + ;
2022-03-24 21:46:50 +03:00
cpuid_topo - > package_id = cpu_topology [ cpu ] . package_id ;
2017-09-21 22:55:01 +03:00
continue ;
}
}
2022-03-24 21:46:50 +03:00
if ( cpuid_topo - > package_id = = - 1 )
max_socket = max ( max_socket , cpu_topology [ cpu ] . package_id ) ;
2005-04-17 02:20:36 +04:00
}
2017-09-21 22:55:01 +03:00
2022-03-24 21:46:50 +03:00
if ( cpuid_topo - > package_id = = - 1 )
cpuid_topo - > package_id = max_socket + 1 ;
2017-09-21 22:55:01 +03:00
update_siblings_masks ( cpuid ) ;
2022-03-18 01:01:09 +03:00
pr_info ( " CPU%u: cpu core %d of socket %d \n " ,
cpuid ,
2017-09-21 22:55:01 +03:00
cpu_topology [ cpuid ] . core_id ,
2022-03-24 21:46:50 +03:00
cpu_topology [ cpuid ] . package_id ) ;
2005-04-17 02:20:36 +04:00
}
2017-09-21 22:55:01 +03:00
/*
* init_cpu_topology is called at boot when only one cpu is running
* which prevent simultaneous write access to cpu_topology array
*/
void __init init_cpu_topology ( void )
{
parisc: fix a crash with multicore scheduler
With the kernel 5.18, the system will hang on boot if it is compiled with
CONFIG_SCHED_MC. The last printed message is "Brought up 1 node, 1 CPU".
The crash happens in sd_init
tl->mask (which is cpu_coregroup_mask) returns an empty mask. This happens
because cpu_topology[0].core_sibling is empty.
Consequently, sd_span is set to an empty mask
sd_id = cpumask_first(sd_span) sets sd_id == NR_CPUS (because the mask is
empty)
sd->shared = *per_cpu_ptr(sdd->sds, sd_id); sets sd->shared to NULL
because sd_id is out of range
atomic_inc(&sd->shared->ref); crashes without printing anything
We can fix it by calling reset_cpu_topology() from init_cpu_topology() -
this will initialize the sibling masks on CPUs, so that they're not empty.
This patch also removes the variable "dualcores_found", it is useless,
because during boot, init_cpu_topology is called before
store_cpu_topology. Thus, set_sched_topology(parisc_mc_topology) is never
called. We don't need to call it at all because default_topology in
kernel/sched/topology.c contains the same items as parisc_mc_topology.
Note that we should not call store_cpu_topology() from init_per_cpu()
because it is called too early in the kernel initialization process and it
results in the message "Failure to register CPU0 device". Before this
patch, store_cpu_topology() would exit immediatelly because
cpuid_topo->core id was uninitialized and it was 0.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org # v5.18
Signed-off-by: Helge Deller <deller@gmx.de>
2022-06-01 20:18:22 +03:00
reset_cpu_topology ( ) ;
2017-09-21 22:55:01 +03:00
}