xref: /kvm-unit-tests/lib/arm/setup.c (revision f6d10793f9b42e852a1c3081afe567bd03004528)
15e61cba0SAndrew Jones /*
25e61cba0SAndrew Jones  * Initialize machine setup information and I/O.
35e61cba0SAndrew Jones  *
45e61cba0SAndrew Jones  * After running setup() unit tests may query how many cpus they have
55e61cba0SAndrew Jones  * (nr_cpus), how much memory they have (PHYS_END - PHYS_OFFSET), may
65e61cba0SAndrew Jones  * use dynamic memory allocation (malloc, etc.), printf, and exit.
75e61cba0SAndrew Jones  * Finally, argc and argv are also ready to be passed to main().
85e61cba0SAndrew Jones  *
95e61cba0SAndrew Jones  * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
105e61cba0SAndrew Jones  *
115e61cba0SAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
125e61cba0SAndrew Jones  */
138cca5668SAndrew Jones #include <libcflat.h>
148cca5668SAndrew Jones #include <libfdt/libfdt.h>
158cca5668SAndrew Jones #include <devicetree.h>
168cca5668SAndrew Jones #include <alloc.h>
17*f6d10793SAndrew Jones #include <asm/thread_info.h>
188cca5668SAndrew Jones #include <asm/setup.h>
198cca5668SAndrew Jones #include <asm/page.h>
208cca5668SAndrew Jones #include <asm/mmu.h>
215e61cba0SAndrew Jones 
225e61cba0SAndrew Jones extern unsigned long stacktop;
235e61cba0SAndrew Jones extern void io_init(void);
245e61cba0SAndrew Jones extern void setup_args(const char *args);
255e61cba0SAndrew Jones 
268d83d5e7SAndrew Jones u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
275e61cba0SAndrew Jones int nr_cpus;
285e61cba0SAndrew Jones 
295e61cba0SAndrew Jones phys_addr_t __phys_offset, __phys_end;
305e61cba0SAndrew Jones 
315e61cba0SAndrew Jones static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
325e61cba0SAndrew Jones {
335e61cba0SAndrew Jones 	assert(nr_cpus < NR_CPUS);
345e61cba0SAndrew Jones 	cpus[nr_cpus++] = regval;
355e61cba0SAndrew Jones }
365e61cba0SAndrew Jones 
375e61cba0SAndrew Jones static void cpu_init(void)
385e61cba0SAndrew Jones {
395e61cba0SAndrew Jones 	nr_cpus = 0;
405e61cba0SAndrew Jones 	assert(dt_for_each_cpu_node(cpu_set, NULL) == 0);
415e61cba0SAndrew Jones }
425e61cba0SAndrew Jones 
435e61cba0SAndrew Jones static void mem_init(phys_addr_t freemem_start)
445e61cba0SAndrew Jones {
455e61cba0SAndrew Jones 	/* we only expect one membank to be defined in the DT */
465e61cba0SAndrew Jones 	struct dt_pbus_reg regs[1];
475e61cba0SAndrew Jones 	phys_addr_t mem_start, mem_end;
485e61cba0SAndrew Jones 
495e61cba0SAndrew Jones 	assert(dt_get_memory_params(regs, 1));
505e61cba0SAndrew Jones 
515e61cba0SAndrew Jones 	mem_start = regs[0].addr;
525e61cba0SAndrew Jones 	mem_end = mem_start + regs[0].size;
535e61cba0SAndrew Jones 
545e61cba0SAndrew Jones 	assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK));
555e61cba0SAndrew Jones 	assert(freemem_start >= mem_start && freemem_start < mem_end);
565e61cba0SAndrew Jones 
575e61cba0SAndrew Jones 	__phys_offset = mem_start;	/* PHYS_OFFSET */
585e61cba0SAndrew Jones 	__phys_end = mem_end;		/* PHYS_END */
595e61cba0SAndrew Jones 
605e61cba0SAndrew Jones 	phys_alloc_init(freemem_start, mem_end - freemem_start);
615e61cba0SAndrew Jones 	phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES);
62153d1936SAndrew Jones 
63153d1936SAndrew Jones 	mmu_enable_idmap();
645e61cba0SAndrew Jones }
655e61cba0SAndrew Jones 
66dd4af6b1SAndrew Jones void setup(const void *fdt)
675e61cba0SAndrew Jones {
685e61cba0SAndrew Jones 	const char *bootargs;
695e61cba0SAndrew Jones 	u32 fdt_size;
705e61cba0SAndrew Jones 
715e61cba0SAndrew Jones 	/*
725e61cba0SAndrew Jones 	 * Move the fdt to just above the stack. The free memory
735e61cba0SAndrew Jones 	 * then starts just after the fdt.
745e61cba0SAndrew Jones 	 */
755e61cba0SAndrew Jones 	fdt_size = fdt_totalsize(fdt);
765e61cba0SAndrew Jones 	assert(fdt_move(fdt, &stacktop, fdt_size) == 0);
775e61cba0SAndrew Jones 	assert(dt_init(&stacktop) == 0);
785e61cba0SAndrew Jones 
795e61cba0SAndrew Jones 	mem_init(PAGE_ALIGN((unsigned long)&stacktop + fdt_size));
805e61cba0SAndrew Jones 	io_init();
815e61cba0SAndrew Jones 	cpu_init();
825e61cba0SAndrew Jones 
83*f6d10793SAndrew Jones 	thread_info_init(current_thread_info(), 0);
84*f6d10793SAndrew Jones 
855e61cba0SAndrew Jones 	assert(dt_get_bootargs(&bootargs) == 0);
865e61cba0SAndrew Jones 	setup_args(bootargs);
875e61cba0SAndrew Jones }
88