--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h.orig 2006-12-01 14:36:39.000000000 -0500 +++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h 2006-12-01 14:49:13.000000000 -0500 @@ -7,6 +7,10 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info); void elf_ia64_usage(void); +int update_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr); +void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr, + unsigned long addr); + #define MAX_MEMORY_RANGES 1024 #define EFI_PAGE_SIZE (1UL<<12) #define ELF_PAGE_SIZE (1UL<<16) --- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig 2006-12-01 14:36:39.000000000 -0500 +++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c 2006-12-01 14:55:16.000000000 -0500 @@ -28,14 +28,16 @@ #include #include #include +#include #include #include "../../kexec.h" #include "../../kexec-syscall.h" +#include "elf.h" #include "kexec-ia64.h" #include static struct memory_range memory_range[MAX_MEMORY_RANGES]; - +static int memory_ranges; /* Reserve range for EFI memmap and Boot parameter */ static int split_range(int range, unsigned long start, unsigned long end) { @@ -73,7 +75,6 @@ unsigned long kexec_flags) { const char iomem[]= "/proc/iomem"; - int memory_ranges = 0; char line[MAX_LINE]; FILE *fp; fp = fopen(iomem, "r"); @@ -209,6 +210,45 @@ return 0; } +int update_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr) +{ + int i; + struct mem_phdr *phdr; + unsigned long start_addr = ULONG_MAX, end_addr = 0; + unsigned long align = 1UL<<26; // 64M + for(i = 0; i < ehdr->e_phnum; i++) { + phdr = &ehdr->e_phdr[i]; + if (phdr->p_type == PT_LOAD) { + if (phdr->p_paddr < start_addr) + start_addr = phdr->p_paddr; + if ((phdr->p_paddr + phdr->p_memsz) > end_addr) + end_addr = phdr->p_paddr + phdr->p_memsz; + } + + } + + for (i = 0; i < memory_ranges + && memory_range[i].start <= start_addr; i++) { + if (memory_range[i].type == RANGE_RAM && + memory_range[i].end > end_addr) + return; + } + + for (i = 0; i < memory_ranges; i++) { + if (memory_range[i].type == RANGE_RAM) { + unsigned long start = + (memory_range[i].start + align - 1)&~(align - 1); + unsigned long end = memory_range[i].end; + if (end > start && + (end - start) > (end_addr - start_addr)) { + move_loaded_segments(info, ehdr, start); + return 0; + } + } + } + return 1; +} + void arch_update_purgatory(struct kexec_info *info) { } --- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig 2006-12-01 14:36:39.000000000 -0500 +++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-12-01 14:59:29.000000000 -0500 @@ -84,7 +84,8 @@ /* Move the crash kerenl physical offset to reserved region */ -static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr) +void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr, + unsigned long addr) { int i; long offset; @@ -92,7 +93,7 @@ for(i = 0; i < ehdr->e_phnum; i++) { phdr = &ehdr->e_phdr[i]; if (phdr->p_type == PT_LOAD) { - offset = mem_min - phdr->p_paddr; + offset = addr - phdr->p_paddr; break; } } @@ -174,8 +175,14 @@ fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n"); return -1; } - move_loaded_segments(info, &ehdr); - } + move_loaded_segments(info, &ehdr, mem_min); + } else { + if (update_loaded_segments(info, &ehdr)) { + fprintf(stderr, "Failed to place kernel\n"); + return -1; + } + } + entry = ehdr.e_entry; max_addr = elf_max_addr(&ehdr);