xref: /kvm-unit-tests/lib/arm/setup.c (revision d3aacb4f57d05f74f2030dbe12e7dfd6aa1b273d)
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/setup.h"
18 #include "asm/page.h"
19 
20 extern unsigned long stacktop;
21 extern void io_init(void);
22 extern void setup_args(const char *args);
23 
24 u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0UL) };
25 int nr_cpus;
26 
27 phys_addr_t __phys_offset, __phys_end;
28 
29 static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
30 {
31 	assert(nr_cpus < NR_CPUS);
32 	cpus[nr_cpus++] = regval;
33 }
34 
35 static void cpu_init(void)
36 {
37 	nr_cpus = 0;
38 	assert(dt_for_each_cpu_node(cpu_set, NULL) == 0);
39 }
40 
41 static void mem_init(phys_addr_t freemem_start)
42 {
43 	/* we only expect one membank to be defined in the DT */
44 	struct dt_pbus_reg regs[1];
45 	phys_addr_t mem_start, mem_end;
46 
47 	assert(dt_get_memory_params(regs, 1));
48 
49 	mem_start = regs[0].addr;
50 	mem_end = mem_start + regs[0].size;
51 
52 	assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK));
53 	assert(freemem_start >= mem_start && freemem_start < mem_end);
54 
55 	__phys_offset = mem_start;	/* PHYS_OFFSET */
56 	__phys_end = mem_end;		/* PHYS_END */
57 
58 	phys_alloc_init(freemem_start, mem_end - freemem_start);
59 	phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES);
60 }
61 
62 void setup(unsigned long arg __unused, unsigned long id __unused,
63 	   const void *fdt)
64 {
65 	const char *bootargs;
66 	u32 fdt_size;
67 
68 	/*
69 	 * Move the fdt to just above the stack. The free memory
70 	 * then starts just after the fdt.
71 	 */
72 	fdt_size = fdt_totalsize(fdt);
73 	assert(fdt_move(fdt, &stacktop, fdt_size) == 0);
74 	assert(dt_init(&stacktop) == 0);
75 
76 	mem_init(PAGE_ALIGN((unsigned long)&stacktop + fdt_size));
77 	io_init();
78 	cpu_init();
79 
80 	assert(dt_get_bootargs(&bootargs) == 0);
81 	setup_args(bootargs);
82 }
83