xref: /kvm-unit-tests/lib/riscv/setup.c (revision 386561f8cd050f58e9dc2ec7562014c8f1680de3) !
1bd744d46SAndrew Jones // SPDX-License-Identifier: GPL-2.0-only
2bd744d46SAndrew Jones /*
3bd744d46SAndrew Jones  * Initialize machine setup information and I/O.
4bd744d46SAndrew Jones  *
5bd744d46SAndrew Jones  * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com>
6bd744d46SAndrew Jones  */
7bd744d46SAndrew Jones #include <libcflat.h>
822f287f4SAndrew Jones #include <alloc.h>
922f287f4SAndrew Jones #include <alloc_phys.h>
1022f287f4SAndrew Jones #include <argv.h>
1122f287f4SAndrew Jones #include <cpumask.h>
1222f287f4SAndrew Jones #include <devicetree.h>
1322f287f4SAndrew Jones #include <asm/csr.h>
1422f287f4SAndrew Jones #include <asm/page.h>
15*386561f8SAndrew Jones #include <asm/processor.h>
16bd744d46SAndrew Jones #include <asm/setup.h>
17bd744d46SAndrew Jones 
1822f287f4SAndrew Jones char *initrd;
1922f287f4SAndrew Jones u32 initrd_size;
2022f287f4SAndrew Jones 
21*386561f8SAndrew Jones struct thread_info cpus[NR_CPUS];
2222f287f4SAndrew Jones int nr_cpus;
2322f287f4SAndrew Jones 
2422f287f4SAndrew Jones int hartid_to_cpu(unsigned long hartid)
2522f287f4SAndrew Jones {
2622f287f4SAndrew Jones 	int cpu;
2722f287f4SAndrew Jones 
2822f287f4SAndrew Jones 	for_each_present_cpu(cpu)
29*386561f8SAndrew Jones 		if (cpus[cpu].hartid == hartid)
3022f287f4SAndrew Jones 			return cpu;
3122f287f4SAndrew Jones 	return -1;
3222f287f4SAndrew Jones }
3322f287f4SAndrew Jones 
3422f287f4SAndrew Jones static void cpu_set_fdt(int fdtnode __unused, u64 regval, void *info __unused)
3522f287f4SAndrew Jones {
3622f287f4SAndrew Jones 	int cpu = nr_cpus++;
3722f287f4SAndrew Jones 
3822f287f4SAndrew Jones 	assert_msg(cpu < NR_CPUS, "Number cpus exceeds maximum supported (%d).", NR_CPUS);
3922f287f4SAndrew Jones 
40*386561f8SAndrew Jones 	cpus[cpu].cpu = cpu;
41*386561f8SAndrew Jones 	cpus[cpu].hartid = regval;
4222f287f4SAndrew Jones 	set_cpu_present(cpu, true);
4322f287f4SAndrew Jones }
4422f287f4SAndrew Jones 
4522f287f4SAndrew Jones static void cpu_init_acpi(void)
4622f287f4SAndrew Jones {
4722f287f4SAndrew Jones 	assert_msg(false, "ACPI not available");
4822f287f4SAndrew Jones }
4922f287f4SAndrew Jones 
5022f287f4SAndrew Jones static void cpu_init(void)
5122f287f4SAndrew Jones {
5222f287f4SAndrew Jones 	int ret;
5322f287f4SAndrew Jones 
5422f287f4SAndrew Jones 	nr_cpus = 0;
5522f287f4SAndrew Jones 	if (dt_available()) {
5622f287f4SAndrew Jones 		ret = dt_for_each_cpu_node(cpu_set_fdt, NULL);
5722f287f4SAndrew Jones 		assert(ret == 0);
5822f287f4SAndrew Jones 	} else {
5922f287f4SAndrew Jones 		cpu_init_acpi();
6022f287f4SAndrew Jones 	}
6122f287f4SAndrew Jones 
6222f287f4SAndrew Jones 	set_cpu_online(hartid_to_cpu(csr_read(CSR_SSCRATCH)), true);
6322f287f4SAndrew Jones }
6422f287f4SAndrew Jones 
6522f287f4SAndrew Jones static void mem_init(phys_addr_t freemem_start)
6622f287f4SAndrew Jones {
6722f287f4SAndrew Jones 	//TODO - for now just assume we've got some memory available
6822f287f4SAndrew Jones 	phys_alloc_init(freemem_start, 16 * SZ_1M);
6922f287f4SAndrew Jones }
7022f287f4SAndrew Jones 
7122f287f4SAndrew Jones static void banner(void)
7222f287f4SAndrew Jones {
7322f287f4SAndrew Jones 	puts("\n");
7422f287f4SAndrew Jones 	puts("##########################################################################\n");
7522f287f4SAndrew Jones 	puts("#    kvm-unit-tests\n");
7622f287f4SAndrew Jones 	puts("##########################################################################\n");
7722f287f4SAndrew Jones 	puts("\n");
7822f287f4SAndrew Jones }
7922f287f4SAndrew Jones 
80bd744d46SAndrew Jones void setup(const void *fdt, phys_addr_t freemem_start)
81bd744d46SAndrew Jones {
8222f287f4SAndrew Jones 	void *freemem;
8322f287f4SAndrew Jones 	const char *bootargs, *tmp;
8422f287f4SAndrew Jones 	u32 fdt_size;
8522f287f4SAndrew Jones 	int ret;
8622f287f4SAndrew Jones 
8722f287f4SAndrew Jones 	assert(sizeof(long) == 8 || freemem_start < (3ul << 30));
8822f287f4SAndrew Jones 	freemem = (void *)(unsigned long)freemem_start;
8922f287f4SAndrew Jones 
9022f287f4SAndrew Jones 	/* Move the FDT to the base of free memory */
9122f287f4SAndrew Jones 	fdt_size = fdt_totalsize(fdt);
9222f287f4SAndrew Jones 	ret = fdt_move(fdt, freemem, fdt_size);
9322f287f4SAndrew Jones 	assert(ret == 0);
9422f287f4SAndrew Jones 	ret = dt_init(freemem);
9522f287f4SAndrew Jones 	assert(ret == 0);
9622f287f4SAndrew Jones 	freemem += fdt_size;
9722f287f4SAndrew Jones 
9822f287f4SAndrew Jones 	/* Move the initrd to the top of the FDT */
9922f287f4SAndrew Jones 	ret = dt_get_initrd(&tmp, &initrd_size);
10022f287f4SAndrew Jones 	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
10122f287f4SAndrew Jones 	if (ret == 0) {
10222f287f4SAndrew Jones 		initrd = freemem;
10322f287f4SAndrew Jones 		memmove(initrd, tmp, initrd_size);
10422f287f4SAndrew Jones 		freemem += initrd_size;
10522f287f4SAndrew Jones 	}
10622f287f4SAndrew Jones 
10722f287f4SAndrew Jones 	mem_init(PAGE_ALIGN((unsigned long)freemem));
10822f287f4SAndrew Jones 	cpu_init();
109*386561f8SAndrew Jones 	thread_info_init();
11022f287f4SAndrew Jones 	io_init();
11122f287f4SAndrew Jones 
11222f287f4SAndrew Jones 	ret = dt_get_bootargs(&bootargs);
11322f287f4SAndrew Jones 	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
11422f287f4SAndrew Jones 	setup_args_progname(bootargs);
11522f287f4SAndrew Jones 
11622f287f4SAndrew Jones 	if (initrd) {
11722f287f4SAndrew Jones 		/* environ is currently the only file in the initrd */
11822f287f4SAndrew Jones 		char *env = malloc(initrd_size);
11922f287f4SAndrew Jones 		memcpy(env, initrd, initrd_size);
12022f287f4SAndrew Jones 		setup_env(env, initrd_size);
12122f287f4SAndrew Jones 	}
12222f287f4SAndrew Jones 
12322f287f4SAndrew Jones 	banner();
124bd744d46SAndrew Jones }
125