arm64: Make kexec_file_load honor iomem reservations
Subsystems (4)
cover arm64: Make kexec_file_load honor iomem reservations
This series is a complete departure from the approach I initially sent almost a month ago[1]. Instead of trying to teach EFI, ACPI and other subsystem to use memblock, I've decided to stick with the iomem resource tree and use that exclusively for arm64.
This means that my current approach is (despite what I initially replied to both Dave and Catalin) to provide an arm64-specific implementation of arch_kexec_locate_mem_hole() which walks the resource tree and excludes ranges of RAM that have been registered for any odd purpose. This is exactly what the userspace implementation does, and I don't really see a good reason to diverge from it.
Again, this allows my Synquacer board to reliably use kexec_file_load with as little as 256M, something that would always fail before as it would overwrite most of the reserved tables.
Obviously, this is now at least 5.14 material. Given how broken kexec_file_load is for non-crash kernels on arm64 at the moment, should we at least disable it in 5.13 and all previous stable kernels?
Thanks,
M.
[1] https://lore.kernel.org/r/[email protected]
Marc Zyngier (4):
kexec_file: Make locate_mem_hole_callback global kernel/resource: Populate child pointer in find_next_iomem_res() kernel/resource: Add walk_excluding_child_res() helper
arm64: kexec_image: Implement arch_kexec_locate_mem_hole()
arch/arm64/kernel/kexec_image.c | 45 ++++++++++++++++++ include/linux/ioport.h | 4 ++ include/linux/kexec.h | 1 + kernel/kexec_file.c | 6 +-- kernel/resource.c | 81 +++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 3 deletions(-)
Signature · 7 lines
2.30.2 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 1/4 kexec_file: Make locate_mem_hole_callback global
In order for architectures to make use of locate_mem_hole_callback() and avoid reinventing a square wheel, make this function global and rename it to kexec_locate_mem_hole_callback() to match the other global kexec symbols.
--- include/linux/kexec.h | 1 + kernel/kexec_file.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-)
include/linux/kexec.h +1 -0
@@ -204,6 +204,7 @@ int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf);extern int kexec_add_buffer (struct kexec_buf *kbuf);int kexec_locate_mem_hole (struct kexec_buf *kbuf); +int kexec_locate_mem_hole_callback (struct resource *res,void *arg);/* Alignment required for elf header segment */ #define ELF_CORE_HEADER_ALIGN 4096
kernel/kexec_file.c +3 -3
@@ -517,7 +517,7 @@ static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end,return 1 ; } -static int locate_mem_hole_callback (struct resource *res,void *arg) +int kexec_locate_mem_hole_callback (struct resource *res,void *arg) {struct kexec_buf *kbuf = (struct kexec_buf *)arg;u64 start = res->start, end = res->end;
@@ -634,9 +634,9 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)return 0 ;if (!IS_ENABLED (CONFIG_ARCH_KEEP_MEMBLOCK )) - ret =kexec_walk_resources (kbuf, locate_mem_hole_callback); + ret =kexec_walk_resources (kbuf, kexec_locate_mem_hole_callback);else - ret =kexec_walk_memblock (kbuf, locate_mem_hole_callback); + ret =kexec_walk_memblock (kbuf, kexec_locate_mem_hole_callback);return ret ==1 ?0 : -EADDRNOTAVAIL ; }
Signature · 7 lines
2.30.2 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 2/4 kernel/resource: Populate child pointer in find_next_iomem_res()
In reply to Marc ZyngierWhen find_next_iomem_res() returns a resource, it doesn't populate the child pointer (but does so with the parent).
As we are about to need to arse child resources, populate this pointer as well.
--- kernel/resource.c | 1 + 1 file changed, 1 insertion(+)
kernel/resource.c +1 -0
@@ -377,6 +377,7 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end, .flags = p->flags, .desc = p->desc, .parent = p->parent, + .child = p->child, }; }
Signature · 7 lines
2.30.2 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Catalin Marinas
maintainerRe: [PATCH 2/4] kernel/resource: Populate child pointer in find_next_iomem_res()
Quoted 5 lines · Marc Zyngier
When
find_next_iomem_res()returns a resource, it doesn't populate the child pointer (but does so with the parent).As we are about to need to arse child resources, populate this pointer as well.
Did you mean "parse"? ;)
Signature · 6 lines
Catalin _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 2/4] kernel/resource: Populate child pointer in find_next_iomem_res()
Quoted 9 lines · Catalin Marinas
Quoted 5 lines · Marc Zyngier
When
find_next_iomem_res()returns a resource, it doesn't populate the child pointer (but does so with the parent).As we are about to need to arse child resources, populate this pointer as well.
Did you mean "parse"? ;)
This is so embarrassing... :-/ Let me fix that right now.
M.
Signature · 6 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 3/4 kernel/resource: Add walk_excluding_child_res() helper
In reply to Marc ZyngierOnce we have obtained a resource of a certain type from find_next_iomem_res(), it doesn't necessarily mean that the whole resource is usable, and we have cases where a child resource denotes an exclusion in the initial resource.
Provide a new walker that deals with this exact case, and calls a callback on each resource fragment that doesn't have a child.
--- include/linux/ioport.h | 4 +++ kernel/resource.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+)
include/linux/ioport.h +4 -0
@@ -323,6 +323,10 @@ extern int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end, void *arg, int (*func)(struct resource *, void *)); +extern int +walk_excluding_child_res (struct resource *res,void *arg, +int (*func)(struct resource *,void *)); +struct resource *devm_request_free_mem_region (struct device *dev,struct resource *base,unsigned long size); struct resource *request_free_mem_region(struct resource *base,
kernel/resource.c +80 -0
86 lines not on this page · raw message
Signature · 7 lines
2.30.2 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 4/4 arm64: kexec_image: Implement arch_kexec_locate_mem_hole()
In reply to Marc ZyngierProvide an arm64-specific implementation for arch_kexec_locate_mem_hole(), using the resource tree instead of memblock, and respecting the reservations added by EFI.
This ensures that kexec_file is finally reliable.
--- arch/arm64/kernel/kexec_image.c | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
arch/arm64/kernel/kexec_image.c +45 -0
@@ -145,3 +145,48 @@ const struct kexec_file_ops kexec_image_ops = { .verify_sig = image_verify_sig,#endif }; + +static int filter_out_reserved_res (struct resource *res,void *arg) +{ +return walk_excluding_child_res (res, arg, + kexec_locate_mem_hole_callback); +} + +/** +* arch_kexec_locate_mem_hole - Find free memory to place the segments. +* @kbuf: Parameters for the memory search. +* +* On success, kbuf->mem will have the start address of the memory region found. +* +* Return: 0 on success, negative errno on error. +*/ +int arch_kexec_locate_mem_hole (struct kexec_buf *kbuf) +{ +int ret; + +/* Arch knows where to place */ +if (kbuf->mem !=KEXEC_BUF_MEM_UNKNOWN ) +return 0 ; + +/* +* Crash kernels land in a well known place that has been +* reserved upfront. +* +* Normal kexec kernels can however land anywhere in memory. +* We have to be extra careful not to step over critical +* memory ranges that have been marked as reserved in the +* iomem resource tree (LPI and ACPI tables, among others), +* hence the use of the child-excluding iterator. This +* matches what the userspace version of kexec does. +*/ +if (kbuf->image->type ==KEXEC_TYPE_CRASH ) + ret =walk_iomem_res_desc (crashk_res.desc, +IORESOURCE_SYSTEM_RAM |IORESOURCE_BUSY , + crashk_res.start, crashk_res.end, + kbuf, kexec_locate_mem_hole_callback); +else + ret =walk_system_ram_res (0 ,ULONG_MAX , kbuf, + filter_out_reserved_res); + +return ret ==1 ?0 : -EADDRNOTAVAIL ; +}
Signature · 7 lines
2.30.2 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 4/4] arm64: kexec_image: Implement arch_kexec_locate_mem_hole()
Quoted 8 lines · Marc Zyngier
Provide an arm64-specific implementation for
arch_kexec_locate_mem_hole(), using the resource tree instead of memblock, and respecting the reservations added by EFI.This ensures that
kexec_fileis finally reliable.Reported-by Moritz Fischer <[email protected]>Signed-off-by Marc Zyngier <[email protected]>
It would have been clearer if __walk_iomem_res_desc() was able to do such child res excluding callback (if asked via a new flag/arg) directly but it's too late in the day to figure out if it's possible. It would save us from another callback in the arch code. But if it's not possible or you want to stick to this approach, fine by me:
Signature · 6 lines
Catalin _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 4/4] arm64: kexec_image: Implement arch_kexec_locate_mem_hole()
Quoted 8 lines · Catalin Marinas
Quoted 6 lines · Marc Zyngier
Provide an arm64-specific implementation for
arch_kexec_locate_mem_hole(), using the resource tree instead of memblock, and respecting the reservations added by EFI.This ensures that
kexec_fileis finally reliable.
Quoted 7 lines
Quoted 2 lines
Reported-by Moritz Fischer <[email protected]>Signed-off-by Marc Zyngier <[email protected]>It would have been clearer if
__walk_iomem_res_desc()was able to do such child res excluding callback (if asked via a new flag/arg) directly but it's too late in the day to figure out if it's possible. It would save us from another callback in the arch code.
Yeah, that should be possible with some minor refactoring of the generic and x86 code, allowing us to get rid of the double arch callback circus.
It would also make the locking a bit saner, but also change it for all the callers... I'll have a play with it.
Quoted 4 lines
But if it's not possible or you want to stick to this approach, fine by me:
Reviewed-by Catalin Marinas <[email protected]>
Thanks,
M.
Signature · 6 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Quoted 12 lines · Marc Zyngier
This series is a complete departure from the approach I initially sent almost a month ago[1]. Instead of trying to teach EFI, ACPI and other subsystem to use memblock, I've decided to stick with the iomem resource tree and use that exclusively for arm64.
This means that my current approach is (despite what I initially replied to both Dave and Catalin) to provide an arm64-specific implementation of
arch_kexec_locate_mem_hole()which walks the resource tree and excludes ranges of RAM that have been registered for any odd purpose. This is exactly what the userspace implementation does, and I don't really see a good reason to diverge from it.
Quoted 7 lines
Again, this allows my Synquacer board to reliably use
kexec_file_loadwith as little as 256M, something that would always fail before as it would overwrite most of the reserved tables.Obviously, this is now at least 5.14 material. Given how broken
kexec_file_loadis for non-crash kernels on arm64 at the moment, should we at least disable it in 5.13 and all previous stable kernels?
I think it makes sense to disable it in the current and earlier kernels.
For this series:
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Ard Biesheuvel
Reviewed-byQuoted 18 lines · Catalin Marinas
Quoted 16 lines · Marc Zyngier
This series is a complete departure from the approach I initially sent almost a month ago[1]. Instead of trying to teach EFI, ACPI and other subsystem to use memblock, I've decided to stick with the iomem resource tree and use that exclusively for arm64.
This means that my current approach is (despite what I initially replied to both Dave and Catalin) to provide an arm64-specific implementation of
arch_kexec_locate_mem_hole()which walks the resource tree and excludes ranges of RAM that have been registered for any odd purpose. This is exactly what the userspace implementation does, and I don't really see a good reason to diverge from it.Again, this allows my Synquacer board to reliably use
kexec_file_loadwith as little as 256M, something that would always fail before as it would overwrite most of the reserved tables.
Quoted 6 lines
Quoted 3 lines
Obviously, this is now at least 5.14 material. Given how broken
kexec_file_loadis for non-crash kernels on arm64 at the moment, should we at least disable it in 5.13 and all previous stable kernels?I think it makes sense to disable it in the current and earlier kernels.
Ack to that
Quoted 3 lines
For this series:
Acked-by Catalin Marinas <[email protected]>
and likewise for the series
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec