Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.2:Ports
kexec-tools
kexec-tools-set-mmconf-reserved.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File kexec-tools-set-mmconf-reserved.patch of Package kexec-tools
From: Thomas Renninger <trenn@suse.de> Subject: Reserve mmconf areas for kdump kernel via memmap=X$Y in cmdline References: bnc#804800 Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Tony Jones <tonyj@suse.de> Upstream: no [limited variant of reverted mainline commit e35aa29fb40b37bf86d980b2e19af5e01c2d2549] This is a SLE11 SP3 only workaround to make mmconf work in the kdump kernel. mmconf region is explicitly checked to be reserved, because of specific Intel platforms where bad MMCONF table data is passed. Therefore all mmconf areas must be set reserved in the kdump kernel which is achieved by reading mmconf areas in the productive kernel from /proc/iomem and those are passed via memmap= command line to the kdump kernel. Passing all reserved regions may overflow the commandline, therefore this workaround approach is taken. Additional change by Cliff Wickman <cpw@sgi.com>: On larger SGI hardware this will still overflow command line, so if overflow occurs, coalesce any mmconf regions higher than system ram into one region, hopefully this coalescing will be limited to SGI hardware --- kexec/arch/i386/crashdump-x86.c | 109 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) --- a/kexec/arch/i386/crashdump-x86.c +++ b/kexec/arch/i386/crashdump-x86.c @@ -51,6 +51,7 @@ #include <x86/x86-linux.h> extern struct arch_options_t arch_options; +static int nr_mem_ranges; static int get_kernel_page_offset(struct kexec_info *UNUSED(info), struct crash_elf_info *elf_info) @@ -186,6 +187,18 @@ static struct memory_range crash_memory_ static struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR]; static int crash_reserved_mem_nr; +static struct memory_range mmconf_mem[CRASH_MAX_MEMORY_RANGES]; +static int mmconf_ranges; + +static void add_mmconf_range(unsigned long long start, unsigned long long end) +{ + if (mmconf_ranges >= CRASH_MAX_MEMORY_RANGES) + return; + mmconf_mem[mmconf_ranges].start = start; + mmconf_mem[mmconf_ranges].end = end; + mmconf_ranges++; +} + /* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to * create Elf headers. Keeping it separate from get_memory_ranges() as * requirements are different in the case of normal kexec and crashdumps. @@ -246,6 +259,9 @@ static int get_crash_memory_ranges(struc gart_end = end; gart = 1; continue; + } else if (memcmp(str, "PCI MMCONFIG", 12) == 0) { + add_mmconf_range(start, end); + continue; } else { continue; } @@ -601,6 +617,49 @@ static void cmdline_add_memmap_internal( die("Command line overflow\n"); strcat(cmdline, str_mmap); } +/* Appends memmap=X$Y commandline for reserved memory to command line*/ +static int +cmdline_add_mmconf_reserved(char *cmdline) +{ + int i, cmdlen, len, align = 1024; + unsigned long startk, endk; + char str_mmap[256], str_tmp[20]; + + + for (i = 0; i < mmconf_ranges; i++){ + + startk = mmconf_mem[i].start/1024; + endk = (mmconf_mem[i].end + align - 1)/1024; + /* + * This is a minimal SLES11 SP3 specific workaround. + * Passing all reserved areas could be many and mmconf one might + * be missing or other side effects may happen (later added important + * boot parameters might be missing). + * Try to identify mmconf area and only pass this one as reserved for + * now. + */ + strcpy (str_mmap, " memmap="); + ultoa((endk - startk), str_tmp); + strcat (str_mmap, str_tmp); + strcat (str_mmap, "K$"); + ultoa(startk, str_tmp); + strcat (str_mmap, str_tmp); + strcat (str_mmap, "K"); + len = strlen(str_mmap); + cmdlen = strlen(cmdline) + len; + if (cmdlen > (COMMAND_LINE_SIZE - 1)) + return 1; + strcat(cmdline, str_mmap); + +#ifdef DEBUG + printf("mmconf area found and reserved 0x%016llx-0x%016llx\n", + mmconf_mem[i].start, mmconf_mem[i].end); + printf("Command line after adding reserved memmap\n"); + printf("%s\n", cmdline); +#endif + } + return 0; +} /* Adds the appropriate memmap= options to command line, indicating the * memory regions the new kernel can use to boot into. */ @@ -797,6 +856,45 @@ static void get_backup_area(struct kexec info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1; } +/* + * Coalesce all MMCONF areas about the highest usable RAM area into one. + * This is done to save memmap= entries on the boot command line. + */ +static void +coalesce_mmconf_ranges(void) +{ + int i, bigentry = -1; + unsigned long long highram = 0, prev = 0; + + /* assure that all mmconf_ranges[] are in ascending order */ + for (i = 0; i < mmconf_ranges; i++) { + if (mmconf_mem[i].start <= prev) { + fprintf(stderr, "Error: mmconf[] not ascending\n"); + return; + } + prev = mmconf_mem[i].start; + } + + /* compute high water mark for normal RAM */ + for (i = 0; i < nr_mem_ranges; i++) { + if ((crash_memory_range[i].type == RANGE_RAM) && + (crash_memory_range[i].end > highram)) + highram = crash_memory_range[i].end; + } + + /* coalesce all entries starting above 'highram' into one */ + for (i = 0; i < mmconf_ranges; i++) { + if (mmconf_mem[i].start > highram) { + if (bigentry >= 0) + mmconf_mem[bigentry].end = mmconf_mem[i].end; + else + bigentry = i; + } + } + if (bigentry >= 0) + mmconf_ranges = bigentry + 1; +} + /* Loads additional segments in case of a panic kernel is being loaded. * One segment for backup region, another segment for storing elf headers * for crash memory image. @@ -807,6 +905,7 @@ int load_crashdump_segments(struct kexec void *tmp; unsigned long sz, bufsz, memsz, elfcorehdr; int nr_ranges = 0, nr_memmap = 0, align = 1024, i; + char *oldend; struct memory_range *mem_range, *memmap_p; struct crash_elf_info elf_info; unsigned kexec_arch; @@ -855,6 +954,8 @@ int load_crashdump_segments(struct kexec dbgprint_mem_range("CRASH MEMORY RANGES", mem_range, nr_ranges); + nr_mem_ranges = nr_ranges; + /* * if the core type has not been set on command line, set it here * automatically @@ -951,6 +1052,14 @@ int load_crashdump_segments(struct kexec end = mem_range[i].end; cmdline_add_memmap_acpi(mod_cmdline, start, end); } + /* Inform second kernel about PCI MMCONF reserved areas. */ + oldend = mod_cmdline + strlen(mod_cmdline); + if (cmdline_add_mmconf_reserved(mod_cmdline)) { + /* reset the command line and coalesce the mmconf's */ + *oldend = '\0'; + coalesce_mmconf_ranges(); + cmdline_add_mmconf_reserved(mod_cmdline); + } return 0; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor