devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 5.10 06/16] of/fdt: Don't calculate initrd size from DT if start > end
       [not found] <20221018001029.2731620-1-sashal@kernel.org>
@ 2022-10-18  0:10 ` Sasha Levin
  2022-10-18  0:10 ` [PATCH AUTOSEL 5.10 12/16] of: Fix "dma-ranges" handling for bus controllers Sasha Levin
  1 sibling, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2022-10-18  0:10 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Marek Bykowski, Rob Herring, Sasha Levin, robh+dt, frowand.list,
	devicetree

From: Marek Bykowski <marek.bykowski@gmail.com>

[ Upstream commit d5e3050c0feb8bf7b9a75482fafcc31b90257926 ]

If the properties 'linux,initrd-start' and 'linux,initrd-end' of
the chosen node populated from the bootloader, eg. U-Boot, are so that
start > end, then the phys_initrd_size calculated from end - start is
negative that subsequently gets converted to a high positive value for
being unsigned long long. Then, the memory region with the (invalid)
size is added to the bootmem and attempted being paged in paging_init()
that results in the kernel fault.

For example, on the FVP ARM64 system I'm running, the U-Boot populates
the 'linux,initrd-start' with 8800_0000 and 'linux,initrd-end' with 0.
The phys_initrd_size calculated is then ffff_ffff_7800_0000
(= 0 - 8800_0000 = -8800_0000 + ULLONG_MAX + 1). paging_init() then
attempts to map the address 8800_0000 + ffff_ffff_7800_0000 and oops'es
as below.

It should be stressed, it is generally a fault of the bootloader's with
the kernel relying on it, however we should not allow the bootloader's
misconfiguration to lead to the kernel oops. Not only the kernel should be
bullet proof against it but also finding the root cause of the paging
fault spanning over the bootloader, DT, and kernel may happen is not so
easy.

  Unable to handle kernel paging request at virtual address fffffffefe43c000
  Mem abort info:
    ESR = 0x96000007
    EC = 0x25: DABT (current EL), IL = 32 bits
    SET = 0, FnV = 0
    EA = 0, S1PTW = 0
  Data abort info:
    ISV = 0, ISS = 0x00000007
    CM = 0, WnR = 0
  swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080e3d000
  [fffffffefe43c000] pgd=0000000080de9003, pud=0000000080de9003
  Unable to handle kernel paging request at virtual address ffffff8000de9f90
  Mem abort info:
    ESR = 0x96000005
    EC = 0x25: DABT (current EL), IL = 32 bits
    SET = 0, FnV = 0
    EA = 0, S1PTW = 0
  Data abort info:
    ISV = 0, ISS = 0x00000005
    CM = 0, WnR = 0
  swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080e3d000
  [ffffff8000de9f90] pgd=0000000000000000, pud=0000000000000000
  Internal error: Oops: 96000005 [#1] PREEMPT SMP
  Modules linked in:
  CPU: 0 PID: 0 Comm: swapper Not tainted 5.4.51-yocto-standard #1
  Hardware name: FVP Base (DT)
  pstate: 60000085 (nZCv daIf -PAN -UAO)
  pc : show_pte+0x12c/0x1b4
  lr : show_pte+0x100/0x1b4
  sp : ffffffc010ce3b30
  x29: ffffffc010ce3b30 x28: ffffffc010ceed80
  x27: fffffffefe43c000 x26: fffffffefe43a028
  x25: 0000000080bf0000 x24: 0000000000000025
  x23: ffffffc010b8d000 x22: ffffffc010e3d000
  x23: ffffffc010b8d000 x22: ffffffc010e3d000
  x21: 0000000080de9000 x20: ffffff7f80000f90
  x19: fffffffefe43c000 x18: 0000000000000030
  x17: 0000000000001400 x16: 0000000000001c00
  x15: ffffffc010cef1b8 x14: ffffffffffffffff
  x13: ffffffc010df1f40 x12: ffffffc010df1b70
  x11: ffffffc010ce3b30 x10: ffffffc010ce3b30
  x9 : 00000000ffffffc8 x8 : 0000000000000000
  x7 : 000000000000000f x6 : ffffffc010df16e8
  x5 : 0000000000000000 x4 : 0000000000000000
  x3 : 00000000ffffffff x2 : 0000000000000000
  x1 : 0000008080000000 x0 : ffffffc010af1d68
  Call trace:
   show_pte+0x12c/0x1b4
   die_kernel_fault+0x54/0x78
   __do_kernel_fault+0x11c/0x128
   do_translation_fault+0x58/0xac
   do_mem_abort+0x50/0xb0
   el1_da+0x1c/0x90
   __create_pgd_mapping+0x348/0x598
   paging_init+0x3f0/0x70d0
   setup_arch+0x2c0/0x5d4
   start_kernel+0x94/0x49c
  Code: 92748eb5 900052a0 9135a000 cb010294 (f8756a96) 

Signed-off-by: Marek Bykowski <marek.bykowski@gmail.com>
Link: https://lore.kernel.org/r/20220909023358.76881-1-marek.bykowski@gmail.com
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/of/fdt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 5a1b8688b460..b54fe601370b 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -885,6 +885,8 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
 	if (!prop)
 		return;
 	end = of_read_number(prop, len/4);
+	if (start > end)
+		return;
 
 	__early_init_dt_declare_initrd(start, end);
 	phys_initrd_start = start;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH AUTOSEL 5.10 12/16] of: Fix "dma-ranges" handling for bus controllers
       [not found] <20221018001029.2731620-1-sashal@kernel.org>
  2022-10-18  0:10 ` [PATCH AUTOSEL 5.10 06/16] of/fdt: Don't calculate initrd size from DT if start > end Sasha Levin
@ 2022-10-18  0:10 ` Sasha Levin
  2022-10-20 13:19   ` Rob Herring
  1 sibling, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2022-10-18  0:10 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Robin Murphy, Serge Semin, Rob Herring, Sasha Levin, robh+dt,
	frowand.list, devicetree

From: Robin Murphy <robin.murphy@arm.com>

[ Upstream commit f1ad5338a4d57fe1fe6475003acb8c70bf9d1bdf ]

Commit 951d48855d86 ("of: Make of_dma_get_range() work on bus nodes")
relaxed the handling of "dma-ranges" for any leaf node on the assumption
that it would still represent a usage error for the property to be
present on a non-bus leaf node. However there turns out to be a fiddly
case where a bus also represents a DMA-capable device in its own right,
such as a PCIe root complex with an integrated DMA engine on its
platform side. In such cases, "dma-ranges" translation is entirely valid
for devices discovered behind the bus, but should not be erroneously
applied to the bus controller device itself which operates in its
parent's address space. Fix this by restoring the previous behaviour for
the specific case where a device is configured via its own OF node,
since it is logical to assume that a device should never represent its
own parent bus.

Reported-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/112e8f3d3e7c054ecf5e12b5ac0aa5596ec00681.1664455433.git.robin.murphy@arm.com
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/of/address.c    | 4 +++-
 drivers/of/device.c     | 9 ++++++++-
 drivers/of/of_private.h | 5 +++++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 73ddf2540f3f..fdacf6c3c91f 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -626,7 +626,8 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
 }
 EXPORT_SYMBOL(of_translate_address);
 
-static struct device_node *__of_get_dma_parent(const struct device_node *np)
+#ifdef CONFIG_HAS_DMA
+struct device_node *__of_get_dma_parent(const struct device_node *np)
 {
 	struct of_phandle_args args;
 	int ret, index;
@@ -643,6 +644,7 @@ static struct device_node *__of_get_dma_parent(const struct device_node *np)
 
 	return of_node_get(args.np);
 }
+#endif
 
 static struct device_node *of_get_next_dma_parent(struct device_node *np)
 {
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 1122daa8e273..f760199abda6 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -93,12 +93,19 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 {
 	const struct iommu_ops *iommu;
 	const struct bus_dma_region *map = NULL;
+	struct device_node *bus_np;
 	u64 dma_start = 0;
 	u64 mask, end, size = 0;
 	bool coherent;
 	int ret;
 
-	ret = of_dma_get_range(np, &map);
+	if (np == dev->of_node)
+		bus_np = __of_get_dma_parent(np);
+	else
+		bus_np = of_node_get(np);
+
+	ret = of_dma_get_range(bus_np, &map);
+	of_node_put(bus_np);
 	if (ret < 0) {
 		/*
 		 * For legacy reasons, we have to assume some devices need
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index d9e6a324de0a..ffc2099935f5 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -161,12 +161,17 @@ struct bus_dma_region;
 #if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA)
 int of_dma_get_range(struct device_node *np,
 		const struct bus_dma_region **map);
+struct device_node *__of_get_dma_parent(const struct device_node *np);
 #else
 static inline int of_dma_get_range(struct device_node *np,
 		const struct bus_dma_region **map)
 {
 	return -ENODEV;
 }
+static inline struct device_node *__of_get_dma_parent(const struct device_node *np)
+{
+	return of_get_parent(np);
+}
 #endif
 
 #endif /* _LINUX_OF_PRIVATE_H */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH AUTOSEL 5.10 12/16] of: Fix "dma-ranges" handling for bus controllers
  2022-10-18  0:10 ` [PATCH AUTOSEL 5.10 12/16] of: Fix "dma-ranges" handling for bus controllers Sasha Levin
@ 2022-10-20 13:19   ` Rob Herring
  0 siblings, 0 replies; 3+ messages in thread
From: Rob Herring @ 2022-10-20 13:19 UTC (permalink / raw)
  To: Sasha Levin
  Cc: linux-kernel, stable, Robin Murphy, Serge Semin, frowand.list,
	devicetree

On Mon, Oct 17, 2022 at 7:10 PM Sasha Levin <sashal@kernel.org> wrote:
>
> From: Robin Murphy <robin.murphy@arm.com>
>
> [ Upstream commit f1ad5338a4d57fe1fe6475003acb8c70bf9d1bdf ]

This was not marked with Fixes or for stable on purpose as there are
not existing devices that need it and I think there is some chance of
regressing existing devices. So please drop it for now.

Rob

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-10-20 13:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20221018001029.2731620-1-sashal@kernel.org>
2022-10-18  0:10 ` [PATCH AUTOSEL 5.10 06/16] of/fdt: Don't calculate initrd size from DT if start > end Sasha Levin
2022-10-18  0:10 ` [PATCH AUTOSEL 5.10 12/16] of: Fix "dma-ranges" handling for bus controllers Sasha Levin
2022-10-20 13:19   ` Rob Herring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).