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