Skip to contentSkip to conversation

kexec skips some load segments on ia64

PATCH Petr Tesarik 2 participants 2 messages Dec 1, 2011 – Dec 2, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

There is a bug in add_loaded_segments_info, which causes that some LOAD segments may be skipped on ia64. For two consecutive segments which cannot be combined, the 'i' counter is incremented twice, effectively skipping over the second segment.

For example, these are the program header of my vmlinux:

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000010000 0xa000000100000000 0x0000000004000000

                 0x0000000000ee0e90 0x0000000000ee0e90  RWE    10000
  LOAD           0x0000000000f00000 0xfffffffffffc0000 0x0000000004f00000
                 0x0000000000006d80 0x0000000000006d80  RW     10000
  LOAD           0x0000000000f10000 0xa000000100f40000 0x0000000004f40000
                 0x00000000005e3028 0x0000000000dc9198  RW     10000
  NOTE           0x000000000098dc60 0xa00000010097dc60 0x000000000497dc60
                 0x0000000000000024 0x0000000000000024  R      4
  IA_64_UNWIND   0x00000000009edd58 0xa0000001009ddd58 0x00000000049ddd58
                 0x000000000005d468 0x000000000005d468  R      8

And these are the resulting load segments:

  0x6004000000 - 0x6004ef0000  (LOAD 1)
  0x6004f40000 - 0x6005d10000  (LOAD 3)
  0x6023fc0000 - 0x6023fc1000  (elfcorehdr)

Note: The crash kernel is loaded at 0x6004000000 on this machine.

---
 kexec/arch/ia64/crashdump-ia64.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
kexec/arch/ia64/crashdump-ia64.c +5 -3
@@ -74,12 +74,14 @@ static int seg_comp(const void *a, const
 static void add_loaded_segments_info(struct kexec_info *info,
 	struct mem_ehdr *ehdr, unsigned long max_addr)
 {
-	 int i;
-         for(i = 0; i < ehdr->e_phnum; i++) {
+	 int i = 0;
+         while(i < ehdr->e_phnum) {
                 struct mem_phdr *phdr;
                 phdr = &ehdr->e_phdr[i];
-                if (phdr->p_type != PT_LOAD)
+                if (phdr->p_type != PT_LOAD) {
+                        i++;
                         continue;
+		}
 
 		loaded_segments[loaded_segments_num].start =
 			phdr->p_paddr & ~(ELF_PAGE_SIZE-1);

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#1 lore raw
Quoted 23 lines · Petr Tesarik

There is a bug in add_loaded_segments_info, which causes that some LOAD segments may be skipped on ia64. For two consecutive segments which cannot be combined, the 'i' counter is incremented twice, effectively skipping over the second segment.

For example, these are the program header of my vmlinux:

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000010000 0xa000000100000000 0x0000000004000000

                 0x0000000000ee0e90 0x0000000000ee0e90  RWE    10000
  LOAD           0x0000000000f00000 0xfffffffffffc0000 0x0000000004f00000
                 0x0000000000006d80 0x0000000000006d80  RW     10000
  LOAD           0x0000000000f10000 0xa000000100f40000 0x0000000004f40000
                 0x00000000005e3028 0x0000000000dc9198  RW     10000
  NOTE           0x000000000098dc60 0xa00000010097dc60 0x000000000497dc60
                 0x0000000000000024 0x0000000000000024  R      4
  IA_64_UNWIND   0x00000000009edd58 0xa0000001009ddd58 0x00000000049ddd58
                 0x000000000005d468 0x000000000005d468  R      8

And these are the resulting load segments:

Quoted 7 lines
  0x6004000000 - 0x6004ef0000  (LOAD 1)
  0x6004f40000 - 0x6005d10000  (LOAD 3)
  0x6023fc0000 - 0x6023fc1000  (elfcorehdr)

Note: The crash kernel is loaded at 0x6004000000 on this machine.

Thanks Petr,

I have applied the following to my tree which is still temporarily on github git://github.com/horms/kexec-tools.git

commit 4f1ac81354d95a1fa35af67da5bf6cc30d0122dd

Author: Petr Tesarik <[email protected]>
Date:   Thu Dec 1 09:56:11 2011 +0100
    kexec skips some load segments on ia64
    
    There is a bug in add_loaded_segments_info, which causes that some LOAD
    segments may be skipped on ia64. For two consecutive segments which cannot
    be
    combined, the 'i' counter is incremented twice, effectively skipping over
    the
    second segment.
    
    For example, these are the program header of my vmlinux:
    
    Program Headers:
      Type           Offset             VirtAddr           PhysAddr
                     FileSiz            MemSiz              Flags  Align
      LOAD           0x0000000000010000 0xa000000100000000 0x0000000004000000
                     0x0000000000ee0e90 0x0000000000ee0e90  RWE    10000
      LOAD           0x0000000000f00000 0xfffffffffffc0000 0x0000000004f00000
                     0x0000000000006d80 0x0000000000006d80  RW     10000
      LOAD           0x0000000000f10000 0xa000000100f40000 0x0000000004f40000
                     0x00000000005e3028 0x0000000000dc9198  RW     10000
      NOTE           0x000000000098dc60 0xa00000010097dc60 0x000000000497dc60
                     0x0000000000000024 0x0000000000000024  R      4
      IA_64_UNWIND   0x00000000009edd58 0xa0000001009ddd58 0x00000000049ddd58
                     0x000000000005d468 0x000000000005d468  R      8
    
    And these are the resulting load segments:
    
      0x6004000000 - 0x6004ef0000  (LOAD 1)
      0x6004f40000 - 0x6005d10000  (LOAD 3)
      0x6023fc0000 - 0x6023fc1000  (elfcorehdr)
    
    Note: The crash kernel is loaded at 0x6004000000 on this machine.
    
    Signed-off-by: Petr Tesarik <[email protected]>
    [[email protected]: Trivial up-port]
    Signed-off-by: Simon Horman <[email protected]>
kexec/arch/ia64/crashdump-ia64.c +5 -3
index 8932395..782f49e 100644
@@ -73,12 +73,14 @@ static int seg_comp(const void *a, const void *b)
  */
 static void add_loaded_segments_info(struct mem_ehdr *ehdr)
 {
-	 unsigned i;
-         for(i = 0; i < ehdr->e_phnum; i++) {
+	unsigned i = 0;
+	while(i < ehdr->e_phnum) {
                 struct mem_phdr *phdr;
                 phdr = &ehdr->e_phdr[i];
-                if (phdr->p_type != PT_LOAD)
+		if (phdr->p_type != PT_LOAD) {
+			i++;
                         continue;
+		}
 
 		loaded_segments[loaded_segments_num].start =
 			phdr->p_paddr & ~(ELF_PAGE_SIZE-1);

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec