[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