1 /* 2 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. 3 * Chen Liqin <liqin.chen@sunplusct.com> 4 * Lennox Wu <lennox.wu@sunplusct.com> 5 * Copyright (C) 2012 Regents of the University of California 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, see the file COPYING, or write 19 * to the Free Software Foundation, Inc., 20 */ 21 22 #include <linux/init.h> 23 #include <linux/mm.h> 24 #include <linux/memblock.h> 25 #include <linux/sched.h> 26 #include <linux/initrd.h> 27 #include <linux/console.h> 28 #include <linux/screen_info.h> 29 #include <linux/of_fdt.h> 30 #include <linux/of_platform.h> 31 #include <linux/sched/task.h> 32 #include <linux/swiotlb.h> 33 34 #include <asm/setup.h> 35 #include <asm/sections.h> 36 #include <asm/pgtable.h> 37 #include <asm/smp.h> 38 #include <asm/sbi.h> 39 #include <asm/tlbflush.h> 40 #include <asm/thread_info.h> 41 42 #ifdef CONFIG_EARLY_PRINTK 43 static void sbi_console_write(struct console *co, const char *buf, 44 unsigned int n) 45 { 46 int i; 47 48 for (i = 0; i < n; ++i) { 49 if (buf[i] == '\n') 50 sbi_console_putchar('\r'); 51 sbi_console_putchar(buf[i]); 52 } 53 } 54 55 struct console riscv_sbi_early_console_dev __initdata = { 56 .name = "early", 57 .write = sbi_console_write, 58 .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME, 59 .index = -1 60 }; 61 #endif 62 63 #ifdef CONFIG_DUMMY_CONSOLE 64 struct screen_info screen_info = { 65 .orig_video_lines = 30, 66 .orig_video_cols = 80, 67 .orig_video_mode = 0, 68 .orig_video_ega_bx = 0, 69 .orig_video_isVGA = 1, 70 .orig_video_points = 8 71 }; 72 #endif 73 74 unsigned long va_pa_offset; 75 EXPORT_SYMBOL(va_pa_offset); 76 unsigned long pfn_base; 77 EXPORT_SYMBOL(pfn_base); 78 79 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss; 80 EXPORT_SYMBOL(empty_zero_page); 81 82 /* The lucky hart to first increment this variable will boot the other cores */ 83 atomic_t hart_lottery; 84 unsigned long boot_cpu_hartid; 85 86 unsigned long __cpuid_to_hartid_map[NR_CPUS] = { 87 [0 ... NR_CPUS-1] = INVALID_HARTID 88 }; 89 90 void __init smp_setup_processor_id(void) 91 { 92 cpuid_to_hartid_map(0) = boot_cpu_hartid; 93 } 94 95 #ifdef CONFIG_BLK_DEV_INITRD 96 static void __init setup_initrd(void) 97 { 98 unsigned long size; 99 100 if (initrd_start >= initrd_end) { 101 printk(KERN_INFO "initrd not found or empty"); 102 goto disable; 103 } 104 if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { 105 printk(KERN_ERR "initrd extends beyond end of memory"); 106 goto disable; 107 } 108 109 size = initrd_end - initrd_start; 110 memblock_reserve(__pa(initrd_start), size); 111 initrd_below_start_ok = 1; 112 113 printk(KERN_INFO "Initial ramdisk at: 0x%p (%lu bytes)\n", 114 (void *)(initrd_start), size); 115 return; 116 disable: 117 pr_cont(" - disabling initrd\n"); 118 initrd_start = 0; 119 initrd_end = 0; 120 } 121 #endif /* CONFIG_BLK_DEV_INITRD */ 122 123 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; 124 pgd_t trampoline_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); 125 126 #ifndef __PAGETABLE_PMD_FOLDED 127 #define NUM_SWAPPER_PMDS ((uintptr_t)-PAGE_OFFSET >> PGDIR_SHIFT) 128 pmd_t swapper_pmd[PTRS_PER_PMD*((-PAGE_OFFSET)/PGDIR_SIZE)] __page_aligned_bss; 129 pmd_t trampoline_pmd[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); 130 #endif 131 132 asmlinkage void __init setup_vm(void) 133 { 134 extern char _start; 135 uintptr_t i; 136 uintptr_t pa = (uintptr_t) &_start; 137 pgprot_t prot = __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_EXEC); 138 139 va_pa_offset = PAGE_OFFSET - pa; 140 pfn_base = PFN_DOWN(pa); 141 142 /* Sanity check alignment and size */ 143 BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0); 144 BUG_ON((pa % (PAGE_SIZE * PTRS_PER_PTE)) != 0); 145 146 #ifndef __PAGETABLE_PMD_FOLDED 147 trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] = 148 pfn_pgd(PFN_DOWN((uintptr_t)trampoline_pmd), 149 __pgprot(_PAGE_TABLE)); 150 trampoline_pmd[0] = pfn_pmd(PFN_DOWN(pa), prot); 151 152 for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) { 153 size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i; 154 swapper_pg_dir[o] = 155 pfn_pgd(PFN_DOWN((uintptr_t)swapper_pmd) + i, 156 __pgprot(_PAGE_TABLE)); 157 } 158 for (i = 0; i < ARRAY_SIZE(swapper_pmd); i++) 159 swapper_pmd[i] = pfn_pmd(PFN_DOWN(pa + i * PMD_SIZE), prot); 160 #else 161 trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] = 162 pfn_pgd(PFN_DOWN(pa), prot); 163 164 for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) { 165 size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i; 166 swapper_pg_dir[o] = 167 pfn_pgd(PFN_DOWN(pa + i * PGDIR_SIZE), prot); 168 } 169 #endif 170 } 171 172 void __init parse_dtb(unsigned int hartid, void *dtb) 173 { 174 early_init_dt_scan(__va(dtb)); 175 } 176 177 static void __init setup_bootmem(void) 178 { 179 struct memblock_region *reg; 180 phys_addr_t mem_size = 0; 181 182 /* Find the memory region containing the kernel */ 183 for_each_memblock(memory, reg) { 184 phys_addr_t vmlinux_end = __pa(_end); 185 phys_addr_t end = reg->base + reg->size; 186 187 if (reg->base <= vmlinux_end && vmlinux_end <= end) { 188 /* 189 * Reserve from the start of the region to the end of 190 * the kernel 191 */ 192 memblock_reserve(reg->base, vmlinux_end - reg->base); 193 mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET); 194 } 195 } 196 BUG_ON(mem_size == 0); 197 198 set_max_mapnr(PFN_DOWN(mem_size)); 199 max_low_pfn = memblock_end_of_DRAM(); 200 201 #ifdef CONFIG_BLK_DEV_INITRD 202 setup_initrd(); 203 #endif /* CONFIG_BLK_DEV_INITRD */ 204 205 early_init_fdt_reserve_self(); 206 early_init_fdt_scan_reserved_mem(); 207 memblock_allow_resize(); 208 memblock_dump_all(); 209 210 for_each_memblock(memory, reg) { 211 unsigned long start_pfn = memblock_region_memory_base_pfn(reg); 212 unsigned long end_pfn = memblock_region_memory_end_pfn(reg); 213 214 memblock_set_node(PFN_PHYS(start_pfn), 215 PFN_PHYS(end_pfn - start_pfn), 216 &memblock.memory, 0); 217 } 218 } 219 220 void __init setup_arch(char **cmdline_p) 221 { 222 #if defined(CONFIG_EARLY_PRINTK) 223 if (likely(early_console == NULL)) { 224 early_console = &riscv_sbi_early_console_dev; 225 register_console(early_console); 226 } 227 #endif 228 *cmdline_p = boot_command_line; 229 230 parse_early_param(); 231 232 init_mm.start_code = (unsigned long) _stext; 233 init_mm.end_code = (unsigned long) _etext; 234 init_mm.end_data = (unsigned long) _edata; 235 init_mm.brk = (unsigned long) _end; 236 237 setup_bootmem(); 238 paging_init(); 239 unflatten_device_tree(); 240 241 #ifdef CONFIG_SWIOTLB 242 swiotlb_init(1); 243 #endif 244 245 #ifdef CONFIG_SMP 246 setup_smp(); 247 #endif 248 249 #ifdef CONFIG_DUMMY_CONSOLE 250 conswitchp = &dummy_con; 251 #endif 252 253 riscv_fill_hwcap(); 254 } 255 256