2019-05-23 02:14:57 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-07-10 18:00:26 -07:00
|
|
|
/*
|
|
|
|
* 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
|
2020-10-12 07:24:10 -07:00
|
|
|
* Copyright (C) 2020 FORTH-ICS/CARV
|
|
|
|
* Nick Kossifidis <mick@ics.forth.gr>
|
2017-07-10 18:00:26 -07:00
|
|
|
*/
|
|
|
|
|
2023-05-14 22:49:15 -07:00
|
|
|
#include <linux/acpi.h>
|
2023-03-29 08:52:05 -07:00
|
|
|
#include <linux/cpu.h>
|
2017-07-10 18:00:26 -07:00
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/memblock.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/console.h>
|
|
|
|
#include <linux/of_fdt.h>
|
|
|
|
#include <linux/sched/task.h>
|
2020-03-17 18:11:44 -07:00
|
|
|
#include <linux/smp.h>
|
2020-09-17 15:37:15 -07:00
|
|
|
#include <linux/efi.h>
|
2021-04-18 17:55:38 -07:00
|
|
|
#include <linux/crash_dump.h>
|
2023-07-22 05:38:47 -07:00
|
|
|
#include <linux/panic_notifier.h>
|
2017-07-10 18:00:26 -07:00
|
|
|
|
2023-05-14 22:49:16 -07:00
|
|
|
#include <asm/acpi.h>
|
2022-05-11 12:29:16 -07:00
|
|
|
#include <asm/alternative.h>
|
2022-07-06 16:15:35 -07:00
|
|
|
#include <asm/cacheflush.h>
|
RISC-V: Enable cbo.zero in usermode
When Zicboz is present, enable its instruction (cbo.zero) in
usermode by setting its respective senvcfg bit. We don't bother
trying to set this bit per-task, which would also require an
interface for tasks to request enabling and/or disabling. Instead,
permanently set the bit for each hart which has the extension when
bringing it online.
This patch also introduces riscv_cpu_has_extension_[un]likely()
functions to check a specific hart's ISA bitmap for extensions.
Prior to checking the specific hart's bitmap in these functions
we try the bitmap which represents the LCD of extensions, but only
when we know it will use its optimized, alternatives path by gating
its call on CONFIG_RISCV_ALTERNATIVE. When alternatives are used, the
compiler ensures that the invocation of the LCD search becomes a
constant true or false. When it's true, even the new functions will
completely vanish from their callsites. OTOH, when the LCD check is
false, we need to do a search of the hart's ISA bitmap. Had we also
checked the LCD bitmap without the use of alternatives, then we would
have ended up with two bitmap searches instead of one.
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230918131518.56803-10-ajones@ventanamicro.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-09-18 06:15:21 -07:00
|
|
|
#include <asm/cpufeature.h>
|
2020-09-17 15:37:11 -07:00
|
|
|
#include <asm/early_ioremap.h>
|
2021-04-12 23:35:14 -07:00
|
|
|
#include <asm/pgtable.h>
|
2017-07-10 18:00:26 -07:00
|
|
|
#include <asm/setup.h>
|
2020-11-04 17:04:38 -07:00
|
|
|
#include <asm/set_memory.h>
|
2017-07-10 18:00:26 -07:00
|
|
|
#include <asm/sections.h>
|
2020-03-17 18:11:35 -07:00
|
|
|
#include <asm/sbi.h>
|
2017-07-10 18:00:26 -07:00
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
#include <asm/thread_info.h>
|
2020-01-06 11:38:32 -07:00
|
|
|
#include <asm/kasan.h>
|
2020-09-17 15:37:15 -07:00
|
|
|
#include <asm/efi.h>
|
2017-07-10 18:00:26 -07:00
|
|
|
|
2019-10-17 15:00:17 -07:00
|
|
|
#include "head.h"
|
|
|
|
|
2020-02-04 04:19:47 -07:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-04-12 23:35:14 -07:00
|
|
|
atomic_t hart_lottery __section(".sdata")
|
|
|
|
#ifdef CONFIG_XIP_KERNEL
|
|
|
|
= ATOMIC_INIT(0xC001BEEF)
|
|
|
|
#endif
|
|
|
|
;
|
2018-10-02 12:15:05 -07:00
|
|
|
unsigned long boot_cpu_hartid;
|
2017-07-10 18:00:26 -07:00
|
|
|
|
2020-10-12 07:24:10 -07:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-04-18 17:55:37 -07:00
|
|
|
static struct resource kimage_res = { .name = "Kernel image", };
|
2020-10-12 07:24:10 -07:00
|
|
|
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", };
|
2021-04-18 17:55:39 -07:00
|
|
|
#ifdef CONFIG_CRASH_DUMP
|
|
|
|
static struct resource elfcorehdr_res = { .name = "ELF Core hdr", };
|
|
|
|
#endif
|
2020-10-12 07:24:10 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
static int __init add_kernel_resources(void)
|
2020-10-12 07:24:10 -07:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The memory region of the kernel image is continuous and
|
2021-04-18 17:55:37 -07:00
|
|
|
* was reserved on setup_bootmem, register it here as a
|
|
|
|
* resource, with the various segments of the image as
|
|
|
|
* child nodes.
|
2020-10-12 07:24:10 -07:00
|
|
|
*/
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
code_res.start = __pa_symbol(_text);
|
|
|
|
code_res.end = __pa_symbol(_etext) - 1;
|
|
|
|
code_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
|
2020-10-12 07:24:10 -07:00
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
rodata_res.start = __pa_symbol(__start_rodata);
|
|
|
|
rodata_res.end = __pa_symbol(__end_rodata) - 1;
|
|
|
|
rodata_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
|
2020-10-12 07:24:10 -07:00
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
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;
|
|
|
|
|
|
|
|
kimage_res.start = code_res.start;
|
|
|
|
kimage_res.end = bss_res.end;
|
|
|
|
kimage_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
|
|
|
|
|
|
|
|
ret = add_resource(&iomem_resource, &kimage_res);
|
2020-10-12 07:24:10 -07:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
ret = add_resource(&kimage_res, &code_res);
|
2020-10-12 07:24:10 -07:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
ret = add_resource(&kimage_res, &rodata_res);
|
2020-10-12 07:24:10 -07:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
ret = add_resource(&kimage_res, &data_res);
|
2020-10-12 07:24:10 -07:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
ret = add_resource(&kimage_res, &bss_res);
|
2020-10-12 07:24:10 -07:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __init init_resources(void)
|
|
|
|
{
|
|
|
|
struct memblock_region *region = NULL;
|
|
|
|
struct resource *res = NULL;
|
2021-01-11 16:45:01 -07:00
|
|
|
struct resource *mem_res = NULL;
|
|
|
|
size_t mem_res_sz = 0;
|
2021-04-18 17:55:37 -07:00
|
|
|
int num_resources = 0, res_idx = 0;
|
|
|
|
int ret = 0;
|
2020-10-12 07:24:10 -07:00
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
/* + 1 as memblock_alloc() might increase memblock.reserved.cnt */
|
|
|
|
num_resources = memblock.memory.cnt + memblock.reserved.cnt + 1;
|
|
|
|
res_idx = num_resources - 1;
|
2020-10-12 07:24:10 -07:00
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
mem_res_sz = num_resources * sizeof(*mem_res);
|
2021-01-11 16:45:01 -07:00
|
|
|
mem_res = memblock_alloc(mem_res_sz, SMP_CACHE_BYTES);
|
|
|
|
if (!mem_res)
|
|
|
|
panic("%s: Failed to allocate %zu bytes\n", __func__, mem_res_sz);
|
2021-04-18 17:55:37 -07:00
|
|
|
|
2020-10-12 07:24:10 -07:00
|
|
|
/*
|
|
|
|
* Start by adding the reserved regions, if they overlap
|
|
|
|
* with /memory regions, insert_resource later on will take
|
|
|
|
* care of it.
|
|
|
|
*/
|
2021-04-18 17:55:37 -07:00
|
|
|
ret = add_kernel_resources();
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
|
2021-04-18 17:55:39 -07:00
|
|
|
#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
|
|
|
|
|
2020-10-12 07:24:10 -07:00
|
|
|
for_each_reserved_mem_region(region) {
|
2021-04-18 17:55:37 -07:00
|
|
|
res = &mem_res[res_idx--];
|
2020-10-12 07:24:10 -07:00
|
|
|
|
|
|
|
res->name = "Reserved";
|
2022-05-17 18:34:28 -07:00
|
|
|
res->flags = IORESOURCE_MEM | IORESOURCE_EXCLUSIVE;
|
2020-10-12 07:24:10 -07:00
|
|
|
res->start = __pfn_to_phys(memblock_region_reserved_base_pfn(region));
|
|
|
|
res->end = __pfn_to_phys(memblock_region_reserved_end_pfn(region)) - 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ignore any other reserved regions within
|
|
|
|
* system memory.
|
|
|
|
*/
|
2021-01-11 16:45:01 -07:00
|
|
|
if (memblock_is_memory(res->start)) {
|
2021-04-18 17:55:37 -07:00
|
|
|
/* Re-use this pre-allocated resource */
|
|
|
|
res_idx++;
|
2020-10-12 07:24:10 -07:00
|
|
|
continue;
|
2021-01-11 16:45:01 -07:00
|
|
|
}
|
2020-10-12 07:24:10 -07:00
|
|
|
|
|
|
|
ret = add_resource(&iomem_resource, res);
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add /memory regions to the resource tree */
|
|
|
|
for_each_mem_region(region) {
|
2021-04-18 17:55:37 -07:00
|
|
|
res = &mem_res[res_idx--];
|
2020-10-12 07:24:10 -07:00
|
|
|
|
|
|
|
if (unlikely(memblock_is_nomap(region))) {
|
|
|
|
res->name = "Reserved";
|
2022-05-17 18:34:28 -07:00
|
|
|
res->flags = IORESOURCE_MEM | IORESOURCE_EXCLUSIVE;
|
2020-10-12 07:24:10 -07:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
2021-04-18 17:55:37 -07:00
|
|
|
/* Clean-up any unused pre-allocated resources */
|
2021-08-07 10:54:50 -07:00
|
|
|
if (res_idx >= 0)
|
2021-11-05 13:43:22 -07:00
|
|
|
memblock_free(mem_res, (res_idx + 1) * sizeof(*mem_res));
|
2020-10-12 07:24:10 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
/* Better an empty resource tree than an inconsistent one */
|
|
|
|
release_child_resources(&iomem_resource);
|
2021-11-05 13:43:22 -07:00
|
|
|
memblock_free(mem_res, mem_res_sz);
|
2020-10-12 07:24:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-17 15:37:10 -07:00
|
|
|
static void __init parse_dtb(void)
|
2017-07-10 18:00:26 -07:00
|
|
|
{
|
2020-09-17 15:37:10 -07:00
|
|
|
/* Early scan of device tree from init memory */
|
2020-11-25 04:44:15 -07:00
|
|
|
if (early_init_dt_scan(dtb_early_va)) {
|
|
|
|
const char *name = of_flat_dt_get_machine_name();
|
|
|
|
|
|
|
|
if (name) {
|
|
|
|
pr_info("Machine model: %s\n", name);
|
|
|
|
dump_stack_set_arch_desc("%s (DT)", name);
|
|
|
|
}
|
2022-07-08 13:38:22 -07:00
|
|
|
} else {
|
|
|
|
pr_err("No DTB passed to the kernel\n");
|
2020-11-25 04:44:15 -07:00
|
|
|
}
|
2018-12-17 20:15:12 -07:00
|
|
|
|
|
|
|
#ifdef CONFIG_CMDLINE_FORCE
|
2021-08-07 00:14:27 -07:00
|
|
|
strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
2018-12-17 20:15:12 -07:00
|
|
|
pr_info("Forcing kernel command line to: %s\n", boot_command_line);
|
|
|
|
#endif
|
2017-07-10 18:00:26 -07:00
|
|
|
}
|
|
|
|
|
2023-06-05 04:07:11 -07:00
|
|
|
extern void __init init_rt_signal_env(void);
|
|
|
|
|
2017-07-10 18:00:26 -07:00
|
|
|
void __init setup_arch(char **cmdline_p)
|
|
|
|
{
|
2020-09-17 15:37:10 -07:00
|
|
|
parse_dtb();
|
2021-07-07 18:08:54 -07:00
|
|
|
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
2017-07-10 18:00:26 -07:00
|
|
|
|
2019-01-07 06:49:14 -07:00
|
|
|
*cmdline_p = boot_command_line;
|
|
|
|
|
2020-09-17 15:37:11 -07:00
|
|
|
early_ioremap_setup();
|
2023-05-14 22:49:08 -07:00
|
|
|
sbi_init();
|
2020-11-06 00:53:59 -07:00
|
|
|
jump_label_init();
|
2019-01-07 06:49:14 -07:00
|
|
|
parse_early_param();
|
|
|
|
|
2020-09-17 15:37:15 -07:00
|
|
|
efi_init();
|
2017-07-10 18:00:26 -07:00
|
|
|
paging_init();
|
2023-05-14 22:49:15 -07:00
|
|
|
|
|
|
|
/* Parse the ACPI tables for possible boot-time configuration */
|
|
|
|
acpi_boot_table_init();
|
|
|
|
|
2020-04-13 21:43:24 -07:00
|
|
|
#if IS_ENABLED(CONFIG_BUILTIN_DTB)
|
|
|
|
unflatten_and_copy_device_tree();
|
|
|
|
#else
|
2023-03-29 01:19:31 -07:00
|
|
|
unflatten_device_tree();
|
2020-04-13 21:43:24 -07:00
|
|
|
#endif
|
2020-11-18 17:38:27 -07:00
|
|
|
misc_mem_init();
|
2018-10-02 01:52:28 -07:00
|
|
|
|
2021-04-18 17:55:38 -07:00
|
|
|
init_resources();
|
2020-11-04 17:04:36 -07:00
|
|
|
|
2020-01-06 11:38:32 -07:00
|
|
|
#ifdef CONFIG_KASAN
|
|
|
|
kasan_init();
|
|
|
|
#endif
|
|
|
|
|
2017-07-10 18:00:26 -07:00
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
setup_smp();
|
|
|
|
#endif
|
|
|
|
|
2024-06-13 01:54:33 -07:00
|
|
|
if (!acpi_disabled) {
|
2023-05-14 22:49:16 -07:00
|
|
|
acpi_init_rintc_map();
|
2024-06-13 01:54:33 -07:00
|
|
|
acpi_map_cpus_to_nodes();
|
|
|
|
}
|
2023-05-14 22:49:16 -07:00
|
|
|
|
2023-02-24 09:26:27 -07:00
|
|
|
riscv_init_cbo_blocksizes();
|
2022-09-12 15:48:01 -07:00
|
|
|
riscv_fill_hwcap();
|
2023-06-05 04:07:11 -07:00
|
|
|
init_rt_signal_env();
|
2022-05-11 12:29:16 -07:00
|
|
|
apply_boot_alternatives();
|
RISC-V: Enable cbo.zero in usermode
When Zicboz is present, enable its instruction (cbo.zero) in
usermode by setting its respective senvcfg bit. We don't bother
trying to set this bit per-task, which would also require an
interface for tasks to request enabling and/or disabling. Instead,
permanently set the bit for each hart which has the extension when
bringing it online.
This patch also introduces riscv_cpu_has_extension_[un]likely()
functions to check a specific hart's ISA bitmap for extensions.
Prior to checking the specific hart's bitmap in these functions
we try the bitmap which represents the LCD of extensions, but only
when we know it will use its optimized, alternatives path by gating
its call on CONFIG_RISCV_ALTERNATIVE. When alternatives are used, the
compiler ensures that the invocation of the LCD search becomes a
constant true or false. When it's true, even the new functions will
completely vanish from their callsites. OTOH, when the LCD check is
false, we need to do a search of the hart's ISA bitmap. Had we also
checked the LCD bitmap without the use of alternatives, then we would
have ended up with two bitmap searches instead of one.
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230918131518.56803-10-ajones@ventanamicro.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-09-18 06:15:21 -07:00
|
|
|
|
2023-01-28 10:28:44 -07:00
|
|
|
if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
|
|
|
|
riscv_isa_extension_available(NULL, ZICBOM))
|
|
|
|
riscv_noncoherent_supported();
|
riscv: allow kmalloc() caches aligned to the smallest value
Currently, riscv defines ARCH_DMA_MINALIGN as L1_CACHE_BYTES, I.E
64Bytes, if CONFIG_RISCV_DMA_NONCOHERENT=y. To support unified kernel
Image, usually we have to enable CONFIG_RISCV_DMA_NONCOHERENT, thus
it brings some bad effects to coherent platforms:
Firstly, it wastes memory, kmalloc-96, kmalloc-32, kmalloc-16 and
kmalloc-8 slab caches don't exist any more, they are replaced with
either kmalloc-128 or kmalloc-64.
Secondly, larger than necessary kmalloc aligned allocations results
in unnecessary cache/TLB pressure.
This issue also exists on arm64 platforms. From last year, Catalin
tried to solve this issue by decoupling ARCH_KMALLOC_MINALIGN from
ARCH_DMA_MINALIGN, limiting kmalloc() minimum alignment to
dma_get_cache_alignment() and replacing ARCH_KMALLOC_MINALIGN usage
in various drivers with ARCH_DMA_MINALIGN etc.[1]
One fact we can make use of for riscv: if the CPU doesn't support
ZICBOM or T-HEAD CMO, we know the platform is coherent. Based on
Catalin's work and above fact, we can easily solve the kmalloc align
issue for riscv: we can override dma_get_cache_alignment(), then let
it return ARCH_DMA_MINALIGN at the beginning and return 1 once we know
the underlying HW neither supports ZICBOM nor supports T-HEAD CMO.
So what about if the CPU supports ZICBOM or T-HEAD CMO, but all the
devices are dma coherent? Well, we use ARCH_DMA_MINALIGN as the
kmalloc minimum alignment, nothing changed in this case. This case
can be improved in the future.
After this patch, a simple test of booting to a small buildroot rootfs
on qemu shows:
kmalloc-96 5041 5041 96 ...
kmalloc-64 9606 9606 64 ...
kmalloc-32 5128 5128 32 ...
kmalloc-16 7682 7682 16 ...
kmalloc-8 10246 10246 8 ...
So we save about 1268KB memory. The saving will be much larger in normal
OS env on real HW platforms.
Link: https://lore.kernel.org/linux-arm-kernel/20230524171904.3967031-1-catalin.marinas@arm.com/ [1]
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230718152214.2907-2-jszhang@kernel.org
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-07-18 08:22:13 -07:00
|
|
|
riscv_set_dma_cache_alignment();
|
RISC-V: Enable cbo.zero in usermode
When Zicboz is present, enable its instruction (cbo.zero) in
usermode by setting its respective senvcfg bit. We don't bother
trying to set this bit per-task, which would also require an
interface for tasks to request enabling and/or disabling. Instead,
permanently set the bit for each hart which has the extension when
bringing it online.
This patch also introduces riscv_cpu_has_extension_[un]likely()
functions to check a specific hart's ISA bitmap for extensions.
Prior to checking the specific hart's bitmap in these functions
we try the bitmap which represents the LCD of extensions, but only
when we know it will use its optimized, alternatives path by gating
its call on CONFIG_RISCV_ALTERNATIVE. When alternatives are used, the
compiler ensures that the invocation of the LCD search becomes a
constant true or false. When it's true, even the new functions will
completely vanish from their callsites. OTOH, when the LCD check is
false, we need to do a search of the hart's ISA bitmap. Had we also
checked the LCD bitmap without the use of alternatives, then we would
have ended up with two bitmap searches instead of one.
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230918131518.56803-10-ajones@ventanamicro.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-09-18 06:15:21 -07:00
|
|
|
|
|
|
|
riscv_user_isa_enable();
|
2017-07-10 18:00:26 -07:00
|
|
|
}
|
2020-03-17 18:11:44 -07:00
|
|
|
|
2023-11-21 06:45:37 -07:00
|
|
|
bool arch_cpu_is_hotpluggable(int cpu)
|
2020-03-17 18:11:44 -07:00
|
|
|
{
|
2023-11-21 06:45:37 -07:00
|
|
|
return cpu_has_hotplug(cpu);
|
2020-03-17 18:11:44 -07:00
|
|
|
}
|
2020-11-04 17:04:38 -07:00
|
|
|
|
|
|
|
void free_initmem(void)
|
|
|
|
{
|
riscv: mm: Proper page permissions after initmem free
64-bit RISC-V kernels have the kernel image mapped separately to alias
the linear map. The linear map and the kernel image map are documented
as "direct mapping" and "kernel" respectively in [1].
At image load time, the linear map corresponding to the kernel image
is set to PAGE_READ permission, and the kernel image map is set to
PAGE_READ|PAGE_EXEC.
When the initmem is freed, the pages in the linear map should be
restored to PAGE_READ|PAGE_WRITE, whereas the corresponding pages in
the kernel image map should be restored to PAGE_READ, by removing the
PAGE_EXEC permission.
This is not the case. For 64-bit kernels, only the linear map is
restored to its proper page permissions at initmem free, and not the
kernel image map.
In practise this results in that the kernel can potentially jump to
dead __init code, and start executing invalid instructions, without
getting an exception.
Restore the freed initmem properly, by setting both the kernel image
map to the correct permissions.
[1] Documentation/riscv/vm-layout.rst
Fixes: e5c35fa04019 ("riscv: Map the kernel with correct permissions the first time")
Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
Reviewed-by: Alexandre Ghiti <alex@ghiti.fr>
Tested-by: Alexandre Ghiti <alex@ghiti.fr>
Link: https://lore.kernel.org/r/20221115090641.258476-1-bjorn@kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2022-11-15 02:06:40 -07:00
|
|
|
if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) {
|
|
|
|
set_kernel_memory(lm_alias(__init_begin), lm_alias(__init_end), set_memory_rw_nx);
|
|
|
|
if (IS_ENABLED(CONFIG_64BIT))
|
|
|
|
set_kernel_memory(__init_begin, __init_end, set_memory_nx);
|
|
|
|
}
|
2021-01-29 12:00:36 -07:00
|
|
|
|
2020-11-04 17:04:38 -07:00
|
|
|
free_initmem_default(POISON_FREE_INITMEM);
|
|
|
|
}
|
2023-07-22 05:38:47 -07:00
|
|
|
|
|
|
|
static int dump_kernel_offset(struct notifier_block *self,
|
|
|
|
unsigned long v, void *p)
|
|
|
|
{
|
|
|
|
pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",
|
|
|
|
kernel_map.virt_offset,
|
|
|
|
KERNEL_LINK_ADDR);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct notifier_block kernel_offset_notifier = {
|
|
|
|
.notifier_call = dump_kernel_offset
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init register_kernel_offset_dumper(void)
|
|
|
|
{
|
|
|
|
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
|
|
|
|
atomic_notifier_chain_register(&panic_notifier_list,
|
|
|
|
&kernel_offset_notifier);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
device_initcall(register_kernel_offset_dumper);
|