xref: /kvm-unit-tests/lib/arm/smp.c (revision 867f820d405ea6ce5fe49ee8f75a2f97a08c7adf)
1 /*
2  * Secondary cpu support
3  *
4  * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com>
5  *
6  * This work is licensed under the terms of the GNU LGPL, version 2.
7  */
8 #include <libcflat.h>
9 #include <alloc.h>
10 #include <asm/thread_info.h>
11 #include <asm/cpumask.h>
12 #include <asm/barrier.h>
13 #include <asm/mmu.h>
14 #include <asm/psci.h>
15 #include <asm/smp.h>
16 
17 cpumask_t cpu_present_mask;
18 cpumask_t cpu_online_mask;
19 struct secondary_data secondary_data;
20 
21 secondary_entry_fn secondary_cinit(void)
22 {
23 	struct thread_info *ti = current_thread_info();
24 	secondary_entry_fn entry;
25 
26 	thread_info_init(ti, 0);
27 	mmu_mark_enabled(ti->cpu);
28 
29 	/*
30 	 * Save secondary_data.entry locally to avoid opening a race
31 	 * window between marking ourselves online and calling it.
32 	 */
33 	entry = secondary_data.entry;
34 	set_cpu_online(ti->cpu, true);
35 	sev();
36 
37 	/*
38 	 * Return to the assembly stub, allowing entry to be called
39 	 * from there with an empty stack.
40 	 */
41 	return entry;
42 }
43 
44 void smp_boot_secondary(int cpu, secondary_entry_fn entry)
45 {
46 	void *stack_base = memalign(THREAD_SIZE, THREAD_SIZE);
47 	int ret;
48 
49 	secondary_data.stack = stack_base + THREAD_START_SP;
50 	secondary_data.entry = entry;
51 	mmu_mark_disabled(cpu);
52 	ret = cpu_psci_cpu_boot(cpu);
53 	assert(ret == 0);
54 
55 	while (!cpu_online(cpu))
56 		wfe();
57 }
58