arch/loongarch/kernel/smp.c

Source file repositories/reference/linux-study-clean/arch/loongarch/kernel/smp.c

File Facts

System
Linux kernel
Corpus path
arch/loongarch/kernel/smp.c
Extension
.c
Size
19656 bytes
Lines
857
Domain
Architecture Layer
Bucket
arch/loongarch
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

core_initcall(ipi_pm_init);
#endif

/* Preload SMP state for boot cpu */
void __init smp_prepare_boot_cpu(void)
{
	unsigned int cpu, node, rr_node;

	set_cpu_possible(0, true);
	set_cpu_online(0, true);
	set_my_cpu_offset(per_cpu_offset(0));
	numa_add_cpu(0);

	rr_node = first_node(node_online_map);
	for_each_possible_cpu(cpu) {
		node = early_cpu_to_node(cpu);

		/*
		 * The mapping between present cpus and nodes has been
		 * built during MADT and SRAT parsing.
		 *
		 * If possible cpus = present cpus here, early_cpu_to_node
		 * will return valid node.
		 *
		 * If possible cpus > present cpus here (e.g. some possible
		 * cpus will be added by cpu-hotplug later), for possible but
		 * not present cpus, early_cpu_to_node will return NUMA_NO_NODE,
		 * and we just map them to online nodes in round-robin way.
		 * Once hotplugged, new correct mapping will be built for them.
		 */
		if (node != NUMA_NO_NODE)
			set_cpu_numa_node(cpu, node);
		else {
			set_cpu_numa_node(cpu, rr_node);
			rr_node = next_node_in(rr_node, node_online_map);
		}
	}

	pv_spinlock_init();
}

/* called from main before smp_init() */
void __init smp_prepare_cpus(unsigned int max_cpus)
{
	init_new_context(current, &init_mm);
	current_thread_info()->cpu = 0;
	loongson_prepare_cpus(max_cpus);
	set_cpu_sibling_map(0);
	set_cpu_llc_shared_map(0);
	set_cpu_core_map(0);
	calculate_cpu_foreign_map();
#ifndef CONFIG_HOTPLUG_CPU
	init_cpu_present(cpu_possible_mask);
#endif
}

int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
	loongson_boot_secondary(cpu, tidle);

	/* Wait for CPU to start and be ready to sync counters */
	if (!wait_for_completion_timeout(&cpu_starting,
					 msecs_to_jiffies(5000))) {
		pr_crit("CPU%u: failed to start\n", cpu);
		return -EIO;
	}

	/* Wait for CPU to finish startup & mark itself online before return */
	wait_for_completion(&cpu_running);

	return 0;
}

/*
 * First C code run on the secondary CPUs after being started up by
 * the master.
 */
asmlinkage void start_secondary(void)
{
	unsigned int cpu;

	sync_counter();
	cpu = raw_smp_processor_id();
	set_my_cpu_offset(per_cpu_offset(cpu));

	cpu_probe();
	constant_clockevent_init();
	loongson_init_secondary();

	set_cpu_sibling_map(cpu);

Annotation

Implementation Notes