diff options
Diffstat (limited to 'kexec')
-rw-r--r-- | kexec/arch/ia64/Makefile | 2 | ||||
-rw-r--r-- | kexec/arch/ia64/crashdump-ia64.c | 351 | ||||
-rw-r--r-- | kexec/arch/ia64/crashdump-ia64.h | 13 | ||||
-rw-r--r-- | kexec/arch/ia64/kexec-elf-ia64.c | 80 | ||||
-rw-r--r-- | kexec/arch/ia64/kexec-elf-rel-ia64.c | 37 | ||||
-rw-r--r-- | kexec/arch/ia64/kexec-ia64.h | 4 | ||||
-rw-r--r-- | kexec/arch/ia64/kexec-ia64.h.orig | 11 | ||||
-rw-r--r-- | kexec/kexec-sha256.h | 2 | ||||
-rw-r--r-- | kexec/kexec.c | 3 |
9 files changed, 494 insertions, 9 deletions
diff --git a/kexec/arch/ia64/Makefile b/kexec/arch/ia64/Makefile index d5d42e7..9aacb4b 100644 --- a/kexec/arch/ia64/Makefile +++ b/kexec/arch/ia64/Makefile @@ -4,3 +4,5 @@ KEXEC_C_SRCS+= kexec/arch/ia64/kexec-ia64.c KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-ia64.c KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-rel-ia64.c +KEXEC_C_SRCS+= kexec/arch/ia64/crashdump-ia64.c + diff --git a/kexec/arch/ia64/crashdump-ia64.c b/kexec/arch/ia64/crashdump-ia64.c new file mode 100644 index 0000000..6ab8686 --- /dev/null +++ b/kexec/arch/ia64/crashdump-ia64.c @@ -0,0 +1,351 @@ +/* + * kexec: crashdum support + * Copyright (C) 2005-2006 Zou Nan hai <nanhai.zou@intel.com> Intel Corp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <elf.h> +#include "../../kexec.h" +#include "../../kexec-elf.h" +#include "../../kexec-syscall.h" +#include "kexec-ia64.h" +#include "crashdump-ia64.h" + +int memory_ranges = 0; +#define LOAD_OFFSET (0xa000000000000000UL + 0x100000000UL - (1UL<<26)) +#define MAX_LINE 160 +/* Stores a sorted list of RAM memory ranges for which to create elf headers. + * A separate program header is created for backup region */ +static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; +/* Memory region reserved for storing panic kernel and other data. */ +static struct memory_range crash_reserved_mem; +unsigned long elfcorehdr; +static unsigned long kernel_code_start; +struct loaded_segment { + unsigned long start; + unsigned long end; + unsigned long reserved; +}; + +#define MAX_LOAD_SEGMENTS 128 +struct loaded_segment loaded_segments[MAX_LOAD_SEGMENTS]; + +unsigned long loaded_segments_num, loaded_segments_base; +static int seg_comp(const void *a, const void *b) +{ + const struct loaded_segment *x = a, *y = b; + /* avoid overflow */ + if (x->start > y->start) return 1; + if (x->start < y->start) return -1; + return 0; +} + +/* purgatory code need this info to patch the EFI memmap + */ +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++) { + unsigned long start, end; + struct mem_phdr *phdr; + phdr = &ehdr->e_phdr[i]; + if (phdr->p_type != PT_LOAD) + continue; + start = phdr->p_paddr; + end = phdr->p_paddr + phdr->p_memsz; + + loaded_segments[loaded_segments_num].start = + start&~(ELF_PAGE_SIZE-1); + loaded_segments[loaded_segments_num].end = + (end + ELF_PAGE_SIZE - 1)&~(ELF_PAGE_SIZE - 1); + loaded_segments[loaded_segments_num].reserved = 0; + loaded_segments_num++; + } +} + +static int get_crash_notes_section_addr(unsigned long *addr, int cpu) +{ + char crash_notes[128]; + char line[MAX_LINE]; + FILE *fp; + sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu); + fp = fopen(crash_notes, "r"); + if (!fp) { + fprintf(stderr, "Cannot open %s: %s\n", + crash_notes, strerror(errno)); + fprintf(stderr, "Try mounting sysfs\n"); + return -1; + } + if (fscanf(fp, "%lx", addr) != 1) { + *addr = 0; + return -1; + } + return 0; +} + +/* Removes crash reserve region from list of memory chunks for whom elf program + * headers have to be created. Assuming crash reserve region to be a single + * continuous area fully contained inside one of the memory chunks */ +static int exclude_crash_reserve_region(int *nr_ranges) +{ + int i, j, tidx = -1; + unsigned long cstart, cend; + struct memory_range temp_region; + + /* Crash reserved region. */ + cstart = crash_reserved_mem.start; + cend = crash_reserved_mem.end; + + for (i = 0; i < (*nr_ranges); i++) { + unsigned long mstart, mend; + mstart = crash_memory_range[i].start; + mend = crash_memory_range[i].end; + if (cstart < mend && cend > mstart) { + if (cstart != mstart && cend != mend) { + /* Split memory region */ + crash_memory_range[i].end = cstart - 1; + temp_region.start = cend + 1; + temp_region.end = mend; + temp_region.type = RANGE_RAM; + tidx = i+1; + } else if (cstart != mstart) + crash_memory_range[i].end = cstart - 1; + else + crash_memory_range[i].start = cend + 1; + } + } + /* Insert split memory region, if any. */ + if (tidx >= 0) { + if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) { + /* No space to insert another element. */ + fprintf(stderr, "Error: Number of crash memory ranges" + " excedeed the max limit\n"); + return -1; + } + for (j = (*nr_ranges - 1); j >= tidx; j--) + crash_memory_range[j+1] = crash_memory_range[j]; + crash_memory_range[tidx].start = temp_region.start; + crash_memory_range[tidx].end = temp_region.end; + crash_memory_range[tidx].type = temp_region.type; + (*nr_ranges)++; + } + return 0; +} + +static int prepare_crash_memory_elf64_headers(struct kexec_info *info, + void *buf, unsigned long size) +{ + Elf64_Ehdr *elf; + Elf64_Phdr *phdr; + int i; + long int nr_cpus = 0; + char *bufp = buf; + unsigned long notes_addr, notes_offset; + + /* Setup ELF Header*/ + elf = (Elf64_Ehdr *) bufp; + bufp += sizeof(Elf64_Ehdr); + memcpy(elf->e_ident, ELFMAG, SELFMAG); + elf->e_ident[EI_CLASS] = ELFCLASS64; + elf->e_ident[EI_DATA] = ELFDATA2LSB; + elf->e_ident[EI_VERSION]= EV_CURRENT; + elf->e_ident[EI_OSABI] = ELFOSABI_NONE; + memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); + elf->e_type = ET_CORE; + elf->e_machine = EM_IA_64; + elf->e_version = EV_CURRENT; + elf->e_entry = 0; + elf->e_phoff = sizeof(Elf64_Ehdr); + elf->e_shoff = 0; + elf->e_flags = 0; + elf->e_ehsize = sizeof(Elf64_Ehdr); + elf->e_phentsize= sizeof(Elf64_Phdr); + elf->e_phnum = 0; + elf->e_shentsize= 0; + elf->e_shnum = 0; + elf->e_shstrndx = 0; + + /* PT_NOTE program headers. One per cpu*/ + nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + if (nr_cpus < 0) { + return -1; + } + + /* Need to find a better way to determine per cpu notes section size. */ +#define MAX_NOTE_BYTES 1024 + + for (i = 0; i < nr_cpus; i++) { + if (get_crash_notes_section_addr (¬es_addr, i) < 0) + break; + notes_offset = notes_addr; + phdr = (Elf64_Phdr *) bufp; + bufp += sizeof(Elf64_Phdr); + phdr->p_type = PT_NOTE; + phdr->p_flags = 0; + phdr->p_offset = notes_offset; + phdr->p_vaddr = phdr->p_paddr = notes_offset; + phdr->p_filesz = phdr->p_memsz = MAX_NOTE_BYTES; + /* Do we need any alignment of segments? */ + phdr->p_align = 0; + + /* Increment number of program headers. */ + (elf->e_phnum)++; + } + + for (i = 0; i < memory_ranges; i++) { + unsigned long mstart, mend; + mstart = crash_memory_range[i].start; + mend = crash_memory_range[i].end; + if (!mstart && !mend) + break; + phdr = (Elf64_Phdr *) bufp; + bufp += sizeof(Elf64_Phdr); + phdr->p_type = PT_LOAD; + phdr->p_flags = PF_R|PF_W|PF_X; + phdr->p_offset = mstart; + /*add region 5 mapping for kernel*/ + if (kernel_code_start >= mstart && kernel_code_start < mend) { + phdr->p_vaddr = mstart + LOAD_OFFSET; + phdr->p_paddr = mstart; + phdr->p_filesz = phdr->p_memsz = mend - mstart + 1; + phdr->p_align = 0; + (elf->e_phnum)++; + + phdr = (Elf64_Phdr *) bufp; + bufp += sizeof(Elf64_Phdr); + phdr->p_type = PT_LOAD; + phdr->p_flags = PF_R|PF_W|PF_X; + phdr->p_offset = mstart; + } + phdr->p_vaddr = mstart + PAGE_OFFSET; + phdr->p_paddr = mstart; + phdr->p_filesz = phdr->p_memsz = mend - mstart + 1; + phdr->p_align = 0; + (elf->e_phnum)++; + } + return 0; +} + +static int get_crash_memory_ranges(struct memory_range **range, int *ranges) +{ + const char iomem[]= "/proc/iomem"; + char line[MAX_LINE]; + FILE *fp; + unsigned long start, end; + + fp = fopen(iomem, "r"); + if (!fp) { + fprintf(stderr, "Cannot open %s: %s\n", + iomem, strerror(errno)); + return -1; + } + while(fgets(line, sizeof(line), fp) != 0) { + char *str; + int type, consumed, count; + if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) + break; + count = sscanf(line, "%lx-%lx : %n", + &start, &end, &consumed); + str = line + consumed; + if (count != 2) + continue; + + if (memcmp(str, "System RAM\n", 11) == 0) { + type = RANGE_RAM; + } else if (memcmp(str, "Crash kernel\n", 13) == 0) { + /* Reserved memory region. New kernel can + * use this region to boot into. */ + crash_reserved_mem.start = start; + crash_reserved_mem.end = end; + crash_reserved_mem.type = RANGE_RAM; + continue; + } + else if (memcmp(str, "Kernel code\n", 12) == 0) { + kernel_code_start = start; + continue; + }else + continue; + crash_memory_range[memory_ranges].start = start; + crash_memory_range[memory_ranges].end = end; + crash_memory_range[memory_ranges].type = type; + memory_ranges++; + } + fclose(fp); + if (exclude_crash_reserve_region(&memory_ranges) < 0) + return -1; + *ranges = memory_ranges; + return 0; +} + +static void +cmdline_add_elfcorehdr(char **cmdline, unsigned long addr) +{ + char *str = *cmdline; + char buf[64]; + size_t len; + sprintf(buf, " elfcorehdr=%ldK", addr/1024); + len = strlen(str) + strlen(buf) + 1; + str = xmalloc(len); + sprintf(str, "%s%s", *cmdline, buf); + *cmdline = str; +} + +int load_crashdump_segments(struct kexec_info *info, struct mem_ehdr *ehdr, + unsigned long max_addr, unsigned long min_base, + char **cmdline) +{ + //struct memory_range *mem_range, *memmap_p; + struct memory_range *mem_range; + int nr_ranges; + size_t size; + void *tmp; + if (info->kexec_flags & KEXEC_ON_CRASH ) { + if (get_crash_memory_ranges(&mem_range, &nr_ranges) == 0) { + size = sizeof(Elf64_Ehdr) + + (nr_ranges + 1) * sizeof(Elf64_Phdr); + size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1); + tmp = xmalloc(size); + memset(tmp, 0, size); + if (prepare_crash_memory_elf64_headers(info, tmp, size) < 0) + return -1; + elfcorehdr = add_buffer(info, tmp, size, size, EFI_PAGE_SIZE, min_base, + max_addr, -1); + loaded_segments[loaded_segments_num].start = elfcorehdr; + loaded_segments[loaded_segments_num].end = elfcorehdr + size; + loaded_segments[loaded_segments_num].reserved = 1; + loaded_segments_num++; + cmdline_add_elfcorehdr(cmdline, elfcorehdr); + } + } + add_loaded_segments_info(info, ehdr, max_addr); + size = sizeof(struct loaded_segment) * loaded_segments_num; + qsort(loaded_segments, loaded_segments_num, + sizeof(struct loaded_segment), seg_comp); + loaded_segments_base = add_buffer(info, loaded_segments, + size, size, 16, 0, max_addr, -1); + + elf_rel_set_symbol(&info->rhdr, "__loaded_segments", + &loaded_segments_base, sizeof(long)); + elf_rel_set_symbol(&info->rhdr, "__loaded_segments_num", + &loaded_segments_num, sizeof(long)); + return 0; +} + + diff --git a/kexec/arch/ia64/crashdump-ia64.h b/kexec/arch/ia64/crashdump-ia64.h new file mode 100644 index 0000000..bb003a6 --- /dev/null +++ b/kexec/arch/ia64/crashdump-ia64.h @@ -0,0 +1,13 @@ +#ifndef CRASHDUMP_IA64_H +#define CRASHDUMP_IA64_H + +#define PAGE_OFFSET 0xe000000000000000UL +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) +extern int load_crashdump_segments(struct kexec_info *info, + struct mem_ehdr *ehdr, unsigned long max_addr, + unsigned long min_base, char **cmdline); + +#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) +#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) + +#endif diff --git a/kexec/arch/ia64/kexec-elf-ia64.c b/kexec/arch/ia64/kexec-elf-ia64.c index 06fe59b..8c2609f 100644 --- a/kexec/arch/ia64/kexec-elf-ia64.c +++ b/kexec/arch/ia64/kexec-elf-ia64.c @@ -40,7 +40,9 @@ #include <boot/elf_boot.h> #include <ip_checksum.h> #include "../../kexec.h" +#include "../../kexec-syscall.h" #include "../../kexec-elf.h" +#include "crashdump-ia64.h" #include <arch/options.h> static const int probe_debug = 0; @@ -80,6 +82,28 @@ void elf_ia64_usage(void) " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n"); } +/* Move the crash kerenl physical offset to reserved region + */ +static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr) +{ + int i; + long offset; + struct mem_phdr *phdr; + 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; + break; + } + } + ehdr->e_entry += offset; + for(i = 0; i < ehdr->e_phnum; i++) { + phdr = &ehdr->e_phdr[i]; + if (phdr->p_type == PT_LOAD) + phdr->p_paddr += offset; + } +} + int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info) { @@ -89,9 +113,11 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, off_t ramdisk_size = 0; unsigned long command_line_len; unsigned long entry, max_addr, gp_value; - unsigned command_line_base, ramdisk_base; + unsigned long command_line_base, ramdisk_base; + unsigned long efi_memmap_base, efi_memmap_size; int result; int opt; + char *efi_memmap_buf; #define OPT_APPEND (OPT_ARCH_MAX+0) #define OPT_RAMDISK (OPT_ARCH_MAX+1) static const struct option options[] = { @@ -135,6 +161,15 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, free_elf_info(&ehdr); return result; } + + if (info->kexec_flags & KEXEC_ON_CRASH ) { + if ((mem_min == 0x00) && (mem_max = ULONG_MAX)) { + fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n"); + return -1; + } + move_loaded_segments(info, &ehdr); + } + entry = ehdr.e_entry; max_addr = elf_max_addr(&ehdr); @@ -149,17 +184,48 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, /* Load the setup code */ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, - 0x80000, ULONG_MAX, 1); + 0x0, ULONG_MAX, -1); - if (command_line_len) { + + if (load_crashdump_segments(info, &ehdr, max_addr, 0, + &command_line) < 0) + return -1; + + // reserve 8k for efi_memmap + efi_memmap_size = 1UL<<14; + efi_memmap_buf = xmalloc(efi_memmap_size); + efi_memmap_base = add_buffer(info, efi_memmap_buf, + efi_memmap_size, efi_memmap_size, 4096, 0, + max_addr, -1); + + elf_rel_set_symbol(&info->rhdr, "__efi_memmap_base", + &efi_memmap_base, sizeof(long)); + + elf_rel_set_symbol(&info->rhdr, "__efi_memmap_size", + &efi_memmap_size, sizeof(long)); + if (command_line) { + command_line_len = strlen(command_line) + 1; + } + if (command_line_len || (info->kexec_flags & KEXEC_ON_CRASH )) { char *cmdline = xmalloc(command_line_len); strcpy(cmdline, command_line); + + if (info->kexec_flags & KEXEC_ON_CRASH) { + char buf[128]; + sprintf(buf," max_addr=%lluM min_addr=%lluM", + mem_max>>20, mem_min>>20); + command_line_len = strlen(cmdline) + strlen(buf) + 1; + cmdline = xrealloc(cmdline, command_line_len); + strcat(cmdline, buf); + } + command_line_len = (command_line_len + 15)&(~15); + command_line_base = add_buffer(info, cmdline, + command_line_len, command_line_len, + getpagesize(), 0UL, + max_addr, -1); elf_rel_set_symbol(&info->rhdr, "__command_line_len", &command_line_len, sizeof(long)); - command_line_base = add_buffer(info, cmdline, - command_line_len, command_line_len, - 16, 0, max_addr, 1); elf_rel_set_symbol(&info->rhdr, "__command_line", &command_line_base, sizeof(long)); } @@ -168,7 +234,7 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, ramdisk_buf = slurp_file(ramdisk, &ramdisk_size); ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size, ramdisk_size, - getpagesize(), 0, max_addr, 1); + getpagesize(), 0, max_addr, -1); elf_rel_set_symbol(&info->rhdr, "__ramdisk_base", &ramdisk_base, sizeof(long)); elf_rel_set_symbol(&info->rhdr, "__ramdisk_size", diff --git a/kexec/arch/ia64/kexec-elf-rel-ia64.c b/kexec/arch/ia64/kexec-elf-rel-ia64.c index 6b2c388..84cfd3c 100644 --- a/kexec/arch/ia64/kexec-elf-rel-ia64.c +++ b/kexec/arch/ia64/kexec-elf-rel-ia64.c @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@intel.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* pugatory relocation code + * Most of the code in this file is + * based on arch/ia64/kernel/module.c in Linux kernel + */ + + /* Most of the code in this file is * based on arch/ia64/kernel/module.c in Linux kernel */ @@ -43,6 +66,15 @@ ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val) b[1] = (b1 & ~m1) | (v1 & m1); } +static void +put_unaligned64(unsigned long val, unsigned char *location) +{ + unsigned char *src = (unsigned char *)&val; + int i; + for (i = 0; i < sizeof(long); i++) + *location++ = *src++; +} + static inline uint64_t bundle (const uint64_t insn) { @@ -102,6 +134,11 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, | ((value & 0x0fffffUL) << 13) /* bit 0 -> 13 */)); } break; + case R_IA64_PCREL64LSB: { + value = value - address; + put_unaligned64(value, location); + } break; + case R_IA64_GPREL22: case R_IA64_LTOFF22X: if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF) die("value out of gp relative range"); diff --git a/kexec/arch/ia64/kexec-ia64.h b/kexec/arch/ia64/kexec-ia64.h index b5419bb..62d05c1 100644 --- a/kexec/arch/ia64/kexec-ia64.h +++ b/kexec/arch/ia64/kexec-ia64.h @@ -7,5 +7,7 @@ int elf_ia64_probe(const char *buf, off_t len); int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info); void elf_ia64_usage(void); - +#define MAX_MEMORY_RANGES 1024 +#define EFI_PAGE_SIZE (1UL<<12) +#define ELF_PAGE_SIZE (1UL<<16) #endif /* KEXEC_IA64_H */ diff --git a/kexec/arch/ia64/kexec-ia64.h.orig b/kexec/arch/ia64/kexec-ia64.h.orig new file mode 100644 index 0000000..b5419bb --- /dev/null +++ b/kexec/arch/ia64/kexec-ia64.h.orig @@ -0,0 +1,11 @@ +#ifndef KEXEC_IA64_H +#define KEXEC_IA64_H + +#define MAX_MEMORY_RANGES 1024 + +int elf_ia64_probe(const char *buf, off_t len); +int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info); +void elf_ia64_usage(void); + +#endif /* KEXEC_IA64_H */ diff --git a/kexec/kexec-sha256.h b/kexec/kexec-sha256.h index e0ebfe4..d414ec5 100644 --- a/kexec/kexec-sha256.h +++ b/kexec/kexec-sha256.h @@ -6,6 +6,6 @@ struct sha256_region { unsigned long len; }; -#define SHA256_REGIONS 8 +#define SHA256_REGIONS 16 #endif /* KEXEC_SHA256_H */ diff --git a/kexec/kexec.c b/kexec/kexec.c index 8b8086f..3994107 100644 --- a/kexec/kexec.c +++ b/kexec/kexec.c @@ -97,6 +97,9 @@ int valid_memory_range(unsigned long sstart, unsigned long send) continue; mstart = memory_range[i].start; mend = memory_range[i].end; + if (i < memory_ranges - 1 && mend == memory_range[i+1].start) + mend = memory_range[i+1].end; + /* Check to see if we are fully contained */ if ((mstart <= sstart) && (mend >= send)) { return 1; |