123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
- * Chen Liqin <liqin.chen@sunplusct.com>
- * Lennox Wu <lennox.wu@sunplusct.com>
- * Copyright (C) 2012 Regents of the University of California
- * Copyright (C) 2020 FORTH-ICS/CARV
- * Nick Kossifidis <mick@ics.forth.gr>
- */
- #include <linux/init.h>
- #include <linux/mm.h>
- #include <linux/memblock.h>
- #include <linux/sched.h>
- #include <linux/console.h>
- #include <linux/screen_info.h>
- #include <linux/of_fdt.h>
- #include <linux/of_platform.h>
- #include <linux/sched/task.h>
- #include <linux/swiotlb.h>
- #include <linux/smp.h>
- #include <linux/efi.h>
- #include <linux/crash_dump.h>
- #include <asm/cpu_ops.h>
- #include <asm/early_ioremap.h>
- #include <asm/setup.h>
- #include <asm/sections.h>
- #include <asm/sbi.h>
- #include <asm/tlbflush.h>
- #include <asm/thread_info.h>
- #include <asm/kasan.h>
- #include <asm/efi.h>
- #include "head.h"
- #if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_EFI)
- struct screen_info screen_info __section(".data") = {
- .orig_video_lines = 30,
- .orig_video_cols = 80,
- .orig_video_mode = 0,
- .orig_video_ega_bx = 0,
- .orig_video_isVGA = 1,
- .orig_video_points = 8
- };
- #endif
- /*
- * The lucky hart to first increment this variable will boot the other cores.
- * This is used before the kernel initializes the BSS so it can't be in the
- * BSS.
- */
- atomic_t hart_lottery __section(".sdata");
- unsigned long boot_cpu_hartid;
- static DEFINE_PER_CPU(struct cpu, cpu_devices);
- /*
- * Place kernel memory regions on the resource tree so that
- * kexec-tools can retrieve them from /proc/iomem. While there
- * also add "System RAM" regions for compatibility with other
- * archs, and the rest of the known regions for completeness.
- */
- static struct resource code_res = { .name = "Kernel code", };
- static struct resource data_res = { .name = "Kernel data", };
- static struct resource rodata_res = { .name = "Kernel rodata", };
- static struct resource bss_res = { .name = "Kernel bss", };
- #ifdef CONFIG_CRASH_DUMP
- static struct resource elfcorehdr_res = { .name = "ELF Core hdr", };
- #endif
- static int __init add_resource(struct resource *parent,
- struct resource *res)
- {
- int ret = 0;
- ret = insert_resource(parent, res);
- if (ret < 0) {
- pr_err("Failed to add a %s resource at %llx\n",
- res->name, (unsigned long long) res->start);
- return ret;
- }
- return 1;
- }
- static int __init add_kernel_resources(struct resource *res)
- {
- int ret = 0;
- /*
- * The memory region of the kernel image is continuous and
- * was reserved on setup_bootmem, find it here and register
- * it as a resource, then register the various segments of
- * the image as child nodes
- */
- if (!(res->start <= code_res.start && res->end >= data_res.end))
- return 0;
- res->name = "Kernel image";
- res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- /*
- * We removed a part of this region on setup_bootmem so
- * we need to expand the resource for the bss to fit in.
- */
- res->end = bss_res.end;
- ret = add_resource(&iomem_resource, res);
- if (ret < 0)
- return ret;
- ret = add_resource(res, &code_res);
- if (ret < 0)
- return ret;
- ret = add_resource(res, &rodata_res);
- if (ret < 0)
- return ret;
- ret = add_resource(res, &data_res);
- if (ret < 0)
- return ret;
- ret = add_resource(res, &bss_res);
- return ret;
- }
- static void __init init_resources(void)
- {
- struct memblock_region *region = NULL;
- struct resource *res = NULL;
- int ret = 0;
- code_res.start = __pa_symbol(_text);
- code_res.end = __pa_symbol(_etext) - 1;
- code_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- rodata_res.start = __pa_symbol(__start_rodata);
- rodata_res.end = __pa_symbol(__end_rodata) - 1;
- rodata_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- data_res.start = __pa_symbol(_data);
- data_res.end = __pa_symbol(_edata) - 1;
- data_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- bss_res.start = __pa_symbol(__bss_start);
- bss_res.end = __pa_symbol(__bss_stop) - 1;
- bss_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- /*
- * Start by adding the reserved regions, if they overlap
- * with /memory regions, insert_resource later on will take
- * care of it.
- */
- #ifdef CONFIG_KEXEC_CORE
- if (crashk_res.start != crashk_res.end) {
- ret = add_resource(&iomem_resource, &crashk_res);
- if (ret < 0)
- goto error;
- }
- #endif
- #ifdef CONFIG_CRASH_DUMP
- if (elfcorehdr_size > 0) {
- elfcorehdr_res.start = elfcorehdr_addr;
- elfcorehdr_res.end = elfcorehdr_addr + elfcorehdr_size - 1;
- elfcorehdr_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- add_resource(&iomem_resource, &elfcorehdr_res);
- }
- #endif
- for_each_reserved_mem_region(region) {
- res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
- if (!res)
- panic("%s: Failed to allocate %zu bytes\n", __func__,
- sizeof(struct resource));
- res->name = "Reserved";
- res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- res->start = __pfn_to_phys(memblock_region_reserved_base_pfn(region));
- res->end = __pfn_to_phys(memblock_region_reserved_end_pfn(region)) - 1;
- ret = add_kernel_resources(res);
- if (ret < 0)
- goto error;
- else if (ret)
- continue;
- /*
- * Ignore any other reserved regions within
- * system memory.
- */
- if (memblock_is_memory(res->start))
- continue;
- ret = add_resource(&iomem_resource, res);
- if (ret < 0)
- goto error;
- }
- /* Add /memory regions to the resource tree */
- for_each_mem_region(region) {
- res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
- if (!res)
- panic("%s: Failed to allocate %zu bytes\n", __func__,
- sizeof(struct resource));
- if (unlikely(memblock_is_nomap(region))) {
- res->name = "Reserved";
- res->flags = IORESOURCE_MEM;
- } else {
- res->name = "System RAM";
- res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- }
- res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
- res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
- ret = add_resource(&iomem_resource, res);
- if (ret < 0)
- goto error;
- }
- return;
- error:
- memblock_free((phys_addr_t) res, sizeof(struct resource));
- /* Better an empty resource tree than an inconsistent one */
- release_child_resources(&iomem_resource);
- }
- static void __init parse_dtb(void)
- {
- /* Early scan of device tree from init memory */
- if (early_init_dt_scan(dtb_early_va))
- return;
- pr_err("No DTB passed to the kernel\n");
- #ifdef CONFIG_CMDLINE_FORCE
- strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
- pr_info("Forcing kernel command line to: %s\n", boot_command_line);
- #endif
- }
- void __init setup_arch(char **cmdline_p)
- {
- parse_dtb();
- init_mm.start_code = (unsigned long) _stext;
- init_mm.end_code = (unsigned long) _etext;
- init_mm.end_data = (unsigned long) _edata;
- init_mm.brk = (unsigned long) _end;
- *cmdline_p = boot_command_line;
- early_ioremap_setup();
- jump_label_init();
- parse_early_param();
- efi_init();
- setup_bootmem();
- paging_init();
- #if IS_ENABLED(CONFIG_BUILTIN_DTB)
- unflatten_and_copy_device_tree();
- #else
- if (early_init_dt_verify(__va(dtb_early_pa)))
- unflatten_device_tree();
- else
- pr_err("No DTB found in kernel mappings\n");
- #endif
- #ifdef CONFIG_SWIOTLB
- swiotlb_init(1);
- #endif
- #ifdef CONFIG_KASAN
- kasan_init();
- #endif
- #if IS_ENABLED(CONFIG_RISCV_SBI)
- init_resources();
- sbi_init();
- #endif
- #ifdef CONFIG_SMP
- setup_smp();
- #endif
- riscv_fill_hwcap();
- }
- static int __init topology_init(void)
- {
- int i;
- for_each_possible_cpu(i) {
- struct cpu *cpu = &per_cpu(cpu_devices, i);
- cpu->hotpluggable = cpu_has_hotplug(i);
- register_cpu(cpu, i);
- }
- return 0;
- }
- subsys_initcall(topology_init);
|