[PATCH RFC 3/6] arm64: allocate memory for other segments after kernel

AKASHI Takahiro takahiro.akashi at linaro.org
Tue Apr 21 03:06:22 PDT 2015


Prayush,
Cc: Geoff

Please add me to Cc if you intend to modify my part of kexec-tools since I don't
subscribe kexec ML, and keep in mind that my repo on git.linaro.org is not for
public review.

On 04/21/2015 01:19 PM, Pratyush Anand wrote:
>
>
> On Monday 20 April 2015 08:51 AM, Baoquan He wrote:
>> On 04/16/15 at 10:17pm, Pratyush Anand wrote:
>>> In case of KEXEC_ON_CRASH, load other segments after the addresses where
>>> kernel segments finish.
>>>
>>> Signed-off-by: Pratyush Anand <panand at redhat.com>
>>> ---
>>>   kexec/arch/arm64/crashdump-arm64.c | 3 ++-
>>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
>>> index 41266f294589..75f4e4d269ca 100644
>>> --- a/kexec/arch/arm64/crashdump-arm64.c
>>> +++ b/kexec/arch/arm64/crashdump-arm64.c
>>> @@ -312,5 +312,6 @@ void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info)
>>>   off_t locate_dtb_in_crashmem(struct kexec_info *info, off_t dtb_size)
>>>   {
>>>       return locate_hole(info, dtb_size, 128UL * 1024,
>>> -        crash_reserved_mem.start, crash_reserved_mem.end, 1);
>>> +        crash_reserved_mem.start + arm64_mem.text_offset +
>>> +        arm64_mem.image_size, crash_reserved_mem.end, 1);
>>
>> So you have decided to hard code the sequence of segment. It
>> seems not good. Why don't do it by calling add_buffer_phys_virt() or
>> implement a similar function if you don't like add_buffer_phys_virt.
>
> I agree that code is a bit tightly coupled here. I think, Takahiro  can comment better.

The *hard-coded* segments order is attributed to Geoff's original code.

> arm64 does use add_buffer_phys_virt to add all the buffers into segment list. arm64_load_other_segments function adds
> buffers for all segments other than kernel and elfcorehdr. This function calls add_buffer_phys_virt to load different
> segments like dtb, initrd and purgatory. Only limitation we are putting that we find free area for all these segments
> after the area where kernel finishes. Currently load sequence is like dtb, initrd and then purgatory. But I believe,
> even if we use other load sequence in arm64_load_other_segments, it should work.

I think that add_buffer_phys_virt() should be used instead of locate_hole() to remove
this enforced ordering because locate_hole() assumes that segments in struct info
be sorted properly.
I'm trying the following hack: (pls ignore #if's)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 2c5238c..642c4a9 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -583,6 +583,7 @@ int arm64_load_other_segments(struct kexec_info *info,
         struct mem_ehdr ehdr;
         unsigned long dtb_max;
         unsigned long dtb_base;
+       unsigned long hole_min, hole_max;
         char *initrd_buf = NULL;
         uint64_t purgatory_sink;
         unsigned long purgatory_base;
@@ -639,17 +640,28 @@ int arm64_load_other_segments(struct kexec_info *info,
          * to the DTB size for any DTB growth.
          */

-       dtb_max = dtb_2.size + 2 * 1024;
+       if (info->kexec_flags & KEXEC_ON_CRASH) {
+#if 1
+               hole_min = crash_reserved_mem.start;
+#else
+               hole_min = crash_reserved_mem.start + arm64_mem.text_offset
+                               + arm64_mem.image_size;
+#endif
+               hole_max = crash_reserved_mem.end;
+       } else {
+               hole_min = arm64_mem.memstart + arm64_mem.text_offset
+                               + arm64_mem.image_size;
+               hole_max = ULONG_MAX;
+       }

-       if (info->kexec_flags & KEXEC_ON_CRASH)
-               dtb_base = locate_dtb_in_crashmem(info, dtb_max);
-       else
-               dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
-                       arm64_mem.memstart + arm64_mem.text_offset
-                               + arm64_mem.image_size,
-                       _ALIGN_UP(arm64_mem.memstart + arm64_mem.text_offset,
-                               512UL * 1024 * 1024),
-                       1);
+       dtb_max = dtb_2.size + 2 * 1024;
+#if 1
+       dtb_base = add_buffer_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_max,
+                       128UL * 1024, hole_min, hole_max, 1, 0);
+#else
+       dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
+                       hole_min, hole_max, 1);
+#endif
         dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
                 dtb_2.size);
@@ -670,8 +686,14 @@ int arm64_load_other_segments(struct kexec_info *info,
                         /* Put the initrd after the DTB with an alignment of
                          * page size. */

+#if 1
+                       initrd_base = add_buffer_phys_virt(info, initrd_buf,
+                               initrd_size, initrd_size, 0,
+                               hole_min, hole_max, 1, 0);
+#else
                         initrd_base = locate_hole(info, initrd_size, 0,
-                               dtb_base + dtb_max, -1, 1);
+                               dtb_base + dtb_max, hole_max, 1);
+#endif

                         dbgprintf("initrd: base %lx, size %lxh (%ld)\n",
                                 initrd_base, initrd_size, initrd_size);
@@ -695,12 +717,14 @@ int arm64_load_other_segments(struct kexec_info *info,
                 return -EINVAL;
         }

+#if 0
         add_segment_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_base,
                 dtb_2.size, 0);

         if (arm64_opts.initrd)
                 add_segment_phys_virt(info, initrd_buf, initrd_size,
                                 initrd_base, initrd_size, 0);
+#endif

         if (arm64_opts.lite)
                 info->entry = (void *)kernel_entry;
@@ -714,8 +738,13 @@ int arm64_load_other_segments(struct kexec_info *info,
                         return -EBADF;
                 }

+#if 1
+               elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+                       hole_min, hole_max, 1, 0);
+#else
                 elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-                       purgatory_base, ULONG_MAX, 1, 0);
+                       purgatory_base, hole_max, 1, 0);
+#endif

                 info->entry = (void *)elf_rel_get_addr(&info->rhdr,
                         "purgatory_start");

Thanks,
-Takahiro AKASHI

>
> Not sure, if understood the question and replied well.
>
> ~Pratyush
>
>
>
>>
>>>   }
>>> --
>>> 2.1.0
>>>
>>>
>>> _______________________________________________
>>> kexec mailing list
>>> kexec at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/kexec
>>
>> _______________________________________________
>> kexec mailing list
>> kexec at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec
>>



More information about the kexec mailing list