mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
- Add Kunit correctness testing and microbenchmarks for strlen(),
strnlen(), and strrchr()
- Add RISC-V-specific strnlen(), strchr(), strrchr() implementations
- Add hardware error exception handling
- Clean up and optimize our unaligned access probe code
- Enable HAVE_IOREMAP_PROT to be able to use generic_access_phys()
- Remove XIP kernel support
- Warn when addresses outside the vmemmap range are passed to
vmemmap_populate()
- Update the ACPI FADT revision check to warn if it's not at least
ACPI v6.6, which is when key RISC-V-specific tables were added to the
specification
- Increase COMMAND_LINE_SIZE to 2048 to match ARM64, x86, PowerPC, etc.
- Make kaslr_offset() a static inline function, since there's no need
for it to show up in the symbol table
- Add KASLR offset and SATP to the VMCOREINFO ELF notes to improve
kdump support
- Add Makefile cleanup rule for vdso_cfi copied source files, and add
a .gitignore for the build artifacts in that directory
- Remove some redundant ifdefs that check Kconfig macros
- Add missing SPDX license tag to the CFI selftest
- Simplify UTS_MACHINE assignment in the RISC-V Makefile
- Clarify some unclear comments and remove some superfluous comments
- Fix various English typos across the RISC-V codebase
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEElRDoIDdEz9/svf2Kx4+xDQu9KksFAmnqoPQACgkQx4+xDQu9
KksBGw/+K4cZ5+m2hnS8RVZmreDHPkpLuRmIxqPe1JG/cS0KHwWBX+IX9uYdrmqP
Ex+hZyt+pqFAdbEcV0t4445RR8Lz7D4SxzFFk6q36OuWkrFahOnQQm0prdO+CSok
Ch4AqbH0WNbgoU5xGpCbfsBeNeDOJWc+sNKmoMGF1mlZyy7s7m5jwu2vxdpuc7Ut
pkzqA87JR2Pn2C0EitlJv2mYiKLrnl+ma+yRLjLC3mtubs1HjIUoPTtS4iEuZt41
SabT0SWKPhKXvjxnVxqxKGizH77eciIz+fjecFGB2lO07Lc3z2asT8sJ1bnCspMI
e0Thbohs5Z2q2vGg49UqfDCm47BUWkSjhtgOi1E/JcWPahgCGGP4mYLD6AVZ9biK
gQofXZq5XGxLWjKOoNqh5nPIYIWDtgQgQkXkLiCNYcp1CZ0RaCkkER64UKeRuhoS
tSZuLIbjNzqQMhD9tKWnPueQS3tz3CdNvSMWiDgy+2HoKYIxcaDJ5zPPCMVTWEHn
ohoTLG63oRglV2x5ol27FQKip4SUpxXaDtnuPBytsgys88m0TIOkXvWpzU5si5jQ
O3n43ZiHsnA7jRl4MVlFKDwzHFnm8eOMxpThU34oHJku8AyYQS9zTc05KfbjJEsp
p7YDuh8bH7FHyxLQXHFNor4dCDRY7xU67urz3wjaGRopKA4UE4g=
=hG4G
-----END PGP SIGNATURE-----
Merge tag 'riscv-for-linus-7.1-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V updates from Paul Walmsley:
"There is one significant change outside arch/riscv in this pull
request: the addition of a set of KUnit tests for strlen(), strnlen(),
and strrchr().
Otherwise, the most notable changes are to add some RISC-V-specific
string function implementations, to remove XIP kernel support, to add
hardware error exception handling, and to optimize our runtime
unaligned access speed testing.
A few comments on the motivation for removing XIP support. It's been
broken in the RISC-V kernel for months. The code is not easy to
maintain. Furthermore, for XIP support to truly be useful for RISC-V,
we think that compile-time feature switches would need to be added for
many of the RISC-V ISA features and microarchitectural properties that
are currently implemented with runtime patching. No one has stepped
forward to take responsibility for that work, so many of us think it's
best to remove it until clear use cases and champions emerge.
Summary:
- Add Kunit correctness testing and microbenchmarks for strlen(),
strnlen(), and strrchr()
- Add RISC-V-specific strnlen(), strchr(), strrchr() implementations
- Add hardware error exception handling
- Clean up and optimize our unaligned access probe code
- Enable HAVE_IOREMAP_PROT to be able to use generic_access_phys()
- Remove XIP kernel support
- Warn when addresses outside the vmemmap range are passed to
vmemmap_populate()
- Update the ACPI FADT revision check to warn if it's not at least
ACPI v6.6, which is when key RISC-V-specific tables were added to
the specification
- Increase COMMAND_LINE_SIZE to 2048 to match ARM64, x86, PowerPC,
etc.
- Make kaslr_offset() a static inline function, since there's no need
for it to show up in the symbol table
- Add KASLR offset and SATP to the VMCOREINFO ELF notes to improve
kdump support
- Add Makefile cleanup rule for vdso_cfi copied source files, and add
a .gitignore for the build artifacts in that directory
- Remove some redundant ifdefs that check Kconfig macros
- Add missing SPDX license tag to the CFI selftest
- Simplify UTS_MACHINE assignment in the RISC-V Makefile
- Clarify some unclear comments and remove some superfluous comments
- Fix various English typos across the RISC-V codebase"
* tag 'riscv-for-linus-7.1-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (31 commits)
riscv: Remove support for XIP kernel
riscv: Reuse compare_unaligned_access() in check_vector_unaligned_access()
riscv: Split out compare_unaligned_access()
riscv: Reuse measure_cycles() in check_vector_unaligned_access()
riscv: Split out measure_cycles() for reuse
riscv: Clean up & optimize unaligned scalar access probe
riscv: lib: add strrchr() implementation
riscv: lib: add strchr() implementation
riscv: lib: add strnlen() implementation
lib/string_kunit: extend benchmarks to strnlen() and chr searches
lib/string_kunit: add performance benchmark for strlen()
lib/string_kunit: add correctness test for strrchr()
lib/string_kunit: add correctness test for strnlen()
lib/string_kunit: add correctness test for strlen()
riscv: vdso_cfi: Add .gitignore for build artifacts
riscv: vdso_cfi: Add clean rule for copied sources
riscv: enable HAVE_IOREMAP_PROT
riscv: mm: WARN_ON() for bad addresses in vmemmap_populate()
riscv: acpi: update FADT revision check to 6.6
riscv: add hardware error trap handler support
...
356 lines
9.4 KiB
C
356 lines
9.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* RISC-V Specific Low-Level ACPI Boot Support
|
|
*
|
|
* Copyright (C) 2013-2014, Linaro Ltd.
|
|
* Author: Al Stone <al.stone@linaro.org>
|
|
* Author: Graeme Gregory <graeme.gregory@linaro.org>
|
|
* Author: Hanjun Guo <hanjun.guo@linaro.org>
|
|
* Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
|
|
* Author: Naresh Bhat <naresh.bhat@linaro.org>
|
|
*
|
|
* Copyright (C) 2021-2023, Ventana Micro Systems Inc.
|
|
* Author: Sunil V L <sunilvl@ventanamicro.com>
|
|
*/
|
|
|
|
#include <linux/acpi.h>
|
|
#include <linux/efi-bgrt.h>
|
|
#include <linux/efi.h>
|
|
#include <linux/io.h>
|
|
#include <linux/memblock.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/serial_core.h>
|
|
|
|
int acpi_noirq = 1; /* skip ACPI IRQ initialization */
|
|
int acpi_disabled = 1;
|
|
EXPORT_SYMBOL(acpi_disabled);
|
|
|
|
int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */
|
|
EXPORT_SYMBOL(acpi_pci_disabled);
|
|
|
|
static bool param_acpi_off __initdata;
|
|
static bool param_acpi_on __initdata;
|
|
static bool param_acpi_force __initdata;
|
|
|
|
static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS];
|
|
|
|
static int __init parse_acpi(char *arg)
|
|
{
|
|
if (!arg)
|
|
return -EINVAL;
|
|
|
|
/* "acpi=off" disables both ACPI table parsing and interpreter */
|
|
if (strcmp(arg, "off") == 0)
|
|
param_acpi_off = true;
|
|
else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */
|
|
param_acpi_on = true;
|
|
else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
|
|
param_acpi_force = true;
|
|
else
|
|
return -EINVAL; /* Core will print when we return error */
|
|
|
|
return 0;
|
|
}
|
|
early_param("acpi", parse_acpi);
|
|
|
|
/*
|
|
* acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
|
|
* checks on it
|
|
*
|
|
* Return 0 on success, <0 on failure
|
|
*/
|
|
static int __init acpi_fadt_sanity_check(void)
|
|
{
|
|
struct acpi_table_header *table;
|
|
struct acpi_table_fadt *fadt;
|
|
acpi_status status;
|
|
int ret = 0;
|
|
|
|
/*
|
|
* FADT is required on riscv; retrieve it to check its presence
|
|
* and carry out revision and ACPI HW reduced compliance tests
|
|
*/
|
|
status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
|
|
if (ACPI_FAILURE(status)) {
|
|
const char *msg = acpi_format_exception(status);
|
|
|
|
pr_err("Failed to get FADT table, %s\n", msg);
|
|
return -ENODEV;
|
|
}
|
|
|
|
fadt = (struct acpi_table_fadt *)table;
|
|
|
|
/*
|
|
* The revision in the table header is the FADT's Major revision. The
|
|
* FADT also has a minor revision, which is stored in the FADT itself.
|
|
*
|
|
* ACPI 6.6 is required for RISC-V as it introduces RISC-V specific
|
|
* tables such as RHCT (RISC-V Hart Capabilities Table) and RIMT
|
|
* (RISC-V I/O Mapping Table).
|
|
*/
|
|
if (table->revision < 6 || (table->revision == 6 && fadt->minor_revision < 6))
|
|
pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 6.6+\n",
|
|
table->revision, fadt->minor_revision);
|
|
|
|
if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
|
|
pr_err("FADT not ACPI hardware reduced compliant\n");
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
/*
|
|
* acpi_get_table() creates FADT table mapping that
|
|
* should be released after parsing and before resuming boot
|
|
*/
|
|
acpi_put_table(table);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* acpi_boot_table_init() called from setup_arch(), always.
|
|
* 1. find RSDP and get its address, and then find XSDT
|
|
* 2. extract all tables and checksums them all
|
|
* 3. check ACPI FADT HW reduced flag
|
|
*
|
|
* We can parse ACPI boot-time tables such as MADT after
|
|
* this function is called.
|
|
*
|
|
* On return ACPI is enabled if either:
|
|
*
|
|
* - ACPI tables are initialized and sanity checks passed
|
|
* - acpi=force was passed in the command line and ACPI was not disabled
|
|
* explicitly through acpi=off command line parameter
|
|
*
|
|
* ACPI is disabled on function return otherwise
|
|
*/
|
|
void __init acpi_boot_table_init(void)
|
|
{
|
|
/*
|
|
* Enable ACPI instead of device tree unless
|
|
* - ACPI has been disabled explicitly (acpi=off), or
|
|
* - firmware has not populated ACPI ptr in EFI system table
|
|
* and ACPI has not been [force] enabled (acpi=on|force)
|
|
*/
|
|
if (param_acpi_off ||
|
|
(!param_acpi_on && !param_acpi_force &&
|
|
efi.acpi20 == EFI_INVALID_TABLE_ADDR))
|
|
goto done;
|
|
|
|
/*
|
|
* ACPI is disabled at this point. Enable it in order to parse
|
|
* the ACPI tables and carry out sanity checks
|
|
*/
|
|
enable_acpi();
|
|
|
|
/*
|
|
* If ACPI tables are initialized and FADT sanity checks passed,
|
|
* leave ACPI enabled and carry on booting; otherwise disable ACPI
|
|
* on initialization error.
|
|
* If acpi=force was passed on the command line it forces ACPI
|
|
* to be enabled even if its initialization failed.
|
|
*/
|
|
if (acpi_table_init() || acpi_fadt_sanity_check()) {
|
|
pr_err("Failed to init ACPI tables\n");
|
|
if (!param_acpi_force)
|
|
disable_acpi();
|
|
}
|
|
|
|
done:
|
|
if (acpi_disabled) {
|
|
if (earlycon_acpi_spcr_enable)
|
|
early_init_dt_scan_chosen_stdout();
|
|
} else {
|
|
acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
|
|
if (IS_ENABLED(CONFIG_ACPI_BGRT))
|
|
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
|
|
}
|
|
}
|
|
|
|
static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end)
|
|
{
|
|
struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header;
|
|
int cpuid;
|
|
|
|
if (!(rintc->flags & ACPI_MADT_ENABLED))
|
|
return 0;
|
|
|
|
cpuid = riscv_hartid_to_cpuid(rintc->hart_id);
|
|
/*
|
|
* When CONFIG_SMP is disabled, mapping won't be created for
|
|
* all cpus.
|
|
* CPUs more than num_possible_cpus, will be ignored.
|
|
*/
|
|
if (cpuid >= 0 && cpuid < num_possible_cpus())
|
|
cpu_madt_rintc[cpuid] = *rintc;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Instead of parsing (and freeing) the ACPI table, cache
|
|
* the RINTC structures since they are frequently used
|
|
* like in cpuinfo.
|
|
*/
|
|
void __init acpi_init_rintc_map(void)
|
|
{
|
|
if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) <= 0) {
|
|
pr_err("No valid RINTC entries exist\n");
|
|
BUG();
|
|
}
|
|
}
|
|
|
|
struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
|
|
{
|
|
return &cpu_madt_rintc[cpu];
|
|
}
|
|
|
|
/*
|
|
* __acpi_map_table() will be called before paging_init(), so early_ioremap()
|
|
* or early_memremap() should be called here to for ACPI table mapping.
|
|
*/
|
|
void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size)
|
|
{
|
|
if (!size)
|
|
return NULL;
|
|
|
|
return early_memremap(phys, size);
|
|
}
|
|
|
|
void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
|
|
{
|
|
if (!map || !size)
|
|
return;
|
|
|
|
early_memunmap(map, size);
|
|
}
|
|
|
|
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
|
|
{
|
|
efi_memory_desc_t *md, *region = NULL;
|
|
pgprot_t prot;
|
|
|
|
if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
|
|
return NULL;
|
|
|
|
for_each_efi_memory_desc(md) {
|
|
u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
|
|
|
|
if (phys < md->phys_addr || phys >= end)
|
|
continue;
|
|
|
|
if (phys + size > end) {
|
|
pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
|
|
return NULL;
|
|
}
|
|
region = md;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* It is fine for AML to remap regions that are not represented in the
|
|
* EFI memory map at all, as it only describes normal memory, and MMIO
|
|
* regions that require a virtual mapping to make them accessible to
|
|
* the EFI runtime services.
|
|
*/
|
|
prot = PAGE_KERNEL_IO;
|
|
if (region) {
|
|
switch (region->type) {
|
|
case EFI_LOADER_CODE:
|
|
case EFI_LOADER_DATA:
|
|
case EFI_BOOT_SERVICES_CODE:
|
|
case EFI_BOOT_SERVICES_DATA:
|
|
case EFI_CONVENTIONAL_MEMORY:
|
|
case EFI_PERSISTENT_MEMORY:
|
|
if (memblock_is_map_memory(phys) ||
|
|
!memblock_is_region_memory(phys, size)) {
|
|
pr_warn(FW_BUG "requested region covers kernel memory\n");
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Mapping kernel memory is permitted if the region in
|
|
* question is covered by a single memblock with the
|
|
* NOMAP attribute set: this enables the use of ACPI
|
|
* table overrides passed via initramfs.
|
|
* This particular use case only requires read access.
|
|
*/
|
|
fallthrough;
|
|
|
|
case EFI_RUNTIME_SERVICES_CODE:
|
|
/*
|
|
* This would be unusual, but not problematic per se,
|
|
* as long as we take care not to create a writable
|
|
* mapping for executable code.
|
|
*/
|
|
prot = PAGE_KERNEL_RO;
|
|
break;
|
|
|
|
case EFI_ACPI_RECLAIM_MEMORY:
|
|
/*
|
|
* ACPI reclaim memory is used to pass firmware tables
|
|
* and other data that is intended for consumption by
|
|
* the OS only, which may decide it wants to reclaim
|
|
* that memory and use it for something else. We never
|
|
* do that, but we usually add it to the linear map
|
|
* anyway, in which case we should use the existing
|
|
* mapping.
|
|
*/
|
|
if (memblock_is_map_memory(phys))
|
|
return (void __iomem *)__va(phys);
|
|
fallthrough;
|
|
|
|
default:
|
|
if (region->attribute & EFI_MEMORY_WB)
|
|
prot = PAGE_KERNEL;
|
|
else if ((region->attribute & EFI_MEMORY_WC) ||
|
|
(region->attribute & EFI_MEMORY_WT))
|
|
prot = pgprot_writecombine(PAGE_KERNEL);
|
|
}
|
|
}
|
|
|
|
return ioremap_prot(phys, size, prot);
|
|
}
|
|
|
|
#ifdef CONFIG_PCI
|
|
|
|
/*
|
|
* raw_pci_read/write - Platform-specific PCI config space access.
|
|
*/
|
|
int raw_pci_read(unsigned int domain, unsigned int bus,
|
|
unsigned int devfn, int reg, int len, u32 *val)
|
|
{
|
|
struct pci_bus *b = pci_find_bus(domain, bus);
|
|
|
|
if (!b)
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
|
return b->ops->read(b, devfn, reg, len, val);
|
|
}
|
|
|
|
int raw_pci_write(unsigned int domain, unsigned int bus,
|
|
unsigned int devfn, int reg, int len, u32 val)
|
|
{
|
|
struct pci_bus *b = pci_find_bus(domain, bus);
|
|
|
|
if (!b)
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
|
return b->ops->write(b, devfn, reg, len, val);
|
|
}
|
|
|
|
#endif /* CONFIG_PCI */
|
|
|
|
int acpi_get_cpu_uid(unsigned int cpu, u32 *uid)
|
|
{
|
|
struct acpi_madt_rintc *rintc;
|
|
|
|
if (cpu >= nr_cpu_ids)
|
|
return -EINVAL;
|
|
|
|
rintc = acpi_cpu_get_madt_rintc(cpu);
|
|
if (!rintc)
|
|
return -ENODEV;
|
|
|
|
*uid = rintc->uid;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(acpi_get_cpu_uid);
|