xref: /kvm-unit-tests/lib/arm/setup.c (revision 867f820d405ea6ce5fe49ee8f75a2f97a08c7adf)
1 /*
2  * Initialize machine setup information and I/O.
3  *
4  * After running setup() unit tests may query how many cpus they have
5  * (nr_cpus), how much memory they have (PHYS_END - PHYS_OFFSET), may
6  * use dynamic memory allocation (malloc, etc.), printf, and exit.
7  * Finally, argc and argv are also ready to be passed to main().
8  *
9  * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
10  *
11  * This work is licensed under the terms of the GNU LGPL, version 2.
12  */
13 #include <libcflat.h>
14 #include <libfdt/libfdt.h>
15 #include <devicetree.h>
16 #include <alloc.h>
17 #include <asm/thread_info.h>
18 #include <asm/setup.h>
19 #include <asm/page.h>
20 #include <asm/mmu.h>
21 #include <asm/smp.h>
22 
23 extern unsigned long stacktop;
24 extern void io_init(void);
25 extern void setup_args(const char *args);
26 
27 u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
28 int nr_cpus;
29 
30 phys_addr_t __phys_offset, __phys_end;
31 
32 static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
33 {
34 	int cpu = nr_cpus++;
35 	assert(cpu < NR_CPUS);
36 	cpus[cpu] = regval;
37 	set_cpu_present(cpu, true);
38 }
39 
40 static void cpu_init(void)
41 {
42 	int ret;
43 
44 	nr_cpus = 0;
45 	ret = dt_for_each_cpu_node(cpu_set, NULL);
46 	assert(ret == 0);
47 	set_cpu_online(0, true);
48 }
49 
50 static void mem_init(phys_addr_t freemem_start)
51 {
52 	/* we only expect one membank to be defined in the DT */
53 	struct dt_pbus_reg regs[1];
54 	phys_addr_t mem_start, mem_end;
55 	int ret;
56 
57 	ret = dt_get_memory_params(regs, 1);
58 	assert(ret != 0);
59 
60 	mem_start = regs[0].addr;
61 	mem_end = mem_start + regs[0].size;
62 
63 	assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK));
64 	assert(freemem_start >= mem_start && freemem_start < mem_end);
65 
66 	__phys_offset = mem_start;	/* PHYS_OFFSET */
67 	__phys_end = mem_end;		/* PHYS_END */
68 
69 	phys_alloc_init(freemem_start, mem_end - freemem_start);
70 	phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES);
71 
72 	mmu_enable_idmap();
73 }
74 
75 void setup(const void *fdt)
76 {
77 	const char *bootargs;
78 	u32 fdt_size;
79 	int ret;
80 
81 	/*
82 	 * Move the fdt to just above the stack. The free memory
83 	 * then starts just after the fdt.
84 	 */
85 	fdt_size = fdt_totalsize(fdt);
86 	ret = fdt_move(fdt, &stacktop, fdt_size);
87 	assert(ret == 0);
88 	ret = dt_init(&stacktop);
89 	assert(ret == 0);
90 
91 	mem_init(PAGE_ALIGN((unsigned long)&stacktop + fdt_size));
92 	io_init();
93 	cpu_init();
94 
95 	thread_info_init(current_thread_info(), 0);
96 
97 	ret = dt_get_bootargs(&bootargs);
98 	assert(ret == 0);
99 	setup_args(bootargs);
100 }
101