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