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