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