* Cleanups and passing memory ranges via e820 table instead of memmap=
@ 2013-04-11 12:26 Thomas Renninger
2013-04-11 12:26 ` [PATCH 1/5] kexec: X86: Show e820 table which gets passed in debug mode Thomas Renninger
` (4 more replies)
0 siblings, 5 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-11 12:26 UTC (permalink / raw)
To: horms; +Cc: kexec
These patches are against latest kexec-tool master branch from:
git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools
The cleanups are intended to do no functional change.
The patches got successfully tested on one platform.
Also the e820 passing should introduce no change.
Whether the memmap=exactmap ... is passed and the crash kernel makes up
the e820 table from memmap=X#Y and similar params or whether exactly the
same ranges are passed via e820 in bootloader structure directly should not
matter at all.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 1/5] kexec: X86: Show e820 table which gets passed in debug mode
2013-04-11 12:26 Cleanups and passing memory ranges via e820 table instead of memmap= Thomas Renninger
@ 2013-04-11 12:26 ` Thomas Renninger
2013-04-11 12:26 ` [PATCH 2/5] kexec: X86: Enhance crash range debug output Thomas Renninger
` (3 subsequent siblings)
4 siblings, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-11 12:26 UTC (permalink / raw)
To: horms; +Cc: kexec, Thomas Renninger
CC: Simon Horman <horms@verge.net.au>
CC: kexec@lists.infradead.org
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
---
kexec/arch/i386/x86-linux-setup.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index 454fad6..c538897 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -518,7 +518,10 @@ void setup_linux_system_parameters(struct kexec_info *info,
ranges = E820MAX;
}
real_mode->e820_map_nr = ranges;
+ dbgprintf("E820 map:\n");
for(i = 0; i < ranges; i++) {
+ dbgprintf("%016Lx-%016Lx (%d)\n", range[i].start,
+ range[i].end, range[i].type);
real_mode->e820_map[i].addr = range[i].start;
real_mode->e820_map[i].size = range[i].end - range[i].start;
switch (range[i].type) {
@@ -550,7 +553,6 @@ void setup_linux_system_parameters(struct kexec_info *info,
}
}
}
-
/* fill the EDD information */
setup_edd_info(real_mode);
}
--
1.7.6.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 2/5] kexec: X86: Enhance crash range debug output
2013-04-11 12:26 Cleanups and passing memory ranges via e820 table instead of memmap= Thomas Renninger
2013-04-11 12:26 ` [PATCH 1/5] kexec: X86: Show e820 table which gets passed in debug mode Thomas Renninger
@ 2013-04-11 12:26 ` Thomas Renninger
2013-04-11 12:26 ` [PATCH 3/5] kexec: X86: Do not exclude memory regions in each get_xy_memory_range() func Thomas Renninger
` (2 subsequent siblings)
4 siblings, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-11 12:26 UTC (permalink / raw)
To: horms; +Cc: kexec, Thomas Renninger
Add the type as done at other places where ranges are shown.
CC: Simon Horman <horms@verge.net.au>
CC: kexec@lists.infradead.org
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
---
kexec/arch/i386/crashdump-x86.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 9ab648b..3f8593d 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -984,7 +984,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
dbgprintf("CRASH MEMORY RANGES\n");
for(i = 0; i < nr_ranges; ++i)
- dbgprintf("%016Lx-%016Lx\n", mem_range[i].start, mem_range[i].end);
+ dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
+ mem_range[i].end, mem_range[i].type);
/*
* if the core type has not been set on command line, set it here
--
1.7.6.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 3/5] kexec: X86: Do not exclude memory regions in each get_xy_memory_range() func
2013-04-11 12:26 Cleanups and passing memory ranges via e820 table instead of memmap= Thomas Renninger
2013-04-11 12:26 ` [PATCH 1/5] kexec: X86: Show e820 table which gets passed in debug mode Thomas Renninger
2013-04-11 12:26 ` [PATCH 2/5] kexec: X86: Enhance crash range debug output Thomas Renninger
@ 2013-04-11 12:26 ` Thomas Renninger
2013-04-11 12:26 ` [PATCH 4/5] kexec: X86: make crash_memory_range global and store its no of elements in crash_ranges Thomas Renninger
2013-04-11 12:26 ` [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter Thomas Renninger
4 siblings, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-11 12:26 UTC (permalink / raw)
To: horms; +Cc: kexec, Thomas Renninger
This allows further code cleanup later.
CC: Simon Horman <horms@verge.net.au>
CC: kexec@lists.infradead.org
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
---
kexec/arch/i386/crashdump-x86.c | 47 +++++++++++++++------------------------
1 files changed, 18 insertions(+), 29 deletions(-)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 3f8593d..a22768b 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -181,7 +181,6 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
/* Forward Declaration. */
static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit);
-static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end);
/* Stores a sorted list of RAM memory ranges for which to create elf headers.
* A separate program header is created for backup region */
@@ -207,11 +206,10 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
int kexec_flags, unsigned long lowmem_limit)
{
const char *iomem = proc_iomem();
- int memory_ranges = 0, gart = 0;
+ int memory_ranges = 0;
char line[MAX_LINE];
FILE *fp;
unsigned long long start, end;
- uint64_t gart_start = 0, gart_end = 0;
fp = fopen(iomem, "r");
if (!fp) {
@@ -249,11 +247,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
type = RANGE_ACPI_NVS;
} else if(memcmp(str,"reserved\n", 9) == 0 ) {
type = RANGE_RESERVED;
- } else if (memcmp(str, "GART\n", 5) == 0) {
- gart_start = start;
- gart_end = end;
- gart = 1;
- continue;
} else {
continue;
}
@@ -284,18 +277,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
crash_reserved_mem.end = mem_max;
crash_reserved_mem.type = RANGE_RAM;
}
- if (exclude_region(&memory_ranges, crash_reserved_mem.start,
- crash_reserved_mem.end) < 0)
- return -1;
- if (crash_reserved_low_mem.start &&
- exclude_region(&memory_ranges, crash_reserved_low_mem.start,
- crash_reserved_low_mem.end) < 0)
- return -1;
- if (gart) {
- /* exclude GART region if the system has one */
- if (exclude_region(&memory_ranges, gart_start, gart_end) < 0)
- return -1;
- }
*range = crash_memory_range;
*ranges = memory_ranges;
@@ -351,10 +332,6 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
- if (exclude_region(ranges, crash_reserved_mem.start,
- crash_reserved_mem.end) < 0)
- goto err;
-
ret = 0;
err:
@@ -434,10 +411,6 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
- if (exclude_region(ranges, crash_reserved_mem.start,
- crash_reserved_mem.end) < 0)
- goto err;
-
ret = 0;
err:
@@ -941,6 +914,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
struct memory_range *mem_range, *memmap_p;
struct crash_elf_info elf_info;
unsigned kexec_arch;
+ uint64_t start, end;
memset(&elf_info, 0x0, sizeof(elf_info));
@@ -973,11 +947,26 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
if (get_crash_memory_ranges_xen(&mem_range, &nr_ranges,
elf_info.lowmem_limit) < 0)
return -1;
- } else
+ } else {
if (get_crash_memory_ranges(&mem_range, &nr_ranges,
info->kexec_flags,
elf_info.lowmem_limit) < 0)
return -1;
+ }
+
+ if (exclude_region(&nr_ranges, crash_reserved_mem.start,
+ crash_reserved_mem.end) < 0)
+ return -1;
+ if (crash_reserved_low_mem.start &&
+ exclude_region(&nr_ranges, crash_reserved_low_mem.start,
+ crash_reserved_low_mem.end) < 0)
+ return -1;
+
+ if (!parse_iomem_single("GART\n", &start, &end)) {
+ /* exclude GART region if the system has one */
+ if (exclude_region(&nr_ranges, start, end) < 0)
+ return -1;
+ }
get_backup_area(info, mem_range, nr_ranges);
--
1.7.6.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 4/5] kexec: X86: make crash_memory_range global and store its no of elements in crash_ranges
2013-04-11 12:26 Cleanups and passing memory ranges via e820 table instead of memmap= Thomas Renninger
` (2 preceding siblings ...)
2013-04-11 12:26 ` [PATCH 3/5] kexec: X86: Do not exclude memory regions in each get_xy_memory_range() func Thomas Renninger
@ 2013-04-11 12:26 ` Thomas Renninger
2013-04-11 12:26 ` [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter Thomas Renninger
4 siblings, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-11 12:26 UTC (permalink / raw)
To: horms; +Cc: kexec, Thomas Renninger
Then exclude_region does not need nr_ranges to get passed.
Also reduce CRASH_MAX_MEMORY_RANGES which currently is:
MAX_MEMORY_RANGES + 2
to MAX_MEMORY_RANGES
MAX_MEMORY_RANGES is 1024 which is a way too big for the e820 table.
Also for the commandline 1024 memmap= parameters would have been a way too
big...
CC: Simon Horman <horms@verge.net.au>
CC: kexec@lists.infradead.org
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
---
kexec/arch/i386/crashdump-x86.c | 61 ++++++++++++++++++++-------------------
kexec/arch/i386/crashdump-x86.h | 1 -
kexec/arch/i386/kexec-x86.h | 2 +
3 files changed, 33 insertions(+), 31 deletions(-)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index a22768b..f7821bc 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -184,7 +184,8 @@ static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit);
/* 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];
+struct memory_range crash_memory_range[MAX_MEMORY_RANGES];
+int crash_ranges;
/* Memory region reserved for storing panic kernel and other data. */
static struct memory_range crash_reserved_mem;
@@ -222,7 +223,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
char *str;
int type, consumed, count;
- if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
+ if (memory_ranges >= MAX_MEMORY_RANGES)
break;
count = sscanf(line, "%Lx-%Lx : %n",
&start, &end, &consumed);
@@ -289,7 +290,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
int *ranges, unsigned long lowmem_limit)
{
int j, rc, ret = -1;
- struct e820entry e820entries[CRASH_MAX_MEMORY_RANGES];
+ struct e820entry e820entries[MAX_MEMORY_RANGES];
unsigned int i;
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_interface *xc;
@@ -313,14 +314,14 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
}
#endif
- rc = xc_get_machine_memory_map(xc, e820entries, CRASH_MAX_MEMORY_RANGES);
+ rc = xc_get_machine_memory_map(xc, e820entries, MAX_MEMORY_RANGES);
if (rc < 0) {
fprintf(stderr, "%s: xc_get_machine_memory_map: %s\n", __func__, strerror(-rc));
goto err;
}
- for (i = 0, j = 0; i < rc && j < CRASH_MAX_MEMORY_RANGES; ++i, ++j) {
+ for (i = 0, j = 0; i < rc && j < MAX_MEMORY_RANGES; ++i, ++j) {
crash_memory_range[j].start = e820entries[i].addr;
crash_memory_range[j].end = e820entries[i].addr + e820entries[i].size - 1;
crash_memory_range[j].type = xen_e820_to_kexec_type(e820entries[i].type);
@@ -357,7 +358,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
}
rc = posix_memalign((void **)&e820entries, getpagesize(),
- sizeof(struct e820entry) * CRASH_MAX_MEMORY_RANGES);
+ sizeof(struct e820entry) * MAX_MEMORY_RANGES);
if (rc) {
fprintf(stderr, "%s: posix_memalign(e820entries): %s\n", __func__, strerror(rc));
@@ -374,7 +375,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
goto err;
}
- if (mlock(e820entries, sizeof(struct e820entry) * CRASH_MAX_MEMORY_RANGES) == -1) {
+ if (mlock(e820entries, sizeof(struct e820entry) * MAX_MEMORY_RANGES) == -1) {
fprintf(stderr, "%s: mlock(e820entries): %m\n", __func__);
goto err;
}
@@ -384,7 +385,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
goto err;
}
- xen_memory_map->nr_entries = CRASH_MAX_MEMORY_RANGES;
+ xen_memory_map->nr_entries = MAX_MEMORY_RANGES;
set_xen_guest_handle(xen_memory_map->buffer, e820entries);
hypercall.op = __HYPERVISOR_memory_op;
@@ -399,7 +400,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
}
for (i = 0, j = 0; i < xen_memory_map->nr_entries &&
- j < CRASH_MAX_MEMORY_RANGES; ++i, ++j) {
+ j < MAX_MEMORY_RANGES; ++i, ++j) {
crash_memory_range[j].start = e820entries[i].addr;
crash_memory_range[j].end = e820entries[i].addr + e820entries[i].size - 1;
crash_memory_range[j].type = xen_e820_to_kexec_type(e820entries[i].type);
@@ -415,7 +416,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
err:
munlock(xen_memory_map, sizeof(struct xen_memory_map));
- munlock(e820entries, sizeof(struct e820entry) * CRASH_MAX_MEMORY_RANGES);
+ munlock(e820entries, sizeof(struct e820entry) * MAX_MEMORY_RANGES);
free(xen_memory_map);
free(e820entries);
close(fd);
@@ -445,7 +446,7 @@ static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit)
crash_memory_range[*nr_ranges].end = lowmem_limit - 1;
- if (*nr_ranges >= CRASH_MAX_MEMORY_RANGES - 1)
+ if (*nr_ranges >= MAX_MEMORY_RANGES - 1)
return;
++*nr_ranges;
@@ -458,13 +459,13 @@ static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit)
/* 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_region(int *nr_ranges, uint64_t start, uint64_t end)
+static int exclude_region(uint64_t start, uint64_t end)
{
int i, j, tidx = -1;
struct memory_range temp_region = {0, 0, 0};
- for (i = 0; i < (*nr_ranges); i++) {
+ for (i = 0; i < (crash_ranges); i++) {
unsigned long long mstart, mend;
mstart = crash_memory_range[i].start;
mend = crash_memory_range[i].end;
@@ -484,16 +485,16 @@ static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end)
}
/* Insert split memory region, if any. */
if (tidx >= 0) {
- if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) {
+ if (crash_ranges == 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--)
+ for (j = (crash_ranges - 1); j >= tidx; j--)
crash_memory_range[j+1] = crash_memory_range[j];
crash_memory_range[tidx] = temp_region;
- (*nr_ranges)++;
+ (crash_ranges)++;
}
return 0;
}
@@ -910,7 +911,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
{
void *tmp;
unsigned long sz, bufsz, memsz, elfcorehdr;
- int nr_ranges = 0, align = 1024, i;
+ int align = 1024, i;
struct memory_range *mem_range, *memmap_p;
struct crash_elf_info elf_info;
unsigned kexec_arch;
@@ -944,35 +945,35 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
}
if (xen_present()) {
- if (get_crash_memory_ranges_xen(&mem_range, &nr_ranges,
+ if (get_crash_memory_ranges_xen(&mem_range, &crash_ranges,
elf_info.lowmem_limit) < 0)
return -1;
} else {
- if (get_crash_memory_ranges(&mem_range, &nr_ranges,
+ if (get_crash_memory_ranges(&mem_range, &crash_ranges,
info->kexec_flags,
elf_info.lowmem_limit) < 0)
return -1;
}
- if (exclude_region(&nr_ranges, crash_reserved_mem.start,
- crash_reserved_mem.end) < 0)
+ if (exclude_region(crash_reserved_mem.start,
+ crash_reserved_mem.end) < 0)
return -1;
if (crash_reserved_low_mem.start &&
- exclude_region(&nr_ranges, crash_reserved_low_mem.start,
- crash_reserved_low_mem.end) < 0)
+ exclude_region(crash_reserved_low_mem.start,
+ crash_reserved_low_mem.end) < 0)
return -1;
if (!parse_iomem_single("GART\n", &start, &end)) {
/* exclude GART region if the system has one */
- if (exclude_region(&nr_ranges, start, end) < 0)
+ if (exclude_region(start, end) < 0)
return -1;
}
- get_backup_area(info, mem_range, nr_ranges);
+ get_backup_area(info, mem_range, crash_ranges);
dbgprintf("CRASH MEMORY RANGES\n");
- for(i = 0; i < nr_ranges; ++i)
+ for(i = 0; i < crash_ranges; ++i)
dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
mem_range[i].end, mem_range[i].type);
@@ -982,7 +983,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
*/
if (arch_options.core_header_type == CORE_TYPE_UNDEF) {
arch_options.core_header_type =
- get_core_type(&elf_info, mem_range, nr_ranges);
+ get_core_type(&elf_info, mem_range, crash_ranges);
}
/* Get the elf class... */
elf_info.class = ELFCLASS32;
@@ -1031,13 +1032,13 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
/* Create elf header segment and store crash image data. */
if (arch_options.core_header_type == CORE_TYPE_ELF64) {
if (crash_create_elf64_headers(info, &elf_info, mem_range,
- nr_ranges, &tmp, &bufsz,
+ crash_ranges, &tmp, &bufsz,
ELF_CORE_HEADER_ALIGN) < 0)
return EFAILED;
}
else {
if (crash_create_elf32_headers(info, &elf_info, mem_range,
- nr_ranges, &tmp, &bufsz,
+ crash_ranges, &tmp, &bufsz,
ELF_CORE_HEADER_ALIGN) < 0)
return EFAILED;
}
@@ -1067,7 +1068,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
/* Inform second kernel about the presence of ACPI tables. */
- for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
+ for (i = 0; i < MAX_MEMORY_RANGES; i++) {
unsigned long start, end;
if ( !( mem_range[i].type == RANGE_ACPI
|| mem_range[i].type == RANGE_ACPI_NVS
diff --git a/kexec/arch/i386/crashdump-x86.h b/kexec/arch/i386/crashdump-x86.h
index b61cf0a..ad389c9 100644
--- a/kexec/arch/i386/crashdump-x86.h
+++ b/kexec/arch/i386/crashdump-x86.h
@@ -21,7 +21,6 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
#define X86_64_KERNEL_TEXT_SIZE (512UL*1024*1024)
#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1)
-#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2)
/* Backup Region, First 640K of System RAM. */
#define BACKUP_SRC_START 0x00000000
diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h
index 5aa2a46..5b554dd 100644
--- a/kexec/arch/i386/kexec-x86.h
+++ b/kexec/arch/i386/kexec-x86.h
@@ -2,6 +2,8 @@
#define KEXEC_X86_H
#define MAX_MEMORY_RANGES 1024
+extern struct memory_range crash_memory_range[MAX_MEMORY_RANGES];
+extern int crash_ranges;
enum coretype {
CORE_TYPE_UNDEF = 0,
--
1.7.6.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 12:26 Cleanups and passing memory ranges via e820 table instead of memmap= Thomas Renninger
` (3 preceding siblings ...)
2013-04-11 12:26 ` [PATCH 4/5] kexec: X86: make crash_memory_range global and store its no of elements in crash_ranges Thomas Renninger
@ 2013-04-11 12:26 ` Thomas Renninger
2013-04-11 14:55 ` Yinghai Lu
` (2 more replies)
4 siblings, 3 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-11 12:26 UTC (permalink / raw)
To: horms
Cc: kexec, cpw, Eric W. Biederman, H. Peter Anvin, yinghai,
Thomas Renninger, vgoyal
Currently ranges are passed via kernel boot parameters:
memmap=exactmap memmap=X#Y memmap=
Pass them via e820 table directly instead.
CC: Simon Horman <horms@verge.net.au>
CC: kexec@lists.infradead.org
CC: H. Peter Anvin <hpa@zytor.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
CC: vgoyal@redhat.com
CC: yinghai@kernel.org
CC: cpw@sgi.com
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
---
kexec/arch/i386/crashdump-x86.c | 221 ++++++++++++++++++-------------------
kexec/arch/i386/x86-linux-setup.c | 11 ++-
2 files changed, 116 insertions(+), 116 deletions(-)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index f7821bc..8009efe 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -659,70 +659,6 @@ static void ultoa(unsigned long i, char *str)
}
}
-static void cmdline_add_memmap_internal(char *cmdline, unsigned long startk,
- unsigned long endk, int type)
-{
- int cmdlen, len;
- char str_mmap[256], str_tmp[20];
-
- strcpy (str_mmap, " memmap=");
- ultoa((endk-startk), str_tmp);
- strcat (str_mmap, str_tmp);
-
- if (type == RANGE_RAM)
- strcat (str_mmap, "K@");
- else if (type == RANGE_RESERVED)
- strcat (str_mmap, "K$");
- else if (type == RANGE_ACPI || type == RANGE_ACPI_NVS)
- 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))
- die("Command line overflow\n");
- strcat(cmdline, str_mmap);
-}
-
-/* Adds the appropriate memmap= options to command line, indicating the
- * memory regions the new kernel can use to boot into. */
-static int cmdline_add_memmap(char *cmdline, struct memory_range *memmap_p)
-{
- int i, cmdlen, len;
- unsigned long min_sizek = 100;
- char str_mmap[256];
-
- /* Exact map */
- strcpy(str_mmap, " memmap=exactmap");
- len = strlen(str_mmap);
- cmdlen = strlen(cmdline) + len;
- if (cmdlen > (COMMAND_LINE_SIZE - 1))
- die("Command line overflow\n");
- strcat(cmdline, str_mmap);
-
- for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
- unsigned long startk, endk;
- startk = (memmap_p[i].start/1024);
- endk = ((memmap_p[i].end + 1)/1024);
- if (!startk && !endk)
- /* All regions traversed. */
- break;
-
- /* A region is not worth adding if region size < 100K. It eats
- * up precious command line length. */
- if ((endk - startk) < min_sizek)
- continue;
- cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RAM);
- }
-
- dbgprintf("Command line after adding memmap\n");
- dbgprintf("%s\n", cmdline);
-
- return 0;
-}
-
/* Adds the elfcorehdr= command line parameter to command line. */
static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr)
{
@@ -803,26 +739,6 @@ static enum coretype get_core_type(struct crash_elf_info *elf_info,
}
}
-/* Appends memmap=X#Y commandline for ACPI to command line*/
-static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
- unsigned long end)
-{
- int align = 1024;
- unsigned long startk, endk;
-
- if (!(end - start))
- return 0;
-
- startk = start/1024;
- endk = (end + align - 1)/1024;
- cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_ACPI);
-
- dbgprintf("Command line after adding acpi memmap\n");
- dbgprintf("%s\n", cmdline);
-
- return 0;
-}
-
/* Appends 'acpi_rsdp=' commandline for efi boot crash dump */
static void cmdline_add_efi(char *cmdline)
{
@@ -881,24 +797,101 @@ static void get_backup_area(struct kexec_info *info,
info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
}
-/* Appends memmap=X$Y commandline for reserved memory to command line*/
-static int cmdline_add_memmap_reserved(char *cmdline, unsigned long start,
- unsigned long end)
+/*
+ * This function takes reserved (all kind of) memory from global
+ * crash_memory_range[] memory ranges and takes memory the kdump/crash
+ * kernel is allowed to use from the passed usable_mem memory ranges.
+ * The passed usable_mem ranges are zero (!start && !end) terminated.
+ *
+ * The final memory map is again written into crash_memory_range[]
+ * and intended to get passed as e820 table to the crash kernel
+ */
+static int create_final_crash_map(struct memory_range *usable_mem)
{
- int align = 1024;
- unsigned long startk, endk;
+ int i, m, c, tmp_map1_ranges, tmp_map2_ranges;
+ unsigned long min_sizek = 100;
+ /* crash_memory_map with usable memory ranges cut out */
+ struct memory_range tmp_map1[MAX_MEMORY_RANGES];
+ /* merge_map, but small ranges cut out */
+ struct memory_range tmp_map2[MAX_MEMORY_RANGES];
- if (!(end - start))
- return 0;
+ /*
+ * Ignore usable memory ranges for kdump kernel smaller
+ * than 100k to avoid too much ranges passed
+ * Save the new ranges (exluding lower than 100k ranges) in tmp_map
+ * and store the number of elements in tmp_map_ranges
+ */
+ for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
+ unsigned long startk, endk;
+ startk = (usable_mem[i].start/1024);
+ endk = ((usable_mem[i].end + 1)/1024);
+ if (!startk && !endk)
+ /* All regions traversed. */
+ break;
+
+ /* A region is not worth adding if region size < 100K. It eats
+ * up precious command line length. */
+ if ((endk - startk) < min_sizek) {
+ dbgprintf("Removing: %luk - %luk\n", startk, endk);
+ continue;
+ } else {
+ tmp_map1[m].start = usable_mem[i].start;
+ tmp_map1[m].end = usable_mem[i].end;
+ tmp_map1[m].type = usable_mem[i].type;
+ m++;
+ }
+ }
+ /* No need to check for !start && !end anymore */
+ tmp_map1_ranges = m;
- startk = start/1024;
- endk = (end + align - 1)/1024;
- cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RESERVED);
+ for(i = 0; i < tmp_map1_ranges; ++i)
+ dbgprintf("%016Lx-%016Lx (%d)\n", tmp_map1[i].start,
+ tmp_map1[i].end, tmp_map1[i].type);
+
+ /*
+ * Cut out RANGE_RAM regions from crash_memory_ranges and store
+ * them in tmp_map2_ranges
+ */
+ for (c = 0, i = 0; i < crash_ranges; i++) {
+ if (crash_memory_range[i].type == RANGE_RAM)
+ continue;
+ tmp_map2[c].start = crash_memory_range[i].start;
+ tmp_map2[c].end = crash_memory_range[i].end;
+ tmp_map2[c].type = crash_memory_range[i].type;
+ c++;
+ }
+ tmp_map2_ranges = c;
+
+ /*
+ * TBD: Check that no ranges overlap?
+ * Can this happen at all?
+ */
+ for (c = 0, m = 0, i = 0; i < MAX_MEMORY_RANGES; i++) {
+ if (m < tmp_map1_ranges &&
+ (c >= tmp_map2_ranges ||
+ tmp_map2[c].start > tmp_map1[m].start)) {
+ crash_memory_range[i].start = tmp_map1[m].start;
+ crash_memory_range[i].end = tmp_map1[m].end;
+ crash_memory_range[i].type = RANGE_RAM;
+ m++;
+ continue;
+ } else if (c < tmp_map2_ranges) {
+ crash_memory_range[i] = tmp_map2[c];
+ c++;
+ continue;
+ } else
+ break;
+ }
+ crash_ranges = i;
+
+ /*
+ * End address has to be exlusive for e820 map
+ * x - 00010000
+ * 00010000 - y
+ */
+ for(i = 0; i < crash_ranges; ++i)
+ crash_memory_range[i].end++;
-#ifdef DEBUG
- printf("Command line after adding reserved memmap\n");
- printf("%s\n", cmdline);
-#endif
return 0;
}
@@ -944,6 +937,12 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
return -1;
}
+ /*
+ * From now on the memory regions are stored in crash_memory_range[]
+ * Currently the end address is inclusive at this point:
+ * x - 0000ffff
+ * 00010000 - y
+ */
if (xen_present()) {
if (get_crash_memory_ranges_xen(&mem_range, &crash_ranges,
elf_info.lowmem_limit) < 0)
@@ -971,7 +970,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
get_backup_area(info, mem_range, crash_ranges);
- dbgprintf("CRASH MEMORY RANGES\n");
+ dbgprintf("TEMPORARY CRASH MEMORY RANGES\n");
for(i = 0; i < crash_ranges; ++i)
dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
@@ -1063,24 +1062,18 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
return -1;
- cmdline_add_memmap(mod_cmdline, memmap_p);
cmdline_add_efi(mod_cmdline);
cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
- /* Inform second kernel about the presence of ACPI tables. */
- for (i = 0; i < MAX_MEMORY_RANGES; i++) {
- unsigned long start, end;
- if ( !( mem_range[i].type == RANGE_ACPI
- || mem_range[i].type == RANGE_ACPI_NVS
- || mem_range[i].type == RANGE_RESERVED) )
- continue;
- start = mem_range[i].start;
- end = mem_range[i].end;
- if (mem_range[i].type == RANGE_RESERVED)
- cmdline_add_memmap_reserved(mod_cmdline, start, end);
- else
- cmdline_add_memmap_acpi(mod_cmdline, start, end);
- }
+ /*
+ * Redo crash_memory_range so that it can get passed as e820 info
+ */
+ create_final_crash_map(memmap_p);
+
+ dbgprintf("FINAL CRASH MEMORY RANGES\n");
+ for(i = 0; i < crash_ranges; ++i)
+ dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
+ mem_range[i].end, mem_range[i].type);
return 0;
}
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index c538897..82b4bb9 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -505,8 +505,15 @@ void setup_linux_system_parameters(struct kexec_info *info,
/* another safe default */
real_mode->aux_device_info = 0;
- range = info->memory_range;
- ranges = info->memory_ranges;
+ if (info->kexec_flags & KEXEC_ON_CRASH ||
+ info->kexec_flags & KEXEC_PRESERVE_CONTEXT) {
+ range = crash_memory_range;
+ ranges = crash_ranges;
+ } else {
+ range = info->memory_range;
+ ranges = info->memory_ranges;
+ }
+
if (ranges > E820MAX) {
if (!(info->kexec_flags & KEXEC_ON_CRASH))
/*
--
1.7.6.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 12:26 ` [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter Thomas Renninger
@ 2013-04-11 14:55 ` Yinghai Lu
2013-04-11 15:06 ` H. Peter Anvin
2013-04-12 12:24 ` Thomas Renninger
2013-04-12 9:56 ` Zhang Yanfei
2013-04-12 15:24 ` Eric W. Biederman
2 siblings, 2 replies; 28+ messages in thread
From: Yinghai Lu @ 2013-04-11 14:55 UTC (permalink / raw)
To: Thomas Renninger
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Simon Horman, Eric W. Biederman, H. Peter Anvin, Cliff Wickman,
Vivek Goyal
On Thu, Apr 11, 2013 at 5:26 AM, Thomas Renninger <trenn@suse.de> wrote:
> Currently ranges are passed via kernel boot parameters:
> memmap=exactmap memmap=X#Y memmap=
>
> Pass them via e820 table directly instead.
how to address "saved_max_pfn" referring in kernel?
kernel need to use saved_max_pfn from old e820 in
drivers/char/mem.c::read_oldmem()
mips and powerpc they are passing that from command line "savemaxmem="
x86 should use that too?
Thanks
Yinghai
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 14:55 ` Yinghai Lu
@ 2013-04-11 15:06 ` H. Peter Anvin
2013-04-12 14:31 ` Vivek Goyal
2013-04-12 12:24 ` Thomas Renninger
1 sibling, 1 reply; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-11 15:06 UTC (permalink / raw)
To: Yinghai Lu
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Thomas Renninger, Simon Horman, Eric W. Biederman, Cliff Wickman,
Vivek Goyal
On 04/11/2013 07:55 AM, Yinghai Lu wrote:
> On Thu, Apr 11, 2013 at 5:26 AM, Thomas Renninger <trenn@suse.de> wrote:
>> Currently ranges are passed via kernel boot parameters:
>> memmap=exactmap memmap=X#Y memmap=
>>
>> Pass them via e820 table directly instead.
>
> how to address "saved_max_pfn" referring in kernel?
>
> kernel need to use saved_max_pfn from old e820 in
> drivers/char/mem.c::read_oldmem()
>
> mips and powerpc they are passing that from command line "savemaxmem="
>
> x86 should use that too?
>
Oh bloody hell, yet another f-ing "max_pfn" variable.
The *only* one that makes any kind of sense is max_low_pfn (marking the
cutoff to highmem)... the pretty much the rest of them are just plain wrong.
And I don't mean "mildly annoying", I mean "catastrophically wrong
semantics". In this case, it introduces a completely arbitrary
distinction between a nonmemory range below a high water mark and a
nonmemory range above that high water mark. In fact, from reading the
code it seems pretty clear that the device will blindly assume that
anything below saved_max_pfn is memory and will try to map it
cachable... which will #MC on quite a few machines.
This kind of crap HAS TO STOP. Memory is discontiguous, deal with it
and deal with it properly.
I also have to admit that I don't see the difference between /dev/mem
and /dev/oldmem, as the former allows access to memory ranges outside
the ones used by the current kernel, which is what the oldmem device
seems to be intended to od.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 12:26 ` [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter Thomas Renninger
2013-04-11 14:55 ` Yinghai Lu
@ 2013-04-12 9:56 ` Zhang Yanfei
2013-04-12 11:12 ` Thomas Renninger
2013-04-15 9:05 ` Thomas Renninger
2013-04-12 15:24 ` Eric W. Biederman
2 siblings, 2 replies; 28+ messages in thread
From: Zhang Yanfei @ 2013-04-12 9:56 UTC (permalink / raw)
To: Thomas Renninger
Cc: kexec, horms, Eric W. Biederman, H. Peter Anvin, yinghai, cpw,
vgoyal
于 2013年04月11日 20:26, Thomas Renninger 写道:
> Currently ranges are passed via kernel boot parameters:
> memmap=exactmap memmap=X#Y memmap=
>
> Pass them via e820 table directly instead.
>
> CC: Simon Horman <horms@verge.net.au>
> CC: kexec@lists.infradead.org
> CC: H. Peter Anvin <hpa@zytor.com>
> CC: Eric W. Biederman <ebiederm@xmission.com>
> CC: vgoyal@redhat.com
> CC: yinghai@kernel.org
> CC: cpw@sgi.com
>
> Signed-off-by: Thomas Renninger <trenn@suse.de>
> Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
> ---
> kexec/arch/i386/crashdump-x86.c | 221 ++++++++++++++++++-------------------
> kexec/arch/i386/x86-linux-setup.c | 11 ++-
> 2 files changed, 116 insertions(+), 116 deletions(-)
>
> diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
> index f7821bc..8009efe 100644
> --- a/kexec/arch/i386/crashdump-x86.c
> +++ b/kexec/arch/i386/crashdump-x86.c
> @@ -659,70 +659,6 @@ static void ultoa(unsigned long i, char *str)
> }
> }
>
> -static void cmdline_add_memmap_internal(char *cmdline, unsigned long startk,
> - unsigned long endk, int type)
> -{
> - int cmdlen, len;
> - char str_mmap[256], str_tmp[20];
> -
> - strcpy (str_mmap, " memmap=");
> - ultoa((endk-startk), str_tmp);
> - strcat (str_mmap, str_tmp);
> -
> - if (type == RANGE_RAM)
> - strcat (str_mmap, "K@");
> - else if (type == RANGE_RESERVED)
> - strcat (str_mmap, "K$");
> - else if (type == RANGE_ACPI || type == RANGE_ACPI_NVS)
> - 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))
> - die("Command line overflow\n");
> - strcat(cmdline, str_mmap);
> -}
> -
> -/* Adds the appropriate memmap= options to command line, indicating the
> - * memory regions the new kernel can use to boot into. */
> -static int cmdline_add_memmap(char *cmdline, struct memory_range *memmap_p)
> -{
> - int i, cmdlen, len;
> - unsigned long min_sizek = 100;
> - char str_mmap[256];
> -
> - /* Exact map */
> - strcpy(str_mmap, " memmap=exactmap");
> - len = strlen(str_mmap);
> - cmdlen = strlen(cmdline) + len;
> - if (cmdlen > (COMMAND_LINE_SIZE - 1))
> - die("Command line overflow\n");
> - strcat(cmdline, str_mmap);
> -
> - for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> - unsigned long startk, endk;
> - startk = (memmap_p[i].start/1024);
> - endk = ((memmap_p[i].end + 1)/1024);
> - if (!startk && !endk)
> - /* All regions traversed. */
> - break;
> -
> - /* A region is not worth adding if region size < 100K. It eats
> - * up precious command line length. */
> - if ((endk - startk) < min_sizek)
> - continue;
> - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RAM);
> - }
> -
> - dbgprintf("Command line after adding memmap\n");
> - dbgprintf("%s\n", cmdline);
> -
> - return 0;
> -}
> -
> /* Adds the elfcorehdr= command line parameter to command line. */
> static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr)
> {
> @@ -803,26 +739,6 @@ static enum coretype get_core_type(struct crash_elf_info *elf_info,
> }
> }
>
> -/* Appends memmap=X#Y commandline for ACPI to command line*/
> -static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
> - unsigned long end)
> -{
> - int align = 1024;
> - unsigned long startk, endk;
> -
> - if (!(end - start))
> - return 0;
> -
> - startk = start/1024;
> - endk = (end + align - 1)/1024;
> - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_ACPI);
> -
> - dbgprintf("Command line after adding acpi memmap\n");
> - dbgprintf("%s\n", cmdline);
> -
> - return 0;
> -}
> -
> /* Appends 'acpi_rsdp=' commandline for efi boot crash dump */
> static void cmdline_add_efi(char *cmdline)
> {
> @@ -881,24 +797,101 @@ static void get_backup_area(struct kexec_info *info,
> info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
> }
>
> -/* Appends memmap=X$Y commandline for reserved memory to command line*/
> -static int cmdline_add_memmap_reserved(char *cmdline, unsigned long start,
> - unsigned long end)
> +/*
> + * This function takes reserved (all kind of) memory from global
> + * crash_memory_range[] memory ranges and takes memory the kdump/crash
> + * kernel is allowed to use from the passed usable_mem memory ranges.
> + * The passed usable_mem ranges are zero (!start && !end) terminated.
> + *
> + * The final memory map is again written into crash_memory_range[]
> + * and intended to get passed as e820 table to the crash kernel
> + */
> +static int create_final_crash_map(struct memory_range *usable_mem)
> {
> - int align = 1024;
> - unsigned long startk, endk;
> + int i, m, c, tmp_map1_ranges, tmp_map2_ranges;
> + unsigned long min_sizek = 100;
> + /* crash_memory_map with usable memory ranges cut out */
> + struct memory_range tmp_map1[MAX_MEMORY_RANGES];
> + /* merge_map, but small ranges cut out */
> + struct memory_range tmp_map2[MAX_MEMORY_RANGES];
>
> - if (!(end - start))
> - return 0;
> + /*
> + * Ignore usable memory ranges for kdump kernel smaller
> + * than 100k to avoid too much ranges passed
> + * Save the new ranges (exluding lower than 100k ranges) in tmp_map
> + * and store the number of elements in tmp_map_ranges
> + */
> + for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> + unsigned long startk, endk;
> + startk = (usable_mem[i].start/1024);
> + endk = ((usable_mem[i].end + 1)/1024);
> + if (!startk && !endk)
> + /* All regions traversed. */
> + break;
> +
> + /* A region is not worth adding if region size < 100K. It eats
> + * up precious command line length. */
Now you are passing the e820 table directly instead of the commandline, so does
this comment make sense now?
> + if ((endk - startk) < min_sizek) {
> + dbgprintf("Removing: %luk - %luk\n", startk, endk);
> + continue;
> + } else {
> + tmp_map1[m].start = usable_mem[i].start;
> + tmp_map1[m].end = usable_mem[i].end;
> + tmp_map1[m].type = usable_mem[i].type;
> + m++;
> + }
> + }
> + /* No need to check for !start && !end anymore */
> + tmp_map1_ranges = m;
>
> - startk = start/1024;
> - endk = (end + align - 1)/1024;
> - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RESERVED);
> + for(i = 0; i < tmp_map1_ranges; ++i)
> + dbgprintf("%016Lx-%016Lx (%d)\n", tmp_map1[i].start,
> + tmp_map1[i].end, tmp_map1[i].type);
> +
> + /*
> + * Cut out RANGE_RAM regions from crash_memory_ranges and store
> + * them in tmp_map2_ranges
> + */
> + for (c = 0, i = 0; i < crash_ranges; i++) {
> + if (crash_memory_range[i].type == RANGE_RAM)
> + continue;
> + tmp_map2[c].start = crash_memory_range[i].start;
> + tmp_map2[c].end = crash_memory_range[i].end;
> + tmp_map2[c].type = crash_memory_range[i].type;
> + c++;
> + }
> + tmp_map2_ranges = c;
> +
> + /*
> + * TBD: Check that no ranges overlap?
> + * Can this happen at all?
> + */
> + for (c = 0, m = 0, i = 0; i < MAX_MEMORY_RANGES; i++) {
> + if (m < tmp_map1_ranges &&
> + (c >= tmp_map2_ranges ||
> + tmp_map2[c].start > tmp_map1[m].start)) {
> + crash_memory_range[i].start = tmp_map1[m].start;
> + crash_memory_range[i].end = tmp_map1[m].end;
> + crash_memory_range[i].type = RANGE_RAM;
> + m++;
> + continue;
> + } else if (c < tmp_map2_ranges) {
> + crash_memory_range[i] = tmp_map2[c];
> + c++;
> + continue;
> + } else
> + break;
> + }
> + crash_ranges = i;
> +
> + /*
> + * End address has to be exlusive for e820 map
> + * x - 00010000
> + * 00010000 - y
> + */
> + for(i = 0; i < crash_ranges; ++i)
> + crash_memory_range[i].end++;
>
> -#ifdef DEBUG
> - printf("Command line after adding reserved memmap\n");
> - printf("%s\n", cmdline);
> -#endif
> return 0;
> }
>
> @@ -944,6 +937,12 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
> return -1;
> }
>
> + /*
> + * From now on the memory regions are stored in crash_memory_range[]
> + * Currently the end address is inclusive at this point:
> + * x - 0000ffff
> + * 00010000 - y
> + */
> if (xen_present()) {
> if (get_crash_memory_ranges_xen(&mem_range, &crash_ranges,
> elf_info.lowmem_limit) < 0)
> @@ -971,7 +970,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
>
> get_backup_area(info, mem_range, crash_ranges);
>
> - dbgprintf("CRASH MEMORY RANGES\n");
> + dbgprintf("TEMPORARY CRASH MEMORY RANGES\n");
>
> for(i = 0; i < crash_ranges; ++i)
> dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
> @@ -1063,24 +1062,18 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
> dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
> if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
> return -1;
> - cmdline_add_memmap(mod_cmdline, memmap_p);
> cmdline_add_efi(mod_cmdline);
> cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
>
> - /* Inform second kernel about the presence of ACPI tables. */
> - for (i = 0; i < MAX_MEMORY_RANGES; i++) {
> - unsigned long start, end;
> - if ( !( mem_range[i].type == RANGE_ACPI
> - || mem_range[i].type == RANGE_ACPI_NVS
> - || mem_range[i].type == RANGE_RESERVED) )
> - continue;
> - start = mem_range[i].start;
> - end = mem_range[i].end;
> - if (mem_range[i].type == RANGE_RESERVED)
> - cmdline_add_memmap_reserved(mod_cmdline, start, end);
> - else
> - cmdline_add_memmap_acpi(mod_cmdline, start, end);
> - }
> + /*
> + * Redo crash_memory_range so that it can get passed as e820 info
> + */
> + create_final_crash_map(memmap_p);
> +
> + dbgprintf("FINAL CRASH MEMORY RANGES\n");
> + for(i = 0; i < crash_ranges; ++i)
> + dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
> + mem_range[i].end, mem_range[i].type);
> return 0;
> }
>
> diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
> index c538897..82b4bb9 100644
> --- a/kexec/arch/i386/x86-linux-setup.c
> +++ b/kexec/arch/i386/x86-linux-setup.c
> @@ -505,8 +505,15 @@ void setup_linux_system_parameters(struct kexec_info *info,
> /* another safe default */
> real_mode->aux_device_info = 0;
>
> - range = info->memory_range;
> - ranges = info->memory_ranges;
> + if (info->kexec_flags & KEXEC_ON_CRASH ||
> + info->kexec_flags & KEXEC_PRESERVE_CONTEXT) {
> + range = crash_memory_range;
> + ranges = crash_ranges;
> + } else {
> + range = info->memory_range;
> + ranges = info->memory_ranges;
> + }
> +
> if (ranges > E820MAX) {
> if (!(info->kexec_flags & KEXEC_ON_CRASH))
> /*
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 9:56 ` Zhang Yanfei
@ 2013-04-12 11:12 ` Thomas Renninger
2013-04-15 9:05 ` Thomas Renninger
1 sibling, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-12 11:12 UTC (permalink / raw)
To: Zhang Yanfei
Cc: kexec, horms, Eric W. Biederman, H. Peter Anvin, yinghai, cpw,
vgoyal
Sorry, my first answer was an html mail, please ignore.
For some reason my mailer switches to html in rare cases, even
default is text...:
On Friday, April 12, 2013 05:56:08 PM Zhang Yanfei wrote:
> 于 2013年04月11日 20:26, Thomas Renninger 写道:
...
> > + * Ignore usable memory ranges for kdump kernel smaller
> > + * than 100k to avoid too much ranges passed
> > + * Save the new ranges (exluding lower than 100k ranges) in tmp_map
> > + * and store the number of elements in tmp_map_ranges
> > + */
> > + for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> > + unsigned long startk, endk;
> > + startk = (usable_mem[i].start/1024);
> > + endk = ((usable_mem[i].end + 1)/1024);
> > + if (!startk && !endk)
> > + /* All regions traversed. */
> > + break;
> > +
> > + /* A region is not worth adding if region size < 100K. It eats
> > + * up precious command line length. */
>
> Now you are passing the e820 table directly instead of the commandline, so
> does this comment make sense now?
Yes.
There is some specific data generated for the crash kernel in the
crashkernel=... area
which must not get used/overridden by crash
kernel usage.
There are some small areas between them which could get used again:
> + if ((endk - startk) < min_sizek) {
> + dbgprintf("Removing: %luk - %luk\n", startk, endk);
> + continue;
In my tests I saw:
Removing: 900552k - 900556k
Removing: 901115k - 901120k
And adding a 4k and a 5k usable memory range is really not worth it.
Also the e820 table is restricted to 128 entries and especially uefi
systems reach them quickly.
The (originally) usable memory ranges are cut out and not passed
(everything is exactly the same as in memmap= case), but usable
memory ranges for the crash kernel are added.
On my system the original BIOS/bootloader e820 table has 21 entries
and the (now) kexec modified ones also have 21. This may vary.
But it's good to not add that much and easier break the 128 e820 tables
work rule.
Hopefully this still reads someone, otherwise I'll send something
if I get further:
I currently try make up a uefi memory map area and point to it by
filling:
struct efi_info {
uint32_t efi_loader_signature;
uint32_t efi_systab;
uint32_t efi_memdesc_size;
uint32_t efi_memdesc_version;
uint32_t efi_memmap;
uint32_t efi_memmap_size;
uint32_t efi_systab_hi;
uint32_t efi_memmap_hi;
};
passed via boot loader structure (zero page).
This would break the 128 e820 entries restriction and lots of memory ranges
on UEFI systems would not be an issue anymore.
Thomas
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 14:55 ` Yinghai Lu
2013-04-11 15:06 ` H. Peter Anvin
@ 2013-04-12 12:24 ` Thomas Renninger
1 sibling, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-12 12:24 UTC (permalink / raw)
To: Yinghai Lu
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Simon Horman, Eric W. Biederman, H. Peter Anvin, Cliff Wickman,
Vivek Goyal
On Thursday, April 11, 2013 07:55:57 AM Yinghai Lu wrote:
> On Thu, Apr 11, 2013 at 5:26 AM, Thomas Renninger <trenn@suse.de> wrote:
> > Currently ranges are passed via kernel boot parameters:
> > memmap=exactmap memmap=X#Y memmap=
> >
> > Pass them via e820 table directly instead.
>
> how to address "saved_max_pfn" referring in kernel?
Yes, this patch won't work as I miss out the previously usable memory
totally.
I have to re-work this one and also pass these ranges as discussed
via a KDUMP_RESERVED or even better a KDUMP_MEMORY e820 type.
KDUMP_RESERVED could get used for reserved memory inside the crash
kernel range at some point of time if it is useful.
Can the other patches get applied already if they are fine?
> kernel need to use saved_max_pfn from old e820 in
> drivers/char/mem.c::read_oldmem()
>
> mips and powerpc they are passing that from command line "savemaxmem="
>
> x86 should use that too?
I could add that.
But things cannot get cleaned up because things have to be
compatible to old kexec tools not passing this param at least for
quite some time.
Thomas
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 15:06 ` H. Peter Anvin
@ 2013-04-12 14:31 ` Vivek Goyal
2013-04-12 14:56 ` H. Peter Anvin
0 siblings, 1 reply; 28+ messages in thread
From: Vivek Goyal @ 2013-04-12 14:31 UTC (permalink / raw)
To: H. Peter Anvin
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Thomas Renninger, Simon Horman, Eric W. Biederman, Yinghai Lu,
Cliff Wickman
On Thu, Apr 11, 2013 at 08:06:50AM -0700, H. Peter Anvin wrote:
> On 04/11/2013 07:55 AM, Yinghai Lu wrote:
> > On Thu, Apr 11, 2013 at 5:26 AM, Thomas Renninger <trenn@suse.de> wrote:
> >> Currently ranges are passed via kernel boot parameters:
> >> memmap=exactmap memmap=X#Y memmap=
> >>
> >> Pass them via e820 table directly instead.
> >
> > how to address "saved_max_pfn" referring in kernel?
> >
> > kernel need to use saved_max_pfn from old e820 in
> > drivers/char/mem.c::read_oldmem()
> >
> > mips and powerpc they are passing that from command line "savemaxmem="
> >
> > x86 should use that too?
> >
>
> Oh bloody hell, yet another f-ing "max_pfn" variable.
>
> The *only* one that makes any kind of sense is max_low_pfn (marking the
> cutoff to highmem)... the pretty much the rest of them are just plain wrong.
>
> And I don't mean "mildly annoying", I mean "catastrophically wrong
> semantics". In this case, it introduces a completely arbitrary
> distinction between a nonmemory range below a high water mark and a
> nonmemory range above that high water mark. In fact, from reading the
> code it seems pretty clear that the device will blindly assume that
> anything below saved_max_pfn is memory and will try to map it
> cachable... which will #MC on quite a few machines.
>
> This kind of crap HAS TO STOP. Memory is discontiguous, deal with it
> and deal with it properly.
Agreed. saved_max_pfn is bad idea. Passing all the mappable memory of
old kernel as "RESERVED" (Or KDUMP_RESERVED or KDUMP_MEM or whatever) to
next kernel in e820 map sounds better. And next kernel can allow access
to RESERVED range using /dev/oldmem interface.
For backward compatibility with old kexec-tools we can probably retain
saved_max_pfn for some time. We can set saved_max_pfn to end of
memory range including "RESERVED" regions. And this will be overwritten
if old kexec-tools have passed this parameter on command line. Also
whenever user passes saved_max_pfn on command line, we can do WARN_ONCE()
to upgrade to kexec-tools and let them know that saved_max_pfn will be
deprecated.
For issue of doing ioremap() on everything as cacheable, we should be
able to modify copy_olmem_page() and it should go through memory map
and check whether said pfn is mappable or not and what flags should
be used to map it.
I think this will again be problem with old kexec-tools. May be we check
of presence of atleast one "KDUMP_RESERVED" range in memory map. If none
is present, we know old kexec-tools were used and in that we can map
all pfn ioremap() blindly. We can do WARN_ONCE() and ask user to upgrade
the kexec-tools and after some time do away with this hack in
copy_oldmem_page() as well as remove saved_max_pfn.
>
> I also have to admit that I don't see the difference between /dev/mem
> and /dev/oldmem, as the former allows access to memory ranges outside
> the ones used by the current kernel, which is what the oldmem device
> seems to be intended to od.
>
I think one difference seems to be that /dev/mem assumes that validly
accessed memory is already mapped in kernel while /dev/oldmeme assumes
it is not mapped and creates temporary mappings explicitly.
Thanks
Vivek
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 14:31 ` Vivek Goyal
@ 2013-04-12 14:56 ` H. Peter Anvin
2013-04-12 22:17 ` Dave Hansen
0 siblings, 1 reply; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-12 14:56 UTC (permalink / raw)
To: Vivek Goyal
Cc: Dave Hansen, kexec@lists.infradead.org, Linux Kernel Mailing List,
Thomas Renninger, Simon Horman, Eric W. Biederman, Yinghai Lu,
Cliff Wickman
On 04/12/2013 07:31 AM, Vivek Goyal wrote:
>>
>> I also have to admit that I don't see the difference between /dev/mem
>> and /dev/oldmem, as the former allows access to memory ranges outside
>> the ones used by the current kernel, which is what the oldmem device
>> seems to be intended to od.
>
> I think one difference seems to be that /dev/mem assumes that validly
> accessed memory is already mapped in kernel while /dev/oldmeme assumes
> it is not mapped and creates temporary mappings explicitly.
>
Dave Hansen has been working on fixing /dev/mem for HIGHMEM.
-hpa
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-11 12:26 ` [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter Thomas Renninger
2013-04-11 14:55 ` Yinghai Lu
2013-04-12 9:56 ` Zhang Yanfei
@ 2013-04-12 15:24 ` Eric W. Biederman
2013-04-15 11:48 ` Thomas Renninger
2 siblings, 1 reply; 28+ messages in thread
From: Eric W. Biederman @ 2013-04-12 15:24 UTC (permalink / raw)
To: Thomas Renninger; +Cc: kexec, horms, H. Peter Anvin, yinghai, cpw, vgoyal
Thomas Renninger <trenn@suse.de> writes:
> Currently ranges are passed via kernel boot parameters:
> memmap=exactmap memmap=X#Y memmap=
>
> Pass them via e820 table directly instead.
Reading through this code I am not seeing us mark areas of memory that
we may not use as reserved. Am I missing something?
Those areas need to be marked reserved or else the pci resource
allocator in the kernel will think it is ok to put pci memory there.
Eric
> CC: Simon Horman <horms@verge.net.au>
> CC: kexec@lists.infradead.org
> CC: H. Peter Anvin <hpa@zytor.com>
> CC: Eric W. Biederman <ebiederm@xmission.com>
> CC: vgoyal@redhat.com
> CC: yinghai@kernel.org
> CC: cpw@sgi.com
>
> Signed-off-by: Thomas Renninger <trenn@suse.de>
> Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
> ---
> kexec/arch/i386/crashdump-x86.c | 221 ++++++++++++++++++-------------------
> kexec/arch/i386/x86-linux-setup.c | 11 ++-
> 2 files changed, 116 insertions(+), 116 deletions(-)
>
> diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
> index f7821bc..8009efe 100644
> --- a/kexec/arch/i386/crashdump-x86.c
> +++ b/kexec/arch/i386/crashdump-x86.c
> @@ -659,70 +659,6 @@ static void ultoa(unsigned long i, char *str)
> }
> }
>
> -static void cmdline_add_memmap_internal(char *cmdline, unsigned long startk,
> - unsigned long endk, int type)
> -{
> - int cmdlen, len;
> - char str_mmap[256], str_tmp[20];
> -
> - strcpy (str_mmap, " memmap=");
> - ultoa((endk-startk), str_tmp);
> - strcat (str_mmap, str_tmp);
> -
> - if (type == RANGE_RAM)
> - strcat (str_mmap, "K@");
> - else if (type == RANGE_RESERVED)
> - strcat (str_mmap, "K$");
> - else if (type == RANGE_ACPI || type == RANGE_ACPI_NVS)
> - 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))
> - die("Command line overflow\n");
> - strcat(cmdline, str_mmap);
> -}
> -
> -/* Adds the appropriate memmap= options to command line, indicating the
> - * memory regions the new kernel can use to boot into. */
> -static int cmdline_add_memmap(char *cmdline, struct memory_range *memmap_p)
> -{
> - int i, cmdlen, len;
> - unsigned long min_sizek = 100;
> - char str_mmap[256];
> -
> - /* Exact map */
> - strcpy(str_mmap, " memmap=exactmap");
> - len = strlen(str_mmap);
> - cmdlen = strlen(cmdline) + len;
> - if (cmdlen > (COMMAND_LINE_SIZE - 1))
> - die("Command line overflow\n");
> - strcat(cmdline, str_mmap);
> -
> - for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> - unsigned long startk, endk;
> - startk = (memmap_p[i].start/1024);
> - endk = ((memmap_p[i].end + 1)/1024);
> - if (!startk && !endk)
> - /* All regions traversed. */
> - break;
> -
> - /* A region is not worth adding if region size < 100K. It eats
> - * up precious command line length. */
> - if ((endk - startk) < min_sizek)
> - continue;
> - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RAM);
> - }
> -
> - dbgprintf("Command line after adding memmap\n");
> - dbgprintf("%s\n", cmdline);
> -
> - return 0;
> -}
> -
> /* Adds the elfcorehdr= command line parameter to command line. */
> static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr)
> {
> @@ -803,26 +739,6 @@ static enum coretype get_core_type(struct crash_elf_info *elf_info,
> }
> }
>
> -/* Appends memmap=X#Y commandline for ACPI to command line*/
> -static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
> - unsigned long end)
> -{
> - int align = 1024;
> - unsigned long startk, endk;
> -
> - if (!(end - start))
> - return 0;
> -
> - startk = start/1024;
> - endk = (end + align - 1)/1024;
> - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_ACPI);
> -
> - dbgprintf("Command line after adding acpi memmap\n");
> - dbgprintf("%s\n", cmdline);
> -
> - return 0;
> -}
> -
> /* Appends 'acpi_rsdp=' commandline for efi boot crash dump */
> static void cmdline_add_efi(char *cmdline)
> {
> @@ -881,24 +797,101 @@ static void get_backup_area(struct kexec_info *info,
> info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
> }
>
> -/* Appends memmap=X$Y commandline for reserved memory to command line*/
> -static int cmdline_add_memmap_reserved(char *cmdline, unsigned long start,
> - unsigned long end)
> +/*
> + * This function takes reserved (all kind of) memory from global
> + * crash_memory_range[] memory ranges and takes memory the kdump/crash
> + * kernel is allowed to use from the passed usable_mem memory ranges.
> + * The passed usable_mem ranges are zero (!start && !end) terminated.
> + *
> + * The final memory map is again written into crash_memory_range[]
> + * and intended to get passed as e820 table to the crash kernel
> + */
> +static int create_final_crash_map(struct memory_range *usable_mem)
> {
> - int align = 1024;
> - unsigned long startk, endk;
> + int i, m, c, tmp_map1_ranges, tmp_map2_ranges;
> + unsigned long min_sizek = 100;
> + /* crash_memory_map with usable memory ranges cut out */
> + struct memory_range tmp_map1[MAX_MEMORY_RANGES];
> + /* merge_map, but small ranges cut out */
> + struct memory_range tmp_map2[MAX_MEMORY_RANGES];
>
> - if (!(end - start))
> - return 0;
> + /*
> + * Ignore usable memory ranges for kdump kernel smaller
> + * than 100k to avoid too much ranges passed
> + * Save the new ranges (exluding lower than 100k ranges) in tmp_map
> + * and store the number of elements in tmp_map_ranges
> + */
> + for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> + unsigned long startk, endk;
> + startk = (usable_mem[i].start/1024);
> + endk = ((usable_mem[i].end + 1)/1024);
> + if (!startk && !endk)
> + /* All regions traversed. */
> + break;
> +
> + /* A region is not worth adding if region size < 100K. It eats
> + * up precious command line length. */
> + if ((endk - startk) < min_sizek) {
> + dbgprintf("Removing: %luk - %luk\n", startk, endk);
> + continue;
> + } else {
> + tmp_map1[m].start = usable_mem[i].start;
> + tmp_map1[m].end = usable_mem[i].end;
> + tmp_map1[m].type = usable_mem[i].type;
> + m++;
> + }
> + }
> + /* No need to check for !start && !end anymore */
> + tmp_map1_ranges = m;
>
> - startk = start/1024;
> - endk = (end + align - 1)/1024;
> - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RESERVED);
> + for(i = 0; i < tmp_map1_ranges; ++i)
> + dbgprintf("%016Lx-%016Lx (%d)\n", tmp_map1[i].start,
> + tmp_map1[i].end, tmp_map1[i].type);
> +
> + /*
> + * Cut out RANGE_RAM regions from crash_memory_ranges and store
> + * them in tmp_map2_ranges
> + */
> + for (c = 0, i = 0; i < crash_ranges; i++) {
> + if (crash_memory_range[i].type == RANGE_RAM)
> + continue;
> + tmp_map2[c].start = crash_memory_range[i].start;
> + tmp_map2[c].end = crash_memory_range[i].end;
> + tmp_map2[c].type = crash_memory_range[i].type;
> + c++;
> + }
> + tmp_map2_ranges = c;
> +
> + /*
> + * TBD: Check that no ranges overlap?
> + * Can this happen at all?
> + */
> + for (c = 0, m = 0, i = 0; i < MAX_MEMORY_RANGES; i++) {
> + if (m < tmp_map1_ranges &&
> + (c >= tmp_map2_ranges ||
> + tmp_map2[c].start > tmp_map1[m].start)) {
> + crash_memory_range[i].start = tmp_map1[m].start;
> + crash_memory_range[i].end = tmp_map1[m].end;
> + crash_memory_range[i].type = RANGE_RAM;
> + m++;
> + continue;
> + } else if (c < tmp_map2_ranges) {
> + crash_memory_range[i] = tmp_map2[c];
> + c++;
> + continue;
> + } else
> + break;
> + }
> + crash_ranges = i;
> +
> + /*
> + * End address has to be exlusive for e820 map
> + * x - 00010000
> + * 00010000 - y
> + */
> + for(i = 0; i < crash_ranges; ++i)
> + crash_memory_range[i].end++;
>
> -#ifdef DEBUG
> - printf("Command line after adding reserved memmap\n");
> - printf("%s\n", cmdline);
> -#endif
> return 0;
> }
>
> @@ -944,6 +937,12 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
> return -1;
> }
>
> + /*
> + * From now on the memory regions are stored in crash_memory_range[]
> + * Currently the end address is inclusive at this point:
> + * x - 0000ffff
> + * 00010000 - y
> + */
> if (xen_present()) {
> if (get_crash_memory_ranges_xen(&mem_range, &crash_ranges,
> elf_info.lowmem_limit) < 0)
> @@ -971,7 +970,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
>
> get_backup_area(info, mem_range, crash_ranges);
>
> - dbgprintf("CRASH MEMORY RANGES\n");
> + dbgprintf("TEMPORARY CRASH MEMORY RANGES\n");
>
> for(i = 0; i < crash_ranges; ++i)
> dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
> @@ -1063,24 +1062,18 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
> dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
> if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
> return -1;
> - cmdline_add_memmap(mod_cmdline, memmap_p);
> cmdline_add_efi(mod_cmdline);
> cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
>
> - /* Inform second kernel about the presence of ACPI tables. */
> - for (i = 0; i < MAX_MEMORY_RANGES; i++) {
> - unsigned long start, end;
> - if ( !( mem_range[i].type == RANGE_ACPI
> - || mem_range[i].type == RANGE_ACPI_NVS
> - || mem_range[i].type == RANGE_RESERVED) )
> - continue;
> - start = mem_range[i].start;
> - end = mem_range[i].end;
> - if (mem_range[i].type == RANGE_RESERVED)
> - cmdline_add_memmap_reserved(mod_cmdline, start, end);
> - else
> - cmdline_add_memmap_acpi(mod_cmdline, start, end);
> - }
> + /*
> + * Redo crash_memory_range so that it can get passed as e820 info
> + */
> + create_final_crash_map(memmap_p);
> +
> + dbgprintf("FINAL CRASH MEMORY RANGES\n");
> + for(i = 0; i < crash_ranges; ++i)
> + dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
> + mem_range[i].end, mem_range[i].type);
> return 0;
> }
>
> diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
> index c538897..82b4bb9 100644
> --- a/kexec/arch/i386/x86-linux-setup.c
> +++ b/kexec/arch/i386/x86-linux-setup.c
> @@ -505,8 +505,15 @@ void setup_linux_system_parameters(struct kexec_info *info,
> /* another safe default */
> real_mode->aux_device_info = 0;
>
> - range = info->memory_range;
> - ranges = info->memory_ranges;
> + if (info->kexec_flags & KEXEC_ON_CRASH ||
> + info->kexec_flags & KEXEC_PRESERVE_CONTEXT) {
> + range = crash_memory_range;
> + ranges = crash_ranges;
> + } else {
> + range = info->memory_range;
> + ranges = info->memory_ranges;
> + }
> +
> if (ranges > E820MAX) {
> if (!(info->kexec_flags & KEXEC_ON_CRASH))
> /*
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 14:56 ` H. Peter Anvin
@ 2013-04-12 22:17 ` Dave Hansen
2013-04-12 23:17 ` H. Peter Anvin
2013-04-15 4:52 ` HATAYAMA Daisuke
0 siblings, 2 replies; 28+ messages in thread
From: Dave Hansen @ 2013-04-12 22:17 UTC (permalink / raw)
To: H. Peter Anvin
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Cliff Wickman, Simon Horman, Eric W. Biederman, Yinghai Lu,
Thomas Renninger, Vivek Goyal
On 04/12/2013 07:56 AM, H. Peter Anvin wrote:
> On 04/12/2013 07:31 AM, Vivek Goyal wrote:
>>> I also have to admit that I don't see the difference between /dev/mem
>>> and /dev/oldmem, as the former allows access to memory ranges outside
>>> the ones used by the current kernel, which is what the oldmem device
>>> seems to be intended to od.
It varies from arch to arch of course.
But, /dev/mem has restrictions on it, like CONFIG_STRICT_DEVMEM or the
ARCH_HAS_VALID_PHYS_ADDR_RANGE. There's a lot of stuff that depends on
it, *and* folks have tried to fix it up so that it's not _as_ blatant of
a way to completely screw your system.
/dev/mem also tries to be nice to arches that have restrictions like:
> /*
> * On ia64 if a page has been mapped somewhere as
> * uncached, then it must also be accessed uncached
> * by the kernel or data corruption may occur
> */
I think /dev/oldmem isn't so nice and could actually cause some real
problems if used on ia64 where the cached/uncached accesses are mixed.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 22:17 ` Dave Hansen
@ 2013-04-12 23:17 ` H. Peter Anvin
2013-04-15 4:52 ` HATAYAMA Daisuke
1 sibling, 0 replies; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-12 23:17 UTC (permalink / raw)
To: Dave Hansen
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Cliff Wickman, Simon Horman, Eric W. Biederman, Yinghai Lu,
Thomas Renninger, Vivek Goyal
Yes... That is one reason I think it is a real problem.
Dave Hansen <dave@sr71.net> wrote:
>On 04/12/2013 07:56 AM, H. Peter Anvin wrote:
>> On 04/12/2013 07:31 AM, Vivek Goyal wrote:
>>>> I also have to admit that I don't see the difference between
>/dev/mem
>>>> and /dev/oldmem, as the former allows access to memory ranges
>outside
>>>> the ones used by the current kernel, which is what the oldmem
>device
>>>> seems to be intended to od.
>
>It varies from arch to arch of course.
>
>But, /dev/mem has restrictions on it, like CONFIG_STRICT_DEVMEM or the
>ARCH_HAS_VALID_PHYS_ADDR_RANGE. There's a lot of stuff that depends on
>it, *and* folks have tried to fix it up so that it's not _as_ blatant
>of
>a way to completely screw your system.
>
>/dev/mem also tries to be nice to arches that have restrictions like:
>
>> /*
>> * On ia64 if a page has been mapped
>somewhere as
>> * uncached, then it must also be accessed
>uncached
>> * by the kernel or data corruption may occur
>> */
>
>I think /dev/oldmem isn't so nice and could actually cause some real
>problems if used on ia64 where the cached/uncached accesses are mixed.
--
Sent from my mobile phone. Please excuse brevity and lack of formatting.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 22:17 ` Dave Hansen
2013-04-12 23:17 ` H. Peter Anvin
@ 2013-04-15 4:52 ` HATAYAMA Daisuke
2013-04-15 5:58 ` Dave Hansen
1 sibling, 1 reply; 28+ messages in thread
From: HATAYAMA Daisuke @ 2013-04-15 4:52 UTC (permalink / raw)
To: Dave Hansen
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Thomas Renninger, Simon Horman, Eric W. Biederman, H. Peter Anvin,
Yinghai Lu, Cliff Wickman, Vivek Goyal
(2013/04/13 7:17), Dave Hansen wrote:
> On 04/12/2013 07:56 AM, H. Peter Anvin wrote:
>> On 04/12/2013 07:31 AM, Vivek Goyal wrote:
>>>> I also have to admit that I don't see the difference between /dev/mem
>>>> and /dev/oldmem, as the former allows access to memory ranges outside
>>>> the ones used by the current kernel, which is what the oldmem device
>>>> seems to be intended to od.
>
> It varies from arch to arch of course.
>
> But, /dev/mem has restrictions on it, like CONFIG_STRICT_DEVMEM or the
> ARCH_HAS_VALID_PHYS_ADDR_RANGE. There's a lot of stuff that depends on
> it, *and* folks have tried to fix it up so that it's not _as_ blatant of
> a way to completely screw your system.
>
> /dev/mem also tries to be nice to arches that have restrictions like:
>
>> /*
>> * On ia64 if a page has been mapped somewhere as
>> * uncached, then it must also be accessed uncached
>> * by the kernel or data corruption may occur
>> */
>
> I think /dev/oldmem isn't so nice and could actually cause some real
> problems if used on ia64 where the cached/uncached accesses are mixed.
This sounds like there's no such issue on x86 cache mechanism. Is it
correct? If so, what is the difference between ia64 and x86 cache
mechanisms?
--
Thanks.
HATAYAMA, Daisuke
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 4:52 ` HATAYAMA Daisuke
@ 2013-04-15 5:58 ` Dave Hansen
2013-04-15 7:58 ` HATAYAMA Daisuke
2013-04-15 14:49 ` H. Peter Anvin
0 siblings, 2 replies; 28+ messages in thread
From: Dave Hansen @ 2013-04-15 5:58 UTC (permalink / raw)
To: HATAYAMA Daisuke
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Thomas Renninger, Simon Horman, Eric W. Biederman, H. Peter Anvin,
Yinghai Lu, Cliff Wickman, Vivek Goyal
On 04/14/2013 09:52 PM, HATAYAMA Daisuke wrote:
> This sounds like there's no such issue on x86 cache mechanism. Is it
> correct? If so, what is the difference between ia64 and x86 cache
> mechanisms?
I'm just going by the code comments:
drivers/char/mem.c
> /*
> * On ia64 if a page has been mapped somewhere as uncached, then
> * it must also be accessed uncached by the kernel or data
> * corruption may occur.
> */
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 5:58 ` Dave Hansen
@ 2013-04-15 7:58 ` HATAYAMA Daisuke
2013-04-15 14:49 ` H. Peter Anvin
1 sibling, 0 replies; 28+ messages in thread
From: HATAYAMA Daisuke @ 2013-04-15 7:58 UTC (permalink / raw)
To: Dave Hansen
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Cliff Wickman, Simon Horman, Eric W. Biederman, H. Peter Anvin,
Yinghai Lu, Thomas Renninger, Vivek Goyal
(2013/04/15 14:58), Dave Hansen wrote:
> On 04/14/2013 09:52 PM, HATAYAMA Daisuke wrote:
>> This sounds like there's no such issue on x86 cache mechanism. Is it
>> correct? If so, what is the difference between ia64 and x86 cache
>> mechanisms?
>
> I'm just going by the code comments:
>
> drivers/char/mem.c
>> /*
>> * On ia64 if a page has been mapped somewhere as uncached, then
>> * it must also be accessed uncached by the kernel or data
>> * corruption may occur.
>> */
I think it reasonable, in complexity of design, to decide cache or
uncache according to whether target memory is RAM or some device. If
we're concerned about page levels, things are to be complicated further
since memory typing is done per pages. How large does such table become
to represent memory types for all the target pages, how do we create it
and when? (I don't know ia64 but I guess caching on ia64 is also done in
per pages just like x86...)
--
Thanks.
HATAYAMA, Daisuke
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 9:56 ` Zhang Yanfei
2013-04-12 11:12 ` Thomas Renninger
@ 2013-04-15 9:05 ` Thomas Renninger
2013-04-15 12:20 ` H. Peter Anvin
1 sibling, 1 reply; 28+ messages in thread
From: Thomas Renninger @ 2013-04-15 9:05 UTC (permalink / raw)
To: Zhang Yanfei
Cc: kexec, horms, Eric W. Biederman, H. Peter Anvin, yinghai, cpw,
vgoyal
On Friday, April 12, 2013 05:56:08 PM Zhang Yanfei wrote:
> 于 2013年04月11日 20:26, Thomas Renninger 写道:
> > Currently ranges are passed via kernel boot parameters:
> > memmap=exactmap memmap=X#Y memmap=
> >
...
> > - if (!(end - start))
> > - return 0;
> > + /*
> > + * Ignore usable memory ranges for kdump kernel smaller
> > + * than 100k to avoid too much ranges passed
> > + * Save the new ranges (exluding lower than 100k ranges) in tmp_map
> > + * and store the number of elements in tmp_map_ranges
> > + */
> > + for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> > + unsigned long startk, endk;
> > + startk = (usable_mem[i].start/1024);
> > + endk = ((usable_mem[i].end + 1)/1024);
> > + if (!startk && !endk)
> > + /* All regions traversed. */
> > + break;
> > +
> > + /* A region is not worth adding if region size < 100K. It eats
> > + * up precious command line length. */
>
> Now you are passing the e820 table directly instead of the commandline, so
> does this comment make sense now?
Yes you are right, the comment is wrong.
It should more be like:
/*
A region is not worth adding if region size < 100K. e820 entries are
restricted to 128 in kernel, with kdump we may have to pass the one or other
more and we want to try to stay at 128 max entries (from original table) as
close as possible.
*/
Thanks,
Thomas
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-12 15:24 ` Eric W. Biederman
@ 2013-04-15 11:48 ` Thomas Renninger
0 siblings, 0 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-15 11:48 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: kexec, horms, H. Peter Anvin, yinghai, cpw, vgoyal
On Friday, April 12, 2013 08:24:12 AM Eric W. Biederman wrote:
> Thomas Renninger <trenn@suse.de> writes:
> > Currently ranges are passed via kernel boot parameters:
> > memmap=exactmap memmap=X#Y memmap=
> >
> > Pass them via e820 table directly instead.
>
> Reading through this code I am not seeing us mark areas of memory that
> we may not use as reserved. Am I missing something?
They are added.
acpi and reserved (only like in the original kernel) come from
crash_memory_range[] array
(like in cmdline_add_memmap_acpi and cmdline_add_memmap_reserved
and the free to use for crash kernel memory is coming from the array
(memmap_p):
cmdline_add_memmap_acpi
I see that the merging function is not that nice to read, but I couldn't come
up with something better for now.
In fact it should work exactly the same way as before with memmap= passing.
There is something odd with not passing the hightest e820 entry.
It seem to be needed, but it was not passed via memmap= as well?, so my
version should also work and a test did:
The dumpfile is saved to /root/abuild/dumps/2013-04-15-12:59/vmcore
file size: 3251795465
free
total
Mem: 32633312
I answer more detailed on Yinghai's mail.
Thomas
> Those areas need to be marked reserved or else the pci resource
> allocator in the kernel will think it is ok to put pci memory there.
>
> Eric
>
> > CC: Simon Horman <horms@verge.net.au>
> > CC: kexec@lists.infradead.org
> > CC: H. Peter Anvin <hpa@zytor.com>
> > CC: Eric W. Biederman <ebiederm@xmission.com>
> > CC: vgoyal@redhat.com
> > CC: yinghai@kernel.org
> > CC: cpw@sgi.com
> >
> > Signed-off-by: Thomas Renninger <trenn@suse.de>
> > Signed-off-by: Thomas Renninger <Thomas Renninger" trenn@suse.de>
> > ---
> >
> > kexec/arch/i386/crashdump-x86.c | 221
> > ++++++++++++++++++------------------- kexec/arch/i386/x86-linux-setup.c
> > | 11 ++-
> > 2 files changed, 116 insertions(+), 116 deletions(-)
> >
> > diff --git a/kexec/arch/i386/crashdump-x86.c
> > b/kexec/arch/i386/crashdump-x86.c index f7821bc..8009efe 100644
> > --- a/kexec/arch/i386/crashdump-x86.c
> > +++ b/kexec/arch/i386/crashdump-x86.c
> > @@ -659,70 +659,6 @@ static void ultoa(unsigned long i, char *str)
> >
> > }
> >
> > }
> >
> > -static void cmdline_add_memmap_internal(char *cmdline, unsigned long
> > startk, - unsigned long endk, int type)
> > -{
> > - int cmdlen, len;
> > - char str_mmap[256], str_tmp[20];
> > -
> > - strcpy (str_mmap, " memmap=");
> > - ultoa((endk-startk), str_tmp);
> > - strcat (str_mmap, str_tmp);
> > -
> > - if (type == RANGE_RAM)
> > - strcat (str_mmap, "K@");
> > - else if (type == RANGE_RESERVED)
> > - strcat (str_mmap, "K$");
> > - else if (type == RANGE_ACPI || type == RANGE_ACPI_NVS)
> > - 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))
> > - die("Command line overflow\n");
> > - strcat(cmdline, str_mmap);
> > -}
> > -
> > -/* Adds the appropriate memmap= options to command line, indicating the
> > - * memory regions the new kernel can use to boot into. */
> > -static int cmdline_add_memmap(char *cmdline, struct memory_range
> > *memmap_p) -{
> > - int i, cmdlen, len;
> > - unsigned long min_sizek = 100;
> > - char str_mmap[256];
> > -
> > - /* Exact map */
> > - strcpy(str_mmap, " memmap=exactmap");
> > - len = strlen(str_mmap);
> > - cmdlen = strlen(cmdline) + len;
> > - if (cmdlen > (COMMAND_LINE_SIZE - 1))
> > - die("Command line overflow\n");
> > - strcat(cmdline, str_mmap);
> > -
> > - for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> > - unsigned long startk, endk;
> > - startk = (memmap_p[i].start/1024);
> > - endk = ((memmap_p[i].end + 1)/1024);
> > - if (!startk && !endk)
> > - /* All regions traversed. */
> > - break;
> > -
> > - /* A region is not worth adding if region size < 100K. It eats
> > - * up precious command line length. */
> > - if ((endk - startk) < min_sizek)
> > - continue;
> > - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RAM);
> > - }
> > -
> > - dbgprintf("Command line after adding memmap\n");
> > - dbgprintf("%s\n", cmdline);
> > -
> > - return 0;
> > -}
> > -
> >
> > /* Adds the elfcorehdr= command line parameter to command line. */
> > static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr)
> > {
> >
> > @@ -803,26 +739,6 @@ static enum coretype get_core_type(struct
> > crash_elf_info *elf_info,>
> > }
> >
> > }
> >
> > -/* Appends memmap=X#Y commandline for ACPI to command line*/
> > -static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
> > - unsigned long end)
> > -{
> > - int align = 1024;
> > - unsigned long startk, endk;
> > -
> > - if (!(end - start))
> > - return 0;
> > -
> > - startk = start/1024;
> > - endk = (end + align - 1)/1024;
> > - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_ACPI);
> > -
> > - dbgprintf("Command line after adding acpi memmap\n");
> > - dbgprintf("%s\n", cmdline);
> > -
> > - return 0;
> > -}
> > -
> >
> > /* Appends 'acpi_rsdp=' commandline for efi boot crash dump */
> > static void cmdline_add_efi(char *cmdline)
> > {
> >
> > @@ -881,24 +797,101 @@ static void get_backup_area(struct kexec_info
> > *info,
> >
> > info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
> >
> > }
> >
> > -/* Appends memmap=X$Y commandline for reserved memory to command line*/
> > -static int cmdline_add_memmap_reserved(char *cmdline, unsigned long
> > start,
> > - unsigned long end)
> > +/*
> > + * This function takes reserved (all kind of) memory from global
> > + * crash_memory_range[] memory ranges and takes memory the kdump/crash
> > + * kernel is allowed to use from the passed usable_mem memory ranges.
> > + * The passed usable_mem ranges are zero (!start && !end) terminated.
> > + *
> > + * The final memory map is again written into crash_memory_range[]
> > + * and intended to get passed as e820 table to the crash kernel
> > + */
> > +static int create_final_crash_map(struct memory_range *usable_mem)
> >
> > {
> >
> > - int align = 1024;
> > - unsigned long startk, endk;
> > + int i, m, c, tmp_map1_ranges, tmp_map2_ranges;
> > + unsigned long min_sizek = 100;
> > + /* crash_memory_map with usable memory ranges cut out */
> > + struct memory_range tmp_map1[MAX_MEMORY_RANGES];
> > + /* merge_map, but small ranges cut out */
> > + struct memory_range tmp_map2[MAX_MEMORY_RANGES];
> >
> > - if (!(end - start))
> > - return 0;
> > + /*
> > + * Ignore usable memory ranges for kdump kernel smaller
> > + * than 100k to avoid too much ranges passed
> > + * Save the new ranges (exluding lower than 100k ranges) in tmp_map
> > + * and store the number of elements in tmp_map_ranges
> > + */
> > + for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
> > + unsigned long startk, endk;
> > + startk = (usable_mem[i].start/1024);
> > + endk = ((usable_mem[i].end + 1)/1024);
> > + if (!startk && !endk)
> > + /* All regions traversed. */
> > + break;
> > +
> > + /* A region is not worth adding if region size < 100K. It eats
> > + * up precious command line length. */
> > + if ((endk - startk) < min_sizek) {
> > + dbgprintf("Removing: %luk - %luk\n", startk, endk);
> > + continue;
> > + } else {
> > + tmp_map1[m].start = usable_mem[i].start;
> > + tmp_map1[m].end = usable_mem[i].end;
> > + tmp_map1[m].type = usable_mem[i].type;
> > + m++;
> > + }
> > + }
> > + /* No need to check for !start && !end anymore */
> > + tmp_map1_ranges = m;
> >
> > - startk = start/1024;
> > - endk = (end + align - 1)/1024;
> > - cmdline_add_memmap_internal(cmdline, startk, endk, RANGE_RESERVED);
> > + for(i = 0; i < tmp_map1_ranges; ++i)
> > + dbgprintf("%016Lx-%016Lx (%d)\n", tmp_map1[i].start,
> > + tmp_map1[i].end, tmp_map1[i].type);
> > +
> > + /*
> > + * Cut out RANGE_RAM regions from crash_memory_ranges and store
> > + * them in tmp_map2_ranges
> > + */
> > + for (c = 0, i = 0; i < crash_ranges; i++) {
> > + if (crash_memory_range[i].type == RANGE_RAM)
> > + continue;
> > + tmp_map2[c].start = crash_memory_range[i].start;
> > + tmp_map2[c].end = crash_memory_range[i].end;
> > + tmp_map2[c].type = crash_memory_range[i].type;
> > + c++;
> > + }
> > + tmp_map2_ranges = c;
> > +
> > + /*
> > + * TBD: Check that no ranges overlap?
> > + * Can this happen at all?
> > + */
> > + for (c = 0, m = 0, i = 0; i < MAX_MEMORY_RANGES; i++) {
> > + if (m < tmp_map1_ranges &&
> > + (c >= tmp_map2_ranges ||
> > + tmp_map2[c].start > tmp_map1[m].start)) {
> > + crash_memory_range[i].start = tmp_map1[m].start;
> > + crash_memory_range[i].end = tmp_map1[m].end;
> > + crash_memory_range[i].type = RANGE_RAM;
> > + m++;
> > + continue;
> > + } else if (c < tmp_map2_ranges) {
> > + crash_memory_range[i] = tmp_map2[c];
> > + c++;
> > + continue;
> > + } else
> > + break;
> > + }
> > + crash_ranges = i;
> > +
> > + /*
> > + * End address has to be exlusive for e820 map
> > + * x - 00010000
> > + * 00010000 - y
> > + */
> > + for(i = 0; i < crash_ranges; ++i)
> > + crash_memory_range[i].end++;
> >
> > -#ifdef DEBUG
> > - printf("Command line after adding reserved memmap\n");
> > - printf("%s\n", cmdline);
> > -#endif
> >
> > return 0;
> >
> > }
> >
> > @@ -944,6 +937,12 @@ int load_crashdump_segments(struct kexec_info *info,
> > char* mod_cmdline,>
> > return -1;
> >
> > }
> >
> > + /*
> > + * From now on the memory regions are stored in crash_memory_range[]
> > + * Currently the end address is inclusive at this point:
> > + * x - 0000ffff
> > + * 00010000 - y
> > + */
> >
> > if (xen_present()) {
> >
> > if (get_crash_memory_ranges_xen(&mem_range, &crash_ranges,
> >
> > elf_info.lowmem_limit) < 0)
> >
> > @@ -971,7 +970,7 @@ int load_crashdump_segments(struct kexec_info *info,
> > char* mod_cmdline,>
> > get_backup_area(info, mem_range, crash_ranges);
> >
> > - dbgprintf("CRASH MEMORY RANGES\n");
> > + dbgprintf("TEMPORARY CRASH MEMORY RANGES\n");
> >
> > for(i = 0; i < crash_ranges; ++i)
> >
> > dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
> >
> > @@ -1063,24 +1062,18 @@ int load_crashdump_segments(struct kexec_info
> > *info, char* mod_cmdline,>
> > dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
> > if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
> >
> > return -1;
> >
> > - cmdline_add_memmap(mod_cmdline, memmap_p);
> >
> > cmdline_add_efi(mod_cmdline);
> > cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
> >
> > - /* Inform second kernel about the presence of ACPI tables. */
> > - for (i = 0; i < MAX_MEMORY_RANGES; i++) {
> > - unsigned long start, end;
> > - if ( !( mem_range[i].type == RANGE_ACPI
> > - || mem_range[i].type == RANGE_ACPI_NVS
> > - || mem_range[i].type == RANGE_RESERVED) )
> > - continue;
> > - start = mem_range[i].start;
> > - end = mem_range[i].end;
> > - if (mem_range[i].type == RANGE_RESERVED)
> > - cmdline_add_memmap_reserved(mod_cmdline, start, end);
> > - else
> > - cmdline_add_memmap_acpi(mod_cmdline, start, end);
> > - }
> > + /*
> > + * Redo crash_memory_range so that it can get passed as e820 info
> > + */
> > + create_final_crash_map(memmap_p);
> > +
> > + dbgprintf("FINAL CRASH MEMORY RANGES\n");
> > + for(i = 0; i < crash_ranges; ++i)
> > + dbgprintf("%016Lx-%016Lx (%d)\n", mem_range[i].start,
> > + mem_range[i].end, mem_range[i].type);
> >
> > return 0;
> >
> > }
> >
> > diff --git a/kexec/arch/i386/x86-linux-setup.c
> > b/kexec/arch/i386/x86-linux-setup.c index c538897..82b4bb9 100644
> > --- a/kexec/arch/i386/x86-linux-setup.c
> > +++ b/kexec/arch/i386/x86-linux-setup.c
> > @@ -505,8 +505,15 @@ void setup_linux_system_parameters(struct kexec_info
> > *info,>
> > /* another safe default */
> > real_mode->aux_device_info = 0;
> >
> > - range = info->memory_range;
> > - ranges = info->memory_ranges;
> > + if (info->kexec_flags & KEXEC_ON_CRASH ||
> > + info->kexec_flags & KEXEC_PRESERVE_CONTEXT) {
> > + range = crash_memory_range;
> > + ranges = crash_ranges;
> > + } else {
> > + range = info->memory_range;
> > + ranges = info->memory_ranges;
> > + }
> > +
> >
> > if (ranges > E820MAX) {
> >
> > if (!(info->kexec_flags & KEXEC_ON_CRASH))
> >
> > /*
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 9:05 ` Thomas Renninger
@ 2013-04-15 12:20 ` H. Peter Anvin
2013-04-15 19:48 ` Thomas Renninger
0 siblings, 1 reply; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-15 12:20 UTC (permalink / raw)
To: Thomas Renninger, Zhang Yanfei
Cc: kexec, horms, Eric W. Biederman, yinghai, cpw, vgoyal
Except that is wrong. The kernel can receive more than 128 e820 entries, they just have to be passed via a different mechanism.
Thomas Renninger <trenn@suse.de> wrote:
>On Friday, April 12, 2013 05:56:08 PM Zhang Yanfei wrote:
>> 于 2013年04月11日 20:26, Thomas Renninger 写道:
>> > Currently ranges are passed via kernel boot parameters:
>> > memmap=exactmap memmap=X#Y memmap=
>> >
>...
>> > - if (!(end - start))
>> > - return 0;
>> > + /*
>> > + * Ignore usable memory ranges for kdump kernel smaller
>> > + * than 100k to avoid too much ranges passed
>> > + * Save the new ranges (exluding lower than 100k ranges) in
>tmp_map
>> > + * and store the number of elements in tmp_map_ranges
>> > + */
>> > + for (m = 0, i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
>> > + unsigned long startk, endk;
>> > + startk = (usable_mem[i].start/1024);
>> > + endk = ((usable_mem[i].end + 1)/1024);
>> > + if (!startk && !endk)
>> > + /* All regions traversed. */
>> > + break;
>> > +
>> > + /* A region is not worth adding if region size < 100K. It eats
>> > + * up precious command line length. */
>>
>> Now you are passing the e820 table directly instead of the
>commandline, so
>> does this comment make sense now?
>Yes you are right, the comment is wrong.
>It should more be like:
>/*
>A region is not worth adding if region size < 100K. e820 entries are
>restricted to 128 in kernel, with kdump we may have to pass the one or
>other
>more and we want to try to stay at 128 max entries (from original
>table) as
>close as possible.
>*/
>
>Thanks,
>
> Thomas
--
Sent from my mobile phone. Please excuse brevity and lack of formatting.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 5:58 ` Dave Hansen
2013-04-15 7:58 ` HATAYAMA Daisuke
@ 2013-04-15 14:49 ` H. Peter Anvin
1 sibling, 0 replies; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-15 14:49 UTC (permalink / raw)
To: Dave Hansen, HATAYAMA Daisuke
Cc: kexec@lists.infradead.org, Linux Kernel Mailing List,
Thomas Renninger, Simon Horman, Eric W. Biederman, Yinghai Lu,
Cliff Wickman, Vivek Goyal
This is also true on some x86 systems.
Dave Hansen <dave@sr71.net> wrote:
>On 04/14/2013 09:52 PM, HATAYAMA Daisuke wrote:
>> This sounds like there's no such issue on x86 cache mechanism. Is it
>> correct? If so, what is the difference between ia64 and x86 cache
>> mechanisms?
>
>I'm just going by the code comments:
>
>drivers/char/mem.c
>> /*
>> * On ia64 if a page has been mapped somewhere as
>uncached, then
>> * it must also be accessed uncached by the kernel or
>data
>> * corruption may occur.
>> */
--
Sent from my mobile phone. Please excuse brevity and lack of formatting.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 12:20 ` H. Peter Anvin
@ 2013-04-15 19:48 ` Thomas Renninger
2013-04-15 19:54 ` H. Peter Anvin
0 siblings, 1 reply; 28+ messages in thread
From: Thomas Renninger @ 2013-04-15 19:48 UTC (permalink / raw)
To: H. Peter Anvin
Cc: kexec, horms, Zhang Yanfei, Eric W. Biederman, yinghai, cpw,
vgoyal
On Monday, April 15, 2013 05:20:24 AM H. Peter Anvin wrote:
> Except that is wrong. The kernel can receive more than 128 e820 entries,
> they just have to be passed via a different mechanism.
Would it make sense to pass the tables via efi_map by moving up
efi_map parsing to the beginning of efi init in arch/x86/platform/efi/efi.c?
And in kexec pass the efi signature, efi map pointers, add add_efi_memmap
param (and possibly some more?)?
Then there would be no limit at all anymore.
Thomas
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 19:48 ` Thomas Renninger
@ 2013-04-15 19:54 ` H. Peter Anvin
2013-04-16 7:52 ` Thomas Renninger
0 siblings, 1 reply; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-15 19:54 UTC (permalink / raw)
To: Thomas Renninger
Cc: kexec, horms, Zhang Yanfei, Eric W. Biederman, yinghai, cpw,
vgoyal
On 04/15/2013 12:48 PM, Thomas Renninger wrote:
> On Monday, April 15, 2013 05:20:24 AM H. Peter Anvin wrote:
>> Except that is wrong. The kernel can receive more than 128 e820 entries,
>> they just have to be passed via a different mechanism.
>
> Would it make sense to pass the tables via efi_map by moving up
> efi_map parsing to the beginning of efi init in arch/x86/platform/efi/efi.c?
>
> And in kexec pass the efi signature, efi map pointers, add add_efi_memmap
> param (and possibly some more?)?
> Then there would be no limit at all anymore.
>
There is no limit... that's what I'm telling you.
kexec should certainly pass the EFI information, otherwise the second
kernel can't invoke EFI runtime calls at all. Therein lies a whole bit
of pain.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-15 19:54 ` H. Peter Anvin
@ 2013-04-16 7:52 ` Thomas Renninger
2013-04-16 11:59 ` H. Peter Anvin
2013-04-16 12:41 ` Zhang Yanfei
0 siblings, 2 replies; 28+ messages in thread
From: Thomas Renninger @ 2013-04-16 7:52 UTC (permalink / raw)
To: H. Peter Anvin
Cc: kexec, horms, Zhang Yanfei, Eric W. Biederman, yinghai, cpw,
vgoyal
On Monday, April 15, 2013 12:54:47 PM H. Peter Anvin wrote:
> On 04/15/2013 12:48 PM, Thomas Renninger wrote:
> > On Monday, April 15, 2013 05:20:24 AM H. Peter Anvin wrote:
> >> Except that is wrong. The kernel can receive more than 128 e820 entries,
> >> they just have to be passed via a different mechanism.
But you do not name/describe it.
Is it the "efi map mechanism" you are talking about or is there
something else?
Thomas
> > Would it make sense to pass the tables via efi_map by moving up
> > efi_map parsing to the beginning of efi init in
> > arch/x86/platform/efi/efi.c?
> >
> > And in kexec pass the efi signature, efi map pointers, add add_efi_memmap
> > param (and possibly some more?)?
> > Then there would be no limit at all anymore.
>
> There is no limit... that's what I'm telling you.
> kexec should certainly pass the EFI information, otherwise the second
> kernel can't invoke EFI runtime calls at all. Therein lies a whole bit
> of pain.
>
> -hpa
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-16 7:52 ` Thomas Renninger
@ 2013-04-16 11:59 ` H. Peter Anvin
2013-04-16 12:41 ` Zhang Yanfei
1 sibling, 0 replies; 28+ messages in thread
From: H. Peter Anvin @ 2013-04-16 11:59 UTC (permalink / raw)
To: Thomas Renninger
Cc: kexec, horms, Zhang Yanfei, Eric W. Biederman, yinghai, cpw,
vgoyal
It is not. Read the boot spec.
Thomas Renninger <trenn@suse.de> wrote:
>On Monday, April 15, 2013 12:54:47 PM H. Peter Anvin wrote:
>> On 04/15/2013 12:48 PM, Thomas Renninger wrote:
>> > On Monday, April 15, 2013 05:20:24 AM H. Peter Anvin wrote:
>> >> Except that is wrong. The kernel can receive more than 128 e820
>entries,
>> >> they just have to be passed via a different mechanism.
>
>But you do not name/describe it.
>Is it the "efi map mechanism" you are talking about or is there
>something else?
>
> Thomas
>
>> > Would it make sense to pass the tables via efi_map by moving up
>> > efi_map parsing to the beginning of efi init in
>> > arch/x86/platform/efi/efi.c?
>> >
>> > And in kexec pass the efi signature, efi map pointers, add
>add_efi_memmap
>> > param (and possibly some more?)?
>> > Then there would be no limit at all anymore.
>>
>> There is no limit... that's what I'm telling you.
>
>> kexec should certainly pass the EFI information, otherwise the second
>> kernel can't invoke EFI runtime calls at all. Therein lies a whole
>bit
>> of pain.
>>
>> -hpa
--
Sent from my mobile phone. Please excuse brevity and lack of formatting.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter
2013-04-16 7:52 ` Thomas Renninger
2013-04-16 11:59 ` H. Peter Anvin
@ 2013-04-16 12:41 ` Zhang Yanfei
1 sibling, 0 replies; 28+ messages in thread
From: Zhang Yanfei @ 2013-04-16 12:41 UTC (permalink / raw)
To: Thomas Renninger
Cc: kexec, horms, Zhang Yanfei, Eric W. Biederman, H. Peter Anvin,
yinghai, cpw, vgoyal
于 2013年04月16日 15:52, Thomas Renninger 写道:
> On Monday, April 15, 2013 12:54:47 PM H. Peter Anvin wrote:
>> On 04/15/2013 12:48 PM, Thomas Renninger wrote:
>>> On Monday, April 15, 2013 05:20:24 AM H. Peter Anvin wrote:
>>>> Except that is wrong. The kernel can receive more than 128 e820 entries,
>>>> they just have to be passed via a different mechanism.
>
> But you do not name/describe it.
> Is it the "efi map mechanism" you are talking about or is there
> something else?
Hi Thomas
I think hpa meant the mechanism related to the field setup_data in
setup_header.
Field name: setup_data
Type: write (special)
Offset/size: 0x250/8
Protocol: 2.09+
The 64-bit physical pointer to NULL terminated single linked list of
struct setup_data. This is used to define a more extensible boot
parameters passing mechanism. The definition of struct setup_data is
as follow:
struct setup_data {
u64 next;
u32 type;
u32 len;
u8 data[0];
};
Where, the next is a 64-bit physical pointer to the next node of
linked list, the next field of the last node is 0; the type is used
to identify the contents of data; the len is the length of data
field; the data holds the real payload.
This list may be modified at a number of points during the bootup
process. Therefore, when modifying this list one should always make
sure to consider the case where the linked list already contains
entries.
And Linux has the setup_data type SETUP_E820_EXT which means extended
e820 entries.
Also see kernel functions:
setup_arch
--> parse_setup_data
--> parse_e820_ext
Thanks
Zhang
>
> Thomas
>
>>> Would it make sense to pass the tables via efi_map by moving up
>>> efi_map parsing to the beginning of efi init in
>>> arch/x86/platform/efi/efi.c?
>>>
>>> And in kexec pass the efi signature, efi map pointers, add add_efi_memmap
>>> param (and possibly some more?)?
>>> Then there would be no limit at all anymore.
>>
>> There is no limit... that's what I'm telling you.
>
>> kexec should certainly pass the EFI information, otherwise the second
>> kernel can't invoke EFI runtime calls at all. Therein lies a whole bit
>> of pain.
>>
>> -hpa
>
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2013-04-16 12:41 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-11 12:26 Cleanups and passing memory ranges via e820 table instead of memmap= Thomas Renninger
2013-04-11 12:26 ` [PATCH 1/5] kexec: X86: Show e820 table which gets passed in debug mode Thomas Renninger
2013-04-11 12:26 ` [PATCH 2/5] kexec: X86: Enhance crash range debug output Thomas Renninger
2013-04-11 12:26 ` [PATCH 3/5] kexec: X86: Do not exclude memory regions in each get_xy_memory_range() func Thomas Renninger
2013-04-11 12:26 ` [PATCH 4/5] kexec: X86: make crash_memory_range global and store its no of elements in crash_ranges Thomas Renninger
2013-04-11 12:26 ` [PATCH 5/5] kexec: X86: Pass memory ranges via e820 table instead of memmap= boot parameter Thomas Renninger
2013-04-11 14:55 ` Yinghai Lu
2013-04-11 15:06 ` H. Peter Anvin
2013-04-12 14:31 ` Vivek Goyal
2013-04-12 14:56 ` H. Peter Anvin
2013-04-12 22:17 ` Dave Hansen
2013-04-12 23:17 ` H. Peter Anvin
2013-04-15 4:52 ` HATAYAMA Daisuke
2013-04-15 5:58 ` Dave Hansen
2013-04-15 7:58 ` HATAYAMA Daisuke
2013-04-15 14:49 ` H. Peter Anvin
2013-04-12 12:24 ` Thomas Renninger
2013-04-12 9:56 ` Zhang Yanfei
2013-04-12 11:12 ` Thomas Renninger
2013-04-15 9:05 ` Thomas Renninger
2013-04-15 12:20 ` H. Peter Anvin
2013-04-15 19:48 ` Thomas Renninger
2013-04-15 19:54 ` H. Peter Anvin
2013-04-16 7:52 ` Thomas Renninger
2013-04-16 11:59 ` H. Peter Anvin
2013-04-16 12:41 ` Zhang Yanfei
2013-04-12 15:24 ` Eric W. Biederman
2013-04-15 11:48 ` Thomas Renninger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox