[2/2] of: fdt: Allow the kernel to mark nomap regions received from fdt

Message ID 20230406151429.524591-3-tanure@linux.com
State New
Headers
Series Fix Random Kernel panic from when fail to reserve memory |

Commit Message

Lucas Tanure April 6, 2023, 3:14 p.m. UTC
  Reserved regions can be described in FDT and device trees, but FDT doesn't
provide the related flags, like nomap.
So allow the kernel to mark regions where the base and size received from
the device tree are the same as the base and region on FDT.
Here we trust that the device tree has a more updated description of the
region than the one received from FDT.

Signed-off-by: Lucas Tanure <tanure@linux.com>
---
 drivers/of/fdt.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
  

Comments

Rob Herring April 6, 2023, 3:48 p.m. UTC | #1
On Thu, Apr 6, 2023 at 10:14 AM Lucas Tanure <tanure@linux.com> wrote:
>
> Reserved regions can be described in FDT and device trees, but FDT doesn't
> provide the related flags, like nomap.

It took me a minute to understand what you meant by FDT vs. device
trees. Use the exact things you are talking about: /memreserve/ and
/reserved-memory node.

> So allow the kernel to mark regions where the base and size received from
> the device tree are the same as the base and region on FDT.
> Here we trust that the device tree has a more updated description of the
> region than the one received from FDT.
>
> Signed-off-by: Lucas Tanure <tanure@linux.com>
> ---
>  drivers/of/fdt.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index d1a68b6d03b3..754a7ea4f45c 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -482,11 +482,13 @@ static int __init early_init_dt_reserve_memory(phys_addr_t base,
>         if (nomap) {
>                 /*
>                  * If the memory is already reserved (by another region), we
> -                * should not allow it to be marked nomap, but don't worry
> -                * if the region isn't memory as it won't be mapped.
> +                * should not allow it to be marked nomap, unless is the exact same region
> +                * (same base and size), which the kernel knows better and should be allowed to mark
> +                *  it as nomap.
> +                * But don't worry if the region isn't memory as it won't be mapped.
>                  */
> -               if (memblock_overlaps_region(&memblock.memory, base, size) &&
> -                   memblock_is_region_reserved(base, size))
> +               if (memblock_overlaps_region(&memblock.memory, base, size) == MEMBLOCK_OVERLAPS &&
> +                   memblock_is_region_reserved(base, size) == MEMBLOCK_OVERLAPS)

Won't this fail to work as IIRC memblock will merge regions when they
are adjacent and have the same atrributes.

Perhaps instead, the DT code should ignore any /memreserve/ entries
that are also in /reserved-memory.

I would suggest just reverse the order they are processed, but I
suspect that might cause some regression. This code is all fragile
especially with platforms putting in 100 regions.

Finally, perhaps fix u-boot. The reason the reserved location goes in
both places was to support an OS not supporting /reserved-memory. I
think that support has been in place for a lot longer than anyone
would care about.

Rob
  
Neil Armstrong April 6, 2023, 4:06 p.m. UTC | #2
On 06/04/2023 17:48, Rob Herring wrote:
> On Thu, Apr 6, 2023 at 10:14 AM Lucas Tanure <tanure@linux.com> wrote:
>>
>> Reserved regions can be described in FDT and device trees, but FDT doesn't
>> provide the related flags, like nomap.
> 
> It took me a minute to understand what you meant by FDT vs. device
> trees. Use the exact things you are talking about: /memreserve/ and
> /reserved-memory node.
> 
>> So allow the kernel to mark regions where the base and size received from
>> the device tree are the same as the base and region on FDT.
>> Here we trust that the device tree has a more updated description of the
>> region than the one received from FDT.
>>
>> Signed-off-by: Lucas Tanure <tanure@linux.com>
>> ---
>>   drivers/of/fdt.c | 10 ++++++----
>>   1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
>> index d1a68b6d03b3..754a7ea4f45c 100644
>> --- a/drivers/of/fdt.c
>> +++ b/drivers/of/fdt.c
>> @@ -482,11 +482,13 @@ static int __init early_init_dt_reserve_memory(phys_addr_t base,
>>          if (nomap) {
>>                  /*
>>                   * If the memory is already reserved (by another region), we
>> -                * should not allow it to be marked nomap, but don't worry
>> -                * if the region isn't memory as it won't be mapped.
>> +                * should not allow it to be marked nomap, unless is the exact same region
>> +                * (same base and size), which the kernel knows better and should be allowed to mark
>> +                *  it as nomap.
>> +                * But don't worry if the region isn't memory as it won't be mapped.
>>                   */
>> -               if (memblock_overlaps_region(&memblock.memory, base, size) &&
>> -                   memblock_is_region_reserved(base, size))
>> +               if (memblock_overlaps_region(&memblock.memory, base, size) == MEMBLOCK_OVERLAPS &&
>> +                   memblock_is_region_reserved(base, size) == MEMBLOCK_OVERLAPS)
> 
> Won't this fail to work as IIRC memblock will merge regions when they
> are adjacent and have the same atrributes.
> 
> Perhaps instead, the DT code should ignore any /memreserve/ entries
> that are also in /reserved-memory.
> 
> I would suggest just reverse the order they are processed, but I
> suspect that might cause some regression. This code is all fragile
> especially with platforms putting in 100 regions.
> 
> Finally, perhaps fix u-boot. The reason the reserved location goes in
> both places was to support an OS not supporting /reserved-memory. I
> think that support has been in place for a lot longer than anyone
> would care about.

Fixing U-Boot won't fix already tagged and in-the-field mainline u-boot
releases that adds /memreserve/ entries, so yes u-boot should be definitely
fixed but Linux should ignore the /memreserve/ entries when they matches
an /reserved-memory node like when the U-Boot /memreserve/ code was added.

Neil

> 
> Rob
> 
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic
  

Patch

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index d1a68b6d03b3..754a7ea4f45c 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -482,11 +482,13 @@  static int __init early_init_dt_reserve_memory(phys_addr_t base,
 	if (nomap) {
 		/*
 		 * If the memory is already reserved (by another region), we
-		 * should not allow it to be marked nomap, but don't worry
-		 * if the region isn't memory as it won't be mapped.
+		 * should not allow it to be marked nomap, unless is the exact same region
+		 * (same base and size), which the kernel knows better and should be allowed to mark
+		 *  it as nomap.
+		 * But don't worry if the region isn't memory as it won't be mapped.
 		 */
-		if (memblock_overlaps_region(&memblock.memory, base, size) &&
-		    memblock_is_region_reserved(base, size))
+		if (memblock_overlaps_region(&memblock.memory, base, size) == MEMBLOCK_OVERLAPS &&
+		    memblock_is_region_reserved(base, size) == MEMBLOCK_OVERLAPS)
 			return -EBUSY;
 
 		return memblock_mark_nomap(base, size);