xref: /kvm-unit-tests/lib/riscv/setup.c (revision 22f287f4024419702c8024174139d1b46d12f2be)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Initialize machine setup information and I/O.
4  *
5  * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com>
6  */
7 #include <libcflat.h>
8 #include <alloc.h>
9 #include <alloc_phys.h>
10 #include <argv.h>
11 #include <cpumask.h>
12 #include <devicetree.h>
13 #include <asm/csr.h>
14 #include <asm/page.h>
15 #include <asm/setup.h>
16 
17 char *initrd;
18 u32 initrd_size;
19 
20 unsigned long cpus[NR_CPUS] = { [0 ... NR_CPUS - 1] = ~0UL };
21 int nr_cpus;
22 
23 int hartid_to_cpu(unsigned long hartid)
24 {
25 	int cpu;
26 
27 	for_each_present_cpu(cpu)
28 		if (cpus[cpu] == hartid)
29 			return cpu;
30 	return -1;
31 }
32 
33 static void cpu_set_fdt(int fdtnode __unused, u64 regval, void *info __unused)
34 {
35 	int cpu = nr_cpus++;
36 
37 	assert_msg(cpu < NR_CPUS, "Number cpus exceeds maximum supported (%d).", NR_CPUS);
38 
39 	cpus[cpu] = regval;
40 	set_cpu_present(cpu, true);
41 }
42 
43 static void cpu_init_acpi(void)
44 {
45 	assert_msg(false, "ACPI not available");
46 }
47 
48 static void cpu_init(void)
49 {
50 	int ret;
51 
52 	nr_cpus = 0;
53 	if (dt_available()) {
54 		ret = dt_for_each_cpu_node(cpu_set_fdt, NULL);
55 		assert(ret == 0);
56 	} else {
57 		cpu_init_acpi();
58 	}
59 
60 	set_cpu_online(hartid_to_cpu(csr_read(CSR_SSCRATCH)), true);
61 }
62 
63 static void mem_init(phys_addr_t freemem_start)
64 {
65 	//TODO - for now just assume we've got some memory available
66 	phys_alloc_init(freemem_start, 16 * SZ_1M);
67 }
68 
69 static void banner(void)
70 {
71 	puts("\n");
72 	puts("##########################################################################\n");
73 	puts("#    kvm-unit-tests\n");
74 	puts("##########################################################################\n");
75 	puts("\n");
76 }
77 
78 void setup(const void *fdt, phys_addr_t freemem_start)
79 {
80 	void *freemem;
81 	const char *bootargs, *tmp;
82 	u32 fdt_size;
83 	int ret;
84 
85 	assert(sizeof(long) == 8 || freemem_start < (3ul << 30));
86 	freemem = (void *)(unsigned long)freemem_start;
87 
88 	/* Move the FDT to the base of free memory */
89 	fdt_size = fdt_totalsize(fdt);
90 	ret = fdt_move(fdt, freemem, fdt_size);
91 	assert(ret == 0);
92 	ret = dt_init(freemem);
93 	assert(ret == 0);
94 	freemem += fdt_size;
95 
96 	/* Move the initrd to the top of the FDT */
97 	ret = dt_get_initrd(&tmp, &initrd_size);
98 	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
99 	if (ret == 0) {
100 		initrd = freemem;
101 		memmove(initrd, tmp, initrd_size);
102 		freemem += initrd_size;
103 	}
104 
105 	mem_init(PAGE_ALIGN((unsigned long)freemem));
106 	cpu_init();
107 	io_init();
108 
109 	ret = dt_get_bootargs(&bootargs);
110 	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
111 	setup_args_progname(bootargs);
112 
113 	if (initrd) {
114 		/* environ is currently the only file in the initrd */
115 		char *env = malloc(initrd_size);
116 		memcpy(env, initrd, initrd_size);
117 		setup_env(env, initrd_size);
118 	}
119 
120 	banner();
121 }
122