Files
build/patch/kernel/archive/spacemit-6.1/061-REVERT-fixes-for-dtb-mapping.patch
2024-07-01 19:15:00 +02:00

249 lines
10 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Sat, 22 Jun 2024 15:32:30 -0400
Subject: REVERT: Fixes for dtb mapping
This breaks PCIe on the BPI-F3 so lets revert it until a solution is found.
https://lore.kernel.org/lkml/mhng-4113481b-4c71-4b5c-ab7e-6896058f074b@palmer-ri-x1c9a/T/
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/diff/?id=v6.1.27&id2=v6.1.26&dt=2
[ 2.854097] spacemit-pmic-pinctrl spacemit-pinctrl@spm8821: DMA mask not set
[ 2.861747] shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
[ 2.862556] k1x-dwc-pcie ca400000.pcie: has no power on gpio.
[ 2.862764] k1x-dwc-pcie ca400000.pcie: host bridge /soc/pcie@ca400000 ranges:
[ 2.862801] k1x-dwc-pcie ca400000.pcie: IO 0x009f002000..0x009f101fff -> 0x009f002000
[ 2.862823] k1x-dwc-pcie ca400000.pcie: MEM 0x0090000000..0x009effffff -> 0x0090000000
[ 2.862865] k1x-dwc-pcie ca400000.pcie: resource collision: [mem 0x90000000-0x9effffff] conflicts with Reserved [mem 0x80000000-0xc07fffff]
[ 2.872584] k1x-dwc-pcie ca400000.pcie: failed to initialize host
[ 2.878747] k1x-dwc-pcie: probe of ca400000.pcie failed with error -12
[ 2.885725] k1x-dwc-pcie ca800000.pcie: has no power on gpio.
[ 2.885912] k1x-dwc-pcie ca800000.pcie: host bridge /soc/pcie@ca800000 ranges:
[ 2.885948] k1x-dwc-pcie ca800000.pcie: IO 0x00b7002000..0x00b7101fff -> 0x00b7002000
[ 2.885969] k1x-dwc-pcie ca800000.pcie: MEM 0x00a0000000..0x00b6ffffff -> 0x00a0000000
[ 2.885987] k1x-dwc-pcie ca800000.pcie: resource collision: [mem 0xa0000000-0xb6ffffff] conflicts with Reserved [mem 0x80000000-0xc07fffff]
[ 2.897922] k1x-dwc-pcie ca800000.pcie: failed to initialize host
[ 2.904083] k1x-dwc-pcie: probe of ca800000.pcie failed with error -12
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
arch/riscv/include/asm/fixmap.h | 8 -
arch/riscv/include/asm/pgtable.h | 8 +-
arch/riscv/kernel/setup.c | 6 +-
arch/riscv/mm/init.c | 78 ++++++----
4 files changed, 52 insertions(+), 48 deletions(-)
diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
index 111111111111..222222222222 100644
--- a/arch/riscv/include/asm/fixmap.h
+++ b/arch/riscv/include/asm/fixmap.h
@@ -22,14 +22,6 @@
*/
enum fixed_addresses {
FIX_HOLE,
- /*
- * The fdt fixmap mapping must be PMD aligned and will be mapped
- * using PMD entries in fixmap_pmd in 64-bit and a PGD entry in 32-bit.
- */
- FIX_FDT_END,
- FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,
-
- /* Below fixmaps will be mapped using fixmap_pte */
FIX_PTE,
FIX_PMD,
FIX_PUD,
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 111111111111..222222222222 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -87,13 +87,9 @@
#define FIXADDR_TOP PCI_IO_START
#ifdef CONFIG_64BIT
-#define MAX_FDT_SIZE PMD_SIZE
-#define FIX_FDT_SIZE (MAX_FDT_SIZE + SZ_2M)
-#define FIXADDR_SIZE (PMD_SIZE + FIX_FDT_SIZE)
+#define FIXADDR_SIZE PMD_SIZE
#else
-#define MAX_FDT_SIZE PGDIR_SIZE
-#define FIX_FDT_SIZE MAX_FDT_SIZE
-#define FIXADDR_SIZE (PGDIR_SIZE + FIX_FDT_SIZE)
+#define FIXADDR_SIZE PGDIR_SIZE
#endif
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 111111111111..222222222222 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -280,8 +280,12 @@ void __init setup_arch(char **cmdline_p)
#if IS_ENABLED(CONFIG_BUILTIN_DTB)
unflatten_and_copy_device_tree();
#else
- unflatten_device_tree();
+ if (early_init_dt_verify(__va(XIP_FIXUP(dtb_early_pa))))
+ unflatten_device_tree();
+ else
+ pr_err("No DTB found in kernel mappings\n");
#endif
+ early_init_fdt_scan_reserved_mem();
misc_mem_init();
init_resources();
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 111111111111..222222222222 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -57,6 +57,7 @@ unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
EXPORT_SYMBOL(empty_zero_page);
extern char _start[];
+#define DTB_EARLY_BASE_VA PGDIR_SIZE
void *_dtb_early_va __initdata;
uintptr_t _dtb_early_pa __initdata;
@@ -241,22 +242,31 @@ static void __init setup_bootmem(void)
set_max_mapnr(max_low_pfn - ARCH_PFN_OFFSET);
reserve_initrd_mem();
-
- /*
- * No allocation should be done before reserving the memory as defined
- * in the device tree, otherwise the allocation could end up in a
- * reserved region.
- */
- early_init_fdt_scan_reserved_mem();
-
/*
* If DTB is built in, no need to reserve its memblock.
* Otherwise, do reserve it but avoid using
* early_init_fdt_reserve_self() since __pa() does
* not work for DTB pointers that are fixmap addresses
*/
- if (!IS_ENABLED(CONFIG_BUILTIN_DTB))
- memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
+ if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) {
+ /*
+ * In case the DTB is not located in a memory region we won't
+ * be able to locate it later on via the linear mapping and
+ * get a segfault when accessing it via __va(dtb_early_pa).
+ * To avoid this situation copy DTB to a memory region.
+ * Note that memblock_phys_alloc will also reserve DTB region.
+ */
+ if (!memblock_is_memory(dtb_early_pa)) {
+ size_t fdt_size = fdt_totalsize(dtb_early_va);
+ phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE);
+ void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size);
+
+ memcpy(new_dtb_early_va, dtb_early_va, fdt_size);
+ early_memunmap(new_dtb_early_va, fdt_size);
+ _dtb_early_pa = new_dtb_early_pa;
+ } else
+ memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
+ }
#ifdef CONFIG_ZONE_DMA32
dma_contiguous_reserve(dma32_phys_limit);
@@ -279,6 +289,9 @@ pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
+static p4d_t __maybe_unused early_dtb_p4d[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
+static pud_t __maybe_unused early_dtb_pud[PTRS_PER_PUD] __initdata __aligned(PAGE_SIZE);
+static pmd_t __maybe_unused early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
#ifdef CONFIG_XIP_KERNEL
#define pt_ops (*(struct pt_alloc_ops *)XIP_FIXUP(&pt_ops))
@@ -623,6 +636,9 @@ static void __init create_p4d_mapping(p4d_t *p4dp,
#define trampoline_pgd_next (pgtable_l5_enabled ? \
(uintptr_t)trampoline_p4d : (pgtable_l4_enabled ? \
(uintptr_t)trampoline_pud : (uintptr_t)trampoline_pmd))
+#define early_dtb_pgd_next (pgtable_l5_enabled ? \
+ (uintptr_t)early_dtb_p4d : (pgtable_l4_enabled ? \
+ (uintptr_t)early_dtb_pud : (uintptr_t)early_dtb_pmd))
#else
#define pgd_next_t pte_t
#define alloc_pgd_next(__va) pt_ops.alloc_pte(__va)
@@ -630,6 +646,7 @@ static void __init create_p4d_mapping(p4d_t *p4dp,
#define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \
create_pte_mapping(__nextp, __va, __pa, __sz, __prot)
#define fixmap_pgd_next ((uintptr_t)fixmap_pte)
+#define early_dtb_pgd_next ((uintptr_t)early_dtb_pmd)
#define create_p4d_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
#define create_pud_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
#define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
@@ -852,27 +869,32 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
* this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR
* entry.
*/
-static void __init create_fdt_early_page_table(uintptr_t fix_fdt_va,
- uintptr_t dtb_pa)
+static void __init create_fdt_early_page_table(pgd_t *pgdir, uintptr_t dtb_pa)
{
#ifndef CONFIG_BUILTIN_DTB
uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1);
- /* Make sure the fdt fixmap address is always aligned on PMD size */
- BUILD_BUG_ON(FIX_FDT % (PMD_SIZE / PAGE_SIZE));
+ create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
+ IS_ENABLED(CONFIG_64BIT) ? early_dtb_pgd_next : pa,
+ PGDIR_SIZE,
+ IS_ENABLED(CONFIG_64BIT) ? PAGE_TABLE : PAGE_KERNEL);
- /* In 32-bit only, the fdt lies in its own PGD */
- if (!IS_ENABLED(CONFIG_64BIT)) {
- create_pgd_mapping(early_pg_dir, fix_fdt_va,
- pa, MAX_FDT_SIZE, PAGE_KERNEL);
- } else {
- create_pmd_mapping(fixmap_pmd, fix_fdt_va,
+ if (pgtable_l5_enabled)
+ create_p4d_mapping(early_dtb_p4d, DTB_EARLY_BASE_VA,
+ (uintptr_t)early_dtb_pud, P4D_SIZE, PAGE_TABLE);
+
+ if (pgtable_l4_enabled)
+ create_pud_mapping(early_dtb_pud, DTB_EARLY_BASE_VA,
+ (uintptr_t)early_dtb_pmd, PUD_SIZE, PAGE_TABLE);
+
+ if (IS_ENABLED(CONFIG_64BIT)) {
+ create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA,
pa, PMD_SIZE, PAGE_KERNEL);
- create_pmd_mapping(fixmap_pmd, fix_fdt_va + PMD_SIZE,
+ create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE,
pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
}
- dtb_early_va = (void *)fix_fdt_va + (dtb_pa & (PMD_SIZE - 1));
+ dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1));
#else
/*
* For 64-bit kernel, __va can't be used since it would return a linear
@@ -1042,7 +1064,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
create_kernel_page_table(early_pg_dir, true);
/* Setup early mapping for FDT early scan */
- create_fdt_early_page_table(__fix_to_virt(FIX_FDT), dtb_pa);
+ create_fdt_early_page_table(early_pg_dir, dtb_pa);
/*
* Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap
@@ -1084,16 +1106,6 @@ static void __init setup_vm_final(void)
u64 i;
/* Setup swapper PGD for fixmap */
-#if !defined(CONFIG_64BIT)
- /*
- * In 32-bit, the device tree lies in a pgd entry, so it must be copied
- * directly in swapper_pg_dir in addition to the pgd entry that points
- * to fixmap_pte.
- */
- unsigned long idx = pgd_index(__fix_to_virt(FIX_FDT));
-
- set_pgd(&swapper_pg_dir[idx], early_pg_dir[idx]);
-#endif
create_pgd_mapping(swapper_pg_dir, FIXADDR_START,
__pa_symbol(fixmap_pgd_next),
PGDIR_SIZE, PAGE_TABLE);
--
Armbian