Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * SMP initialisation and IPI support
  4 * Based on arch/arm64/kernel/smp.c
  5 *
  6 * Copyright (C) 2012 ARM Ltd.
  7 * Copyright (C) 2015 Regents of the University of California
  8 * Copyright (C) 2017 SiFive
  9 */
 10
 11#include <linux/arch_topology.h>
 12#include <linux/module.h>
 13#include <linux/init.h>
 14#include <linux/kernel.h>
 15#include <linux/mm.h>
 16#include <linux/sched.h>
 17#include <linux/kernel_stat.h>
 18#include <linux/notifier.h>
 19#include <linux/cpu.h>
 20#include <linux/percpu.h>
 21#include <linux/delay.h>
 22#include <linux/err.h>
 23#include <linux/irq.h>
 24#include <linux/of.h>
 25#include <linux/sched/task_stack.h>
 26#include <linux/sched/mm.h>
 27#include <asm/cpu_ops.h>
 28#include <asm/irq.h>
 29#include <asm/mmu_context.h>
 30#include <asm/numa.h>
 31#include <asm/tlbflush.h>
 32#include <asm/sections.h>
 33#include <asm/sbi.h>
 34#include <asm/smp.h>
 
 35
 36#include "head.h"
 37
 38static DECLARE_COMPLETION(cpu_running);
 39
 40void __init smp_prepare_boot_cpu(void)
 41{
 
 
 
 
 42}
 43
 44void __init smp_prepare_cpus(unsigned int max_cpus)
 45{
 46	int cpuid;
 47	int ret;
 48	unsigned int curr_cpuid;
 49
 50	init_cpu_topology();
 51
 52	curr_cpuid = smp_processor_id();
 53	store_cpu_topology(curr_cpuid);
 54	numa_store_cpu_info(curr_cpuid);
 55	numa_add_cpu(curr_cpuid);
 56
 57	/* This covers non-smp usecase mandated by "nosmp" option */
 58	if (max_cpus == 0)
 59		return;
 60
 61	for_each_possible_cpu(cpuid) {
 62		if (cpuid == curr_cpuid)
 63			continue;
 64		if (cpu_ops[cpuid]->cpu_prepare) {
 65			ret = cpu_ops[cpuid]->cpu_prepare(cpuid);
 66			if (ret)
 67				continue;
 68		}
 69		set_cpu_present(cpuid, true);
 70		numa_store_cpu_info(cpuid);
 71	}
 72}
 73
 74void __init setup_smp(void)
 75{
 76	struct device_node *dn;
 77	unsigned long hart;
 78	bool found_boot_cpu = false;
 79	int cpuid = 1;
 80	int rc;
 81
 82	cpu_set_ops(0);
 83
 84	for_each_of_cpu_node(dn) {
 85		rc = riscv_of_processor_hartid(dn, &hart);
 86		if (rc < 0)
 87			continue;
 88
 89		if (hart == cpuid_to_hartid_map(0)) {
 90			BUG_ON(found_boot_cpu);
 91			found_boot_cpu = 1;
 92			early_map_cpu_to_node(0, of_node_to_nid(dn));
 93			continue;
 94		}
 95		if (cpuid >= NR_CPUS) {
 96			pr_warn("Invalid cpuid [%d] for hartid [%lu]\n",
 97				cpuid, hart);
 98			continue;
 99		}
100
101		cpuid_to_hartid_map(cpuid) = hart;
102		early_map_cpu_to_node(cpuid, of_node_to_nid(dn));
103		cpuid++;
104	}
105
106	BUG_ON(!found_boot_cpu);
107
108	if (cpuid > nr_cpu_ids)
109		pr_warn("Total number of cpus [%d] is greater than nr_cpus option value [%d]\n",
110			cpuid, nr_cpu_ids);
111
112	for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) {
113		if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) {
114			cpu_set_ops(cpuid);
115			set_cpu_possible(cpuid, true);
116		}
117	}
118}
119
120static int start_secondary_cpu(int cpu, struct task_struct *tidle)
121{
122	if (cpu_ops[cpu]->cpu_start)
123		return cpu_ops[cpu]->cpu_start(cpu, tidle);
124
125	return -EOPNOTSUPP;
126}
127
128int __cpu_up(unsigned int cpu, struct task_struct *tidle)
129{
130	int ret = 0;
131	tidle->thread_info.cpu = cpu;
132
133	ret = start_secondary_cpu(cpu, tidle);
134	if (!ret) {
135		wait_for_completion_timeout(&cpu_running,
136					    msecs_to_jiffies(1000));
137
138		if (!cpu_online(cpu)) {
139			pr_crit("CPU%u: failed to come online\n", cpu);
140			ret = -EIO;
141		}
142	} else {
143		pr_crit("CPU%u: failed to start\n", cpu);
144	}
145
146	return ret;
147}
148
149void __init smp_cpus_done(unsigned int max_cpus)
150{
151}
152
153/*
154 * C entry point for a secondary processor.
155 */
156asmlinkage __visible void smp_callin(void)
157{
158	struct mm_struct *mm = &init_mm;
159	unsigned int curr_cpuid = smp_processor_id();
160
161	riscv_clear_ipi();
162
163	/* All kernel threads share the same mm context.  */
164	mmgrab(mm);
165	current->active_mm = mm;
166
167	store_cpu_topology(curr_cpuid);
168	notify_cpu_starting(curr_cpuid);
169	numa_add_cpu(curr_cpuid);
 
170	set_cpu_online(curr_cpuid, 1);
171
172	/*
173	 * Remote TLB flushes are ignored while the CPU is offline, so emit
174	 * a local TLB flush right now just in case.
175	 */
176	local_flush_tlb_all();
177	complete(&cpu_running);
178	/*
179	 * Disable preemption before enabling interrupts, so we don't try to
180	 * schedule a CPU that hasn't actually started yet.
181	 */
182	local_irq_enable();
183	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
184}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * SMP initialisation and IPI support
  4 * Based on arch/arm64/kernel/smp.c
  5 *
  6 * Copyright (C) 2012 ARM Ltd.
  7 * Copyright (C) 2015 Regents of the University of California
  8 * Copyright (C) 2017 SiFive
  9 */
 10
 11#include <linux/arch_topology.h>
 12#include <linux/module.h>
 13#include <linux/init.h>
 14#include <linux/kernel.h>
 15#include <linux/mm.h>
 16#include <linux/sched.h>
 17#include <linux/kernel_stat.h>
 18#include <linux/notifier.h>
 19#include <linux/cpu.h>
 20#include <linux/percpu.h>
 21#include <linux/delay.h>
 22#include <linux/err.h>
 23#include <linux/irq.h>
 24#include <linux/of.h>
 25#include <linux/sched/task_stack.h>
 26#include <linux/sched/mm.h>
 27#include <asm/cpu_ops.h>
 28#include <asm/irq.h>
 29#include <asm/mmu_context.h>
 30#include <asm/numa.h>
 31#include <asm/tlbflush.h>
 32#include <asm/sections.h>
 33#include <asm/sbi.h>
 34#include <asm/smp.h>
 35#include <asm/alternative.h>
 36
 37#include "head.h"
 38
 39static DECLARE_COMPLETION(cpu_running);
 40
 41void __init smp_prepare_boot_cpu(void)
 42{
 43	init_cpu_topology();
 44#ifdef CONFIG_RISCV_ERRATA_ALTERNATIVE
 45	apply_boot_alternatives();
 46#endif
 47}
 48
 49void __init smp_prepare_cpus(unsigned int max_cpus)
 50{
 51	int cpuid;
 52	int ret;
 53	unsigned int curr_cpuid;
 54
 
 
 55	curr_cpuid = smp_processor_id();
 
 56	numa_store_cpu_info(curr_cpuid);
 57	numa_add_cpu(curr_cpuid);
 58
 59	/* This covers non-smp usecase mandated by "nosmp" option */
 60	if (max_cpus == 0)
 61		return;
 62
 63	for_each_possible_cpu(cpuid) {
 64		if (cpuid == curr_cpuid)
 65			continue;
 66		if (cpu_ops[cpuid]->cpu_prepare) {
 67			ret = cpu_ops[cpuid]->cpu_prepare(cpuid);
 68			if (ret)
 69				continue;
 70		}
 71		set_cpu_present(cpuid, true);
 72		numa_store_cpu_info(cpuid);
 73	}
 74}
 75
 76void __init setup_smp(void)
 77{
 78	struct device_node *dn;
 79	int hart;
 80	bool found_boot_cpu = false;
 81	int cpuid = 1;
 
 82
 83	cpu_set_ops(0);
 84
 85	for_each_of_cpu_node(dn) {
 86		hart = riscv_of_processor_hartid(dn);
 87		if (hart < 0)
 88			continue;
 89
 90		if (hart == cpuid_to_hartid_map(0)) {
 91			BUG_ON(found_boot_cpu);
 92			found_boot_cpu = 1;
 93			early_map_cpu_to_node(0, of_node_to_nid(dn));
 94			continue;
 95		}
 96		if (cpuid >= NR_CPUS) {
 97			pr_warn("Invalid cpuid [%d] for hartid [%d]\n",
 98				cpuid, hart);
 99			break;
100		}
101
102		cpuid_to_hartid_map(cpuid) = hart;
103		early_map_cpu_to_node(cpuid, of_node_to_nid(dn));
104		cpuid++;
105	}
106
107	BUG_ON(!found_boot_cpu);
108
109	if (cpuid > nr_cpu_ids)
110		pr_warn("Total number of cpus [%d] is greater than nr_cpus option value [%d]\n",
111			cpuid, nr_cpu_ids);
112
113	for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) {
114		if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) {
115			cpu_set_ops(cpuid);
116			set_cpu_possible(cpuid, true);
117		}
118	}
119}
120
121static int start_secondary_cpu(int cpu, struct task_struct *tidle)
122{
123	if (cpu_ops[cpu]->cpu_start)
124		return cpu_ops[cpu]->cpu_start(cpu, tidle);
125
126	return -EOPNOTSUPP;
127}
128
129int __cpu_up(unsigned int cpu, struct task_struct *tidle)
130{
131	int ret = 0;
132	tidle->thread_info.cpu = cpu;
133
134	ret = start_secondary_cpu(cpu, tidle);
135	if (!ret) {
136		wait_for_completion_timeout(&cpu_running,
137					    msecs_to_jiffies(1000));
138
139		if (!cpu_online(cpu)) {
140			pr_crit("CPU%u: failed to come online\n", cpu);
141			ret = -EIO;
142		}
143	} else {
144		pr_crit("CPU%u: failed to start\n", cpu);
145	}
146
147	return ret;
148}
149
150void __init smp_cpus_done(unsigned int max_cpus)
151{
152}
153
154/*
155 * C entry point for a secondary processor.
156 */
157asmlinkage __visible void smp_callin(void)
158{
159	struct mm_struct *mm = &init_mm;
160	unsigned int curr_cpuid = smp_processor_id();
161
162	riscv_clear_ipi();
163
164	/* All kernel threads share the same mm context.  */
165	mmgrab(mm);
166	current->active_mm = mm;
167
 
168	notify_cpu_starting(curr_cpuid);
169	numa_add_cpu(curr_cpuid);
170	update_siblings_masks(curr_cpuid);
171	set_cpu_online(curr_cpuid, 1);
172
173	/*
174	 * Remote TLB flushes are ignored while the CPU is offline, so emit
175	 * a local TLB flush right now just in case.
176	 */
177	local_flush_tlb_all();
178	complete(&cpu_running);
179	/*
180	 * Disable preemption before enabling interrupts, so we don't try to
181	 * schedule a CPU that hasn't actually started yet.
182	 */
183	local_irq_enable();
184	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
185}