From amwang at redhat.com  Wed Mar  2 11:10:43 2011
From: amwang at redhat.com (Amerigo Wang)
Date: Thu,  3 Mar 2011 00:10:43 +0800
Subject: [Patch] get the backup area dynamically
Message-ID: <1299082243-25716-1-git-send-email-amwang@redhat.com>

Currently we hard-coded the first 640K area as backup area,
however, this is not correct on some system which has reserved
memory area in the first 640K:

BIOS-e820: 0000000000010000 - 0000000000097000 (usable)
BIOS-e820: 0000000000097000 - 00000000000a0000 (reserved)

on such system we still mark all the first 640K as usable
in capture kernel, this will cause kernel panic.

The solution, pointed by Vivek, is that we can get the backup
area dynamically by reading /proc/iomem.

The reporter has tested this patch and it fixes the problem.

Signed-off-by: WANG Cong <amwang at redhat.com>
Cc: Vivek Goyal <vgoyal at redhat.com>

---
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 40f989a..ef4a6f6 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -200,15 +200,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 		return -1;
 	}
 
-	/* First entry is for first 640K region. Different bios report first
-	 * 640K in different manner hence hardcoding it */
-	if (!(kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
-		crash_memory_range[0].start = 0x00000000;
-		crash_memory_range[0].end = 0x0009ffff;
-		crash_memory_range[0].type = RANGE_RAM;
-		memory_ranges++;
-	}
-
 	while(fgets(line, sizeof(line), fp) != 0) {
 		char *str;
 		int type, consumed, count;
@@ -254,10 +245,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 			continue;
 		}
 
-		/* First 640K already registered */
-		if (end <= 0x0009ffff)
-			continue;
-
 		crash_memory_range[memory_ranges].start = start;
 		crash_memory_range[memory_ranges].end = end;
 		crash_memory_range[memory_ranges].type = type;
@@ -678,6 +665,49 @@ static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
 	return 0;
 }
 
+static void get_backup_area(unsigned long *start, unsigned long *end)
+{
+	const char *iomem = proc_iomem();
+	char line[MAX_LINE];
+	FILE *fp;
+
+	fp = fopen(iomem, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s: %s\n",
+			iomem, strerror(errno));
+		return;
+	}
+
+	while(fgets(line, sizeof(line), fp) != 0) {
+		char *str;
+		int count, consumed;
+		unsigned long mstart, mend;
+
+		count = sscanf(line, "%lx-%lx : %n",
+			&mstart, &mend, &consumed);
+		if (count != 2)
+			continue;
+		str = line + consumed;
+#ifdef DEBUG
+		printf("%016lx-%016lx : %s",
+			mstart, mend, str);
+#endif
+		/* Hopefully there is only one RAM region in the first 640K */
+		if (memcmp(str, "System RAM\n", 11) == 0 && mend <= 0xa0000 ) {
+#ifdef DEBUG
+			printf("%s: %016lx-%016lx : %s", __func__, mstart, mend, str);
+#endif
+			*start = mstart;
+			*end = mend;
+			fclose(fp);
+			return;
+		}
+	}
+	*start = BACKUP_SRC_START;
+	*end = BACKUP_SRC_END;
+	fclose(fp);
+}
+
 /* Loads additional segments in case of a panic kernel is being loaded.
  * One segment for backup region, another segment for storing elf headers
  * for crash memory image.
@@ -695,8 +725,10 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 
 	/* Constant parts of the elf_info */
 	elf_info.data             = ELFDATA2LSB;
-	elf_info.backup_src_start = BACKUP_SRC_START;
-	elf_info.backup_src_end   = BACKUP_SRC_END;
+	get_backup_area(&elf_info.backup_src_start, &elf_info.backup_src_end);
+	info->backup_src_start = elf_info.backup_src_start;
+	info->backup_src_size = elf_info.backup_src_end
+				- elf_info.backup_src_start + 1;
 
         /* Get the elf architecture of the running kernel */
 	if ((info->kexec_flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_X86_64) {
@@ -739,13 +771,15 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 	sz = (sizeof(struct memory_range) * (KEXEC_MAX_SEGMENTS + 1));
 	memmap_p = xmalloc(sz);
 	memset(memmap_p, 0, sz);
-	add_memmap(memmap_p, BACKUP_SRC_START, BACKUP_SRC_SIZE);
+	add_memmap(memmap_p, elf_info.backup_src_start,
+		   elf_info.backup_src_end - elf_info.backup_src_start + 1);
 	sz = crash_reserved_mem.end - crash_reserved_mem.start +1;
 	add_memmap(memmap_p, crash_reserved_mem.start, sz);
 
 	/* Create a backup region segment to store backup data*/
 	if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
-		sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
+		sz = (elf_info.backup_src_end - elf_info.backup_src_start + align)
+		     & ~(align - 1);
 		tmp = xmalloc(sz);
 		memset(tmp, 0, sz);
 		info->backup_start = add_buffer(info, tmp, sz, sz, align,
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
index c34fd92..6c42c32 100644
--- a/kexec/arch/x86_64/kexec-x86_64.c
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -157,6 +157,10 @@ void arch_update_purgatory(struct kexec_info *info)
 		&arch_options.console_vga, sizeof(arch_options.console_vga));
 	elf_rel_set_symbol(&info->rhdr, "console_serial",
 		&arch_options.console_serial, sizeof(arch_options.console_serial));
+	elf_rel_set_symbol(&info->rhdr, "backup_src_start",
+		&info->backup_src_start, sizeof(info->backup_src_start));
+	elf_rel_set_symbol(&info->rhdr, "backup_src_size",
+		&info->backup_src_size, sizeof(info->backup_src_size));
 
 	if (info->kexec_flags & KEXEC_ON_CRASH) {
 		panic_kernel = 1;
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 9a70224..9b59890 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -122,6 +122,8 @@ struct kexec_info {
 	struct mem_ehdr rhdr;
 	unsigned long backup_start;
 	unsigned long kexec_flags;
+	unsigned long backup_src_start;
+	unsigned long backup_src_size;
 };
 
 struct arch_map_entry {
diff --git a/purgatory/arch/i386/crashdump_backup.c b/purgatory/arch/i386/crashdump_backup.c
index c619446..365eb5d 100644
--- a/purgatory/arch/i386/crashdump_backup.c
+++ b/purgatory/arch/i386/crashdump_backup.c
@@ -20,13 +20,15 @@
 
 #include <stdint.h>
 #include <string.h>
-#include "../../../kexec/arch/i386/crashdump-x86.h"
 
 /* Backup region start gets set after /proc/iomem has been parsed. */
 /* We reuse the same code for x86_64 also so changing backup_start to
    unsigned long */
 unsigned long  backup_start = 0;
 
+unsigned long backup_src_start = 0;
+unsigned long backup_src_size = 0;
+
 /* Backup first 640K of memory to backup region as reserved by kexec.
  * Assuming first 640K has to be present on i386 machines and no address
  * validity checks have to be performed. */
@@ -34,11 +36,16 @@ unsigned long  backup_start = 0;
 void crashdump_backup_memory(void)
 {
 	void *dest, *src;
+	size_t size;
+
+	src = (void *) backup_src_start;
+	size = (size_t) backup_src_size;
 
-	src = (void *) BACKUP_SRC_START;
+	if (!size)
+		return;
 
 	if (backup_start) {
 		dest = (void *)(backup_start);
-		memcpy(dest, src, BACKUP_SRC_SIZE);
+		memcpy(dest, src, size);
 	}
 }


From vgoyal at redhat.com  Wed Mar  2 11:44:21 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Wed, 2 Mar 2011 11:44:21 -0500
Subject: [Patch] get the backup area dynamically
In-Reply-To: <1299082243-25716-1-git-send-email-amwang@redhat.com>
References: <1299082243-25716-1-git-send-email-amwang@redhat.com>
Message-ID: <20110302164421.GB16583@redhat.com>

On Thu, Mar 03, 2011 at 12:10:43AM +0800, Amerigo Wang wrote:
> Currently we hard-coded the first 640K area as backup area,
> however, this is not correct on some system which has reserved
> memory area in the first 640K:
> 
> BIOS-e820: 0000000000010000 - 0000000000097000 (usable)
> BIOS-e820: 0000000000097000 - 00000000000a0000 (reserved)
> 
> on such system we still mark all the first 640K as usable
> in capture kernel, this will cause kernel panic.

We recently had an issue where the BIOS area which was marked as reserved
in first kernel, and second kernel tried to use it and led to panic. The
believe is that kernel shouldn't have used that area as it is BIOS
reserved.

So we need to move away from hardcoded first 640K and instead try to
determine that area dynamically. In more generic form, which should
have the capability to have multiple backup areas or multiple ranges
in single backup area. But I think as a first step, having single
backup area is fine. 

If we run into issues where BIOS split first 640K into multiple small
"usable" pieces, then we shall have to go for more generic form.

So this approach sounds reasonable to me.

Acked-by: Vivek Goyal <vgoyal at redhat.com>

Vivek

> 
> The solution, pointed by Vivek, is that we can get the backup
> area dynamically by reading /proc/iomem.
> 
> The reporter has tested this patch and it fixes the problem.
> 
> Signed-off-by: WANG Cong <amwang at redhat.com>
> Cc: Vivek Goyal <vgoyal at redhat.com>
> 
> ---
> diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
> index 40f989a..ef4a6f6 100644
> --- a/kexec/arch/i386/crashdump-x86.c
> +++ b/kexec/arch/i386/crashdump-x86.c
> @@ -200,15 +200,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
>  		return -1;
>  	}
>  
> -	/* First entry is for first 640K region. Different bios report first
> -	 * 640K in different manner hence hardcoding it */
> -	if (!(kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
> -		crash_memory_range[0].start = 0x00000000;
> -		crash_memory_range[0].end = 0x0009ffff;
> -		crash_memory_range[0].type = RANGE_RAM;
> -		memory_ranges++;
> -	}
> -
>  	while(fgets(line, sizeof(line), fp) != 0) {
>  		char *str;
>  		int type, consumed, count;
> @@ -254,10 +245,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
>  			continue;
>  		}
>  
> -		/* First 640K already registered */
> -		if (end <= 0x0009ffff)
> -			continue;
> -
>  		crash_memory_range[memory_ranges].start = start;
>  		crash_memory_range[memory_ranges].end = end;
>  		crash_memory_range[memory_ranges].type = type;
> @@ -678,6 +665,49 @@ static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
>  	return 0;
>  }
>  
> +static void get_backup_area(unsigned long *start, unsigned long *end)
> +{
> +	const char *iomem = proc_iomem();
> +	char line[MAX_LINE];
> +	FILE *fp;
> +
> +	fp = fopen(iomem, "r");
> +	if (!fp) {
> +		fprintf(stderr, "Cannot open %s: %s\n",
> +			iomem, strerror(errno));
> +		return;
> +	}
> +
> +	while(fgets(line, sizeof(line), fp) != 0) {
> +		char *str;
> +		int count, consumed;
> +		unsigned long mstart, mend;
> +
> +		count = sscanf(line, "%lx-%lx : %n",
> +			&mstart, &mend, &consumed);
> +		if (count != 2)
> +			continue;
> +		str = line + consumed;
> +#ifdef DEBUG
> +		printf("%016lx-%016lx : %s",
> +			mstart, mend, str);
> +#endif
> +		/* Hopefully there is only one RAM region in the first 640K */
> +		if (memcmp(str, "System RAM\n", 11) == 0 && mend <= 0xa0000 ) {
> +#ifdef DEBUG
> +			printf("%s: %016lx-%016lx : %s", __func__, mstart, mend, str);
> +#endif
> +			*start = mstart;
> +			*end = mend;
> +			fclose(fp);
> +			return;
> +		}
> +	}
> +	*start = BACKUP_SRC_START;
> +	*end = BACKUP_SRC_END;
> +	fclose(fp);
> +}
> +
>  /* Loads additional segments in case of a panic kernel is being loaded.
>   * One segment for backup region, another segment for storing elf headers
>   * for crash memory image.
> @@ -695,8 +725,10 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
>  
>  	/* Constant parts of the elf_info */
>  	elf_info.data             = ELFDATA2LSB;
> -	elf_info.backup_src_start = BACKUP_SRC_START;
> -	elf_info.backup_src_end   = BACKUP_SRC_END;
> +	get_backup_area(&elf_info.backup_src_start, &elf_info.backup_src_end);
> +	info->backup_src_start = elf_info.backup_src_start;
> +	info->backup_src_size = elf_info.backup_src_end
> +				- elf_info.backup_src_start + 1;
>  
>          /* Get the elf architecture of the running kernel */
>  	if ((info->kexec_flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_X86_64) {
> @@ -739,13 +771,15 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
>  	sz = (sizeof(struct memory_range) * (KEXEC_MAX_SEGMENTS + 1));
>  	memmap_p = xmalloc(sz);
>  	memset(memmap_p, 0, sz);
> -	add_memmap(memmap_p, BACKUP_SRC_START, BACKUP_SRC_SIZE);
> +	add_memmap(memmap_p, elf_info.backup_src_start,
> +		   elf_info.backup_src_end - elf_info.backup_src_start + 1);
>  	sz = crash_reserved_mem.end - crash_reserved_mem.start +1;
>  	add_memmap(memmap_p, crash_reserved_mem.start, sz);
>  
>  	/* Create a backup region segment to store backup data*/
>  	if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
> -		sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
> +		sz = (elf_info.backup_src_end - elf_info.backup_src_start + align)
> +		     & ~(align - 1);
>  		tmp = xmalloc(sz);
>  		memset(tmp, 0, sz);
>  		info->backup_start = add_buffer(info, tmp, sz, sz, align,
> diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
> index c34fd92..6c42c32 100644
> --- a/kexec/arch/x86_64/kexec-x86_64.c
> +++ b/kexec/arch/x86_64/kexec-x86_64.c
> @@ -157,6 +157,10 @@ void arch_update_purgatory(struct kexec_info *info)
>  		&arch_options.console_vga, sizeof(arch_options.console_vga));
>  	elf_rel_set_symbol(&info->rhdr, "console_serial",
>  		&arch_options.console_serial, sizeof(arch_options.console_serial));
> +	elf_rel_set_symbol(&info->rhdr, "backup_src_start",
> +		&info->backup_src_start, sizeof(info->backup_src_start));
> +	elf_rel_set_symbol(&info->rhdr, "backup_src_size",
> +		&info->backup_src_size, sizeof(info->backup_src_size));
>  
>  	if (info->kexec_flags & KEXEC_ON_CRASH) {
>  		panic_kernel = 1;
> diff --git a/kexec/kexec.h b/kexec/kexec.h
> index 9a70224..9b59890 100644
> --- a/kexec/kexec.h
> +++ b/kexec/kexec.h
> @@ -122,6 +122,8 @@ struct kexec_info {
>  	struct mem_ehdr rhdr;
>  	unsigned long backup_start;
>  	unsigned long kexec_flags;
> +	unsigned long backup_src_start;
> +	unsigned long backup_src_size;
>  };
>  
>  struct arch_map_entry {
> diff --git a/purgatory/arch/i386/crashdump_backup.c b/purgatory/arch/i386/crashdump_backup.c
> index c619446..365eb5d 100644
> --- a/purgatory/arch/i386/crashdump_backup.c
> +++ b/purgatory/arch/i386/crashdump_backup.c
> @@ -20,13 +20,15 @@
>  
>  #include <stdint.h>
>  #include <string.h>
> -#include "../../../kexec/arch/i386/crashdump-x86.h"
>  
>  /* Backup region start gets set after /proc/iomem has been parsed. */
>  /* We reuse the same code for x86_64 also so changing backup_start to
>     unsigned long */
>  unsigned long  backup_start = 0;
>  
> +unsigned long backup_src_start = 0;
> +unsigned long backup_src_size = 0;
> +
>  /* Backup first 640K of memory to backup region as reserved by kexec.
>   * Assuming first 640K has to be present on i386 machines and no address
>   * validity checks have to be performed. */
> @@ -34,11 +36,16 @@ unsigned long  backup_start = 0;
>  void crashdump_backup_memory(void)
>  {
>  	void *dest, *src;
> +	size_t size;
> +
> +	src = (void *) backup_src_start;
> +	size = (size_t) backup_src_size;
>  
> -	src = (void *) BACKUP_SRC_START;
> +	if (!size)
> +		return;
>  
>  	if (backup_start) {
>  		dest = (void *)(backup_start);
> -		memcpy(dest, src, BACKUP_SRC_SIZE);
> +		memcpy(dest, src, size);
>  	}
>  }


From horms at verge.net.au  Wed Mar  2 17:16:58 2011
From: horms at verge.net.au (Simon Horman)
Date: Thu, 3 Mar 2011 07:16:58 +0900
Subject: [Patch] get the backup area dynamically
In-Reply-To: <20110302164421.GB16583@redhat.com>
References: <1299082243-25716-1-git-send-email-amwang@redhat.com>
	<20110302164421.GB16583@redhat.com>
Message-ID: <20110302221658.GG8193@verge.net.au>

On Wed, Mar 02, 2011 at 11:44:21AM -0500, Vivek Goyal wrote:
> On Thu, Mar 03, 2011 at 12:10:43AM +0800, Amerigo Wang wrote:
> > Currently we hard-coded the first 640K area as backup area,
> > however, this is not correct on some system which has reserved
> > memory area in the first 640K:
> > 
> > BIOS-e820: 0000000000010000 - 0000000000097000 (usable)
> > BIOS-e820: 0000000000097000 - 00000000000a0000 (reserved)
> > 
> > on such system we still mark all the first 640K as usable
> > in capture kernel, this will cause kernel panic.
> 
> We recently had an issue where the BIOS area which was marked as reserved
> in first kernel, and second kernel tried to use it and led to panic. The
> believe is that kernel shouldn't have used that area as it is BIOS
> reserved.
> 
> So we need to move away from hardcoded first 640K and instead try to
> determine that area dynamically. In more generic form, which should
> have the capability to have multiple backup areas or multiple ranges
> in single backup area. But I think as a first step, having single
> backup area is fine. 
> 
> If we run into issues where BIOS split first 640K into multiple small
> "usable" pieces, then we shall have to go for more generic form.
> 
> So this approach sounds reasonable to me.
> 
> Acked-by: Vivek Goyal <vgoyal at redhat.com>

Thanks, applied.


From horms at verge.net.au  Wed Mar  2 17:46:15 2011
From: horms at verge.net.au (Simon Horman)
Date: Thu,  3 Mar 2011 07:46:15 +0900
Subject: [PATCH 1/2] Remove bogus check for too many program headers
Message-ID: <1299105976-11360-1-git-send-email-horms@verge.net.au>

This test appears bogus because the e_phnum element of Elf32_Phdr and
is an unsigned 16bit entity.

This addresses the following warnings:

vmcore-dmesg/vmcore-dmesg.c: In function 'read_elf32':
vmcore-dmesg/vmcore-dmesg.c:116: warning: comparison is always false due to limited range of data type
vmcore-dmesg/vmcore-dmesg.c: In function ?read_elf64?:
vmcore-dmesg/vmcore-dmesg.c:192: warning: comparison is always false due to limited range of data type

Cc: Eric W. Biederman <ebiederm at xmission.com>
Signed-off-by: Simon Horman <horms at verge.net.au>
---
 vmcore-dmesg/vmcore-dmesg.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
index 7015894..365e293 100644
--- a/vmcore-dmesg/vmcore-dmesg.c
+++ b/vmcore-dmesg/vmcore-dmesg.c
@@ -113,10 +113,6 @@ static void read_elf32(int fd)
 			ehdr.e_phentsize, sizeof(Elf32_Phdr));
 		exit(12);
 	}
-	if (ehdr.e_phnum > ULONG_MAX/sizeof(Elf64_Phdr)) {
-		fprintf(stderr, "Too many elf program header entries\n");
-		exit(13);
-	}
 	phdrs32_size = ehdr.e_phnum * sizeof(Elf32_Phdr);
 	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
 	phdr32 = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr));
@@ -189,10 +185,6 @@ static void read_elf64(int fd)
 			ehdr.e_phentsize, sizeof(Elf64_Phdr));
 		exit(12);
 	}
-	if (ehdr.e_phnum > ULONG_MAX/sizeof(Elf64_Phdr)) {
-		fprintf(stderr, "Too many program header entries\n");
-		exit(13);
-	}
 	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
 	phdr64 = calloc(ehdr.e_phnum, sizeof(Elf64_Phdr));
 	if (!phdr64) {
-- 
1.7.2.3



From horms at verge.net.au  Wed Mar  2 17:46:16 2011
From: horms at verge.net.au (Simon Horman)
Date: Thu,  3 Mar 2011 07:46:16 +0900
Subject: [PATCH 2/2] Avoid signed/unsigned comparsions
In-Reply-To: <1299105976-11360-1-git-send-email-horms@verge.net.au>
References: <1299105976-11360-1-git-send-email-horms@verge.net.au>
Message-ID: <1299105976-11360-2-git-send-email-horms@verge.net.au>

Cc: Eric W. Biederman <ebiederm at xmission.com>
Signed-off-by: Simon Horman <horms at verge.net.au>
---
 vmcore-dmesg/vmcore-dmesg.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
index 365e293..f7eef16 100644
--- a/vmcore-dmesg/vmcore-dmesg.c
+++ b/vmcore-dmesg/vmcore-dmesg.c
@@ -79,8 +79,7 @@ static void read_elf32(int fd)
 {
 	Elf32_Ehdr ehdr32;
 	Elf32_Phdr *phdr32;
-	size_t phdrs32_size, phdrs_size;
-	ssize_t ret, i;
+	ssize_t phdrs32_size, phdrs_size, ret, i;
 
 	ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
 	if (ret != sizeof(ehdr32)) {
@@ -151,8 +150,7 @@ static void read_elf64(int fd)
 {
 	Elf64_Ehdr ehdr64;
 	Elf64_Phdr *phdr64;
-	size_t phdrs_size;
-	ssize_t ret, i;
+	size_t phdrs_size, ret, i;
 
 	ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
 	if (ret != sizeof(ehdr)) {
@@ -240,8 +238,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
 	};
 
 	for (pos = start; pos <= last; pos = eol + 1) {
-		size_t len;
-		int i;
+		size_t len, i;
 		/* Find the end of the current line */
 		for (eol = pos; (eol <= last) && (*eol != '\n') ; eol++)
 			;
@@ -274,8 +271,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
 static void scan_notes(int fd, loff_t start, loff_t lsize)
 {
 	char *buf, *last, *note, *next;
-	size_t size;
-	ssize_t ret;
+	ssize_t size, ret;
 
 	if (lsize > LONG_MAX) {
 		fprintf(stderr, "Unable to handle note section of %llu bytes\n",
-- 
1.7.2.3



From charles----jackson at att.net  Thu Mar  3 01:58:18 2011
From: charles----jackson at att.net (BILL GATE)
Date: Wed, 2 Mar 2011 22:58:18 -0800 (PST)
Subject: Congratulation Claim Contact Us ( microosftnat@w.cn )
Message-ID: <950185.23541.qm@web181306.mail.ne1.yahoo.com>

Congrats Your E-Mail ID has won You (?750,000GBP) Claim provide name,address
ECTS ( microosftnat at w.cn )


From ebiederm at xmission.com  Thu Mar  3 16:48:54 2011
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 03 Mar 2011 13:48:54 -0800
Subject: [PULL] x86_64 kdump fixes
Message-ID: <m1k4gfswmx.fsf@fess.ebiederm.org>


These are bug fixes that were tested several months ago and I forgot to
ask for them to be pulled.  I have tested against the latest tree and
these changes still apply and build cleanly.

git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/kexec-tools-devel.git 


Eric W. Biederman (2):
      kexec-syscall.h: Document what the architecture default arch is.
      x86 crashdump: On x86_64 generate EM_X86_64 crashdump headers.

Eric



From ebiederm at xmission.com  Thu Mar  3 16:50:09 2011
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 03 Mar 2011 13:50:09 -0800
Subject: [PATCH 1/2] Remove bogus check for too many program headers
In-Reply-To: <1299105976-11360-1-git-send-email-horms@verge.net.au> (Simon
	Horman's message of "Thu, 3 Mar 2011 07:46:15 +0900")
References: <1299105976-11360-1-git-send-email-horms@verge.net.au>
Message-ID: <m1ei6nswku.fsf@fess.ebiederm.org>

Simon Horman <horms at verge.net.au> writes:

> This test appears bogus because the e_phnum element of Elf32_Phdr and
> is an unsigned 16bit entity.

The test is a basic sanity check, that apparently can never fail.  So I
see no harm in removing it.

Reviewed-by: "Eric W. Biederman" <ebiederm at xmission.com>


> This addresses the following warnings:
>
> vmcore-dmesg/vmcore-dmesg.c: In function 'read_elf32':
> vmcore-dmesg/vmcore-dmesg.c:116: warning: comparison is always false due to limited range of data type
> vmcore-dmesg/vmcore-dmesg.c: In function ?read_elf64?:
> vmcore-dmesg/vmcore-dmesg.c:192: warning: comparison is always false due to limited range of data type
>
> Cc: Eric W. Biederman <ebiederm at xmission.com>
> Signed-off-by: Simon Horman <horms at verge.net.au>
> ---
>  vmcore-dmesg/vmcore-dmesg.c |    8 --------
>  1 files changed, 0 insertions(+), 8 deletions(-)
>
> diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
> index 7015894..365e293 100644
> --- a/vmcore-dmesg/vmcore-dmesg.c
> +++ b/vmcore-dmesg/vmcore-dmesg.c
> @@ -113,10 +113,6 @@ static void read_elf32(int fd)
>  			ehdr.e_phentsize, sizeof(Elf32_Phdr));
>  		exit(12);
>  	}
> -	if (ehdr.e_phnum > ULONG_MAX/sizeof(Elf64_Phdr)) {
> -		fprintf(stderr, "Too many elf program header entries\n");
> -		exit(13);
> -	}
>  	phdrs32_size = ehdr.e_phnum * sizeof(Elf32_Phdr);
>  	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
>  	phdr32 = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr));
> @@ -189,10 +185,6 @@ static void read_elf64(int fd)
>  			ehdr.e_phentsize, sizeof(Elf64_Phdr));
>  		exit(12);
>  	}
> -	if (ehdr.e_phnum > ULONG_MAX/sizeof(Elf64_Phdr)) {
> -		fprintf(stderr, "Too many program header entries\n");
> -		exit(13);
> -	}
>  	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
>  	phdr64 = calloc(ehdr.e_phnum, sizeof(Elf64_Phdr));
>  	if (!phdr64) {


From ebiederm at xmission.com  Thu Mar  3 16:53:33 2011
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 03 Mar 2011 13:53:33 -0800
Subject: [PATCH 2/2] Avoid signed/unsigned comparsions
In-Reply-To: <1299105976-11360-2-git-send-email-horms@verge.net.au> (Simon
	Horman's message of "Thu, 3 Mar 2011 07:46:16 +0900")
References: <1299105976-11360-1-git-send-email-horms@verge.net.au>
	<1299105976-11360-2-git-send-email-horms@verge.net.au>
Message-ID: <m162rzswf6.fsf@fess.ebiederm.org>

Simon Horman <horms at verge.net.au> writes:

At least the change of ret from ssize_t to size_t is bogus.
pread returns a ssize_t and I am comparing it against sizeof(X).  We
might as we type convert in the comparison.   That test is a necessary 
and real comparison and I don't think hiding that fact with an implicit
conversion does anything but obfuscate things.

> Cc: Eric W. Biederman <ebiederm at xmission.com>
> Signed-off-by: Simon Horman <horms at verge.net.au>
> ---
>  vmcore-dmesg/vmcore-dmesg.c |   12 ++++--------
>  1 files changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
> index 365e293..f7eef16 100644
> --- a/vmcore-dmesg/vmcore-dmesg.c
> +++ b/vmcore-dmesg/vmcore-dmesg.c
> @@ -79,8 +79,7 @@ static void read_elf32(int fd)
>  {
>  	Elf32_Ehdr ehdr32;
>  	Elf32_Phdr *phdr32;
> -	size_t phdrs32_size, phdrs_size;
> -	ssize_t ret, i;
> +	ssize_t phdrs32_size, phdrs_size, ret, i;
>  
>  	ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
>  	if (ret != sizeof(ehdr32)) {
> @@ -151,8 +150,7 @@ static void read_elf64(int fd)
>  {
>  	Elf64_Ehdr ehdr64;
>  	Elf64_Phdr *phdr64;
> -	size_t phdrs_size;
> -	ssize_t ret, i;
> +	size_t phdrs_size, ret, i;
>  
>  	ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
>  	if (ret != sizeof(ehdr)) {
> @@ -240,8 +238,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
>  	};
>  
>  	for (pos = start; pos <= last; pos = eol + 1) {
> -		size_t len;
> -		int i;
> +		size_t len, i;
>  		/* Find the end of the current line */
>  		for (eol = pos; (eol <= last) && (*eol != '\n') ; eol++)
>  			;
> @@ -274,8 +271,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
>  static void scan_notes(int fd, loff_t start, loff_t lsize)
>  {
>  	char *buf, *last, *note, *next;
> -	size_t size;
> -	ssize_t ret;
> +	ssize_t size, ret;
>  
>  	if (lsize > LONG_MAX) {
>  		fprintf(stderr, "Unable to handle note section of %llu bytes\n",


From horms at verge.net.au  Thu Mar  3 19:11:04 2011
From: horms at verge.net.au (Simon Horman)
Date: Fri, 4 Mar 2011 09:11:04 +0900
Subject: [PATCH 2/2] Avoid signed/unsigned comparsions
In-Reply-To: <m162rzswf6.fsf@fess.ebiederm.org>
References: <1299105976-11360-1-git-send-email-horms@verge.net.au>
	<1299105976-11360-2-git-send-email-horms@verge.net.au>
	<m162rzswf6.fsf@fess.ebiederm.org>
Message-ID: <20110304001104.GB15019@verge.net.au>

On Thu, Mar 03, 2011 at 01:53:33PM -0800, Eric W. Biederman wrote:
> Simon Horman <horms at verge.net.au> writes:
> 
> At least the change of ret from ssize_t to size_t is bogus.
> pread returns a ssize_t and I am comparing it against sizeof(X).  We
> might as we type convert in the comparison.   That test is a necessary 
> and real comparison and I don't think hiding that fact with an implicit
> conversion does anything but obfuscate things.

Thanks, I'll restore ret to a ssize_t.

> 
> > Cc: Eric W. Biederman <ebiederm at xmission.com>
> > Signed-off-by: Simon Horman <horms at verge.net.au>
> > ---
> >  vmcore-dmesg/vmcore-dmesg.c |   12 ++++--------
> >  1 files changed, 4 insertions(+), 8 deletions(-)
> >
> > diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
> > index 365e293..f7eef16 100644
> > --- a/vmcore-dmesg/vmcore-dmesg.c
> > +++ b/vmcore-dmesg/vmcore-dmesg.c
> > @@ -79,8 +79,7 @@ static void read_elf32(int fd)
> >  {
> >  	Elf32_Ehdr ehdr32;
> >  	Elf32_Phdr *phdr32;
> > -	size_t phdrs32_size, phdrs_size;
> > -	ssize_t ret, i;
> > +	ssize_t phdrs32_size, phdrs_size, ret, i;
> >  
> >  	ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
> >  	if (ret != sizeof(ehdr32)) {
> > @@ -151,8 +150,7 @@ static void read_elf64(int fd)
> >  {
> >  	Elf64_Ehdr ehdr64;
> >  	Elf64_Phdr *phdr64;
> > -	size_t phdrs_size;
> > -	ssize_t ret, i;
> > +	size_t phdrs_size, ret, i;
> >  
> >  	ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
> >  	if (ret != sizeof(ehdr)) {
> > @@ -240,8 +238,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
> >  	};
> >  
> >  	for (pos = start; pos <= last; pos = eol + 1) {
> > -		size_t len;
> > -		int i;
> > +		size_t len, i;
> >  		/* Find the end of the current line */
> >  		for (eol = pos; (eol <= last) && (*eol != '\n') ; eol++)
> >  			;
> > @@ -274,8 +271,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
> >  static void scan_notes(int fd, loff_t start, loff_t lsize)
> >  {
> >  	char *buf, *last, *note, *next;
> > -	size_t size;
> > -	ssize_t ret;
> > +	ssize_t size, ret;
> >  
> >  	if (lsize > LONG_MAX) {
> >  		fprintf(stderr, "Unable to handle note section of %llu bytes\n",
> 


From horms at verge.net.au  Thu Mar  3 19:11:27 2011
From: horms at verge.net.au (Simon Horman)
Date: Fri, 4 Mar 2011 09:11:27 +0900
Subject: [PATCH 1/2] Remove bogus check for too many program headers
In-Reply-To: <m1ei6nswku.fsf@fess.ebiederm.org>
References: <1299105976-11360-1-git-send-email-horms@verge.net.au>
	<m1ei6nswku.fsf@fess.ebiederm.org>
Message-ID: <20110304001127.GC15019@verge.net.au>

On Thu, Mar 03, 2011 at 01:50:09PM -0800, Eric W. Biederman wrote:
> Simon Horman <horms at verge.net.au> writes:
> 
> > This test appears bogus because the e_phnum element of Elf32_Phdr and
> > is an unsigned 16bit entity.
> 
> The test is a basic sanity check, that apparently can never fail.  So I
> see no harm in removing it.

Thanks, I will push this change.

> Reviewed-by: "Eric W. Biederman" <ebiederm at xmission.com>
> 
> 
> > This addresses the following warnings:
> >
> > vmcore-dmesg/vmcore-dmesg.c: In function 'read_elf32':
> > vmcore-dmesg/vmcore-dmesg.c:116: warning: comparison is always false due to limited range of data type
> > vmcore-dmesg/vmcore-dmesg.c: In function ?read_elf64?:
> > vmcore-dmesg/vmcore-dmesg.c:192: warning: comparison is always false due to limited range of data type
> >
> > Cc: Eric W. Biederman <ebiederm at xmission.com>
> > Signed-off-by: Simon Horman <horms at verge.net.au>
> > ---
> >  vmcore-dmesg/vmcore-dmesg.c |    8 --------
> >  1 files changed, 0 insertions(+), 8 deletions(-)
> >
> > diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
> > index 7015894..365e293 100644
> > --- a/vmcore-dmesg/vmcore-dmesg.c
> > +++ b/vmcore-dmesg/vmcore-dmesg.c
> > @@ -113,10 +113,6 @@ static void read_elf32(int fd)
> >  			ehdr.e_phentsize, sizeof(Elf32_Phdr));
> >  		exit(12);
> >  	}
> > -	if (ehdr.e_phnum > ULONG_MAX/sizeof(Elf64_Phdr)) {
> > -		fprintf(stderr, "Too many elf program header entries\n");
> > -		exit(13);
> > -	}
> >  	phdrs32_size = ehdr.e_phnum * sizeof(Elf32_Phdr);
> >  	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
> >  	phdr32 = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr));
> > @@ -189,10 +185,6 @@ static void read_elf64(int fd)
> >  			ehdr.e_phentsize, sizeof(Elf64_Phdr));
> >  		exit(12);
> >  	}
> > -	if (ehdr.e_phnum > ULONG_MAX/sizeof(Elf64_Phdr)) {
> > -		fprintf(stderr, "Too many program header entries\n");
> > -		exit(13);
> > -	}
> >  	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
> >  	phdr64 = calloc(ehdr.e_phnum, sizeof(Elf64_Phdr));
> >  	if (!phdr64) {
> 


From horms at verge.net.au  Thu Mar  3 19:20:03 2011
From: horms at verge.net.au (Simon Horman)
Date: Fri, 4 Mar 2011 09:20:03 +0900
Subject: [PULL] x86_64 kdump fixes
In-Reply-To: <m1k4gfswmx.fsf@fess.ebiederm.org>
References: <m1k4gfswmx.fsf@fess.ebiederm.org>
Message-ID: <20110304002003.GH15019@verge.net.au>

On Thu, Mar 03, 2011 at 01:48:54PM -0800, Eric W. Biederman wrote:
> 
> These are bug fixes that were tested several months ago and I forgot to
> ask for them to be pulled.  I have tested against the latest tree and
> these changes still apply and build cleanly.
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/kexec-tools-devel.git 
> 
> 
> Eric W. Biederman (2):
>       kexec-syscall.h: Document what the architecture default arch is.
>       x86 crashdump: On x86_64 generate EM_X86_64 crashdump headers.

Thanks, applied.


From mahesh at linux.vnet.ibm.com  Wed Mar  9 01:32:06 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Wed, 09 Mar 2011 12:02:06 +0530
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <m139u37cii.fsf@fess.ebiederm.org>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
Message-ID: <4D771EE6.5050404@linux.vnet.ibm.com>

On 08/25/2010 06:07 AM, Eric W. Biederman wrote:
> Anton Blanchard <anton at samba.org> writes:
> 
>> On ppc64 the crashkernel region almost always overlaps an area of firmware.
>> This works fine except when using the sysfs interface to reduce the kdump
>> region. If we free the firmware area we are guaranteed to crash.
> 
> That is ppc64 bug.  firmware should not be in the reserved region.  Any
> random kernel like thing can be put in to that region at any valid
> address and the fact that shrinking the region frees your firmware means
> that using that region could also stomp your firmware (which I assume
> would be a bad thing).
The issue only happens while shrinking the region using sysfs interface.
We already have checks in kexec for not to stomp over on the firmware
overlap area while loading capture kernel. Currently we do a top-down
allocation for the firmware region which means it sits at the top of the
RMO, right in the middle of the crashdump region. We can not move the
crashkernel region beyond firmware region because kernel needs its some
of memory in RMO region.
> 
> So please fix the ppc64 reservation.
> 
> Eric
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev



From liberad.media at gmail.com  Wed Mar  9 06:16:13 2011
From: liberad.media at gmail.com (Programme LiberAD)
Date: 9 Mar 2011 11:16:13 -0000
Subject: Votre demande de désinscription au programme LiberAD
Message-ID: <20110309111613.16129.qmail@ks300910.kimsufi.com>


Bonjour,

Nous vous confirmons que nous avons enregistr? votre demande de d?sinscription pour l'adresse kexec at lists.infradead.org
Vous ne recevrez donc plus de messages promotionnels de la part du programme LiberAD ? cette adresse.
VEUILLEZ NOTER QUE LE DELAI DE PRISE EN COMPTE PAR NOTRE PRESTATAIRE D'ENVOI D'EMAIL PEUT PRENDRE JUSQU'A 48H.

Cordialement,
LiberAD Media

Important: vous ?tes peut-?tre inscrits ? d'autres newsletters sans rapport avec le Programme LiberAD. Dans ce cas, veuillez noter que la r?ception de messages de leurs parts ne rel?ve pas de la responsabilit? du Programme LiberAD



From centralmarques at gmail.com  Wed Mar  9 05:32:13 2011
From: centralmarques at gmail.com (Central-Marques)
Date: 9 Mar 2011 10:32:13 -0000
Subject: Désinscription de la mailing-list de Central-Marques
Message-ID: <20110309103213.15681.qmail@ks367486.kimsufi.com>


Bonjour,

Votre demande de d?sinscription pour kexec at lists.infradead.org a bien ?t? enregistr?e et sera effective sous 48h maximum.

Cordialement,
Central-Marques




From mahesh at linux.vnet.ibm.com  Wed Mar  9 07:15:48 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Wed, 09 Mar 2011 17:45:48 +0530
Subject: [PATCH] makedumpfile: Copy correct nr_cpus info to dumpfile during
	re-filtering
Message-ID: <20110309121506.13403.73845.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

During re-filtering nr_cpus is to 0 in the o/p dumpfile and hence crash
utility fails to open the re-filtered dumpfile.

This patch fixes this issue by copying nr_cpus info from kdump-compressed
dumpfile to info->nr_cpus which then get's correctly copied to o/p
dumpfile.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---

 makedumpfile.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index a0fad6a..7d0c663 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -924,6 +924,7 @@ get_kdump_compressed_header_info(char *filename)
 		goto error;
 	}
 	memcpy(info->kh_memory, &kh, sizeof(kh));
+	info->nr_cpus = dh.nr_cpus;
 
 	if (dh.header_version >= 3) {
 		/* A dumpfile contains vmcoreinfo data. */



From xiyou.wangcong at gmail.com  Wed Mar  9 07:20:46 2011
From: xiyou.wangcong at gmail.com (=?utf-8?Q?Am=C3=A9rico?= Wang)
Date: Wed, 9 Mar 2011 20:20:46 +0800
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <4D771EE6.5050404@linux.vnet.ibm.com>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
Message-ID: <20110309122046.GC16951@cr0.redhat.com>

On Wed, Mar 09, 2011 at 12:02:06PM +0530, Mahesh Jagannath Salgaonkar wrote:
>On 08/25/2010 06:07 AM, Eric W. Biederman wrote:
>> Anton Blanchard <anton at samba.org> writes:
>> 
>>> On ppc64 the crashkernel region almost always overlaps an area of firmware.
>>> This works fine except when using the sysfs interface to reduce the kdump
>>> region. If we free the firmware area we are guaranteed to crash.
>> 
>> That is ppc64 bug.  firmware should not be in the reserved region.  Any
>> random kernel like thing can be put in to that region at any valid
>> address and the fact that shrinking the region frees your firmware means
>> that using that region could also stomp your firmware (which I assume
>> would be a bad thing).
>The issue only happens while shrinking the region using sysfs interface.
>We already have checks in kexec for not to stomp over on the firmware
>overlap area while loading capture kernel. Currently we do a top-down
>allocation for the firmware region which means it sits at the top of the
>RMO, right in the middle of the crashdump region. We can not move the
>crashkernel region beyond firmware region because kernel needs its some
>of memory in RMO region.

The crashkernel region is specified via kernel cmdline, so why
not just drop a failure when it overlaps with RMO region?
Am I missing something?

Thanks.


From anton at samba.org  Wed Mar  9 07:46:57 2011
From: anton at samba.org (Anton Blanchard)
Date: Wed, 9 Mar 2011 23:46:57 +1100
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <20110309122046.GC16951@cr0.redhat.com>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
	<20110309122046.GC16951@cr0.redhat.com>
Message-ID: <20110309234657.264d3080@kryten>


Hi,

> The crashkernel region is specified via kernel cmdline, so why
> not just drop a failure when it overlaps with RMO region?
> Am I missing something?

Unfortunately a ppc64 kernel requires a chunk of RMO memory. We would
need the ability to specify multiple crashkernel regions - about 32MB
in the RMO and the rest can be anywhere. That sounds pretty fragile for
a user to configure successfully on the cmdline.

Thats why the ppc64 crashkernel region begins mid way through the RMO
region. It means both kernels get a chunk of RMO and we only have to
deal with one crashkernel reservation in all the tools and
documentation.

Anton


From xiyou.wangcong at gmail.com  Wed Mar  9 09:21:08 2011
From: xiyou.wangcong at gmail.com (=?utf-8?Q?Am=C3=A9rico?= Wang)
Date: Wed, 9 Mar 2011 22:21:08 +0800
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <20110309234657.264d3080@kryten>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
	<20110309122046.GC16951@cr0.redhat.com>
	<20110309234657.264d3080@kryten>
Message-ID: <20110309142108.GD16951@cr0.redhat.com>

On Wed, Mar 09, 2011 at 11:46:57PM +1100, Anton Blanchard wrote:
>
>Hi,
>
>> The crashkernel region is specified via kernel cmdline, so why
>> not just drop a failure when it overlaps with RMO region?
>> Am I missing something?
>
>Unfortunately a ppc64 kernel requires a chunk of RMO memory. We would
>need the ability to specify multiple crashkernel regions - about 32MB
>in the RMO and the rest can be anywhere. That sounds pretty fragile for
>a user to configure successfully on the cmdline.
>
>Thats why the ppc64 crashkernel region begins mid way through the RMO
>region. It means both kernels get a chunk of RMO and we only have to
>deal with one crashkernel reservation in all the tools and
>documentation.
>

So, when I specify 128M in cmdline, 32M of them are RMO, and the
rest 96M are normal memory? And when I want to free all of them,
actually the 32M RMO will never be freed?



From oomichi at mxs.nes.nec.co.jp  Fri Mar 11 00:29:22 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 11 Mar 2011 14:29:22 +0900
Subject: [PATCH] makedumpfile: Copy correct nr_cpus info to dumpfile
	during re-filtering
In-Reply-To: <20110309121506.13403.73845.stgit@mars.in.ibm.com>
References: <20110309121506.13403.73845.stgit@mars.in.ibm.com>
Message-ID: <20110311142922.b60b80e7.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

Nice catching!
Your patch has been merged to mainline:
http://makedumpfile.git.sourceforge.net/git/gitweb.cgi?p=makedumpfile/makedumpfile;a=summary

Thank you very much.


Thanks
Ken'ichi Ohmichi

On Wed, 09 Mar 2011 17:45:48 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>
> From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> 
> During re-filtering nr_cpus is to 0 in the o/p dumpfile and hence crash
> utility fails to open the re-filtered dumpfile.
> 
> This patch fixes this issue by copying nr_cpus info from kdump-compressed
> dumpfile to info->nr_cpus which then get's correctly copied to o/p
> dumpfile.
> 
> Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> ---
> 
>  makedumpfile.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index a0fad6a..7d0c663 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -924,6 +924,7 @@ get_kdump_compressed_header_info(char *filename)
>  		goto error;
>  	}
>  	memcpy(info->kh_memory, &kh, sizeof(kh));
> +	info->nr_cpus = dh.nr_cpus;
>  
>  	if (dh.header_version >= 3) {
>  		/* A dumpfile contains vmcoreinfo data. */
> 



From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:04:32 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:34:32 +0530
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter out
	kernel data from vmcore
Message-ID: <20110311075647.14587.50626.stgit@mars.in.ibm.com>

Hi All,

Please find the makedumpfile enhancement patchset that introduces a data
filtering feature which enables makedumpfile to filter out desired kernel
symbol data and it's members from the specified VMCORE file. The data to be
filtered out is poisoned with character 'X' (58 in Hex).

This feature will be very useful for the customers who wants to erase the
customer sensitive data like security keys and other confidential data, in
DUMPFILE before sending it to support team for analysis.

This feature introduces a filter config file where, using filter commands,
user can specify desired kernel data symbols and it's members that need to be
filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
provided in the filter.conf(8) man page.

The first 4 patches prepares the base work for filtering framework. The last 2
patches implements the generic filtering framework to erase desired kernel
data.

I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
kernel. The feature supports filtering data from ELF as well as
kdump-compressed formatted dump.

Please review the patchset and let me know your comments.

Thanks,
-Mahesh.

---

Mahesh Salgaonkar (6):
      makedumpfile: Add '--config' option to specify filter config file.
      makedumpfile: Apply relocation while loading module debuginfo.
      makedumpfile: Load the module symbol data from vmcore.
      makedumpfile: Introduce routines to get type name from debuginfo.
      makedumpfile: Read and process filter commands from config file.
      makedumpfile: Read and process 'for' command from config file.


 Makefile       |    8 
 filter.conf    |  149 ++++
 filter.conf.8  |  419 +++++++++++
 makedumpfile.8 |   20 +
 makedumpfile.c | 2113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 makedumpfile.h |  152 ++++
 6 files changed, 2782 insertions(+), 79 deletions(-)
 create mode 100644 filter.conf
 create mode 100644 filter.conf.8

-- 
Signature


From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:04:45 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:34:45 +0530
Subject: [PATCH v1 1/6] makedumpfile: Add '--config' option to specify filter
	config file.
Message-ID: <20110311080438.14587.57652.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

This patch adds '--config' option to specify config file that contains filter
commands to filter out desired kernel data and it's members.

Updated makedumpfile man page with '--config' option info.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---

 makedumpfile.8 |   20 +++++++++++++++++++-
 makedumpfile.c |   17 +++++++++++++++++
 makedumpfile.h |    7 +++++++
 3 files changed, 43 insertions(+), 1 deletions(-)

diff --git a/makedumpfile.8 b/makedumpfile.8
index 4a0271d..a1aaa3e 100644
--- a/makedumpfile.8
+++ b/makedumpfile.8
@@ -6,6 +6,8 @@ makedumpfile \- make a small dumpfile of kdump
 .br
 \fBmakedumpfile\fR \-F [\fIOPTION\fR] [\-x \fIVMLINUX\fR|\-i \fIVMCOREINFO\fR] \fIVMCORE\fR
 .br
+\fBmakedumpfile\fR   [\fIOPTION\fR] \-x \fIVMLINUX\fR \-\-config \fIFILTERCONFIGFILE\fR \fIVMCORE\fR \fIDUMPFILE\fR
+.br
 \fBmakedumpfile\fR \-R \fIDUMPFILE\fR
 .br
 \fBmakedumpfile\fR \-\-split [\fIOPTION\fR] [\-x \fIVMLINUX\fR|\-i \fIVMCOREINFO\fR] \fIVMCORE\fR \fIDUMPFILE1\fR \fIDUMPFILE2\fR [\fIDUMPFILE3\fR ..]
@@ -55,6 +57,15 @@ compression support. The ELF format is readable with GDB and the crash utility.
 If a user wants to use GDB, \fIDUMPFILE\fR format has to be explicitly
 specified to be the ELF format.
 .PP
+Apart from the exclusion of unnecessary pages mentioned above, makedumpfile
+allows user to filter out targeted kernel data. The filter config file can
+be used to specify kernel/module symbols and its members that need to be
+filtered out through the erase command syntax. makedumpfile reads the filter
+config and builds the list of memory addresses and its sizes after processing
+filter commands. The memory locations that require to be filtered out are
+then poisoned with character 'X' (58 in Hex). Refer to \fBfilter.conf(8)\fR
+for file format.
+.PP
 To analyze the first kernel's memory usage, makedumpfile can refer to
 \fIVMCOREINFO\fR instead of \fIVMLINUX\fR. \fIVMCOREINFO\fR contains the first
 kernel's information (structure size, field offset, etc.), and \fIVMCOREINFO\fR
@@ -232,6 +243,13 @@ specified.
 # makedumpfile \-g vmcoreinfo \-x vmlinux
 
 .TP
+\fB\-\-config\fR \fIFILTERCONFIGFILE\fR
+Used in conjunction with \-x \fIVMLINUX\fR option, to specify the filter
+config file \fIFILTERCONFIGFILE\fR that contains erase commands to filter out
+desired kernel data from vmcore while creating \fIDUMPFILE\fR. For filter
+command syntax please refer to \fBfilter.conf(8)\fR.
+
+.TP
 \fB\-F\fR
 Output the dump data in the flattened format to the standard output for
 transporting the dump data by SSH.
@@ -482,5 +500,5 @@ Written by Masaki Tachibana, and Ken'ichi Ohmichi.
 
 .SH SEE ALSO
 .PP
-crash(8), gdb(1), kexec(8)
+crash(8), gdb(1), kexec(8), filter.conf(8)
 
diff --git a/makedumpfile.c b/makedumpfile.c
index 7d0c663..f136eba 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -636,6 +636,11 @@ print_usage(void)
 	MSG("  Creating DUMPFILE:\n");
 	MSG("  # makedumpfile    [-c|-E] [-d DL] [-x VMLINUX|-i VMCOREINFO] VMCORE DUMPFILE\n");
 	MSG("\n");
+	MSG("  Creating DUMPFILE with filtered kernel data specified through filter config\n");
+	MSG("  file:\n");
+	MSG("  # makedumpfile    [-c|-E] [-d DL] -x VMLINUX --config FILTERCONFIGFILE VMCORE\n");
+	MSG("    DUMPFILE\n");
+	MSG("\n");
 	MSG("  Outputting the dump data in the flattened format to the standard output:\n");
 	MSG("  # makedumpfile -F [-c|-E] [-d DL] [-x VMLINUX|-i VMCOREINFO] VMCORE\n");
 	MSG("\n");
@@ -714,6 +719,11 @@ print_usage(void)
 	MSG("      other system that is running the same first kernel. [-x VMLINUX] must\n");
 	MSG("      be specified.\n");
 	MSG("\n");
+	MSG("  [--config FILTERCONFIGFILE]:\n");
+	MSG("      Used in conjunction with -x VMLINUX option, to specify the filter config\n");
+	MSG("      file that contains filter commands to filter out desired kernel data\n");
+	MSG("      from vmcore while creating DUMPFILE.\n");
+	MSG("\n");
 	MSG("  [-F]:\n");
 	MSG("      Output the dump data in the flattened format to the standard output\n");
 	MSG("      for transporting the dump data by SSH.\n");
@@ -7729,6 +7739,9 @@ check_param_for_creating_dumpfile(int argc, char *argv[])
 	if (info->flag_flatten && info->flag_split)
 		return FALSE;
 
+	if (info->name_filterconfig && !info->name_vmlinux)
+		return FALSE;
+
 	if ((argc == optind + 2) && !info->flag_flatten
 				 && !info->flag_split) {
 		/*
@@ -7821,6 +7834,7 @@ static struct option longopts[] = {
 	{"message-level", required_argument, NULL, 'm'},
 	{"vtop", required_argument, NULL, 'V'},
 	{"dump-dmesg", no_argument, NULL, 'M'}, 
+	{"config", required_argument, NULL, 'C'},
 	{"help", no_argument, NULL, 'h'},
 	{0, 0, 0, 0}
 };
@@ -7851,6 +7865,9 @@ main(int argc, char *argv[])
 		case 'b':
 			info->block_order = atoi(optarg);
 			break;
+		case 'C':
+			info->name_filterconfig = optarg;
+			break;
 		case 'c':
 			info->flag_compress = 1;
 			break;
diff --git a/makedumpfile.h b/makedumpfile.h
index 11e1a93..342e419 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -888,6 +888,13 @@ struct DumpInfo {
 	unsigned long	vmemmap_end;
 
 	/*
+	 * Filter config file containing filter commands to filter out kernel
+	 * data from vmcore.
+	 */
+	char		*name_filterconfig;
+	FILE		*file_filterconfig;
+
+	/*
 	 * diskdimp info:
 	 */
 	int		block_order;



From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:04:53 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:34:53 +0530
Subject: [PATCH v1 2/6] makedumpfile: Apply relocation while loading module
	debuginfo.
Message-ID: <20110311080450.14587.57458.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

So far makedumpfile implementation does not have to deal with module
debuginfo files. In order to support filtering of kernel module data,
it needs to read dwarf information from module debuginfo files. The linux
kernel module debuginfo are of ET_REL type and requires relocation to be
applied in order to get the dwarf information.

This patch uses dwfl_* API's to make the code relocation-aware while
loading module debuginfo files. It also uses dwfl_* API to search module
debuginfo files installed under default debuginfo path.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---

 makedumpfile.c |  261 +++++++++++++++++++++++++++++++++++++++++++++-----------
 makedumpfile.h |    7 ++
 2 files changed, 216 insertions(+), 52 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index f136eba..2274b18 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1372,6 +1372,146 @@ get_elf_info(void)
 	return TRUE;
 }
 
+static int
+process_module (Dwfl_Module *dwflmod,
+		void **userdata __attribute__ ((unused)),
+		const char *name __attribute__ ((unused)),
+		Dwarf_Addr base __attribute__ ((unused)),
+		void *arg)
+{
+	const char *fname, *mod_name, *debugfile;
+	Dwarf_Addr dwbias;
+
+	/* get a debug context descriptor.*/
+	dwarf_info.dwarfd = dwfl_module_getdwarf (dwflmod, &dwbias);
+	dwarf_info.elfd = dwarf_getelf(dwarf_info.dwarfd);
+
+	mod_name = dwfl_module_info(dwflmod, NULL, NULL, NULL, NULL, NULL,
+							&fname, &debugfile);
+
+	if (!strcmp(dwarf_info.module_name, mod_name) &&
+		!dwarf_info.name_debuginfo && debugfile) {
+		/*
+		 * Store the debuginfo filename. Next time we will
+		 * open debuginfo file direclty instead of searching
+		 * for it again.
+		 */
+		dwarf_info.name_debuginfo = strdup(debugfile);
+	}
+
+	return DWARF_CB_OK;
+}
+
+static int
+dwfl_report_module_p(const char *modname, const char *filename)
+{
+	if (filename && !strcmp(modname, dwarf_info.module_name))
+		return 1;
+	return 0;
+}
+
+static void
+clean_dwfl_info(void)
+{
+	if (dwarf_info.dwfl)
+		dwfl_end(dwarf_info.dwfl);
+
+	dwarf_info.dwfl = NULL;
+	dwarf_info.dwarfd = NULL;
+	dwarf_info.elfd = NULL;
+}
+
+/*
+ * Intitialize the dwarf info.
+ * Linux kernel module debuginfo are of ET_REL (relocatable) type. The old
+ * implementation of get_debug_info() function that reads the debuginfo was
+ * not relocation-aware and hence could not read the dwarf info properly
+ * from module debuginfo.
+ *
+ * This function uses dwfl API's to apply relocation before reading the
+ * dwarf information from module debuginfo.
+ * On success, this function sets the dwarf_info.elfd and dwarf_info.dwarfd
+ * after applying relocation to module debuginfo.
+ */
+static int
+init_dwarf_info(void)
+{
+	Dwfl *dwfl = NULL;
+	int dwfl_fd = -1;
+	static char *debuginfo_path = DEFAULT_DEBUGINFO_PATH;
+	static const Dwfl_Callbacks callbacks = {
+		.section_address = dwfl_offline_section_address,
+		.find_debuginfo = dwfl_standard_find_debuginfo,
+		.debuginfo_path = &debuginfo_path,
+	};
+
+	dwarf_info.elfd = NULL;
+	dwarf_info.dwarfd = NULL;
+
+	if ((dwfl = dwfl_begin(&callbacks)) == NULL) {
+		ERRMSG("Can't create a handle for a new dwfl session.\n");
+		return FALSE;
+	}
+
+	if (dwarf_info.name_debuginfo) {
+		/* We have absolute path for debuginfo file, use it directly
+		 * instead of searching it through
+		 * dwfl_linux_kernel_report_offline() call.
+		 *
+		 * Open the debuginfo file if it is not already open.
+		 */
+		if (dwarf_info.fd_debuginfo < 0)
+			dwarf_info.fd_debuginfo =
+				open(dwarf_info.name_debuginfo, O_RDONLY);
+
+		dwfl_fd = dup(dwarf_info.fd_debuginfo);
+		if (dwfl_fd < 0) {
+			ERRMSG("Failed to get a duplicate handle for"
+				" debuginfo.\n");
+			goto err_out;
+		}
+	}
+	if (dwarf_info.fd_debuginfo > 0) {
+		if (dwfl_report_offline(dwfl, dwarf_info.module_name,
+				dwarf_info.name_debuginfo, dwfl_fd) == NULL) {
+			ERRMSG("Failed reading %s: %s\n",
+				dwarf_info.name_debuginfo, dwfl_errmsg (-1));
+			/* dwfl_fd is consumed on success, not on failure */
+			close(dwfl_fd);
+			goto err_out;
+		}
+	}
+	else if (dwfl_linux_kernel_report_offline(dwfl,
+						info->system_utsname.release,
+						&dwfl_report_module_p)) {
+		ERRMSG("Can't get Module debuginfo for module '%s'\n",
+					dwarf_info.module_name);
+		goto err_out;
+	}
+	dwfl_report_end(dwfl, NULL, NULL);
+
+	dwfl_getmodules(dwfl, &process_module, NULL, 0);
+
+	if (dwarf_info.elfd == NULL) {
+		ERRMSG("Can't get first elf header of %s.\n",
+		    dwarf_info.name_debuginfo);
+		goto err_out;
+	}
+
+	if (dwarf_info.dwarfd == NULL) {
+		ERRMSG("Can't get debug context descriptor for %s.\n",
+		    dwarf_info.name_debuginfo);
+		goto err_out;
+	}
+	dwarf_info.dwfl = dwfl;
+	return TRUE;
+err_out:
+	if (dwfl)
+		dwfl_end(dwfl);
+
+	return FALSE;
+}
+
 unsigned long long
 get_symbol_addr(char *symname)
 {
@@ -1383,18 +1523,12 @@ get_symbol_addr(char *symname)
 	Elf_Data *data = NULL;
 	Elf_Scn *scn = NULL;
 	char *sym_name = NULL;
-	const off_t failed = (off_t)-1;
 
-	if (lseek(dwarf_info.fd_debuginfo, 0, SEEK_SET) == failed) {
-		ERRMSG("Can't seek the kernel file(%s). %s\n",
-		    dwarf_info.name_debuginfo, strerror(errno));
-		return NOT_FOUND_SYMBOL;
-	}
-	if (!(elfd = elf_begin(dwarf_info.fd_debuginfo, ELF_C_READ, NULL))) {
-		ERRMSG("Can't get first elf header of %s.\n",
-		    dwarf_info.name_debuginfo);
-		return NOT_FOUND_SYMBOL;
-	}
+	if (!init_dwarf_info())
+		return 0;
+
+	elfd = dwarf_info.elfd;
+
 	while ((scn = elf_nextscn(elfd, scn)) != NULL) {
 		if (gelf_getshdr(scn, &shdr) == NULL) {
 			ERRMSG("Can't get section header.\n");
@@ -1431,8 +1565,7 @@ get_symbol_addr(char *symname)
 		}
 	}
 out:
-	if (elfd != NULL)
-		elf_end(elfd);
+	clean_dwfl_info();
 
 	return symbol;
 }
@@ -1449,18 +1582,12 @@ get_next_symbol_addr(char *symname)
 	Elf_Data *data = NULL;
 	Elf_Scn *scn = NULL;
 	char *sym_name = NULL;
-	const off_t failed = (off_t)-1;
 
-	if (lseek(dwarf_info.fd_debuginfo, 0, SEEK_SET) == failed) {
-		ERRMSG("Can't seek the kernel file(%s). %s\n",
-		    dwarf_info.name_debuginfo, strerror(errno));
-		return NOT_FOUND_SYMBOL;
-	}
-	if (!(elfd = elf_begin(dwarf_info.fd_debuginfo, ELF_C_READ, NULL))) {
-		ERRMSG("Can't get first elf header of %s.\n",
-		    dwarf_info.name_debuginfo);
-		return NOT_FOUND_SYMBOL;
-	}
+	if (!init_dwarf_info())
+		return 0;
+
+	elfd = dwarf_info.elfd;
+
 	while ((scn = elf_nextscn(elfd, scn)) != NULL) {
 		if (gelf_getshdr(scn, &shdr) == NULL) {
 			ERRMSG("Can't get section header.\n");
@@ -1522,8 +1649,7 @@ get_next_symbol_addr(char *symname)
 		}
 	}
 out:
-	if (elfd != NULL)
-		elf_end(elfd);
+	clean_dwfl_info();
 
 	return next_symbol;
 }
@@ -2034,24 +2160,15 @@ get_debug_info(void)
 	Elf_Scn *scn = NULL;
 	GElf_Shdr scnhdr_mem, *scnhdr = NULL;
 	Dwarf_Die cu_die;
-	const off_t failed = (off_t)-1;
 
 	int ret = FALSE;
 
-	if (lseek(dwarf_info.fd_debuginfo, 0, SEEK_SET) == failed) {
-		ERRMSG("Can't seek the kernel file(%s). %s\n",
-		    dwarf_info.name_debuginfo, strerror(errno));
-		return FALSE;
-	}
-	if (!(elfd = elf_begin(dwarf_info.fd_debuginfo, ELF_C_READ_MMAP, NULL))) {
-		ERRMSG("Can't get first elf header of %s.\n",
-		    dwarf_info.name_debuginfo);
+	if (!init_dwarf_info())
 		return FALSE;
-	}
-	if (!(dwarfd = dwarf_begin_elf(elfd, DWARF_C_READ, NULL))) {
-		ERRMSG("Can't create a handle for a new debug session.\n");
-		goto out;
-	}
+
+	elfd = dwarf_info.elfd;
+	dwarfd = dwarf_info.dwarfd;
+
 	if (elf_getshstrndx(elfd, &shstrndx) < 0) {
 		ERRMSG("Can't get the section index of the string table.\n");
 		goto out;
@@ -2088,10 +2205,7 @@ get_debug_info(void)
 	}
 	ret = TRUE;
 out:
-	if (dwarfd != NULL)
-		dwarf_end(dwarfd);
-	if (elfd != NULL)
-		elf_end(elfd);
+	clean_dwfl_info();
 
 	return ret;
 }
@@ -2448,14 +2562,58 @@ get_mem_type(void)
 	return ret;
 }
 
+/*
+ * Set the dwarf_info with kernel/module debuginfo file information.
+ */
+int
+set_dwarf_debuginfo(char *mod_name, char *name_debuginfo, int fd_debuginfo)
+{
+	if (!mod_name)
+		return FALSE;
+	if (dwarf_info.module_name && !strcmp(dwarf_info.module_name, mod_name))
+		return TRUE;
+
+	/* Switching to different module.
+	 *
+	 * Close the file descriptor if previous module is != kernel and
+	 * xen-syms. The reason is, vmlinux file will always be supplied
+	 * by user and code to open/close kernel debuginfo file already
+	 * in place. The module debuginfo files are opened only if '--config'
+	 * option is used. This helps not to break the existing functionlity
+	 * if called without '--config' option.
+	 */
+
+	if (dwarf_info.module_name
+			&& strcmp(dwarf_info.module_name, "vmlinux")
+			&& strcmp(dwarf_info.module_name, "xen-syms")) {
+		if (dwarf_info.fd_debuginfo > 0)
+			close(dwarf_info.fd_debuginfo);
+		if (dwarf_info.name_debuginfo)
+			free(dwarf_info.name_debuginfo);
+	}
+	dwarf_info.fd_debuginfo = fd_debuginfo;
+	dwarf_info.name_debuginfo = name_debuginfo;
+	dwarf_info.module_name = mod_name;
+
+	if (!strcmp(dwarf_info.module_name, "vmlinux") ||
+		!strcmp(dwarf_info.module_name, "xen-syms"))
+		return TRUE;
+
+	/* check to see whether module debuginfo is available */
+	if (!init_dwarf_info())
+		return FALSE;
+	else
+		clean_dwfl_info();
+	return TRUE;
+}
+
 int
 generate_vmcoreinfo(void)
 {
 	if (!set_page_size(sysconf(_SC_PAGE_SIZE)))
 		return FALSE;
 
-	dwarf_info.fd_debuginfo   = info->fd_vmlinux;
-	dwarf_info.name_debuginfo = info->name_vmlinux;
+	set_dwarf_debuginfo("vmlinux", info->name_vmlinux, info->fd_vmlinux);
 
 	if (!get_symbol_info())
 		return FALSE;
@@ -3888,8 +4046,8 @@ initial(void)
 	 * Get the debug information for analysis from the kernel file
 	 */
 	} else if (info->name_vmlinux) {
-		dwarf_info.fd_debuginfo   = info->fd_vmlinux;
-		dwarf_info.name_debuginfo = info->name_vmlinux;
+		set_dwarf_debuginfo("vmlinux", info->name_vmlinux,
+						info->fd_vmlinux);
 
 		if (!get_symbol_info())
 			return FALSE;
@@ -6552,8 +6710,7 @@ generate_vmcoreinfo_xen(void)
 		ERRMSG("Can't get the size of page.\n");
 		return FALSE;
 	}
-	dwarf_info.fd_debuginfo   = info->fd_xen_syms;
-	dwarf_info.name_debuginfo = info->name_xen_syms;
+	set_dwarf_debuginfo("xen-syms", info->name_xen_syms, info->fd_xen_syms);
 
 	if (!get_symbol_info_xen())
 		return FALSE;
@@ -6820,8 +6977,8 @@ initial_xen(void)
 	 * Get the debug information for analysis from the xen-syms file
 	 */
 	} else if (info->name_xen_syms) {
-		dwarf_info.fd_debuginfo   = info->fd_xen_syms;
-		dwarf_info.name_debuginfo = info->name_xen_syms;
+		set_dwarf_debuginfo("xen-syms", info->name_xen_syms,
+							info->fd_xen_syms);
 
 		if (!get_symbol_info_xen())
 			return FALSE;
diff --git a/makedumpfile.h b/makedumpfile.h
index 342e419..92e3e41 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -27,6 +27,7 @@
 #include <sys/wait.h>
 #include <zlib.h>
 #include <elfutils/libdw.h>
+#include <elfutils/libdwfl.h>
 #include <libelf.h>
 #include <dwarf.h>
 #include <byteswap.h>
@@ -1177,6 +1178,8 @@ extern struct srcfile_table	srcfile_table;
 /*
  * Debugging information
  */
+#define DEFAULT_DEBUGINFO_PATH	"/usr/lib/debug"
+
 enum {
 	DWARF_INFO_GET_STRUCT_SIZE,
 	DWARF_INFO_GET_MEMBER_OFFSET,
@@ -1194,10 +1197,14 @@ struct dwarf_info {
 	unsigned int	cmd;		/* IN */
 	int	fd_debuginfo;		/* IN */
 	char	*name_debuginfo;	/* IN */
+	char	*module_name;		/* IN */
 	char	*struct_name;		/* IN */
 	char	*symbol_name;		/* IN */
 	char	*member_name;		/* IN */
 	char	*enum_name;		/* IN */
+	Elf	*elfd;			/* OUT */
+	Dwarf	*dwarfd;		/* OUT */
+	Dwfl	*dwfl;			/* OUT */
 	long	struct_size;		/* OUT */
 	long	member_offset;		/* OUT */
 	long	array_length;		/* OUT */



From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:05:02 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:35:02 +0530
Subject: [PATCH v1 3/6] makedumpfile: Load the module symbol data from vmcore.
Message-ID: <20110311080458.14587.29263.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

This patch enables makedumpfile to load module symbol data from vmcore. This
info is required during kernel module data filtering process. Traverse the
modules list and load all module's symbol info data in the memory for fast
lookup.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---

 makedumpfile.c |  305 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 makedumpfile.h |   52 ++++++++++
 2 files changed, 357 insertions(+), 0 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 2274b18..7601e3d 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -26,6 +26,7 @@ struct srcfile_table	srcfile_table;
 struct dwarf_info	dwarf_info;
 struct vm_table		vt = { 0 };
 struct DumpInfo		*info = NULL;
+struct module_sym_table	mod_st = { 0 };
 
 char filename_stdout[] = FILENAME_STDOUT;
 int message_level;
@@ -1512,6 +1513,54 @@ err_out:
 	return FALSE;
 }
 
+static struct module_info *
+get_loaded_module(char *mod_name)
+{
+	unsigned int i;
+	struct module_info *modules;
+
+	modules = mod_st.modules;
+	if (strcmp(mod_name, modules[mod_st.current_mod].name)) {
+		for (i = 0; i < mod_st.num_modules; i++) {
+			if (!strcmp(mod_name, modules[i].name))
+				break;
+		}
+		if (i == mod_st.num_modules)
+			return NULL;
+		/* set the current_mod for fast lookup next time */
+		mod_st.current_mod = i;
+	}
+
+	return &modules[mod_st.current_mod];
+}
+
+int
+sym_in_module(char *symname, unsigned long long *symbol_addr)
+{
+	int i;
+	struct module_info *module_ptr;
+	struct symbol_info *sym_info;
+
+	if (!mod_st.num_modules
+		|| !strcmp(dwarf_info.module_name, "vmlinux")
+		|| !strcmp(dwarf_info.module_name, "xen-syms"))
+		return FALSE;
+
+	module_ptr = get_loaded_module(dwarf_info.module_name);
+	if (!module_ptr)
+		return FALSE;
+	sym_info = module_ptr->sym_info;
+	if (!sym_info)
+		return FALSE;
+	for (i = 1; i < module_ptr->num_syms; i++) {
+		if (sym_info[i].name && !strcmp(sym_info[i].name, symname)) {
+			*symbol_addr = sym_info[i].value;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
 unsigned long long
 get_symbol_addr(char *symname)
 {
@@ -1524,6 +1573,13 @@ get_symbol_addr(char *symname)
 	Elf_Scn *scn = NULL;
 	char *sym_name = NULL;
 
+	/*
+	 * If we are looking for module symbol then traverse through
+	 * mod_st.modules for symbol lookup
+	 */
+	if (sym_in_module(symname, &symbol))
+		return symbol;
+
 	if (!init_dwarf_info())
 		return 0;
 
@@ -2335,6 +2391,7 @@ get_symbol_info(void)
 	SYMBOL_INIT(log_buf_len, "log_buf_len");
 	SYMBOL_INIT(log_end, "log_end");
 	SYMBOL_INIT(max_pfn, "max_pfn");
+	SYMBOL_INIT(modules, "modules");
 
 	if (SYMBOL(node_data) != NOT_FOUND_SYMBOL)
 		SYMBOL_ARRAY_TYPE_INIT(node_data, "node_data");
@@ -2437,6 +2494,20 @@ get_structure_info(void)
 
 	OFFSET_INIT(vm_struct.addr, "vm_struct", "addr");
 
+	/*
+	 * Get offset of the module members.
+	 */
+	SIZE_INIT(module, "module");
+	OFFSET_INIT(module.strtab, "module", "strtab");
+	OFFSET_INIT(module.symtab, "module", "symtab");
+	OFFSET_INIT(module.num_symtab, "module", "num_symtab");
+	OFFSET_INIT(module.list, "module", "list");
+	OFFSET_INIT(module.name, "module", "name");
+	OFFSET_INIT(module.module_core, "module", "module_core");
+	OFFSET_INIT(module.core_size, "module", "core_size");
+	OFFSET_INIT(module.module_init, "module", "module_init");
+	OFFSET_INIT(module.init_size, "module", "init_size");
+
 	ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES");
 	ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE");
 
@@ -7254,6 +7325,240 @@ writeout_multiple_dumpfiles(void)
 	return ret;
 }
 
+static unsigned int
+get_num_modules(unsigned long head, unsigned int *num)
+{
+	unsigned long cur;
+	unsigned int num_modules = 0;
+
+	if (!num)
+		return FALSE;
+
+	if (!readmem(VADDR, head + OFFSET(list_head.next), &cur, sizeof cur)) {
+		ERRMSG("Can't get next list_head.\n");
+		return FALSE;
+	}
+	while (cur != head) {
+		num_modules++;
+		if (!readmem(VADDR, cur + OFFSET(list_head.next),
+					&cur, sizeof cur)) {
+			ERRMSG("Can't get next list_head.\n");
+			return FALSE;
+		}
+	}
+	*num = num_modules;
+	return TRUE;
+}
+
+static void
+free_symbol_info(struct module_info *module)
+{
+	int i;
+
+	if (module->num_syms) {
+		for (i = 1; i < module->num_syms; i++)
+			if (module->sym_info[i].name)
+				free(module->sym_info[i].name);
+		free(module->sym_info);
+	}
+}
+
+static void
+clean_module_symbols(void)
+{
+	int i;
+
+	for (i = 0; i < mod_st.num_modules; i++)
+		free_symbol_info(&mod_st.modules[i]);
+
+	if (mod_st.num_modules) {
+		free(mod_st.modules);
+		mod_st.modules = NULL;
+		mod_st.num_modules = 0;
+	}
+}
+
+static int
+load_module_symbols(void)
+{
+	unsigned long head, cur, cur_module;
+	unsigned long symtab, strtab;
+	unsigned long mod_base, mod_init;
+	unsigned int mod_size, mod_init_size;
+	unsigned char *module_struct_mem, *module_core_mem;
+	unsigned char *module_init_mem = NULL;
+	unsigned char *symtab_mem;
+	char *module_name, *strtab_mem, *nameptr;
+	struct module_info *modules = NULL;
+	struct symbol_info *sym_info;
+	unsigned int num_symtab;
+	unsigned int i = 0, nsym;
+
+	head = SYMBOL(modules);
+	if (!get_num_modules(head, &mod_st.num_modules)) {
+		ERRMSG("Can't get module count\n");
+		return FALSE;
+	}
+	if (!mod_st.num_modules) {
+		return FALSE;
+	}
+	mod_st.modules = calloc(mod_st.num_modules,
+					sizeof(struct module_info));
+	if (!mod_st.modules) {
+		ERRMSG("Can't allocate memory for module info\n");
+		return FALSE;
+	}
+	modules = mod_st.modules;
+
+	/* Allocate buffer to read struct module data from vmcore. */
+	if ((module_struct_mem = calloc(1, SIZE(module))) == NULL) {
+		ERRMSG("Failed to allocate buffer for module\n");
+		return FALSE;
+	}
+
+	if (!readmem(VADDR, head + OFFSET(list_head.next), &cur, sizeof cur)) {
+		ERRMSG("Can't get next list_head.\n");
+		return FALSE;
+	}
+
+	/* Travese the list and read module symbols */
+	while (cur != head) {
+		cur_module = cur - OFFSET(module.list);
+		if (!readmem(VADDR, cur_module, module_struct_mem,
+							SIZE(module))) {
+			ERRMSG("Can't get module info.\n");
+			return FALSE;
+		}
+
+		module_name = (char *)(module_struct_mem + OFFSET(module.name));
+		if (strlen(module_name) < MOD_NAME_LEN)
+			strcpy(modules[i].name, module_name);
+		else
+			strncpy(modules[i].name, module_name, MOD_NAME_LEN-1);
+
+		mod_init = ULONG(module_struct_mem +
+						OFFSET(module.module_init));
+		mod_init_size = UINT(module_struct_mem +
+						OFFSET(module.init_size));
+		mod_base = ULONG(module_struct_mem +
+						OFFSET(module.module_core));
+		mod_size = UINT(module_struct_mem +
+						OFFSET(module.core_size));
+
+		DEBUG_MSG("Module: %s, Base: 0x%lx, Size: %u\n",
+				module_name, mod_base, mod_size);
+		if (mod_init_size > 0) {
+			module_init_mem = calloc(1, mod_init_size);
+			if (module_init_mem == NULL) {
+				ERRMSG("Can't allocate memory for module "
+								"init\n");
+				return FALSE;
+			}
+			if (!readmem(VADDR, mod_init, module_init_mem,
+							mod_init_size)) {
+				ERRMSG("Can't access module init in memory.\n");
+				return FALSE;
+			}
+		}
+
+		if ((module_core_mem = calloc(1, mod_size)) == NULL) {
+			ERRMSG("Can't allocate memory for module\n");
+			return FALSE;
+		}
+		if (!readmem(VADDR, mod_base, module_core_mem, mod_size)) {
+			ERRMSG("Can't access module in memory.\n");
+			return FALSE;
+		}
+
+		num_symtab = UINT(module_struct_mem +
+						OFFSET(module.num_symtab));
+		if (!num_symtab) {
+			ERRMSG("%s: Symbol info not available\n", module_name);
+			return FALSE;
+		}
+		modules[i].num_syms = num_symtab;
+		DEBUG_MSG("num_sym: %d\n", num_symtab);
+
+		symtab = ULONG(module_struct_mem + OFFSET(module.symtab));
+		strtab = ULONG(module_struct_mem + OFFSET(module.strtab));
+
+		/* check if symtab and strtab are inside the module space. */
+		if (!IN_RANGE(symtab, mod_base, mod_size) &&
+			!IN_RANGE(symtab, mod_init, mod_init_size)) {
+			ERRMSG("%s: module symtab is outseide of module "
+				"address space\n", module_name);
+			return FALSE;
+		}
+		if (IN_RANGE(symtab, mod_base, mod_size))
+			symtab_mem = module_core_mem + (symtab - mod_base);
+		else
+			symtab_mem = module_init_mem + (symtab - mod_init);
+
+		if (!IN_RANGE(strtab, mod_base, mod_size) &&
+			!IN_RANGE(strtab, mod_init, mod_init_size)) {
+			ERRMSG("%s: module strtab is outseide of module "
+				"address space\n", module_name);
+			return FALSE;
+		}
+		if (IN_RANGE(strtab, mod_base, mod_size))
+			strtab_mem = (char *)(module_core_mem
+						+ (strtab - mod_base));
+		else
+			strtab_mem = (char *)(module_init_mem
+						+ (strtab - mod_init));
+
+		modules[i].sym_info = calloc(num_symtab,
+						sizeof(struct symbol_info));
+		if (modules[i].sym_info == NULL) {
+			ERRMSG("Can't allocate memory to store sym info\n");
+			return FALSE;
+		}
+		sym_info = modules[i].sym_info;
+
+		/* symbols starts from 1 */
+		for (nsym = 1; nsym < num_symtab; nsym++) {
+			Elf32_Sym *sym32;
+			Elf64_Sym *sym64;
+			/*
+			 * We can not depend on info->flag_elf64_memory if
+			 * the input vmcore file is kdump-compressed format.
+			 * We will fix this in the next patch and remove the
+			 * dependancy on info->flag_elf64_memory.
+			 */
+			if (info->flag_elf64_memory) {
+				sym64 = (Elf64_Sym *) (symtab_mem
+						+ (nsym * sizeof(Elf64_Sym)));
+				sym_info[nsym].value =
+					(unsigned long long) sym64->st_value;
+				nameptr = strtab_mem + sym64->st_name;
+			}
+			else {
+				sym32 = (Elf32_Sym *) (symtab_mem
+						+ (nsym * sizeof(Elf32_Sym)));
+				sym_info[nsym].value =
+					(unsigned long long) sym32->st_value;
+				nameptr = strtab_mem + sym32->st_name;
+			}
+			if (strlen(nameptr))
+				sym_info[nsym].name = strdup(nameptr);
+			DEBUG_MSG("\t[%d] %llx %s\n", nsym,
+						sym_info[nsym].value, nameptr);
+		}
+
+		if (!readmem(VADDR, cur + OFFSET(list_head.next),
+					&cur, sizeof cur)) {
+			ERRMSG("Can't get next list_head.\n");
+			return FALSE;
+		}
+		i++;
+		free(module_core_mem);
+		if (mod_init_size > 0)
+			free(module_init_mem);
+	} while (cur != head);
+	free(module_struct_mem);
+	return TRUE;
+}
+
 int
 create_dumpfile(void)
 {
diff --git a/makedumpfile.h b/makedumpfile.h
index 92e3e41..a21eaef 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -1012,6 +1012,33 @@ struct vm_table {
 };
 extern struct vm_table		vt;
 
+/*
+ * Loaded module symbols info.
+ */
+#define MOD_NAME_LEN	64
+#define IN_RANGE(addr, mbase, sz) \
+	(((unsigned long)(addr) >= (unsigned long)mbase) \
+	&& ((unsigned long)addr < (unsigned long)(mbase + sz)))
+
+struct symbol_info {
+	char			*name;
+	unsigned long long	value;
+};
+
+struct module_info {
+	char			name[MOD_NAME_LEN];
+	unsigned int		num_syms;
+	struct symbol_info	*sym_info;
+};
+
+struct module_sym_table {
+	unsigned int		num_modules;
+	unsigned int		current_mod;
+	struct module_info	*modules;
+};
+
+extern struct module_sym_table	mod_st;
+
 struct symbol_table {
 	unsigned long long	mem_map;
 	unsigned long long	vmem_map;
@@ -1052,6 +1079,12 @@ struct symbol_table {
 	unsigned long long	frametable_pg_dir;
 	unsigned long long	max_page;
 	unsigned long long	alloc_bitmap;
+
+	/*
+	 * for loading module symbol data
+	 */
+
+	unsigned long long	modules;
 };
 
 struct size_table {
@@ -1069,6 +1102,11 @@ struct size_table {
 	 */
 	long	page_info;
 	long	domain;
+
+	/*
+	 * for loading module symbol data
+	 */
+	long	module;
 };
 
 struct offset_table {
@@ -1123,6 +1161,20 @@ struct offset_table {
 		long	next_in_list;
 	} domain;
 
+	/*
+	 * for loading module symbol data
+	 */
+	struct module {
+		long	list;
+		long	name;
+		long	module_core;
+		long	core_size;
+		long	module_init;
+		long	init_size;
+		long	num_symtab;
+		long	symtab;
+		long	strtab;
+	} module;
 };
 
 /*



From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:05:12 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:35:12 +0530
Subject: [PATCH v1 4/6] makedumpfile: Introduce routines to get type name from
	debuginfo.
Message-ID: <20110311080509.14587.87261.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

This patch implements following routines that returns type, type name and
size of kernel symbol/member using dwarf info:

	char *get_symbol_type_name();
	char *get_member_type_name();
	long get_pointer_size();

These routines will be used to resolve symbol/member information specified
through filter config commands.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---

 makedumpfile.c |  142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 makedumpfile.h |   13 +++++
 2 files changed, 148 insertions(+), 7 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 7601e3d..f7d37cc 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -30,6 +30,7 @@ struct module_sym_table	mod_st = { 0 };
 
 char filename_stdout[] = FILENAME_STDOUT;
 int message_level;
+long pointer_size;
 
 /*
  * Forward declarations
@@ -1822,6 +1823,41 @@ check_array_type(Dwarf *dwarfd, Dwarf_Die *die)
 	return TRUE;
 }
 
+static int
+get_dwarf_base_type(Dwarf *dwarfd, Dwarf_Die *die)
+{
+	int tag;
+	const char *name;
+
+	while (get_die_type(dwarfd, die, die)) {
+		tag = dwarf_tag(die);
+		switch (tag) {
+		case DW_TAG_array_type:
+			dwarf_info.type_flag |= TYPE_ARRAY;
+			break;
+		case DW_TAG_pointer_type:
+			dwarf_info.type_flag |= TYPE_PTR;
+			break;
+		case DW_TAG_structure_type:
+			dwarf_info.type_flag |= TYPE_STRUCT;
+			break;
+		case DW_TAG_base_type:
+			dwarf_info.type_flag |= TYPE_BASE;
+			break;
+		}
+	}
+
+	name = dwarf_diename(die);
+	if (name)
+		dwarf_info.type_name = strdup(name);
+	else if (dwarf_info.type_flag == TYPE_PTR)
+		dwarf_info.type_name = strdup("void");
+
+	dwarf_info.struct_size = dwarf_bytesize(die);
+
+	return TRUE;
+}
+
 /*
  * Function for searching struct page.union.struct.mapping.
  */
@@ -1902,6 +1938,15 @@ search_member(Dwarf *dwarfd, Dwarf_Die *die)
 			continue;
 
 		switch (dwarf_info.cmd) {
+		case DWARF_INFO_GET_MEMBER_TYPE:
+			if ((!name) || strcmp(name, dwarf_info.member_name))
+				continue;
+			/*
+			 * Get the member offset.
+			 */
+			if (!get_dwarf_base_type(dwarfd, walker))
+				continue;
+			return;
 		case DWARF_INFO_GET_MEMBER_OFFSET:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
@@ -1964,6 +2009,7 @@ is_search_structure(int cmd)
 {
 	if ((cmd == DWARF_INFO_GET_STRUCT_SIZE)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET)
+	    || (cmd == DWARF_INFO_GET_MEMBER_TYPE)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_ARRAY_LENGTH))
@@ -1985,6 +2031,7 @@ int
 is_search_symbol(int cmd)
 {
 	if ((cmd == DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH)
+	    || (cmd == DWARF_INFO_GET_SYMBOL_TYPE)
 	    || (cmd == DWARF_INFO_CHECK_SYMBOL_ARRAY_TYPE))
 		return TRUE;
 	else
@@ -2041,6 +2088,7 @@ search_structure(Dwarf *dwarfd, Dwarf_Die *die, int *found)
 	switch (dwarf_info.cmd) {
 	case DWARF_INFO_GET_STRUCT_SIZE:
 		break;
+	case DWARF_INFO_GET_MEMBER_TYPE:
 	case DWARF_INFO_GET_MEMBER_OFFSET:
 	case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
 	case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
@@ -2173,6 +2221,9 @@ search_symbol(Dwarf *dwarfd, Dwarf_Die *die, int *found)
 	case DWARF_INFO_CHECK_SYMBOL_ARRAY_TYPE:
 		check_array_type(dwarfd, die);
 		break;
+	case DWARF_INFO_GET_SYMBOL_TYPE:
+		get_dwarf_base_type(dwarfd, die);
+		break;
 	}
 }
 
@@ -2249,6 +2300,10 @@ get_debug_info(void)
 	 */
 	while (dwarf_nextcu(dwarfd, off, &next_off, &header_size,
 	    &abbrev_offset, &address_size, &offset_size) == 0) {
+		if (dwarf_info.cmd == DWARF_INFO_GET_PTR_SIZE) {
+			dwarf_info.struct_size = address_size;
+			break;
+		}
 		off += header_size;
 		if (dwarf_offdie(dwarfd, off, &cu_die) == NULL) {
 			ERRMSG("Can't get CU die.\n");
@@ -2287,6 +2342,47 @@ get_structure_size(char *structname, int flag_typedef)
 }
 
 /*
+ * Get the size of pointer.
+ */
+long
+get_pointer_size()
+{
+	dwarf_info.cmd = DWARF_INFO_GET_PTR_SIZE;
+	/* reuse struct_size member to report pointer size */
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+
+	if (!get_debug_info())
+		return FAILED_DWARFINFO;
+
+	return dwarf_info.struct_size;
+}
+
+/*
+ * Get the type of given symbol.
+ */
+char *
+get_symbol_type_name(char *symname, int cmd, long *size,
+					unsigned long *flag)
+{
+	dwarf_info.cmd = cmd;
+	dwarf_info.symbol_name = symname;
+	dwarf_info.type_name = NULL;
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+	dwarf_info.type_flag = 0;
+
+	if (!get_debug_info())
+		return NULL;
+
+	if (size)
+		*size = dwarf_info.struct_size;
+
+	if (flag)
+		*flag = dwarf_info.type_flag;
+
+	return dwarf_info.type_name;
+}
+
+/*
  * Get the offset of member.
  */
 long
@@ -2305,6 +2401,35 @@ get_member_offset(char *structname, char *membername, int cmd)
 }
 
 /*
+ * Get the type name and size of member.
+ */
+char *
+get_member_type_name(char *structname, char *membername, int cmd, long *size,
+						unsigned long *flag)
+{
+	dwarf_info.cmd = cmd;
+	dwarf_info.struct_name = structname;
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+	dwarf_info.member_name = membername;
+	dwarf_info.type_name = NULL;
+	dwarf_info.type_flag = 0;
+
+	if (!get_debug_info())
+		return NULL;
+
+	if (dwarf_info.struct_size == NOT_FOUND_STRUCTURE)
+		return NULL;
+
+	if (size)
+		*size = dwarf_info.struct_size;
+
+	if (flag)
+		*flag = dwarf_info.type_flag;
+
+	return dwarf_info.type_name;
+}
+
+/*
  * Get the length of array.
  */
 long
@@ -2402,6 +2527,8 @@ get_symbol_info(void)
 	if (SYMBOL(node_memblk) != NOT_FOUND_SYMBOL)
 		SYMBOL_ARRAY_LENGTH_INIT(node_memblk, "node_memblk");
 
+	pointer_size = get_pointer_size();
+
 	return TRUE;
 }
 
@@ -7519,13 +7646,16 @@ load_module_symbols(void)
 		for (nsym = 1; nsym < num_symtab; nsym++) {
 			Elf32_Sym *sym32;
 			Elf64_Sym *sym64;
-			/*
-			 * We can not depend on info->flag_elf64_memory if
-			 * the input vmcore file is kdump-compressed format.
-			 * We will fix this in the next patch and remove the
-			 * dependancy on info->flag_elf64_memory.
+			/* If case of ELF vmcore then the word size can be
+			 * determined using info->flag_elf64_memory flag.
+			 * But in case of kdump-compressed dump, kdump header
+			 * does not carry word size info. May be in future
+			 * this info will be available in kdump header.
+			 * Until then, in order to make this logic work on both
+			 * situation we depend on pointer_size that is
+			 * extracted from vmlinux dwarf information.
 			 */
-			if (info->flag_elf64_memory) {
+			if ((pointer_size * 8) == 64) {
 				sym64 = (Elf64_Sym *) (symtab_mem
 						+ (nsym * sizeof(Elf64_Sym)));
 				sym_info[nsym].value =
diff --git a/makedumpfile.h b/makedumpfile.h
index a21eaef..79ff56e 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -1242,7 +1242,10 @@ enum {
 	DWARF_INFO_GET_TYPEDEF_SIZE,
 	DWARF_INFO_GET_TYPEDEF_SRCNAME,
 	DWARF_INFO_GET_ENUM_NUMBER,
-	DWARF_INFO_CHECK_SYMBOL_ARRAY_TYPE
+	DWARF_INFO_CHECK_SYMBOL_ARRAY_TYPE,
+	DWARF_INFO_GET_SYMBOL_TYPE,
+	DWARF_INFO_GET_MEMBER_TYPE,
+	DWARF_INFO_GET_PTR_SIZE,
 };
 
 struct dwarf_info {
@@ -1257,13 +1260,21 @@ struct dwarf_info {
 	Elf	*elfd;			/* OUT */
 	Dwarf	*dwarfd;		/* OUT */
 	Dwfl	*dwfl;			/* OUT */
+	char	*type_name;		/* OUT */
 	long	struct_size;		/* OUT */
 	long	member_offset;		/* OUT */
 	long	array_length;		/* OUT */
 	long	enum_number;		/* OUT */
+	unsigned char	type_flag;	/* OUT */
 	char	src_name[LEN_SRCFILE];	/* OUT */
 };
 
+/* flags for dwarf_info.type_flag */
+#define TYPE_BASE	0x01
+#define TYPE_ARRAY	0x02
+#define TYPE_PTR	0x04
+#define TYPE_STRUCT	0x08
+
 extern struct dwarf_info	dwarf_info;
 
 int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size);



From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:05:22 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:35:22 +0530
Subject: [PATCH v1 5/6] makedumpfile: Read and process filter commands from
	config file.
Message-ID: <20110311080520.14587.10916.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

This patch enables to makedumpfile to read and process filter commands from
specified config file. It builds a list of filter info consisting of memory
address (paddr) and size to be filtered out. This list is used during
read_pfn() function to filter out user specified kernel data from vmcore
before writing it to compressed DUMPFILE. The filtered memory locations are
filled with 'X' (0x58) character.

The filter command syntax is:
	erase <Symbol>[.member[...]] [size <SizeValue>[K|M]]
	erase <Symbol>[.member[...]] [size <SizeSymbol>]
	erase <Symbol>[.member[...]] [nullify]

Below are the examples how filter commands in config file look like:

	erase modules
	erase cred_jar.name size 10
	erase vmlist.addr nullify

This is useful feature for the customers who wants to erase the customer
sensitive data like security keys, in DUMPFILE before sending it to
support team for analysis.

The man page for filter.conf(8) has been introduced that describes the config
file format and erase command syntax.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---

 Makefile       |    8 -
 filter.conf    |   82 +++++
 filter.conf.8  |  213 ++++++++++++++
 makedumpfile.c |  841 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 makedumpfile.h |   60 ++++
 5 files changed, 1203 insertions(+), 1 deletions(-)
 create mode 100644 filter.conf
 create mode 100644 filter.conf.8

diff --git a/Makefile b/Makefile
index 47467e3..c98a0e8 100644
--- a/Makefile
+++ b/Makefile
@@ -37,12 +37,18 @@ makedumpfile: $(SRC) $(OBJ_ARCH)
 	grep -v "^.TH MAKEDUMPFILE 8" makedumpfile.8 >> temp.8
 	mv temp.8 makedumpfile.8
 	gzip -c ./makedumpfile.8 > ./makedumpfile.8.gz
+	echo .TH FILTER.CONF 8 \"$(DATE)\" \"makedumpfile v$(VERSION)\" \"Linux System Administrator\'s Manual\" > temp.8
+	grep -v "^.TH FILTER.CONF 8" filter.conf.8 >> temp.8
+	mv temp.8 filter.conf.8
+	gzip -c ./filter.conf.8 > ./filter.conf.8.gz
 
 clean:
-	rm -f $(OBJ) $(OBJ_ARCH) makedumpfile makedumpfile.8.gz
+	rm -f $(OBJ) $(OBJ_ARCH) makedumpfile makedumpfile.8.gz filter.conf.8.gz
 
 install:
 	cp makedumpfile ${DESTDIR}/bin
 	cp makedumpfile-R.pl ${DESTDIR}/bin
 	cp makedumpfile.8.gz ${DESTDIR}/usr/share/man/man8
+	cp filter.conf.8.gz ${DESTDIR}/usr/share/man/man8
+	cp filter.conf ${DESTDIR}/etc/filter.conf.sample
 
diff --git a/filter.conf b/filter.conf
new file mode 100644
index 0000000..da29282
--- /dev/null
+++ b/filter.conf
@@ -0,0 +1,82 @@
+## Filter config file
+##
+## Description:
+## Configuration file to specify filter commands to filter out desired
+## kernel data from vmcore. It supports erasing of symbol data and
+## it's members of any data type. In case of filtering of data pointed by
+## void * pointer, user needs to provide size to filter out.
+##
+## Please refer to manpage filter.conf(8) for more details.
+##
+##
+## - Module section
+## =========================================================
+## Syntax:
+## [ModuleName]
+##
+## Define the module section where the symbols specified in subsequent erase
+## commands belong to. The section name is a kernel module name (including
+## vmlinux). The unnamed section defaults to [vmlinux] section.
+##
+## NOTE: There should not be any whitespaces before or after the ModuleName.
+##
+## e.g.
+##	[vmlinux] # Symbols in erase command belongs to main kernel (vmlinux)
+##	erase modules
+##	erase cred_jar.name
+##	erase cred_jar.name size 10
+##	erase cred_jar.array
+##	erase vmlist.addr nullify
+##
+##	[z90crypt] # Symbols in erase command belongs to kernel module z90crypt
+##	erase ap_device_list
+##
+##	# erase entire CPRBX structure
+##	erase static_cprbx
+##
+##
+## - To erase kernel data referred through a kernel Symbol
+## =========================================================
+## Syntax:
+## erase <Symbol>[.member[...]] [size <SizeValue>[K|M]]
+## erase <Symbol>[.member[...]] [size <SizeSymbol>]
+## erase <Symbol>[.member[...]] [nullify]]
+##
+## where
+##	<Symbol>
+##		A variable name from the kernel or module, which is part of
+##		global symbols '/proc/kallsyms'.
+##	<SizeValue>
+##		Integer value that specifies size of data to be erased. The
+##		suffixes 'K' and 'M' can be used to specify kilobytes and
+##		megabytes respectively where, K means 1024 bytes and M means
+##		1024 ^ 2 = 1048576 bytes.
+##	<SizeSymbol>
+##		A simple axpression of the form <Symbol>[.member[...]] that
+##		denotes a symbol which contains a positive integer value as a
+##		size of the data in bytes to be erased.
+##
+## Filter out the specified size of the data referred by symbol/member.
+## If size option is not provided then the size of <Symbol> will be calculated
+## according to it's data type. For 'char *' data type, string length will be
+## determined with an upper limit of 1024.
+##
+## If specified <Symbol> is of type 'void *', then user needs to provide
+## either 'size' or 'nullify' option. Otherwise erase command will not have
+## any effect.
+##
+## The option 'nullify' will work only if filter symbol/member is a pointer and
+## is used to set NULL value to the pointer type symbol/member.
+##
+## NOTE: Please note that by nullifying pointer values will affect the
+## debug ability of created DUMPFILE. Use 'nullify' option only when size of
+## data to be filter out is not known e.g. data pointed by 'void *'.
+##
+## e.g.
+##	[vmlinux]
+##	erase modules
+##	erase cred_jar.name
+##	erase cred_jar.name size 10
+##	erase cred_jar.array
+##	erase vmlist.addr nullify
+##
diff --git a/filter.conf.8 b/filter.conf.8
new file mode 100644
index 0000000..f6b0257
--- /dev/null
+++ b/filter.conf.8
@@ -0,0 +1,213 @@
+.TH FILTER.CONF 8 "16 November 2010" "makedumpfile v1.3.7" "Linux System Administrator's Manual"
+.SH NAME
+filter.conf \- The filter configuration file for makedumpfile(8).
+.SH DESCRIPTION
+.PP
+The filter.conf is a configuration file for makedumpfile tool. filter.conf file
+contains the erase commands to filter out desired kernel data from the vmcore
+while creating \fIDUMPFILE\fR using makedumpfile tool. makedumpfile reads the
+filter config and builds the list of memory addresses and its sizes after
+processing filter commands. The memory locations that require to be filtered
+out are then poisoned with character ?X? (58 in Hex).
+.SH FILE FORMAT
+.PP
+The file consists of module sections that contains filter commands. A section
+begins with the name of the section in square brackets and continues until the
+next section begins.
+
+.br
+"["<\fIModuleName\fR>"]"
+.br
+<\fIFilterCommands\fR>
+.br
+
+where
+.br
+"[" is the character \fB[\fR
+.br
+"]" is the character \fB]\fR
+.TP
+<\fIModuleName\fR>
+is either 'vmlinux' or name of a Linux kernel module.
+.TP
+<\fIFilterCommands\fR>
+is a list of one or more filter commands as described in the section
+\fBFILTER COMMANDS\fR of this manual page.
+.PP
+The section name indicates a kernel module name (including \fBvmlinux\fR) where
+the symbols specified in subsequent erase commands belong to. The unnamed
+section defaults to \fB[vmlinux]\fR section. However, a user can also explicitly
+define \fB[vmlinux]\fR section. The sections help makedumpfile tool to select
+appropriate kernel or module debuginfo file before processing the subsequent
+erase commands. Before selecting appropriate debuginfo file, the module name
+is validated against the loaded modules from the vmcore. If no match is found,
+then the section is ignored and makedumpfile skips to the next module section.
+If match is found, then makedumpfile will try to load the corresponding
+module debuginfo file. If module debuginfo is not available then, makedumpfile
+will skip the section with a warning message.
+.SH FILTER COMMANDS
+.SS filter command
+.PP
+A filter command is an erase command. Each erase command must start with a new
+line. Each filter command describes data in the dump to be erased.
+
+.br
+<\fIEraseCommands\fR>
+.br
+
+where
+.TP
+<\fIEraseCommands\fR>
+Described in the subsection \fBerase command\fR of this manual page.
+.SS erase command
+.PP
+Erase specified size of a kernel data referred by specified kernel/module
+symbol or its member component. The erase command syntax is:
+
+.br
+\fBerase\fR <\fISymbol\fR>[.\fImember\fR[...]] [\fBsize\fR
+<\fISizeValue\fR>[K|M]]
+.br
+\fBerase\fR <\fISymbol\fR>[.\fImember\fR[...]] [\fBsize\fR <\fISizeSymbol\fR>]
+.br
+\fBerase\fR <\fISymbol\fR>[.\fImember\fR[...]] [\fBnullify\fR]
+.br
+
+where
+.br
+.TP
+<\fISymbol\fR>
+A kernel or module symbol (variable) name that is part of global symbols
+\fB/proc/kallsyms\fR.
+.TP
+<\fISizeValue\fR>
+A positive integer value as a size of the data in bytes to be erased. The
+suffixes 'K' and 'M' can be used to specify kilobytes and Megabytes
+respectively where, K means 1024 bytes and M means 1024 ^ 2 = 1048576 bytes.
+The suffixes are not case sensitive.
+.TP
+<\fISizeSymbol\fR>
+A simple expression of the form <\fISymbol\fR>[.\fImember\fR[...]] that denotes
+a symbol which contains a positive integer value as a size of the data in bytes
+to be erased.
+.TP
+<\fISymbol\fR>[.\fImember\fR[...]]
+A simple expression that results into either a global kernel symbol name or
+its member components. The expression always uses '.' operator to specify
+the \fImember\fR component of kernel symbol or its member irrespective of
+whether it is of pointer type or not.
+.TP
+\fImember\fR[...]
+Member or component of member in <\fISymbol\fR>.
+.PP
+The \fBerase\fR command takes two arguments 1. kernel symbol name or its
+member components and 2. size of the data referred by argument (1) OR
+\fBnullify\fR keyword. The second argument \fBsize\fR OR \fBnullify\fR is
+optional. The unit for size value is in \fBbytes\fR. If \fBsize\fR option is
+not specified then the size of the first argument is determined according to
+its data type using dwarf info from debuginfo file. In case of '\fBchar *\fR'
+data type, the length of string pointed by '\fBchar *\fR' pointer is determined
+with an upper limit of 1024. The \fBsize\fR can be specified in two forms 1.
+a integer value as explained above (<\fISizeValue\fR>) and 2. a simple
+expression in the form of <\fISymbol\fR>[.\fImember\fR[...]]] that results into
+base type (integer) variable.
+.PP
+If the specified <\fISymbol\fR> is of type '\fBvoid *\fR', then user needs to
+provide either \fBsize\fR or \fBnullify\fR option, otherwise the erase command
+will not have any effect.
+.PP
+The \fBnullify\fR option only works if specified <\fISymbol\fR> is a pointer.
+Instead of erasing data pointed by the specified pointer \fBnullify\fR erases
+the pointer value and set it to '0' (NULL). Please note that by nullifying
+the pointer values may affect the debug ability of created \fIDUMPFILE\fR.
+Use the \fBnullify\fR option only when the size of data to be erased is not
+known.  \fBe.g.\fR data pointed by '\fBvoid *\fR'.
+.PP
+Let us look at the filter.conf file from the example below which was
+configured to erase desired kernel data from the kernel module with name
+\fBmymodule\fR. At line 1 and 3, the user has not specified size option while
+erasing 'array_var' and 'mystruct1.name' symbols. Instead the user depends on
+makedumpfile to automatically determine the sizes to be erased \fBi.e\fR
+100 bytes for 'array_var' and 11 bytes for 'mystruct1.name'.  At line 2,
+while erasing the 'mystruct1.buffer' member the user has specified the size
+value 25 against the actual size of 50. In this case the user specified
+\fBsize\fR takes the precedence and makedumpfile erases only 25 bytes from
+\'mystruct1.buffer'. At line 4, the size of the data pointed by \fBvoid *\fR
+pointer 'mystruct1.addr' is unknown. Hence the \fBnullify\fR option has been
+specified to reset the pointer value to NULL. At line 5, the
+\'mystruct2.addr_size' is specified as \fBsize\fR argument to determine the
+size of the data pointed by \fBvoid *\fR pointer 'mystruct2.addr'.
+.br
+
+.B Example:
+.PP
+Assuming the following piece of code is from kernel module 'mymodule':
+.br
+
+struct s1 {
+.br
+	char *name;
+.br
+	void *addr1;
+.br
+	void *addr2;
+.br
+	char buffer[50];
+.br
+};
+.br
+struct s2 {
+.br
+	void *addr;
+.br
+	long addr_size;
+.br
+};
+.br
+
+/* Global symbols */
+.br
+char array_var[100];
+.br
+struct s1 mystruct1;
+.br
+struct s2 *mystruct2;
+.br
+
+int foo()
+.br
+{
+.br
+	...
+.br
+	s1.name = "Hello World";
+.br
+	...
+.br
+}
+.br
+
+\fBfilter.conf:\fR
+.br
+[mymodule]
+.br
+erase array_var
+.br
+erase mystruct1.buffer size 25
+.br
+erase mystruct1.name
+.br
+erase mystruct1.addr1 nullify
+.br
+# Assuming addr2 points to 1024 bytes
+.br
+erase mystruct1.addr2 size 1K
+.br
+erase mystruct2.addr size mystruct2.addr_size
+.br
+.B EOF
+
+.SH SEE ALSO
+.PP
+makedumpfile(8)
+
diff --git a/makedumpfile.c b/makedumpfile.c
index f7d37cc..a803f1c 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -27,10 +27,13 @@ struct dwarf_info	dwarf_info;
 struct vm_table		vt = { 0 };
 struct DumpInfo		*info = NULL;
 struct module_sym_table	mod_st = { 0 };
+struct filter_info	*filter_info = NULL;
+struct filter_config	filter_config;
 
 char filename_stdout[] = FILENAME_STDOUT;
 int message_level;
 long pointer_size;
+char config_buf[BUFSIZE_FGETS];
 
 /*
  * Forward declarations
@@ -6047,6 +6050,78 @@ get_num_dumpable(void)
 	return num_dumpable;
 }
 
+void
+split_filter_info(struct filter_info *prev, unsigned long long next_paddr,
+						size_t size)
+{
+	struct filter_info *new;
+
+	if ((new = calloc(1, sizeof(struct filter_info))) == NULL) {
+		ERRMSG("Can't allocate memory to split filter info\n");
+		return;
+	}
+	new->nullify = prev->nullify;
+	new->paddr = next_paddr;
+	new->size = size;
+	new->next = prev->next;
+	prev->next = new;
+}
+
+int
+extract_filter_info(unsigned long long start_paddr,
+			unsigned long long end_paddr,
+			struct filter_info *fl_info)
+{
+	struct filter_info *fi = filter_info;
+	struct filter_info *prev = NULL;
+	size_t size1, size2;
+
+	if (!fl_info)
+		return FALSE;
+
+	while (fi) {
+		if ((fi->paddr >= start_paddr) && (fi->paddr < end_paddr)) {
+			size1 = end_paddr - fi->paddr;
+			if (fi->size <= size1)
+				break;
+			size2 = fi->size - size1;
+			fi->size = size1;
+			split_filter_info(fi, fi->paddr + size1, size2);
+			break;
+		}
+		prev = fi;
+		fi = fi->next;
+	}
+	if (fi) {
+		*fl_info = *fi;
+		fl_info->next = NULL;
+		/* Delete this node */
+		if (!prev)
+			filter_info = fi->next;
+		else
+			prev->next = fi->next;
+		free(fi);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+void
+filter_data_buffer(unsigned char *buf, unsigned long long paddr,
+					size_t size)
+{
+	struct filter_info fl_info;
+	unsigned char *buf_ptr;
+
+	while (extract_filter_info(paddr, paddr + size, &fl_info)) {
+		buf_ptr = buf + (fl_info.paddr - paddr);
+		if (fl_info.nullify)
+			memset(buf_ptr, 0, fl_info.size);
+		else
+			memset(buf_ptr, 'X', fl_info.size);
+	}
+}
+
 int
 write_elf_load_segment(struct cache_data *cd_page, unsigned long long paddr,
 		       off_t off_memory, long long size)
@@ -6078,6 +6153,8 @@ write_elf_load_segment(struct cache_data *cd_page, unsigned long long paddr,
 			    info->name_memory, strerror(errno));
 			return FALSE;
 		}
+		filter_data_buffer((unsigned char *)buf, paddr, bufsz_write);
+		paddr += bufsz_write;
 		if (!write_cache(cd_page, buf, bufsz_write))
 			return FALSE;
 
@@ -6296,6 +6373,7 @@ read_pfn(unsigned long long pfn, unsigned char *buf)
 			ERRMSG("Can't get the page data.\n");
 			return FALSE;
 		}
+		filter_data_buffer(buf, paddr, info->page_size);
 		return TRUE;
 	}
 
@@ -6318,6 +6396,7 @@ read_pfn(unsigned long long pfn, unsigned char *buf)
 		ERRMSG("Can't get the page data.\n");
 		return FALSE;
 	}
+	filter_data_buffer(buf, paddr, size1);
 	if (size1 != info->page_size) {
 		size2 = info->page_size - size1;
 		if (!offset2) {
@@ -6327,6 +6406,7 @@ read_pfn(unsigned long long pfn, unsigned char *buf)
 				ERRMSG("Can't get the page data.\n");
 				return FALSE;
 			}
+			filter_data_buffer(buf + size1, paddr + size1, size2);
 		}
 	}
 	return TRUE;
@@ -7689,6 +7769,764 @@ load_module_symbols(void)
 	return TRUE;
 }
 
+void
+free_config_entry(struct config_entry *ce)
+{
+	struct config_entry *p;
+
+	while(ce) {
+		p = ce;
+		ce = p->next;
+		if (p->name)
+			free(p->name);
+		if (p->type_name)
+			free(p->type_name);
+		free(p);
+	}
+}
+
+void
+free_config(struct config *config)
+{
+	if (config) {
+		if (config->module_name)
+			free(config->module_name);
+		if (config->filter_symbol)
+			free_config_entry(config->filter_symbol);
+		if (config->size_symbol)
+			free_config_entry(config->size_symbol);
+		free(config);
+	}
+}
+
+void
+print_config_entry(struct config_entry *ce)
+{
+	while (ce) {
+		DEBUG_MSG("Name: %s\n", ce->name);
+		DEBUG_MSG("Type Name: %s, ", ce->type_name);
+		DEBUG_MSG("flag: %x, ", ce->flag);
+		DEBUG_MSG("Type flag: %lx, ", ce->type_flag);
+		DEBUG_MSG("sym_addr: %llx, ", ce->sym_addr);
+		DEBUG_MSG("addr: %llx, ", ce->addr);
+		DEBUG_MSG("offset: %lx, ", ce->offset);
+		DEBUG_MSG("size: %zd\n", ce->size);
+
+		ce = ce->next;
+	}
+}
+
+/*
+ * Read the non-terminal's which are in the form of <Symbol>[.member[...]]
+ */
+struct config_entry *
+create_config_entry(const char *token, unsigned short flag, int line)
+{
+	struct config_entry *ce = NULL, *ptr, *prev_ce;
+	char *str, *cur, *next;
+	long len;
+	int depth = 0;
+
+	if (!token)
+		return NULL;
+
+	cur = str = strdup(token);
+	prev_ce = ptr = NULL;
+	while (cur != NULL) {
+		if ((next = strchr(cur, '.')) != NULL) {
+			*next++ = '\0';
+		}
+		if (!strlen(cur)) {
+			cur = next;
+			continue;
+		}
+
+		if ((ptr = calloc(1, sizeof(struct config_entry))) == NULL) {
+			ERRMSG("Can't allocate memory for config_entry\n");
+			goto err_out;
+		}
+		ptr->line = line;
+		ptr->flag |= flag;
+		if (depth == 0) {
+			/* First node is always a symbol name */
+			ptr->flag |= SYMBOL_ENTRY;
+		}
+		if (flag & FILTER_ENTRY) {
+			ptr->name = strdup(cur);
+		}
+		if (flag & SIZE_ENTRY) {
+			char ch = '\0';
+			int n = 0;
+			/* See if absolute length is provided */
+			if ((depth == 0) &&
+				((n = sscanf(cur, "%zd%c", &len, &ch)) > 0)) {
+				if (len < 0) {
+					ERRMSG("Config error at %d: size "
+						"value must be positive.\n",
+						line);
+					goto err_out;
+				}
+				ptr->size = len;
+				ptr->flag |= ENTRY_RESOLVED;
+				if (n == 2) {
+					/* Handle suffix.
+					 * K = Kilobytes
+					 * M = Megabytes
+					 */
+					switch (ch) {
+					case 'M':
+					case 'm':
+						ptr->size *= 1024;
+					case 'K':
+					case 'k':
+						ptr->size *= 1024;
+						break;
+					}
+				}
+			}
+			else
+				ptr->name = strdup(cur);
+		}
+		if (prev_ce) {
+			prev_ce->next = ptr;
+			prev_ce = ptr;
+		}
+		else
+			ce = prev_ce = ptr;
+		cur = next;
+		depth++;
+		ptr = NULL;
+	}
+	free(str);
+	return ce;
+
+err_out:
+	if (ce)
+		free_config_entry(ce);
+	if (ptr)
+		free_config_entry(ptr);
+	return NULL;
+}
+
+int
+is_module_loaded(char *mod_name)
+{
+	if (!strcmp(mod_name, "vmlinux") || get_loaded_module(mod_name))
+		return TRUE;
+	return FALSE;
+}
+
+/*
+ * read filter config file and return each string token. If the parameter
+ * expected_token is non-NULL, then return the current token if it matches
+ * with expected_token otherwise save the current token and return NULL.
+ * At start of every module section filter_config.new_section is set to 1 and
+ * subsequent function invocations return NULL untill filter_config.new_section
+ * is reset to 0 by passing @flag = CONFIG_NEW_CMD (0x02).
+ *
+ * Parameters:
+ * @expected_token	INPUT
+ *	Token string to match with currnet token.
+ *	=NULL - return the current available token.
+ *
+ * @flag		INPUT
+ *	=0x01 - Skip to next module section.
+ *	=0x02 - Treat the next token as next filter command and reset.
+ *
+ * @line		OUTPUT
+ *	Line number of current token in filter config file.
+ *
+ * @cur_mod		OUTPUT
+ *	Points to current module section name on non-NULL return value.
+ *
+ * @eof			OUTPUT
+ *	set to -1 when end of file is reached.
+ *	set to -2 when end of section is reached.
+ */
+static char *
+get_config_token(char *expected_token, unsigned char flag, int *line,
+			char **cur_mod, int *eof)
+{
+	char *p;
+	struct filter_config *fc = &filter_config;
+	int skip = flag & CONFIG_SKIP_SECTION;
+
+	if (!fc->file_filterconfig)
+		return NULL;
+
+	if (eof)
+		*eof = 0;
+
+	/*
+	 * set token and saved_token to NULL if skip module section is set
+	 * to 1.
+	 */
+	if (skip) {
+		fc->token = NULL;
+		fc->saved_token = NULL;
+	}
+
+	if (fc->saved_token) {
+		fc->token = fc->saved_token;
+		fc->saved_token = NULL;
+	}
+	else if (fc->token)
+		fc->token = strtok(NULL, " ");
+
+	/* Read next line if we are done all tokens from previous line */
+	while (!fc->token && fgets(config_buf, sizeof(config_buf),
+					fc->file_filterconfig)) {
+		if ((p = strchr(config_buf, '\n'))) {
+			*p = '\0';
+			fc->line_count++;
+		}
+		if ((p = strchr(config_buf, '#'))) {
+			*p = '\0';
+		}
+		/* replace all tabs with spaces */
+		for (p = config_buf; *p != '\0'; p++)
+			if (*p == '\t')
+				*p = ' ';
+		if (config_buf[0] == '[') {
+			/* module section entry */
+			p = strchr(config_buf, ']');
+			if (!p) {
+				ERRMSG("Config error at %d: Invalid module "
+					"section entry.\n", fc->line_count);
+				/* skip to next valid module section */
+				skip = 1;
+			}
+			else {
+				/*
+				 * Found the valid module section. Reset the
+				 * skip flag.
+				 */
+				*p = '\0';
+				if (fc->cur_module)
+					free(fc->cur_module);
+				fc->cur_module = strdup(&config_buf[1]);
+				skip = 0;
+				fc->new_section = 1;
+			}
+			continue;
+		}
+		/*
+		 * If symbol info for current module is not loaded then
+		 * skip to next module section.
+		 */
+		if (skip ||
+			(fc->cur_module && !is_module_loaded(fc->cur_module)))
+			continue;
+
+		fc->token = strtok(config_buf, " ");
+	}
+	if (!fc->token) {
+		if (eof)
+			*eof = -1;
+		return NULL;
+	}
+	if (fc->new_section && !(flag & CONFIG_NEW_CMD)) {
+		fc->saved_token = fc->token;
+		if (eof)
+			*eof = -2;
+		return NULL;
+	}
+	else
+		fc->new_section = 0;
+
+	if (cur_mod)
+		*cur_mod = fc->cur_module;
+
+	if (line)
+		*line = fc->line_count;
+
+	if (expected_token && strcmp(fc->token, expected_token)) {
+		fc->saved_token = fc->token;
+		return NULL;
+	}
+	return fc->token;
+}
+
+static int
+read_size_entry(struct config *config, int line)
+{
+	char *token = get_config_token(NULL, 0, &line, NULL, NULL);
+
+	if (!token || IS_KEYWORD(token)) {
+		ERRMSG("Config error at %d: expected size symbol after"
+		" 'size' keyword.\n", line);
+		return FALSE;
+	}
+	config->size_symbol = create_config_entry(token, SIZE_ENTRY, line);
+	if (!config->size_symbol) {
+		ERRMSG("Error at line %d: Failed to read size symbol\n",
+									line);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/*
+ * Read erase command entry. The erase command syntax is:
+ *
+ *	erase <Symbol>[.member[...]] [size <SizeValue>[K|M]]
+ *	erase <Symbol>[.member[...]] [size <SizeSymbol>]
+ *	erase <Symbol>[.member[...]] [nullify]
+ */
+static int
+read_filter_entry(struct config *config, int line)
+{
+	char *token = get_config_token(NULL, 0, &line, NULL, NULL);
+
+	if (!token || IS_KEYWORD(token)) {
+		ERRMSG("Config error at %d: expected kernel symbol after"
+		" 'erase' command.\n", line);
+		return FALSE;
+	}
+	config->filter_symbol =
+			create_config_entry(token, FILTER_ENTRY, line);
+	if (!config->filter_symbol) {
+		ERRMSG("Error at line %d: Failed to read filter symbol\n",
+									line);
+		return FALSE;
+	}
+	if (get_config_token("nullify", 0, &line, NULL, NULL)) {
+		config->filter_symbol->nullify = 1;
+	}
+	else if (get_config_token("size", 0, &line, NULL, NULL)) {
+		if (!read_size_entry(config, line))
+			return FALSE;
+	}
+	return TRUE;
+}
+
+/*
+ * Configuration file 'makedumpfile.conf' contains filter commands.
+ * Every individual filter command is considered as a config entry. A config
+ * entry can be provided on a single line or multiple lines.
+ */
+struct config *
+get_config(int skip)
+{
+	struct config *config;
+	char *token = NULL;
+	static int line_count = 0;
+	char *cur_module = NULL;
+	int eof = 0;
+	unsigned char flag = CONFIG_NEW_CMD | skip;
+
+	if ((config = calloc(1, sizeof(struct config))) == NULL)
+		return NULL;
+
+	if (get_config_token("erase", flag, &line_count, &cur_module, &eof)) {
+		if (cur_module)
+			config->module_name = strdup(cur_module);
+
+		if (!read_filter_entry(config, line_count))
+			goto err_out;
+	}
+	else {
+		if (!eof) {
+			token = get_config_token(NULL, 0, &line_count,
+								NULL, NULL);
+			ERRMSG("Config error at %d: Invalid token '%s'.\n",
+							line_count, token);
+		}
+		goto err_out;
+	}
+	return config;
+err_out:
+	if (config)
+		free_config(config);
+	return NULL;
+}
+
+static unsigned long long
+read_pointer_value(unsigned long long addr)
+{
+	uint32_t val_32;
+	uint64_t val_64;
+
+	switch (pointer_size) {
+	case 4:
+		if (!readmem(VADDR, addr, &val_32, sizeof(val_32))) {
+			ERRMSG("Can't read pointer value\n");
+			return 0;
+		}
+		return (unsigned long long)val_32;
+		break;
+	case 8:
+		if (!readmem(VADDR, addr, &val_64, sizeof(val_64))) {
+			ERRMSG("Can't read pointer value\n");
+			return 0;
+		}
+		return (unsigned long long)val_64;
+		break;
+	}
+	return 0;
+}
+
+int
+resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
+						char *base_struct_name)
+{
+	char buf[BUFSIZE + 1];
+
+	if (ce->flag & SYMBOL_ENTRY) {
+		/* find the symbol info */
+		if (!ce->name)
+			return FALSE;
+
+		ce->sym_addr = get_symbol_addr(ce->name);
+		if (!ce->sym_addr) {
+			ERRMSG("Config error at %d: Can't find symbol '%s'.\n",
+							ce->line, ce->name);
+			return FALSE;
+		}
+		ce->type_name = get_symbol_type_name(ce->name,
+					DWARF_INFO_GET_SYMBOL_TYPE,
+					&ce->size, &ce->type_flag);
+		if (ce->type_flag & TYPE_ARRAY) {
+			ce->array_length = get_array_length(ce->name, NULL,
+					DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH);
+			if (ce->array_length < 0)
+				ce->array_length = 0;
+		}
+	}
+	else {
+		/* find the member offset */
+		ce->offset = get_member_offset(base_struct_name,
+				ce->name, DWARF_INFO_GET_MEMBER_OFFSET);
+		ce->sym_addr = base_addr + ce->offset;
+		ce->type_name = get_member_type_name(base_struct_name,
+				ce->name, DWARF_INFO_GET_MEMBER_TYPE,
+				&ce->size, &ce->type_flag);
+		if (ce->type_flag & TYPE_ARRAY) {
+			ce->array_length = get_array_length(base_struct_name,
+					ce->name,
+					DWARF_INFO_GET_MEMBER_ARRAY_LENGTH);
+			if (ce->array_length < 0)
+				ce->array_length = 0;
+		}
+	}
+	if (ce->type_name == NULL) {
+		if (!(ce->flag & SYMBOL_ENTRY))
+			ERRMSG("Config error at %d: struct '%s' has no member"
+				" with name '%s'.\n",
+				ce->line, base_struct_name, ce->name);
+		return FALSE;
+	}
+	ce->addr = ce->sym_addr;
+	if (ce->size < 0)
+		ce->size = 0;
+	if ((ce->type_flag & (TYPE_ARRAY | TYPE_PTR)) == TYPE_PTR) {
+		/* If it's a pointer variable (not array) then read the
+		 * pointer value. */
+		ce->addr = read_pointer_value(ce->sym_addr);
+
+		/*
+		 * if it is a void pointer then reset the size to 0
+		 * User need to provide a size to filter data referenced
+		 * by 'void *' pointer.
+		 */
+		if (!strcmp(ce->type_name, "void"))
+			ce->size = 0;
+
+	}
+	if ((ce->type_flag & TYPE_BASE) && (ce->type_flag & TYPE_PTR)) {
+		/*
+		 * Determine the string length for 'char' pointer.
+		 * BUFSIZE(1024) is the upper limit for string length.
+		 */
+		if (!strcmp(ce->type_name, "char")) {
+			if (readmem(VADDR, ce->addr, buf, BUFSIZE)) {
+				buf[BUFSIZE] = '\0';
+				ce->size = strlen(buf);
+			}
+		}
+	}
+	if (!ce->next && (ce->flag & SIZE_ENTRY)) {
+		void *val;
+
+		/* leaf node of size entry */
+		/* If it is size argument then update the size with data
+		 * value of this symbol/member.
+		 * Check if current symbol/member is of base data type.
+		 */
+
+		if (((ce->type_flag & (TYPE_ARRAY | TYPE_BASE)) != TYPE_BASE)
+				|| (ce->size > sizeof(long))) {
+			ERRMSG("Config error at %d: size symbol/member '%s' "
+				"is not of base type.\n", ce->line, ce->name);
+			return FALSE;
+		}
+		if ((val = calloc(1, ce->size)) == NULL) {
+			ERRMSG("Can't get memory for size parameter\n");
+			return FALSE;
+		}
+
+		if (!readmem(VADDR, ce->addr, val, ce->size)) {
+			ERRMSG("Can't read symbol/member data value\n");
+			return FALSE;
+		}
+		switch (ce->size) {
+		case 1:
+			ce->size = (long)(*((uint8_t *)val));
+			break;
+		case 2:
+			ce->size = (long)(*((uint16_t *)val));
+			break;
+		case 4:
+			ce->size = (long)(*((uint32_t *)val));
+			break;
+		case 8:
+			ce->size = (long)(*((uint64_t *)val));
+			break;
+		}
+		free(val);
+	}
+	ce->flag |= ENTRY_RESOLVED;
+	return TRUE;
+}
+
+unsigned long long
+get_config_symbol_addr(struct config_entry *ce,
+			unsigned long long base_addr,
+			char *base_struct_name)
+{
+	if (!(ce->flag & ENTRY_RESOLVED)) {
+		if (!resolve_config_entry(ce, base_addr, base_struct_name))
+			return 0;
+	}
+
+	if (ce->next && ce->addr) {
+		/* Populate nullify flag down the list */
+		ce->next->nullify = ce->nullify;
+		return get_config_symbol_addr(ce->next, ce->addr,
+							ce->type_name);
+	}
+	else if (ce->nullify) {
+		/* nullify is applicable to pointer type */
+		if (ce->type_flag & TYPE_PTR)
+			return ce->sym_addr;
+		else
+			return 0;
+	}
+	else
+		return ce->addr;
+}
+
+long
+get_config_symbol_size(struct config_entry *ce,
+			unsigned long long base_addr,
+			char *base_struct_name)
+{
+	if (!(ce->flag & ENTRY_RESOLVED)) {
+		if (!resolve_config_entry(ce, base_addr, base_struct_name))
+			return 0;
+	}
+
+	if (ce->next && ce->addr)
+		return get_config_symbol_size(ce->next, ce->addr,
+							ce->type_name);
+	else {
+		if (ce->type_flag & TYPE_ARRAY) {
+			if (ce->type_flag & TYPE_PTR)
+				return ce->array_length * pointer_size;
+			else
+				return ce->array_length * ce->size;
+		}
+		return ce->size;
+	}
+}
+
+void
+insert_filter_info(struct filter_info *fl_info)
+{
+	struct filter_info *prev = NULL;
+	struct filter_info *ptr = filter_info;
+
+	if (!ptr) {
+		filter_info = fl_info;
+		return;
+	}
+
+	while (ptr) {
+		if (fl_info->paddr <= ptr->paddr)
+			break;
+		prev = ptr;
+		ptr = ptr->next;
+	}
+	if (ptr && (fl_info->paddr == ptr->paddr)) {
+		if (fl_info->size > ptr->size)
+			ptr->size = fl_info->size;
+		return;
+	}
+
+	if (prev) {
+		fl_info->next = ptr;
+		prev->next = fl_info;
+	}
+	else {
+		fl_info->next = filter_info;
+		filter_info = fl_info;
+	}
+	return;
+}
+
+int
+update_filter_info(struct config_entry *filter_symbol,
+			struct config_entry *size_symbol)
+{
+	unsigned long long addr;
+	long size;
+	struct filter_info *fl_info;
+
+	addr = get_config_symbol_addr(filter_symbol, 0, NULL);
+	if (message_level & ML_PRINT_DEBUG_MSG)
+		print_config_entry(filter_symbol);
+	if (!addr)
+		return FALSE;
+
+	if (filter_symbol->nullify)
+		size = pointer_size;
+	else if (size_symbol) {
+		size = get_config_symbol_size(size_symbol, 0, NULL);
+		if (message_level & ML_PRINT_DEBUG_MSG)
+			print_config_entry(size_symbol);
+	}
+	else
+		size = get_config_symbol_size(filter_symbol, 0, NULL);
+
+	if (size <= 0)
+		return FALSE;
+
+	if ((fl_info = calloc(1, sizeof(struct filter_info))) == NULL) {
+		ERRMSG("Can't allocate filter info\n");
+		return FALSE;
+	}
+	fl_info->address = addr;
+	fl_info->paddr = vaddr_to_paddr(addr);
+	fl_info->size = size;
+	fl_info->nullify = filter_symbol->nullify;
+
+	insert_filter_info(fl_info);
+	return TRUE;
+}
+
+/*
+ * Process the config entry that has been read by get_config.
+ * return TRUE on success
+ * return FALSE if module debuginfo is not available.
+ */
+int
+process_config(struct config *config)
+{
+	update_filter_info(config->filter_symbol, config->size_symbol);
+
+	return TRUE;
+}
+
+void
+print_filter_info()
+{
+	struct filter_info *fl_info = filter_info;
+
+	DEBUG_MSG("\n");
+	while (fl_info) {
+		DEBUG_MSG("filter address: paddr (%llx), sym_addr (%llx),"
+			" Size (%ld)\n",
+			fl_info->paddr, fl_info->address, fl_info->size);
+		fl_info = fl_info->next;
+	}
+}
+
+void
+init_filter_config()
+{
+	filter_config.name_filterconfig = info->name_filterconfig;
+	filter_config.file_filterconfig = info->file_filterconfig;
+	filter_config.saved_token = NULL;
+	filter_config.token = NULL;
+	filter_config.cur_module = NULL;
+	filter_config.new_section = 0;
+	filter_config.line_count = 0;
+}
+
+/*
+ * Read and process each config entry (filter commands) from filter config
+ * file. If no module debuginfo found for specified module section then skip
+ * to next module section.
+ */
+int
+process_config_file(const char *name_config)
+{
+	struct config *config;
+	int skip_section = 0;
+
+	if (!name_config)
+		return FALSE;
+
+	if ((info->file_filterconfig = fopen(name_config, "r")) == NULL) {
+		ERRMSG("Can't open config file(%s). %s\n",
+		    name_config, strerror(errno));
+		return FALSE;
+	}
+
+	init_filter_config();
+
+	while((config = get_config(skip_section)) != NULL) {
+		skip_section = 0;
+		if (config->module_name &&
+				strcmp(config->module_name, "vmlinux")) {
+			/*
+			 * if Module debuginfo is not available, then skip to
+			 * next module section.
+			 */
+			if (!set_dwarf_debuginfo(config->module_name,
+								NULL, -1)) {
+				ERRMSG("Skipping to next Module section\n");
+				skip_section = 1;
+				free_config(config);
+				continue;
+			}
+		}
+		else {
+			set_dwarf_debuginfo("vmlinux", info->name_vmlinux,
+							info->fd_vmlinux);
+		}
+		process_config(config);
+		free_config(config);
+	}
+
+	fclose(info->file_filterconfig);
+	print_filter_info();
+	return TRUE;
+}
+
+int
+gather_filter_info()
+{
+	/*
+	 * Before processing filter config file, load the symbol data of
+	 * loaded modules from vmcore.
+	 */
+	set_dwarf_debuginfo("vmlinux", info->name_vmlinux, info->fd_vmlinux);
+	if (!load_module_symbols())
+		return FALSE;
+
+	process_config_file(info->name_filterconfig);
+
+	/*
+	 * Remove modules symbol information, we dont need now.
+	 * Reset the dwarf debuginfo to vmlinux to close open file
+	 * descripter of module debuginfo file, if any.
+	 */
+	clean_module_symbols();
+	set_dwarf_debuginfo("vmlinux", info->name_vmlinux, info->fd_vmlinux);
+	return TRUE;
+}
+
 int
 create_dumpfile(void)
 {
@@ -7724,6 +8562,9 @@ retry:
 		}
 	}
 
+	if (info->name_filterconfig && !gather_filter_info())
+		return FALSE;
+
 	if (!create_dump_bitmap())
 		return FALSE;
 
diff --git a/makedumpfile.h b/makedumpfile.h
index 79ff56e..08d1615 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -226,6 +226,7 @@ do { \
 #define BITPERBYTE		(8)
 #define PGMM_CACHED		(512)
 #define PFN_EXCLUDED		(256)
+#define BUFSIZE			(1024)
 #define BUFSIZE_FGETS		(1500)
 #define BUFSIZE_BITMAP		(4096)
 #define PFN_BUFBITMAP		(BITPERBYTE*BUFSIZE_BITMAP)
@@ -1277,6 +1278,65 @@ struct dwarf_info {
 
 extern struct dwarf_info	dwarf_info;
 
+/*
+ * Filtering information
+ */
+struct filter_info {
+	unsigned long long      address;
+	unsigned long long      paddr;
+	long			size;
+	struct filter_info      *next;
+	unsigned short          nullify;
+};
+
+struct config_entry {
+	char			*name;
+	char			*type_name;
+	unsigned short		flag;
+	unsigned short		nullify;
+	unsigned long long	sym_addr;	/* Symbol address */
+	unsigned long long	addr;		/* Symbol address or
+						   value pointed by sym_addr */
+	unsigned long		offset;
+	unsigned long		type_flag;
+	long			array_length;
+	long			size;
+	int			line;	/* Line number in config file. */
+	struct config_entry	*next;
+};
+
+/* flags for config_entry.flag */
+#define FILTER_ENTRY	0x0001
+#define SIZE_ENTRY	0x0002
+#define SYMBOL_ENTRY	0x0010
+#define ENTRY_RESOLVED	0x8000
+
+/*
+ * Filter config information
+ */
+struct filter_config {
+	char		*name_filterconfig;
+	FILE		*file_filterconfig;
+	char		*cur_module;
+	char		*saved_token;
+	char		*token;
+	int		new_section;
+	int		line_count;
+};
+
+#define CONFIG_SKIP_SECTION	0x01
+#define CONFIG_NEW_CMD		0x02
+
+struct config {
+	char			*module_name;
+	struct config_entry	*filter_symbol;
+	struct config_entry	*size_symbol;
+};
+
+#define IS_KEYWORD(tkn)	\
+	(!strcmp(tkn, "erase") || !strcmp(tkn, "size") || \
+	!strcmp(tkn, "nullify"))
+
 int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size);
 off_t paddr_to_offset(unsigned long long paddr);
 unsigned long long vaddr_to_paddr_general(unsigned long long vaddr);



From mahesh at linux.vnet.ibm.com  Fri Mar 11 03:05:32 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Fri, 11 Mar 2011 13:35:32 +0530
Subject: [PATCH v1 6/6] makedumpfile: Read and process 'for' command from
	config file.
Message-ID: <20110311080530.14587.41075.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

This patch adds support to read and process 'for' command from config file
to filter multiple memory locations that are accessible through an array,
link list or list_head.

The syntax for 'for' (loop construct) filter command is:

for <id> in {<ArrayVar> |
	     <StructVar> via <NextMember> |
	     <ListHeadVar> within <StructName>:<ListHeadMember>}
	erase <id>[.MemberExpression] [size <SizeExpression>|nullify]
	[erase <id> ...]
	[...]
endfor

Updated filter.conf(8) man page that describes the syntax for loop construct.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---

 filter.conf    |   67 +++++++
 filter.conf.8  |  212 ++++++++++++++++++++++
 makedumpfile.c |  533 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 makedumpfile.h |   19 ++
 4 files changed, 814 insertions(+), 17 deletions(-)

diff --git a/filter.conf b/filter.conf
index da29282..74c9c4f 100644
--- a/filter.conf
+++ b/filter.conf
@@ -80,3 +80,70 @@
 ##	erase cred_jar.array
 ##	erase vmlist.addr nullify
 ##
+##
+## - To filter kernel data referred through Array/list_head Symbol
+## =================================================================
+## Syntax:
+## for <id> in { <ArrayVar> |
+##		 <StructVar> via <NextMember> |
+##		 <ListHeadVar> within <StructName>:<ListHeadMember> }
+##	erase <id>[.MemberExpression] [size <SizeExpression>|nullify]
+##	[erase <id> ...]
+##	[...]
+## endfor
+##
+## where
+##	<id>
+##		Arbitrary name used to temporarily point to elements of the
+##		list. Referred as iteration variable.
+##	<ArrayVar>
+##		A simple expression in the form of <Symbol>[.member[...]] that
+##		results into an array variable.
+##	<StructVar>
+##		A simple expression in the form of <Symbol>[.member[...]] that
+##		results into a variable that points to a structure.
+##	<NextMember>
+##		Member within <StructVar> that points to an object of same
+##		type that of <StructVar>.
+##	<ListHeadVar>
+##		A simple expression in the form of <Symbol>[.member[...]] that
+##		results into a variable of type struct list_head.
+##	<StructName>
+##		Name of the structure type that can be traversed using
+##		HEAD variable <ListHeadVar> and contains a member named
+##		<ListHeadMember>.
+##	<ListHeadMember>
+##		Name of a member in <StructName>, of type struct list_head.
+##	<MemberExpression>
+##		A simple expression in the form of [.member[...]] to specify a
+##		member or component of a member in <ArrayVar>, <StructVar> or
+##		<StructName>.
+##	<SizeExpression>
+##		One of the following:
+##		- An integer value.
+##		- <Symbol>[.member[...]]
+##		- <id>[.MemberExpresion]
+##
+## The <ArrayVar>, <StructVar> and <ListHeadVar> is also referred as LIST
+## entry
+##
+## Filter out the specified size of the data accessible through LIST entries.
+## e.g.
+##	[vmlinux]
+##	# Traversing <ListHeadVar>
+##	for m in modules.next within module:list
+##		erase m.holders_dir.name
+##	endfor
+##	# Traversing <ArrayVar>
+##	for lc in lowcore_ptr
+##		erase lc
+##	endfor
+##	# Traversing link-list
+##	for cj in cred_jar via slabp_cache
+##		erase cj.name
+##	endfor
+##	[z90crypt]
+##	for ap_dev in ap_device_list.next within ap_device:list
+##		erase ap_dev.reply.message size ap_dev.reply.length
+##	endfor
+##
diff --git a/filter.conf.8 b/filter.conf.8
index f6b0257..7137e3b 100644
--- a/filter.conf.8
+++ b/filter.conf.8
@@ -48,17 +48,21 @@ will skip the section with a warning message.
 .SH FILTER COMMANDS
 .SS filter command
 .PP
-A filter command is an erase command. Each erase command must start with a new
-line. Each filter command describes data in the dump to be erased.
+A filter command is either an erase command or a loop construct. Each erase
+command and loop construct must start with a new line. Each filter command
+describes data in the dump to be erased. Syntax:
 
 .br
-<\fIEraseCommands\fR>
+<\fIEraseCommands\fR>|<\fILoopConstruct\fR>
 .br
 
 where
 .TP
 <\fIEraseCommands\fR>
 Described in the subsection \fBerase command\fR of this manual page.
+.TP
+<\fILoopConstruct\fR>
+Described in the subsection \fBLoop construct\fR of this manual page.
 .SS erase command
 .PP
 Erase specified size of a kernel data referred by specified kernel/module
@@ -207,6 +211,208 @@ erase mystruct2.addr size mystruct2.addr_size
 .br
 .B EOF
 
+.SS Loop construct
+.PP
+A Loop construct allows the user to traverse the linked list or array elements
+and erase the data contents referred by each element.
+
+.br
+\fBfor\fR <\fIid\fR> \fBin\fR {<\fIArrayVar\fR> |
+.br
+		   <\fIStructVar\fR> \fBvia\fR <\fINextMember\fR> |
+.br
+		   <\fIListHeadVar\fR> \fBwithin\fR
+<\fIStructName\fR>\fB:\fR<\fIListHeadMember\fR>}
+.br
+	\fBerase\fR <\fIid\fR>[.\fIMemberExpression\fR]
+[\fBsize\fR <\fISizeExpression\fR>|\fBnullify\fR]
+.br
+	[\fBerase\fR <\fIid\fR>...]
+.br
+	[...]
+.br
+\fBendfor\fR
+.PP
+where
+.PP
+.TP
+<\fIid\fR>
+Arbitrary name used to temporarily point to elements of the list. This is
+also called iteration variable.
+.TP
+<\fIArrayVar\fR>
+A simple expression in the form of <\fISymbol\fR>[.\fImember\fR[...]] that
+results into an array variable.
+.TP
+<\fIStructVar\fR>
+A simple expression in the form of <\fISymbol\fR>[.\fImember\fR[...]] that
+results into a variable that points to a structure.
+.TP
+<\fINextMember\fR>
+Member within <\fIStructVar\fR> that points to an object of same type that of
+<\fIStructVar\fR>.
+.TP
+<\fIListHeadVar\fR>
+A simple expression in the form of <\fISymbol\fR>[.\fImember\fR[...]] that
+results into a variable of type struct list_head.
+.TP
+<\fIStructName\fR>
+Name of the structure type that can be traversed using HEAD variable
+<\fIListHeadVar\fR> and contains a member named <\fIListHeadMember\fR>.
+.TP
+<\fIListHeadMember\fR>
+Name of a member in <\fIStructName\fR>, of type struct list_head.
+.TP
+<\fIMemberExpression\fR>
+A simple expression in the form of [.\fImember\fR[...]] to specify a member
+or component of an element in <\fIArrayVar\fR>, <\fIStructVar\fR>
+or <\fIStructName\fR>.
+.TP
+<\fISizeExpression\fR>
+Size value in the form of <\fISizeValue\fR>, <\fIid\fR>[.\fIMemberExpression\fR]
+or <\fISymbol\fR>[.\fImember\fR[...]].
+.PP
+The \fBfor\fR loop construct allows to iterate on list of elements in an array
+or linked lists. Each element in the list is assigned to iteration variable
+<\fIid\fR>. The type of the iteration variable is determined by that of the
+list elements. The entry specified after '\fBin\fR' terminal is called LIST
+entry. The LIST entry can be an array variable, structure variable/pointer or a
+struct list_head type variable. The set of \fBerase\fR commands specified
+between \fBfor\fR and \fBendfor\fR, will be executed for each element in the
+LIST entry.
+.PP
+If the LIST entry specified is an array variable, then the loop will be
+executed for each array element. The size of the array will be determined by
+using dwarf information.
+.PP
+If the LIST entry specified is a structure variable/pointer, then a traversal
+member (<\fINextMember\fR>) must be specified using '\fBvia\fR' terminal. The
+\fBfor\fR loop will continue until the value of traversal member is NULL or
+matches with address of the first node <\fIStructVar\fR> if it is a circular
+linked list.
+.PP
+If the LIST entry is specified using a struct list_head type variable, then
+\fBwithin\fR terminal must be used to specify the structure name
+<\fIStructName\fR> that is surrounding to it along with the struct list_head
+type member after '\fB:\fR' which is part of the linked list. In the erase
+statement <\fIid\fR> then denotes the structure that the list_head is
+contained in (ELEMENT_OF).
+.PP
+The below example illustrates how to use loop construct for traversing
+Array, linked list via next member and list_head.
+
+.B Example:
+.PP
+Assuming following piece of code is from kernel module 'mymodule':
+.br
+
+struct s1 {
+.br
+	struct *next;
+.br
+	struct list_head list;
+.br
+	char private[100];
+.br
+	void *key;
+.br
+	long key_size;
+.br
+};
+.br
+
+/* Global symbols */
+.br
+struct s1 mystruct1;
+.br
+static LIST_HEAD(s1_list_head);
+.br
+struct s1 myarray[100];
+.br
+
+void foo()
+.br
+{
+.br
+	struct s1 *s1_ptr;
+.br
+	...
+.br
+	...
+.br
+	s1_ptr = malloc(...);
+.br
+	...
+.br
+	...
+.br
+	list_add(&s1_ptr->list, &s1_list_head);
+.br
+	...
+.br
+}
+.br
+
+\fBfilter.conf:\fR
+.br
+[mymodule]
+.br
+# erase private fields from list starting with mystruct1 connected via
+.br
+# 'next' member:
+.br
+for mys1 in mystruct1 via next
+.br
+	erase mys1.private
+.br
+	erase mys1.key size mys1.key_size
+.br
+endfor
+.br
+
+# erase private fields from list starting with list_head variable
+.br
+# s1_list_head.
+.br
+for mys1 in s1_list_head.next within s1:list
+.br
+	erase mys1.private
+.br
+	erase mys1.key size mys1.key_size
+.br
+endfor
+.br
+
+# erase private fields from all elements of the array myarray:
+.br
+for mys1 in myarray
+.br
+	erase mys1.private
+.br
+	erase mys1.key size mys1.key_size
+.br
+endfor
+.br
+.B EOF
+.PP
+In the above example, the first \fBfor\fR construct traverses the linked list
+through a specified structure variable \fBmystruct1\fR of type \fBstruct s1\fR.
+The linked list can be traversed using '\fBnext\fR' member of \fBmystruct1\fR.
+Hence a \fBvia\fR terminal has been used to specify the traversal member
+name '\fBnext\fR'.
+.PP
+The second \fBfor\fR construct traverses the linked list through a specified
+struct list_head variable \fBs1_list_head.next\fR. The global symbol
+\fBs1_list_head\fR is a start address of the linked list and its \fBnext\fR
+member points to the address of struct list_head type member '\fBlist\fR' from
+\fBstruct s1\fR. Hence a \fBwithin\fR terminal is used to specify the structure
+name '\fBs1\fR' that can be traversed using \fBs1_list_head.next\fR variable
+along with the name of struct list_head type member '\fBlist\fR' which is part
+of the linked list that starts from \fBs1_list_head\fR global symbol.
+.PP
+The third \fBfor\fR construct traverses the array elements specified through
+a array variable \fBmyarray\fR.
+.br
 .SH SEE ALSO
 .PP
 makedumpfile(8)
diff --git a/makedumpfile.c b/makedumpfile.c
index a803f1c..d50248a 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -7788,13 +7788,20 @@ free_config_entry(struct config_entry *ce)
 void
 free_config(struct config *config)
 {
+	int i;
 	if (config) {
 		if (config->module_name)
 			free(config->module_name);
+		for (i = 0; i < config->num_filter_symbols; i++) {
+			if (config->filter_symbol[i])
+				free_config_entry(config->filter_symbol[i]);
+			if (config->size_symbol[i])
+				free_config_entry(config->size_symbol[i]);
+		}
 		if (config->filter_symbol)
-			free_config_entry(config->filter_symbol);
+			free(config->filter_symbol);
 		if (config->size_symbol)
-			free_config_entry(config->size_symbol);
+			free(config->size_symbol);
 		free(config);
 	}
 }
@@ -7851,7 +7858,16 @@ create_config_entry(const char *token, unsigned short flag, int line)
 			/* First node is always a symbol name */
 			ptr->flag |= SYMBOL_ENTRY;
 		}
-		if (flag & FILTER_ENTRY) {
+		if (flag & ITERATION_ENTRY) {
+			/* Max depth for iteration entry is 1 */
+			if (depth > 0) {
+				ERRMSG("Config error at %d: Invalid iteration "
+					"variable entry.\n", line);
+				goto err_out;
+			}
+			ptr->name = strdup(cur);
+		}
+		if (flag & (FILTER_ENTRY | LIST_ENTRY)) {
 			ptr->name = strdup(cur);
 		}
 		if (flag & SIZE_ENTRY) {
@@ -8050,6 +8066,7 @@ get_config_token(char *expected_token, unsigned char flag, int *line,
 static int
 read_size_entry(struct config *config, int line)
 {
+	int idx = config->num_filter_symbols - 1;
 	char *token = get_config_token(NULL, 0, &line, NULL, NULL);
 
 	if (!token || IS_KEYWORD(token)) {
@@ -8057,12 +8074,19 @@ read_size_entry(struct config *config, int line)
 		" 'size' keyword.\n", line);
 		return FALSE;
 	}
-	config->size_symbol = create_config_entry(token, SIZE_ENTRY, line);
-	if (!config->size_symbol) {
+	config->size_symbol[idx] = create_config_entry(token, SIZE_ENTRY, line);
+	if (!config->size_symbol[idx]) {
 		ERRMSG("Error at line %d: Failed to read size symbol\n",
 									line);
 		return FALSE;
 	}
+	if (config->iter_entry && config->size_symbol[idx]->name &&
+					(!strcmp(config->size_symbol[idx]->name,
+					config->iter_entry->name))) {
+		config->size_symbol[idx]->flag &= ~SYMBOL_ENTRY;
+		config->size_symbol[idx]->flag |= VAR_ENTRY;
+		config->size_symbol[idx]->refer_to = config->iter_entry;
+	}
 	return TRUE;
 }
 
@@ -8076,6 +8100,7 @@ read_size_entry(struct config *config, int line)
 static int
 read_filter_entry(struct config *config, int line)
 {
+	int size, idx;
 	char *token = get_config_token(NULL, 0, &line, NULL, NULL);
 
 	if (!token || IS_KEYWORD(token)) {
@@ -8083,15 +8108,41 @@ read_filter_entry(struct config *config, int line)
 		" 'erase' command.\n", line);
 		return FALSE;
 	}
-	config->filter_symbol =
+
+	idx = config->num_filter_symbols;
+	config->num_filter_symbols++;
+	size = config->num_filter_symbols * sizeof(struct config_entry *);
+	config->filter_symbol = realloc(config->filter_symbol, size);
+	config->size_symbol = realloc(config->size_symbol, size);
+
+	if (!config->filter_symbol || !config->size_symbol) {
+		ERRMSG("Can't get memory to read config symbols.\n");
+		return FALSE;
+	}
+	config->filter_symbol[idx] = NULL;
+	config->size_symbol[idx] = NULL;
+
+	config->filter_symbol[idx] =
 			create_config_entry(token, FILTER_ENTRY, line);
-	if (!config->filter_symbol) {
+	if (!config->filter_symbol[idx]) {
 		ERRMSG("Error at line %d: Failed to read filter symbol\n",
 									line);
 		return FALSE;
 	}
+	if (config->iter_entry) {
+		if (strcmp(config->filter_symbol[idx]->name,
+				config->iter_entry->name)) {
+			ERRMSG("Config error at %d: unused iteration"
+				" variable '%s'.\n", line,
+				config->iter_entry->name);
+			return FALSE;
+		}
+		config->filter_symbol[idx]->flag &= ~SYMBOL_ENTRY;
+		config->filter_symbol[idx]->flag |= VAR_ENTRY;
+		config->filter_symbol[idx]->refer_to = config->iter_entry;
+	}
 	if (get_config_token("nullify", 0, &line, NULL, NULL)) {
-		config->filter_symbol->nullify = 1;
+		config->filter_symbol[idx]->nullify = 1;
 	}
 	else if (get_config_token("size", 0, &line, NULL, NULL)) {
 		if (!read_size_entry(config, line))
@@ -8100,6 +8151,150 @@ read_filter_entry(struct config *config, int line)
 	return TRUE;
 }
 
+static int
+add_traversal_entry(struct config_entry *ce, char *member, int line)
+{
+	if (!ce)
+		return FALSE;
+
+	while (ce->next)
+		ce = ce->next;
+
+	ce->next = create_config_entry(member, LIST_ENTRY, line);
+	if (ce->next == NULL) {
+		ERRMSG("Error at line %d: Failed to read 'via' member\n",
+									line);
+		return FALSE;
+	}
+
+	ce->next->flag |= TRAVERSAL_ENTRY;
+	ce->next->flag &= ~SYMBOL_ENTRY;
+	return TRUE;
+}
+
+static int
+read_list_entry(struct config *config, int line)
+{
+	char *token = get_config_token(NULL, 0, &line, NULL, NULL);
+
+	if (!token || IS_KEYWORD(token)) {
+		ERRMSG("Config error at %d: expected list symbol after"
+		" 'in' keyword.\n", line);
+		return FALSE;
+	}
+	config->list_entry = create_config_entry(token, LIST_ENTRY, line);
+	if (!config->list_entry) {
+		ERRMSG("Error at line %d: Failed to read list symbol\n",
+									line);
+		return FALSE;
+	}
+	/* Check if user has provided 'via' or 'within' keyword */
+	if (get_config_token("via", 0, &line, NULL, NULL)) {
+		/* next token is traversal member NextMember */
+		token = get_config_token(NULL, 0, &line, NULL, NULL);
+		if (!token) {
+			ERRMSG("Config error at %d: expected member name after"
+			" 'via' keyword.\n", line);
+			return FALSE;
+		}
+		if (!add_traversal_entry(config->list_entry, token, line))
+			return FALSE;
+	}
+	else if (get_config_token("within", 0, &line, NULL, NULL)) {
+		char *s_name, *lh_member;
+		/* next value is StructName:ListHeadMember */
+		s_name = get_config_token(NULL, 0, &line, NULL, NULL);
+		if (!s_name || IS_KEYWORD(s_name)) {
+			ERRMSG("Config error at %d: expected struct name after"
+			" 'within' keyword.\n", line);
+			return FALSE;
+		}
+		lh_member = strchr(s_name, ':');
+		if (lh_member) {
+			*lh_member++ = '\0';
+			if (!strlen(lh_member)) {
+				ERRMSG("Config error at %d: expected list_head"
+					" member after ':'.\n", line);
+				return FALSE;
+			}
+			config->iter_entry->next =
+				create_config_entry(lh_member,
+							ITERATION_ENTRY, line);
+			if (!config->iter_entry->next)
+				return FALSE;
+			config->iter_entry->next->flag &= ~SYMBOL_ENTRY;
+		}
+		if (!strlen(s_name)) {
+			ERRMSG("Config error at %d: Invalid token found "
+				"after 'within' keyword.\n", line);
+			return FALSE;
+		}
+		config->iter_entry->type_name = strdup(s_name);
+	}
+	return TRUE;
+}
+
+/*
+ * Read the iteration entry (LoopConstruct). The syntax is:
+ *
+ *	for <id> in {<ArrayVar> |
+ *		    <StructVar> via <NextMember> |
+ *		    <ListHeadVar> within <StructName>:<ListHeadMember>}
+ *		erase <id>[.MemberExpression] [size <SizeExpression>|nullify]
+ *		[erase <id>...]
+ *		[...]
+ *	endfor
+ */
+static int
+read_iteration_entry(struct config *config, int line)
+{
+	int eof = 0;
+	char *token = get_config_token(NULL, 0, &line, NULL, NULL);
+
+	if (!token || IS_KEYWORD(token)) {
+		ERRMSG("Config error at %d: expected iteration VAR entry after"
+		" 'for' keyword.\n", line);
+		return FALSE;
+	}
+	config->iter_entry =
+		create_config_entry(token, ITERATION_ENTRY, line);
+	if (!config->iter_entry) {
+		ERRMSG("Error at line %d: "
+			"Failed to read iteration VAR entry.\n", line);
+		return FALSE;
+	}
+	if (!get_config_token("in", 0, &line, NULL, NULL)) {
+		char *token;
+		token = get_config_token(NULL, 0, &line, NULL, NULL);
+		if (token)
+			ERRMSG("Config error at %d: Invalid token '%s'.\n",
+								line, token);
+		ERRMSG("Config error at %d: expected token 'in'.\n", line);
+		return FALSE;
+	}
+	if (!read_list_entry(config, line))
+		return FALSE;
+
+	while (!get_config_token("endfor", 0, &line, NULL, &eof) && !eof) {
+		if (get_config_token("erase", 0, &line, NULL, NULL)) {
+			if (!read_filter_entry(config, line))
+				return FALSE;
+		}
+		else {
+			token = get_config_token(NULL, 0, &line, NULL, NULL);
+			ERRMSG("Config error at %d: "
+				"Invalid token '%s'.\n", line, token);
+			return FALSE;
+		}
+	}
+	if (eof) {
+		ERRMSG("Config error at %d: No matching 'endfor' found.\n",
+									line);
+		return FALSE;
+	}
+	return TRUE;
+}
+
 /*
  * Configuration file 'makedumpfile.conf' contains filter commands.
  * Every individual filter command is considered as a config entry. A config
@@ -8125,6 +8320,13 @@ get_config(int skip)
 		if (!read_filter_entry(config, line_count))
 			goto err_out;
 	}
+	else if (get_config_token("for", 0, &line_count, &cur_module, &eof)) {
+		if (cur_module)
+			config->module_name = strdup(cur_module);
+
+		if (!read_iteration_entry(config, line_count))
+			goto err_out;
+	}
 	else {
 		if (!eof) {
 			token = get_config_token(NULL, 0, &line_count,
@@ -8193,6 +8395,24 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 				ce->array_length = 0;
 		}
 	}
+	else if (ce->flag & VAR_ENTRY) {
+		/* iteration variable.
+		 * read the value from ce->refer_to
+		 */
+		ce->addr = ce->refer_to->addr;
+		ce->sym_addr = ce->refer_to->sym_addr;
+		ce->size = ce->refer_to->size;
+		ce->type_flag = ce->refer_to->type_flag;
+		if (!ce->type_name)
+			ce->type_name = strdup(ce->refer_to->type_name);
+
+		/* This entry has been changed hence next entry needs to
+		 * be resolved accordingly.
+		 */
+		if (ce->next)
+			ce->next->flag &= ~ENTRY_RESOLVED;
+		return TRUE;
+	}
 	else {
 		/* find the member offset */
 		ce->offset = get_member_offset(base_struct_name,
@@ -8216,9 +8436,58 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 				ce->line, base_struct_name, ce->name);
 		return FALSE;
 	}
+	if (!strcmp(ce->type_name, "list_head")) {
+		ce->type_flag |= TYPE_LIST_HEAD;
+		/* If this list head expression is a LIST entry then
+		 * mark the next entry as TRAVERSAL_ENTRY, if any.
+		 * Error out if next entry is not a last node.
+		 */
+		if ((ce->flag & LIST_ENTRY) && ce->next) {
+			if (ce->next->next) {
+				ERRMSG("Config error at %d: Only one traversal"
+					" entry is allowed for list_head type"
+					" LIST entry", ce->line);
+				return FALSE;
+			}
+			ce->next->flag |= TRAVERSAL_ENTRY;
+		}
+	}
 	ce->addr = ce->sym_addr;
 	if (ce->size < 0)
 		ce->size = 0;
+	if ((ce->flag & LIST_ENTRY) && !ce->next) {
+		/* This is the last node of LIST entry.
+		 * For the list entry symbol, the allowed data types are:
+		 * Array, Structure Pointer (with 'next' member) and list_head.
+		 *
+		 * If this is a struct or list_head data type then
+		 * create a leaf node entry with 'next' member.
+		 */
+		if ((ce->type_flag & TYPE_BASE)
+					&& (strcmp(ce->type_name, "void")))
+			return FALSE;
+
+		if ((ce->type_flag & TYPE_LIST_HEAD)
+			|| ((ce->type_flag & (TYPE_STRUCT | TYPE_ARRAY))
+							== TYPE_STRUCT)) {
+			if (!(ce->flag & TRAVERSAL_ENTRY)) {
+				ce->next = create_config_entry("next",
+							LIST_ENTRY, ce->line);
+				if (ce->next == NULL)
+					return FALSE;
+
+				ce->next->flag |= TRAVERSAL_ENTRY;
+				ce->next->flag &= ~SYMBOL_ENTRY;
+			}
+		}
+		if (ce->flag & TRAVERSAL_ENTRY) {
+			/* type name of traversal entry should match with
+			 * that of parent node.
+			 */
+			if (strcmp(base_struct_name, ce->type_name))
+				return FALSE;
+		}
+	}
 	if ((ce->type_flag & (TYPE_ARRAY | TYPE_PTR)) == TYPE_PTR) {
 		/* If it's a pointer variable (not array) then read the
 		 * pointer value. */
@@ -8227,7 +8496,7 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 		/*
 		 * if it is a void pointer then reset the size to 0
 		 * User need to provide a size to filter data referenced
-		 * by 'void *' pointer.
+		 * by 'void *' pointer or nullify option.
 		 */
 		if (!strcmp(ce->type_name, "void"))
 			ce->size = 0;
@@ -8286,6 +8555,8 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 		free(val);
 	}
 	ce->flag |= ENTRY_RESOLVED;
+	if (ce->next)
+		ce->next->flag &= ~ENTRY_RESOLVED;
 	return TRUE;
 }
 
@@ -8294,18 +8565,87 @@ get_config_symbol_addr(struct config_entry *ce,
 			unsigned long long base_addr,
 			char *base_struct_name)
 {
+	unsigned long long addr = 0;
+
 	if (!(ce->flag & ENTRY_RESOLVED)) {
 		if (!resolve_config_entry(ce, base_addr, base_struct_name))
 			return 0;
 	}
 
+	if ((ce->flag & LIST_ENTRY)) {
+		/* handle List entry differently */
+		if (!ce->next) {
+			/* leaf node. */
+			if (ce->type_flag & TYPE_ARRAY) {
+				if (ce->index == ce->array_length)
+					return 0;
+				if (!(ce->type_flag & TYPE_PTR))
+					return (ce->addr +
+							(ce->index * ce->size));
+				/* Array of pointers.
+				 *
+				 * Array may contain NULL pointers at some
+				 * indexes. Hence return the next non-null
+				 * address value.
+				 */
+				while (ce->index < ce->array_length) {
+					addr = read_pointer_value(ce->addr +
+						(ce->index * pointer_size));
+					ce->index++;
+					if (addr)
+						break;
+				}
+				return addr;
+			}
+			else {
+				if (ce->addr == ce->cmp_addr)
+					return 0;
+
+				/* Set the leaf node as unresolved, so that
+				 * it will be resolved every time when
+				 * get_config_symbol_addr is called untill
+				 * it hits the exit condiftion.
+				 */
+				ce->flag &= ~ENTRY_RESOLVED;
+			}
+		}
+		else if ((ce->next->next == NULL) &&
+					!(ce->next->type_flag & TYPE_ARRAY)) {
+			/* the next node is leaf node. for non-array element
+			 * Set the sym_addr and addr of this node with that of
+			 * leaf node.
+			 */
+			addr = ce->addr;
+			ce->addr = ce->next->addr;
+
+			if (!(ce->type_flag & TYPE_LIST_HEAD)) {
+				if (addr == ce->next->cmp_addr)
+					return 0;
+
+				if (!ce->next->cmp_addr) {
+					/* safeguard against circular
+					 * link-list
+					 */
+					ce->next->cmp_addr = addr;
+				}
+
+				/* Force resolution of traversal node */
+				if (ce->addr && !resolve_config_entry(ce->next,
+						ce->addr, ce->type_name))
+					return 0;
+
+				return addr;
+			}
+		}
+	}
+
 	if (ce->next && ce->addr) {
 		/* Populate nullify flag down the list */
 		ce->next->nullify = ce->nullify;
 		return get_config_symbol_addr(ce->next, ce->addr,
 							ce->type_name);
 	}
-	else if (ce->nullify) {
+	else if (!ce->next && ce->nullify) {
 		/* nullify is applicable to pointer type */
 		if (ce->type_flag & TYPE_PTR)
 			return ce->sym_addr;
@@ -8340,6 +8680,48 @@ get_config_symbol_size(struct config_entry *ce,
 	}
 }
 
+static int
+resolve_list_entry(struct config_entry *ce, unsigned long long base_addr,
+			char *base_struct_name, char **out_type_name,
+			unsigned char *out_type_flag)
+{
+	if (!(ce->flag & ENTRY_RESOLVED)) {
+		if (!resolve_config_entry(ce, base_addr, base_struct_name))
+			return FALSE;
+	}
+
+	if (ce->next && (ce->next->flag & TRAVERSAL_ENTRY) &&
+				(ce->type_flag & TYPE_ARRAY)) {
+		/*
+		 * We are here because user has provided
+		 * traversal member for ArrayVar using 'via' keyword.
+		 *
+		 * Print warning and continue.
+		 */
+		ERRMSG("Warning: line %d: 'via' keyword not required "
+			"for ArrayVar.\n", ce->next->line);
+		free_config_entry(ce->next);
+		ce->next = NULL;
+	}
+	if ((ce->type_flag & TYPE_LIST_HEAD) && ce->next &&
+			(ce->next->flag & TRAVERSAL_ENTRY)) {
+		/* set cmp_addr for list empty condition.  */
+		ce->next->cmp_addr = ce->sym_addr;
+	}
+	if (ce->next && ce->addr) {
+		return resolve_list_entry(ce->next, ce->addr,
+				ce->type_name, out_type_name, out_type_flag);
+	}
+	else {
+		ce->index = 0;
+		if (out_type_name)
+			*out_type_name = ce->type_name;
+		if (out_type_flag)
+			*out_type_flag = ce->type_flag;
+	}
+	return TRUE;
+}
+
 void
 insert_filter_info(struct filter_info *fl_info)
 {
@@ -8420,9 +8802,138 @@ update_filter_info(struct config_entry *filter_symbol,
  * return FALSE if module debuginfo is not available.
  */
 int
+initialize_iteration_entry(struct config_entry *ie,
+				char *type_name, unsigned char type_flag)
+{
+	if (!(ie->flag & ITERATION_ENTRY))
+		return FALSE;
+
+	if (type_flag & TYPE_LIST_HEAD) {
+		if (!ie->type_name) {
+			ERRMSG("Config error at %d: Use 'within' keyword "
+				"to specify StructName:ListHeadMember.\n",
+				ie->line);
+			return FALSE;
+		}
+		/*
+		 * If the LIST entry is of list_head type and user has not
+		 * specified the member name where iteration entry is hooked
+		 * on to list_head, then we default to member name 'list'.
+		 */
+		if (!ie->next) {
+			ie->next = create_config_entry("list", ITERATION_ENTRY,
+								ie->line);
+			ie->next->flag &= ~SYMBOL_ENTRY;
+		}
+	}
+	else {
+		if (ie->type_name) {
+			/* looks like user has used 'within' keyword for
+			 * non-list_head VAR. Print the warning and continue.
+			 */
+			ERRMSG("Warning: line %d: 'within' keyword not "
+				"required for ArrayVar/StructVar.\n", ie->line);
+			free(ie->type_name);
+
+			/* remove the next list_head member from iteration
+			 * entry that would have added as part of 'within'
+			 * keyword processing.
+			 */
+			if (ie->next) {
+				free_config_entry(ie->next);
+				ie->next = NULL;
+			}
+		}
+		ie->type_name = strdup(type_name);
+	}
+
+	if (!ie->size) {
+		ie->size = get_structure_size(ie->type_name,
+						DWARF_INFO_GET_STRUCT_SIZE);
+		if (ie->size == FAILED_DWARFINFO) {
+			ERRMSG("Config error at %d: "
+				"Can't get size for type: %s.\n",
+				ie->line, ie->type_name);
+			return FALSE;
+		}
+		else if (ie->size == NOT_FOUND_STRUCTURE) {
+			ERRMSG("Config error at %d: "
+				"Can't find structure: %s.\n",
+				ie->line, ie->type_name);
+			return FALSE;
+		}
+	}
+	if (type_flag & TYPE_LIST_HEAD) {
+		if (!resolve_config_entry(ie->next, 0, ie->type_name))
+			return FALSE;
+
+		if (strcmp(ie->next->type_name, "list_head")) {
+			ERRMSG("Config error at %d: "
+				"Member '%s' is not of 'list_head' type.\n",
+				ie->next->line, ie->next->name);
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+int
+list_entry_empty(struct config_entry *le, struct config_entry *ie)
+{
+	unsigned long long addr;
+
+	/* Error out if arguments are not correct */
+	if (!(le->flag & LIST_ENTRY) || !(ie->flag & ITERATION_ENTRY)) {
+		ERRMSG("Invalid arguments\n");
+		return TRUE;
+	}
+	addr = get_config_symbol_addr(le, 0, NULL);
+	if (!addr)
+		return TRUE;
+
+	if (ie->next) {
+		/* we are dealing with list_head */
+		ie->next->addr = addr;
+		ie->addr = addr - ie->next->offset;
+		//resolve_iteration_entry(ie, addr);
+	}
+	else
+		ie->addr = addr;
+	return FALSE;
+}
+
+int
 process_config(struct config *config)
 {
-	update_filter_info(config->filter_symbol, config->size_symbol);
+	int i;
+	if (config->list_entry) {
+		unsigned char type_flag;
+		char *type_name = NULL;
+		/*
+		 * We are dealing with 'for' command.
+		 * - First resolve list entry.
+		 * - Initialize iteration entry for iteration.
+		 * - Populate iteration entry untill list entry empty.
+		 */
+		if (!resolve_list_entry(config->list_entry, 0, NULL,
+					&type_name, &type_flag)) {
+			return FALSE;
+		}
+		if (!initialize_iteration_entry(config->iter_entry,
+						type_name, type_flag)) {
+			return FALSE;
+		}
+
+		while (!list_entry_empty(config->list_entry,
+						config->iter_entry)) {
+			for (i = 0; i < config->num_filter_symbols; i++)
+				update_filter_info(config->filter_symbol[i],
+							config->size_symbol[i]);
+		}
+	}
+	else
+		update_filter_info(config->filter_symbol[0],
+						config->size_symbol[0]);
 
 	return TRUE;
 }
diff --git a/makedumpfile.h b/makedumpfile.h
index 08d1615..2241ff2 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -1275,6 +1275,7 @@ struct dwarf_info {
 #define TYPE_ARRAY	0x02
 #define TYPE_PTR	0x04
 #define TYPE_STRUCT	0x08
+#define TYPE_LIST_HEAD	0x10
 
 extern struct dwarf_info	dwarf_info;
 
@@ -1297,18 +1298,25 @@ struct config_entry {
 	unsigned long long	sym_addr;	/* Symbol address */
 	unsigned long long	addr;		/* Symbol address or
 						   value pointed by sym_addr */
+	unsigned long long	cmp_addr;	/* for LIST_ENTRY */
 	unsigned long		offset;
 	unsigned long		type_flag;
 	long			array_length;
+	long			index;
 	long			size;
 	int			line;	/* Line number in config file. */
+	struct config_entry	*refer_to;
 	struct config_entry	*next;
 };
 
 /* flags for config_entry.flag */
 #define FILTER_ENTRY	0x0001
 #define SIZE_ENTRY	0x0002
+#define ITERATION_ENTRY	0x0004
+#define LIST_ENTRY	0x0008
 #define SYMBOL_ENTRY	0x0010
+#define VAR_ENTRY	0x0020
+#define TRAVERSAL_ENTRY	0x0040
 #define ENTRY_RESOLVED	0x8000
 
 /*
@@ -1329,13 +1337,18 @@ struct filter_config {
 
 struct config {
 	char			*module_name;
-	struct config_entry	*filter_symbol;
-	struct config_entry	*size_symbol;
+	struct config_entry	*iter_entry;
+	struct config_entry	*list_entry;
+	int			num_filter_symbols;
+	struct config_entry	**filter_symbol;
+	struct config_entry	**size_symbol;
 };
 
 #define IS_KEYWORD(tkn)	\
 	(!strcmp(tkn, "erase") || !strcmp(tkn, "size") || \
-	!strcmp(tkn, "nullify"))
+	!strcmp(tkn, "nullify") || !strcmp(tkn, "for") || \
+	!strcmp(tkn, "in") || !strcmp(tkn, "within") || \
+	!strcmp(tkn, "endfor"))
 
 int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size);
 off_t paddr_to_offset(unsigned long long paddr);



From anderson at redhat.com  Fri Mar 11 09:07:50 2011
From: anderson at redhat.com (Dave Anderson)
Date: Fri, 11 Mar 2011 09:07:50 -0500 (EST)
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
Message-ID: <1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>



----- Original Message -----
> Hi All,
> 
> Please find the makedumpfile enhancement patchset that introduces a data
> filtering feature which enables makedumpfile to filter out desired kernel
> symbol data and it's members from the specified VMCORE file. The data to be
> filtered out is poisoned with character 'X' (58 in Hex).
> 
> This feature will be very useful for the customers who wants to erase the
> customer sensitive data like security keys and other confidential data, in
> DUMPFILE before sending it to support team for analysis.
> 
> This feature introduces a filter config file where, using filter commands,
> user can specify desired kernel data symbols and it's members that need to be
> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
> provided in the filter.conf(8) man page.
> 
> The first 4 patches prepares the base work for filtering framework.  The last 2
> patches implements the generic filtering framework to erase desired kernel
> data.
> 
> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
> kernel. The feature supports filtering data from ELF as well as kdump-compressed
> formatted dump.
> 
> Please review the patchset and let me know your comments.
> 
> Thanks,
> -Mahesh.

Hi Mahesh,

Is there any notation in the filtered ELF kdump or compressed kdump file
that filtering has been done?  Given that there may be potential ramifications
in crash utility behavior (or outright failure?), the crash utility should
display a warning message early on during invocation.

Thanks,
  Dave

 
> ---
> 
> Mahesh Salgaonkar (6):
> makedumpfile: Add '--config' option to specify filter config file.
> makedumpfile: Apply relocation while loading module debuginfo.
> makedumpfile: Load the module symbol data from vmcore.
> makedumpfile: Introduce routines to get type name from debuginfo.
> makedumpfile: Read and process filter commands from config file.
> makedumpfile: Read and process 'for' command from config file.
> 
> 
> Makefile | 8
> filter.conf | 149 ++++
> filter.conf.8 | 419 +++++++++++
> makedumpfile.8 | 20 +
> makedumpfile.c | 2113
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> makedumpfile.h | 152 ++++
> 6 files changed, 2782 insertions(+), 79 deletions(-)
> create mode 100644 filter.conf
> create mode 100644 filter.conf.8
> 
> --
> Signature


From oomichi at mxs.nes.nec.co.jp  Sun Mar 13 21:55:45 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Mon, 14 Mar 2011 10:55:45 +0900
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
References: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
Message-ID: <20110314105545.547fbac8.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Fri, 11 Mar 2011 13:34:32 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> 
> Please find the makedumpfile enhancement patchset that introduces a data
> filtering feature which enables makedumpfile to filter out desired kernel
> symbol data and it's members from the specified VMCORE file. The data to be
> filtered out is poisoned with character 'X' (58 in Hex).
> 
> This feature will be very useful for the customers who wants to erase the
> customer sensitive data like security keys and other confidential data, in
> DUMPFILE before sending it to support team for analysis.
> 
> This feature introduces a filter config file where, using filter commands,
> user can specify desired kernel data symbols and it's members that need to be
> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
> provided in the filter.conf(8) man page.
> 
> The first 4 patches prepares the base work for filtering framework. The last 2
> patches implements the generic filtering framework to erase desired kernel
> data.
> 
> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
> kernel. The feature supports filtering data from ELF as well as
> kdump-compressed formatted dump.
> 
> Please review the patchset and let me know your comments.

This patchset is interesting, and I start reviewing.
I haven't reviewed the code yet, and this is a quick review.

* About the filename of configuration.
  Is filter.conf only for makedumpfile command ?
  If so, I feel filter.conf is too generic file name.
  How about makedumpfile.conf ?

  If makedumpfile.conf, it is clear that the file is only for
  makedumpfile, and we will be able to use the file for not only
  erasing secret data but also other purpose.
  (ex: specifying the other options like -d 31 in the file)


Thanks
Ken'ichi Ohmichi


From oomichi at mxs.nes.nec.co.jp  Sun Mar 13 22:44:57 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Mon, 14 Mar 2011 11:44:57 +0900
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
References: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
	<1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
Message-ID: <20110314114457.7e252f0d.oomichi@mxs.nes.nec.co.jp>


Hi Dave, Mahesh,

On Fri, 11 Mar 2011 09:07:50 -0500 (EST)
Dave Anderson <anderson at redhat.com> wrote:
> > 
> > Please find the makedumpfile enhancement patchset that introduces a data
> > filtering feature which enables makedumpfile to filter out desired kernel
> > symbol data and it's members from the specified VMCORE file. The data to be
> > filtered out is poisoned with character 'X' (58 in Hex).
> > 
> > This feature will be very useful for the customers who wants to erase the
> > customer sensitive data like security keys and other confidential data, in
> > DUMPFILE before sending it to support team for analysis.
> > 
> > This feature introduces a filter config file where, using filter commands,
> > user can specify desired kernel data symbols and it's members that need to be
> > filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
> > provided in the filter.conf(8) man page.
> > 
> > The first 4 patches prepares the base work for filtering framework.  The last 2
> > patches implements the generic filtering framework to erase desired kernel
> > data.
> > 
> > I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
> > kernel. The feature supports filtering data from ELF as well as kdump-compressed
> > formatted dump.
> > 
> > Please review the patchset and let me know your comments.
> > 
> > Thanks,
> > -Mahesh.
> 
> Hi Mahesh,
> 
> Is there any notation in the filtered ELF kdump or compressed kdump file
> that filtering has been done?  Given that there may be potential ramifications
> in crash utility behavior (or outright failure?), the crash utility should
> display a warning message early on during invocation.

That is a good point.

How about adding new members (like offset_eraseinfo, size_eraseinfo)
into the sub header in compressed kdump file, and setting version 5
in the header version (disk_dump_header.header_version) ?
These members show the erased information like the following:

struct kdump_sub_header {
        unsigned long   phys_base;
        int             dump_level;     /* header_version 1 and later */
        int             split;          /* header_version 2 and later */
        unsigned long   start_pfn;      /* header_version 2 and later */
        unsigned long   end_pfn;        /* header_version 2 and later */
        off_t           offset_vmcoreinfo;/* header_version 3 and later */
        unsigned long   size_vmcoreinfo;  /* header_version 3 and later */
        off_t           offset_note;      /* header_version 4 and later */
        unsigned long   size_note;        /* header_version 4 and later */
+       off_t           offset_eraseinfo; /* header_version 5 and later */
+       unsigned long   size_eraseinfo;   /* header_version 5 and later */
};

The erased information contains only effective lines in the
configuration file. 
In case of ELF kdump file, how about adding a ELF note section
which also show the erased information ?

The crash utility will be able to know the name list of the
erased symbols from the information.


Thanks
Ken'ichi Ohmichi


From mahesh at linux.vnet.ibm.com  Mon Mar 14 02:18:19 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Mon, 14 Mar 2011 11:48:19 +0530
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
References: <1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
Message-ID: <4D7DB32B.9030705@linux.vnet.ibm.com>

On 03/11/2011 07:37 PM, Dave Anderson wrote:
> 
> 
> ----- Original Message -----
>> Hi All,
>>
>> Please find the makedumpfile enhancement patchset that introduces a data
>> filtering feature which enables makedumpfile to filter out desired kernel
>> symbol data and it's members from the specified VMCORE file. The data to be
>> filtered out is poisoned with character 'X' (58 in Hex).
>>
>> This feature will be very useful for the customers who wants to erase the
>> customer sensitive data like security keys and other confidential data, in
>> DUMPFILE before sending it to support team for analysis.
>>
>> This feature introduces a filter config file where, using filter commands,
>> user can specify desired kernel data symbols and it's members that need to be
>> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
>> provided in the filter.conf(8) man page.
>>
>> The first 4 patches prepares the base work for filtering framework.  The last 2
>> patches implements the generic filtering framework to erase desired kernel
>> data.
>>
>> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
>> kernel. The feature supports filtering data from ELF as well as kdump-compressed
>> formatted dump.
>>
>> Please review the patchset and let me know your comments.
>>
>> Thanks,
>> -Mahesh.
> 
> Hi Mahesh,
> 
> Is there any notation in the filtered ELF kdump or compressed kdump file
> that filtering has been done?  Given that there may be potential ramifications
> in crash utility behavior (or outright failure?), the crash utility should
> display a warning message early on during invocation.

Hmm... I did not think about it. I am thinking of following approach:

- Set a bit in dump_level (DL_FILTER_KERNEL_DATA => 0x800) that will
denote that filtering has been done.
- For compressed kdump file we anyway have dump_level available in kdump
sub header
- For ELF kdump, currently we do not have any way to convey dump_level
info to crash utility (Ken'chi, correct me if I am wrong). How about
introducing an additional ELF note (NT_DUMP_LEVEL) that will include
dump_level info.

Any other suggestions are welcome.

Thanks,
-Mahesh.
> 
> Thanks,
>   Dave
> 
> 
>> ---
>>
>> Mahesh Salgaonkar (6):
>> makedumpfile: Add '--config' option to specify filter config file.
>> makedumpfile: Apply relocation while loading module debuginfo.
>> makedumpfile: Load the module symbol data from vmcore.
>> makedumpfile: Introduce routines to get type name from debuginfo.
>> makedumpfile: Read and process filter commands from config file.
>> makedumpfile: Read and process 'for' command from config file.
>>
>>
>> Makefile | 8
>> filter.conf | 149 ++++
>> filter.conf.8 | 419 +++++++++++
>> makedumpfile.8 | 20 +
>> makedumpfile.c | 2113
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>> makedumpfile.h | 152 ++++
>> 6 files changed, 2782 insertions(+), 79 deletions(-)
>> create mode 100644 filter.conf
>> create mode 100644 filter.conf.8
>>
>> --
>> Signature



From mahesh at linux.vnet.ibm.com  Mon Mar 14 02:26:17 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Mon, 14 Mar 2011 11:56:17 +0530
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <20110314105545.547fbac8.oomichi@mxs.nes.nec.co.jp>
References: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
	<20110314105545.547fbac8.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4D7DB509.5070107@linux.vnet.ibm.com>

On 03/14/2011 07:25 AM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Fri, 11 Mar 2011 13:34:32 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>>
>> Please find the makedumpfile enhancement patchset that introduces a data
>> filtering feature which enables makedumpfile to filter out desired kernel
>> symbol data and it's members from the specified VMCORE file. The data to be
>> filtered out is poisoned with character 'X' (58 in Hex).
>>
>> This feature will be very useful for the customers who wants to erase the
>> customer sensitive data like security keys and other confidential data, in
>> DUMPFILE before sending it to support team for analysis.
>>
>> This feature introduces a filter config file where, using filter commands,
>> user can specify desired kernel data symbols and it's members that need to be
>> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
>> provided in the filter.conf(8) man page.
>>
>> The first 4 patches prepares the base work for filtering framework. The last 2
>> patches implements the generic filtering framework to erase desired kernel
>> data.
>>
>> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
>> kernel. The feature supports filtering data from ELF as well as
>> kdump-compressed formatted dump.
>>
>> Please review the patchset and let me know your comments.
> 
> This patchset is interesting, and I start reviewing.
> I haven't reviewed the code yet, and this is a quick review.
> 
> * About the filename of configuration.
>   Is filter.conf only for makedumpfile command ?
>   If so, I feel filter.conf is too generic file name.
>   How about makedumpfile.conf ?

:-) I initially started with that name. But since it was only for
filtering purpose I went for filter.conf. However, I am ok with the name
makdumpfile.conf
> 
>   If makedumpfile.conf, it is clear that the file is only for
>   makedumpfile, and we will be able to use the file for not only
>   erasing secret data but also other purpose.
>   (ex: specifying the other options like -d 31 in the file)

Agree, Makes sense.
> 
> 
> Thanks
> Ken'ichi Ohmichi



From oomichi at mxs.nes.nec.co.jp  Mon Mar 14 03:05:28 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Mon, 14 Mar 2011 16:05:28 +0900
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <4D7DB32B.9030705@linux.vnet.ibm.com>
References: <1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
	<4D7DB32B.9030705@linux.vnet.ibm.com>
Message-ID: <20110314160528.943d9149.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Mon, 14 Mar 2011 11:48:19 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > 
> > 
> > ----- Original Message -----
> >> Hi All,
> >>
> >> Please find the makedumpfile enhancement patchset that introduces a data
> >> filtering feature which enables makedumpfile to filter out desired kernel
> >> symbol data and it's members from the specified VMCORE file. The data to be
> >> filtered out is poisoned with character 'X' (58 in Hex).
> >>
> >> This feature will be very useful for the customers who wants to erase the
> >> customer sensitive data like security keys and other confidential data, in
> >> DUMPFILE before sending it to support team for analysis.
> >>
> >> This feature introduces a filter config file where, using filter commands,
> >> user can specify desired kernel data symbols and it's members that need to be
> >> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
> >> provided in the filter.conf(8) man page.
> >>
> >> The first 4 patches prepares the base work for filtering framework.  The last 2
> >> patches implements the generic filtering framework to erase desired kernel
> >> data.
> >>
> >> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
> >> kernel. The feature supports filtering data from ELF as well as kdump-compressed
> >> formatted dump.
> >>
> >> Please review the patchset and let me know your comments.
> >>
> >> Thanks,
> >> -Mahesh.
> > 
> > Hi Mahesh,
> > 
> > Is there any notation in the filtered ELF kdump or compressed kdump file
> > that filtering has been done?  Given that there may be potential ramifications
> > in crash utility behavior (or outright failure?), the crash utility should
> > display a warning message early on during invocation.
> 
> Hmm... I did not think about it. I am thinking of following approach:
> 
> - Set a bit in dump_level (DL_FILTER_KERNEL_DATA => 0x800) that will
> denote that filtering has been done.
> - For compressed kdump file we anyway have dump_level available in kdump
> sub header
> - For ELF kdump, currently we do not have any way to convey dump_level
> info to crash utility (Ken'chi, correct me if I am wrong). How about
> introducing an additional ELF note (NT_DUMP_LEVEL) that will include
> dump_level info.

On your above approach, a member of support team for analysis cannot
know what symbols are erased.
And he/she will not believe the received dumpfile from a customer site.

I have one question, do you think it is better not to inform support
team of the erased symbols ?
Is also the list of the erased symbols secret ?


Thanks
Ken'ichi Ohmichi


From BUENDGEN at de.ibm.com  Mon Mar 14 04:51:35 2011
From: BUENDGEN at de.ibm.com (Reinhard Buendgen)
Date: Mon, 14 Mar 2011 09:51:35 +0100
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <20110314160528.943d9149.oomichi@mxs.nes.nec.co.jp>
References: <1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
	<4D7DB32B.9030705@linux.vnet.ibm.com>
	<20110314160528.943d9149.oomichi@mxs.nes.nec.co.jp>
Message-ID: <OF551E2EE1.486CA207-ONC1257853.002F9F47-C1257853.0030A8D2@de.ibm.com>

Hi,

I do not think the list of erased symbols must be secret. After all we use 
a special value to do most of the erasing. Thus hinting at what was 
erased. 
The intention of this item is certainly not to unduly confuse service. 

this work shall increase the customers confidence that no sensitive data 
may leak through a dump - clearly at the cost with very low probability 
some problems may no longer be analyzed. - But that's all you can do if 
sensitive data is really needed to analyze a problem.

Mit freundlichen Gr??en/Best Regards/Cordialement 

Reinhard

Dr. Reinhard B?ndgen 
RAS & Crypto Architect for Linux on System z 
Virtualization and Systems Management 
 
Mail:buendgen at de.ibm.com
Phone: ++49-(0)7031-16-1130
Fax: ++49-(0)7031-16-3456 
 
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Gesch?ftsf?hrung: Dirk Wittkopp 
Sitz der Gesellschaft: B?blingen
Registergericht: Amtsgericht Stuttgart, HRB 243294





From:   "Ken'ichi Ohmichi" <oomichi at mxs.nes.nec.co.jp>
To:     Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com>
Cc:     Dave Anderson <anderson at redhat.com>, V Srivatsa 
<vsrivatsa at in.ibm.com>, kexec at lists.infradead.org, Ananth N 
Mavinakayanahalli <ananth at in.ibm.com>, Reinhard Buendgen/Germany/IBM at IBMDE
Date:   14.03.2011 08:08
Subject:        Re: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement 
to filter out kernel data from vmcore




Hi Mahesh,

On Mon, 14 Mar 2011 11:48:19 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > 
> > 
> > ----- Original Message -----
> >> Hi All,
> >>
> >> Please find the makedumpfile enhancement patchset that introduces a 
data
> >> filtering feature which enables makedumpfile to filter out desired 
kernel
> >> symbol data and it's members from the specified VMCORE file. The data 
to be
> >> filtered out is poisoned with character 'X' (58 in Hex).
> >>
> >> This feature will be very useful for the customers who wants to erase 
the
> >> customer sensitive data like security keys and other confidential 
data, in
> >> DUMPFILE before sending it to support team for analysis.
> >>
> >> This feature introduces a filter config file where, using filter 
commands,
> >> user can specify desired kernel data symbols and it's members that 
need to be
> >> filtered out while creating o/p DUMPFILE. The Syntax for filter 
commands are
> >> provided in the filter.conf(8) man page.
> >>
> >> The first 4 patches prepares the base work for filtering framework. 
The last 2
> >> patches implements the generic filtering framework to erase desired 
kernel
> >> data.
> >>
> >> I have tested these patches on x86_64 and s390x architecture against 
RHEL6 GA
> >> kernel. The feature supports filtering data from ELF as well as 
kdump-compressed
> >> formatted dump.
> >>
> >> Please review the patchset and let me know your comments.
> >>
> >> Thanks,
> >> -Mahesh.
> > 
> > Hi Mahesh,
> > 
> > Is there any notation in the filtered ELF kdump or compressed kdump 
file
> > that filtering has been done?  Given that there may be potential 
ramifications
> > in crash utility behavior (or outright failure?), the crash utility 
should
> > display a warning message early on during invocation.
> 
> Hmm... I did not think about it. I am thinking of following approach:
> 
> - Set a bit in dump_level (DL_FILTER_KERNEL_DATA => 0x800) that will
> denote that filtering has been done.
> - For compressed kdump file we anyway have dump_level available in kdump
> sub header
> - For ELF kdump, currently we do not have any way to convey dump_level
> info to crash utility (Ken'chi, correct me if I am wrong). How about
> introducing an additional ELF note (NT_DUMP_LEVEL) that will include
> dump_level info.

On your above approach, a member of support team for analysis cannot
know what symbols are erased.
And he/she will not believe the received dumpfile from a customer site.

I have one question, do you think it is better not to inform support
team of the erased symbols ?
Is also the list of the erased symbols secret ?


Thanks
Ken'ichi Ohmichi

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110314/1c4d8a88/attachment-0001.html>

From mahesh at linux.vnet.ibm.com  Mon Mar 14 14:13:15 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Mon, 14 Mar 2011 23:43:15 +0530
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <20110309142108.GD16951@cr0.redhat.com>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
	<20110309122046.GC16951@cr0.redhat.com>
	<20110309234657.264d3080@kryten>
	<20110309142108.GD16951@cr0.redhat.com>
Message-ID: <20110314181315.GA16075@in.ibm.com>

On Wed, Mar 09, 2011 at 10:21:08PM +0800, Am?rico Wang wrote:
> On Wed, Mar 09, 2011 at 11:46:57PM +1100, Anton Blanchard wrote:
> >
> >Hi,
> >
> >> The crashkernel region is specified via kernel cmdline, so why
> >> not just drop a failure when it overlaps with RMO region?
> >> Am I missing something?
> >
> >Unfortunately a ppc64 kernel requires a chunk of RMO memory. We would
> >need the ability to specify multiple crashkernel regions - about 32MB
> >in the RMO and the rest can be anywhere. That sounds pretty fragile for
> >a user to configure successfully on the cmdline.
> >
> >Thats why the ppc64 crashkernel region begins mid way through the RMO
> >region. It means both kernels get a chunk of RMO and we only have to
> >deal with one crashkernel reservation in all the tools and
> >documentation.
> >
> 
> So, when I specify 128M in cmdline, 32M of them are RMO, and the
> rest 96M are normal memory? And when I want to free all of them,
> actually the 32M RMO will never be freed?

In ppc64 implementation the crashkernel region begins mid way through
the RMO and spans across into the normal memory. For e.g. on power system
with 128M RMO size, when user specifies 128M in cmdline, the crashkernel
starts from default offset 64M through 192M. Which means 64M in RMO region
and rest beyond RMO.

 <-------------------RMO--------------->
                             <---rtas-->
0                    64M               128M                     End
|=====================|=================|===========|============|
           Crash_start|<------------128M----------->| Crash End

During free we do free all of them including RMO region. But since the rtas
region is always on top of RMO, crashkernel memory overlaps rtas region and
we endup freeing that even, which is causing the crash.

> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

-- 
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>


From mahesh at linux.vnet.ibm.com  Tue Mar 15 01:29:24 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Tue, 15 Mar 2011 10:59:24 +0530
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <20110314114457.7e252f0d.oomichi@mxs.nes.nec.co.jp>
References: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
	<1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
	<20110314114457.7e252f0d.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4D7EF934.3090008@linux.vnet.ibm.com>

Hi Ken'chi,

On 03/14/2011 08:14 AM, Ken'ichi Ohmichi wrote:
> 
> Hi Dave, Mahesh,
> 
> On Fri, 11 Mar 2011 09:07:50 -0500 (EST)
> Dave Anderson <anderson at redhat.com> wrote:
>>>
>>> Please find the makedumpfile enhancement patchset that introduces a data
>>> filtering feature which enables makedumpfile to filter out desired kernel
>>> symbol data and it's members from the specified VMCORE file. The data to be
>>> filtered out is poisoned with character 'X' (58 in Hex).
>>>
>>> This feature will be very useful for the customers who wants to erase the
>>> customer sensitive data like security keys and other confidential data, in
>>> DUMPFILE before sending it to support team for analysis.
>>>
>>> This feature introduces a filter config file where, using filter commands,
>>> user can specify desired kernel data symbols and it's members that need to be
>>> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
>>> provided in the filter.conf(8) man page.
>>>
>>> The first 4 patches prepares the base work for filtering framework.  The last 2
>>> patches implements the generic filtering framework to erase desired kernel
>>> data.
>>>
>>> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
>>> kernel. The feature supports filtering data from ELF as well as kdump-compressed
>>> formatted dump.
>>>
>>> Please review the patchset and let me know your comments.
>>>
>>> Thanks,
>>> -Mahesh.
>>
>> Hi Mahesh,
>>
>> Is there any notation in the filtered ELF kdump or compressed kdump file
>> that filtering has been done?  Given that there may be potential ramifications
>> in crash utility behavior (or outright failure?), the crash utility should
>> display a warning message early on during invocation.
> 
> That is a good point.
> 
> How about adding new members (like offset_eraseinfo, size_eraseinfo)
> into the sub header in compressed kdump file, and setting version 5
> in the header version (disk_dump_header.header_version) ?
> These members show the erased information like the following:
> 
> struct kdump_sub_header {
>         unsigned long   phys_base;
>         int             dump_level;     /* header_version 1 and later */
>         int             split;          /* header_version 2 and later */
>         unsigned long   start_pfn;      /* header_version 2 and later */
>         unsigned long   end_pfn;        /* header_version 2 and later */
>         off_t           offset_vmcoreinfo;/* header_version 3 and later */
>         unsigned long   size_vmcoreinfo;  /* header_version 3 and later */
>         off_t           offset_note;      /* header_version 4 and later */
>         unsigned long   size_note;        /* header_version 4 and later */
> +       off_t           offset_eraseinfo; /* header_version 5 and later */
> +       unsigned long   size_eraseinfo;   /* header_version 5 and later */
> };
> 
> The erased information contains only effective lines in the
> configuration file.

Do you mean the info would contain symbol name/expression, resolved
symbol/vmalloc addresses and its sizes that got filtered out?

What I mean by symbol expression is, user can ask makedumpfile to erase
a data referred by a member from the symbol variable of structure type.
e.g.
	struct S1 {
		int a;
	};
	struct S2 {
		struct S1 *mystruct1;
	};

	struct S2 mystruct2;

	#Filter command
	erase mystruct2.mystruct1.a

So the erase information in kdump header would contain:

-----------------------------------
Symbol Name: mystruct2.mystruct1.a
Filter Addr: &mystruct2.mystruct1->a
Filter Size: 4	(sizeof type int)
-----------------------------------

For erase commands in loop construct we will have multiple Filter addresses.

Please let me know your comment on the above format.

Hi Dave,

Do you think the above information would be enough for crash utility to
interpret?

Thanks,
-Mahesh.

> In case of ELF kdump file, how about adding a ELF note section
> which also show the erased information ?
> 
> The crash utility will be able to know the name list of the
> erased symbols from the information.
> 
> 
> Thanks
> Ken'ichi Ohmichi
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



From oomichi at mxs.nes.nec.co.jp  Tue Mar 15 02:12:47 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Tue, 15 Mar 2011 15:12:47 +0900
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <4D7EF934.3090008@linux.vnet.ibm.com>
References: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
	<1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
	<20110314114457.7e252f0d.oomichi@mxs.nes.nec.co.jp>
	<4D7EF934.3090008@linux.vnet.ibm.com>
Message-ID: <20110315151247.23fc84bc.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Tue, 15 Mar 2011 10:59:24 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >>
> >> Is there any notation in the filtered ELF kdump or compressed kdump file
> >> that filtering has been done?  Given that there may be potential ramifications
> >> in crash utility behavior (or outright failure?), the crash utility should
> >> display a warning message early on during invocation.
> > 
> > That is a good point.
> > 
> > How about adding new members (like offset_eraseinfo, size_eraseinfo)
> > into the sub header in compressed kdump file, and setting version 5
> > in the header version (disk_dump_header.header_version) ?
> > These members show the erased information like the following:
> > 
> > struct kdump_sub_header {
> >         unsigned long   phys_base;
> >         int             dump_level;     /* header_version 1 and later */
> >         int             split;          /* header_version 2 and later */
> >         unsigned long   start_pfn;      /* header_version 2 and later */
> >         unsigned long   end_pfn;        /* header_version 2 and later */
> >         off_t           offset_vmcoreinfo;/* header_version 3 and later */
> >         unsigned long   size_vmcoreinfo;  /* header_version 3 and later */
> >         off_t           offset_note;      /* header_version 4 and later */
> >         unsigned long   size_note;        /* header_version 4 and later */
> > +       off_t           offset_eraseinfo; /* header_version 5 and later */
> > +       unsigned long   size_eraseinfo;   /* header_version 5 and later */
> > };
> > 
> > The erased information contains only effective lines in the
> > configuration file.
> 
> Do you mean the info would contain symbol name/expression, resolved
> symbol/vmalloc addresses and its sizes that got filtered out?
> 
> What I mean by symbol expression is, user can ask makedumpfile to erase
> a data referred by a member from the symbol variable of structure type.
> e.g.
> 	struct S1 {
> 		int a;
> 	};
> 	struct S2 {
> 		struct S1 *mystruct1;
> 	};
> 
> 	struct S2 mystruct2;
> 
> 	#Filter command
> 	erase mystruct2.mystruct1.a
> 
> So the erase information in kdump header would contain:
> 
> -----------------------------------
> Symbol Name: mystruct2.mystruct1.a
> Filter Addr: &mystruct2.mystruct1->a
> Filter Size: 4	(sizeof type int)
> -----------------------------------
> 
> For erase commands in loop construct we will have multiple Filter addresses.
> 
> Please let me know your comment on the above format.

In my idea, offset_eraseinfo points the *file offset* of the erased
information and size_eraseinfo is the information size.

The erased information would contain *multiple* erased symbol names.
For example, the following is based on your above example.

 	struct S1 {
 		int a;
 		int b;
 		int c;
 	};
 	struct S2 {
 		struct S1 *mystruct1;
 		struct S1 *mystruct2;
 	};
 
 	struct S2 mystruct2;
 
 	#Filter command
 	erase mystruct2.mystruct1.a
 	erase mystruct2.mystruct1.c
 	erase mystruct2.mystruct2.b

	#The erased information
 	erase mystruct2.mystruct1.a 4
 	erase mystruct2.mystruct1.c 4
 	erase mystruct2.mystruct2.b 4


The dumpfile image :

       header             dump data             the erased information
+------------------+-----------------------+-------------------------------+
| ................ | ..................... | erase mystruct2.mystruct1.a 4 |
| offset_eraseinfo | ..................... | erase mystruct2.mystruct1.c 4 |
|   size_eraseinfo | ..................... | erase mystruct2.mystruct2.b 4 |
+------------------+-------------------------------------------------------+
                                           : offset_eraseinfo (offset in dumpfile)
                                            <------ size_eraseinfo ------->
                                            
Thanks
Ken'ichi Ohmichi


From xiyou.wangcong at gmail.com  Tue Mar 15 03:52:38 2011
From: xiyou.wangcong at gmail.com (=?UTF-8?Q?Am=C3=A9rico_Wang?=)
Date: Tue, 15 Mar 2011 15:52:38 +0800
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <20110314181315.GA16075@in.ibm.com>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
	<20110309122046.GC16951@cr0.redhat.com>
	<20110309234657.264d3080@kryten>
	<20110309142108.GD16951@cr0.redhat.com>
	<20110314181315.GA16075@in.ibm.com>
Message-ID: <AANLkTi=aDzCaa7_=5XTrnJCzmZPrDy3omXwDarEF8XmH@mail.gmail.com>

On Tue, Mar 15, 2011 at 2:13 AM, Mahesh J Salgaonkar
<mahesh at linux.vnet.ibm.com> wrote:
>
> During free we do free all of them including RMO region. But since the rtas
> region is always on top of RMO, crashkernel memory overlaps rtas region and
> we endup freeing that even, which is causing the crash.
>

Okay, but with this patch applied, we will just ignore rtas region, right?
Thus, when I echo 0 to free all the 128M crashkernel memory, the final
result will be 32M left, which means crash_size will still show 32M.
This looks odd.

How about skipping the 32M as a whole? I mean once the region being freed
has overlap with this rtas region, skip the whole rtas region, and let
crash_size
show 0?

Thanks.


From anggriawan.sugianto at gmail.com  Tue Mar 15 06:31:34 2011
From: anggriawan.sugianto at gmail.com (Anggriawan Sugianto)
Date: Tue, 15 Mar 2011 17:31:34 +0700
Subject: kexec on ARM - oops undefined instruction
Message-ID: <AANLkTikKgVYjO_v0xTHg-H1c0R1Z6QxuyVTDkx8Jy6zg@mail.gmail.com>

Dear all,

Currently I am learning about how kexec works in ARM kernel. I have
cross-compiled kexec-tools successfully, but when I run kexec, it
gives me kernel oops - undefined instruction.
_______________

#> ./kexec -l zImage --command-line=`cat /proc/cmdline`
#> ./kexec -e
Starting new kernel
Bye!
.
.
Internal error: Oops - undefined instruction: 0 [#1] PREEMPT
Modules linked in:
 wl(P)(0xbf1d8000) kernel version : 0068_262 RELEASE preempt mod_unload ARMv7
 snd_usb_audio(0xbf1c5000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 snd_usb_lib(0xbf1c0000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 snd_seq_midi(0xbf1b6000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 snd_rawmidi(0xbf1ad000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 ftdi_sio(0xbf1a1000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 snd_hwdep(0xbf19a000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 usbhid(0xbf181000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 usbserial(0xbf177000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 sdp_mac(0xbf16e000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 usb_storage(0xbf161000) kernel version : 1005_272 RELEASE preempt
mod_unload ARMv7
 ohci_hcd(0xbf155000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 ehci_hcd(0xbf146000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 usbcore(0xbf127000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 fpi(P)(0xbf120000) kernel version : 0068_262 RELEASE preempt mod_unload ARMv7
 sdp_ahci(0xbf115000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 libata(0xbf0f4000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 sd_mod(0xbf0ea000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 sr_mod(0xbf0e2000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7
 cdrom(0xbf0d5000) kernel version : 1005_272 RELEASE preempt mod_unload ARMv7

CPU: 0    Tainted: P            (2.6.30.9 #48)
pc : [<747e4000>]    lr : [<c002acbc>]    psr: 60000013
sp : c768de58  ip : c6d92fc0  fp : c768de6c
r10: 00000000  r9 : c768c000  r8 : c0025568
r7 : 00000000  r6 : 45584543  r5 : c6ee3000  r4 : 747e3000
r3 : 00000c02  r2 : 000005f8  r1 : 000005f8  r0 : 747e3000
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c53c7d  Table: 74690019  DAC: 00000015
Process kexec (pid: 501, stack limit = 0xc768c2e0)
.
.
Backtrace:
Function entered at [<c002abb4>] from [<c008cfe0>]
 r5:28121969 r4:c0477a70
Function entered at [<c008cf90>] from [<c005b4e0>]
 r4:fee1dead r3:45584543
Function entered at [<c005b34c>] from [<c00253c0>]
 r7:00000058 r6:410338d8 r5:41033ac4 r4:0d696914
Code: 00000000 00000000 00000000 00000000 (dc9d7fc2)
_______________

I see the backtrace & lr. It guides me to:

$ cat objdump.txt | grep c002acbc
c002abc8:       e59fc0ec        ldr     ip, [pc, #236]  ; c002acbc
<machine_kexec+0x108>
c002acbc:       c03dc768        .word   0xc03dc768

$ cat objdump.txt | grep c002abb4
c002abb4 <machine_kexec>:
c002abb4:       e1a0c00d        mov     ip, sp
c008cfdc:       ebfe76f4        bl      c002abb4 <machine_kexec>
c008d234:       ebfe765e        bl      c002abb4 <machine_kexec>

$ cat objdump.txt | grep c008cf90
c005b4dc:       eb00c6ab        bl      c008cf90 <kernel_kexec>
c008cf90 <kernel_kexec>:
c008cf90:       e1a0c00d        mov     ip, sp

_______________

Can anyone help me what's wrong with "oops - undefined instruction" ?

Does it mean there is something wrong with machine_kexec() call in
kernel_kexec() function in <kernel_source>/kernel/kexec.c ? Or, is the
problem located in linked modules?

Thank you for your time.


Regards,
Anggriawan Sugianto


From anderson at redhat.com  Tue Mar 15 10:43:01 2011
From: anderson at redhat.com (Dave Anderson)
Date: Tue, 15 Mar 2011 10:43:01 -0400 (EDT)
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to filter
	out kernel data from vmcore
In-Reply-To: <4D7EF934.3090008@linux.vnet.ibm.com>
Message-ID: <2104293694.426816.1300200181206.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>


----- Original Message -----
>
>Hi Ken'chi,
>
>On 03/14/2011 08:14 AM, Ken'ichi Ohmichi wrote:
>> 
>> Hi Dave, Mahesh,
>> 
>> On Fri, 11 Mar 2011 09:07:50 -0500 (EST)
>> Dave Anderson <anderson at redhat.com> wrote:
>>>>
>>>> Please find the makedumpfile enhancement patchset that introduces a data
>>>> filtering feature which enables makedumpfile to filter out desired kernel
>>>> symbol data and it's members from the specified VMCORE file. The data to be
>>>> filtered out is poisoned with character 'X' (58 in Hex).
>>>>
>>>> This feature will be very useful for the customers who wants to erase the
>>>> customer sensitive data like security keys and other confidential data, in
>>>> DUMPFILE before sending it to support team for analysis.
>>>>
>>>> This feature introduces a filter config file where, using filter commands,
>>>> user can specify desired kernel data symbols and it's members that need to be
>>>> filtered out while creating o/p DUMPFILE. The Syntax for filter commands are
>>>> provided in the filter.conf(8) man page.
>>>>
>>>> The first 4 patches prepares the base work for filtering framework.  The last 2
>>>> patches implements the generic filtering framework to erase desired kernel
>>>> data.
>>>>
>>>> I have tested these patches on x86_64 and s390x architecture against RHEL6 GA
>>>> kernel. The feature supports filtering data from ELF as well as kdump-compressed
>>>> formatted dump.
>>>>
>>>> Please review the patchset and let me know your comments.
>>>>
>>>> Thanks,
>>>> -Mahesh.
>>>
>>> Hi Mahesh,
>>>
>>> Is there any notation in the filtered ELF kdump or compressed kdump file
>>> that filtering has been done?  Given that there may be potential ramifications
>>> in crash utility behavior (or outright failure?), the crash utility should
>>> display a warning message early on during invocation.
>> 
>> That is a good point.
>> 
>> How about adding new members (like offset_eraseinfo, size_eraseinfo)
>> into the sub header in compressed kdump file, and setting version 5
>> in the header version (disk_dump_header.header_version) ?
>> These members show the erased information like the following:
>> 
>> struct kdump_sub_header {
>>         unsigned long   phys_base;
>>         int             dump_level;     /* header_version 1 and later */
>>         int             split;          /* header_version 2 and later */
>>         unsigned long   start_pfn;      /* header_version 2 and later */
>>         unsigned long   end_pfn;        /* header_version 2 and later */
>>         off_t           offset_vmcoreinfo;/* header_version 3 and later */
>>         unsigned long   size_vmcoreinfo;  /* header_version 3 and later */
>>         off_t           offset_note;      /* header_version 4 and later */
>>         unsigned long   size_note;        /* header_version 4 and later */
>> +       off_t           offset_eraseinfo; /* header_version 5 and later */
>> +       unsigned long   size_eraseinfo;   /* header_version 5 and later */
>> };
>> 
>> The erased information contains only effective lines in the
>> configuration file.
>
>Do you mean the info would contain symbol name/expression, resolved
>symbol/vmalloc addresses and its sizes that got filtered out?
>
>What I mean by symbol expression is, user can ask makedumpfile to erase
>a data referred by a member from the symbol variable of structure type.
>e.g.
>	struct S1 {
>		int a;
>	};
>	struct S2 {
>		struct S1 *mystruct1;
>	};
>
>	struct S2 mystruct2;
>
>	#Filter command
>	erase mystruct2.mystruct1.a
>
>So the erase information in kdump header would contain:
>
>-----------------------------------
>Symbol Name: mystruct2.mystruct1.a
>Filter Addr: &mystruct2.mystruct1->a
>Filter Size: 4	(sizeof type int)
>-----------------------------------
>
>For erase commands in loop construct we will have multiple Filter addresses.
>
>Please let me know your comment on the above format.
>
>Hi Dave,
>
>Do you think the above information would be enough for crash utility to
>interpret?

To clarify -- I have *no* plans to *interpret* the filter data.  I just
want to know that filtering has been done, and to display a WARNING 
message early on during crash invocation that it has been done.  And
when things subsequently break, at least the user knows why, and I don't
get a bunch of unexplainable bug reports.

So about as far as I would take it in the crash utility would be for the
"help -n" output to display the filter data strings that are appended to
the dumpfile or stored in an ELF note -- much the same way that VMCOREINFO
data can be dumped.

Dave




>Thanks,
>-Mahesh.
>
>> In case of ELF kdump file, how about adding a ELF note section
>> which also show the erased information ?
>> 
>> The crash utility will be able to know the name list of the
>> erased symbols from the information.
>> 
>> 
>> Thanks
>> Ken'ichi Ohmichi


From mahesh at linux.vnet.ibm.com  Tue Mar 15 12:52:19 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Tue, 15 Mar 2011 22:22:19 +0530
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <AANLkTi=aDzCaa7_=5XTrnJCzmZPrDy3omXwDarEF8XmH@mail.gmail.com>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
	<20110309122046.GC16951@cr0.redhat.com>
	<20110309234657.264d3080@kryten>
	<20110309142108.GD16951@cr0.redhat.com>
	<20110314181315.GA16075@in.ibm.com>
	<AANLkTi=aDzCaa7_=5XTrnJCzmZPrDy3omXwDarEF8XmH@mail.gmail.com>
Message-ID: <20110315165219.GA22509@in.ibm.com>

On Tue, Mar 15, 2011 at 03:52:38PM +0800, Am?rico Wang wrote:
> On Tue, Mar 15, 2011 at 2:13 AM, Mahesh J Salgaonkar
> <mahesh at linux.vnet.ibm.com> wrote:
> >
> > During free we do free all of them including RMO region. But since the rtas
> > region is always on top of RMO, crashkernel memory overlaps rtas region and
> > we endup freeing that even, which is causing the crash.
> >
> 
> Okay, but with this patch applied, we will just ignore rtas region, right?
Correct.
> Thus, when I echo 0 to free all the 128M crashkernel memory, the final
> result will be 32M left, which means crash_size will still show 32M.
> This looks odd.
> 
> How about skipping the 32M as a whole? I mean once the region being freed
> has overlap with this rtas region, skip the whole rtas region, and let
> crash_size
> show 0?
The existing code from crash_shrink_memory() function reduces the crash
size to 0 when echo'ed 0. I did test this patchset and verified that
/sys/kernel/kexec_crash_size show 0 value.

Thanks,
-Mahesh.
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

-- 
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>


From mahesh at linux.vnet.ibm.com  Tue Mar 15 13:09:23 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Tue, 15 Mar 2011 22:39:23 +0530
Subject: [PATCH] makedumpfile: s390x: Fix KVBASE to correct value for s390x
	arcitecture.
Message-ID: <20110315170902.32471.52757.stgit@mars.in.ibm.com>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

While excluding free pages from s390x dumps taken on LPAR, makedumpfile
fails to convert page address to pfn. The reason is, the memory for
mem_section structure is allocated below '_stext' and since KVBASE is
set to SYMBOL(_stext), the function is_kvaddr() fails and return NULL
address.

Set KVBASE to KENRELBASE(0) for s390x architecture to fix this issue.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---

 makedumpfile.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/makedumpfile.h b/makedumpfile.h
index 11e1a93..4ec77b7 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -615,7 +615,7 @@ do { \
 #ifdef __s390x__
 #define __PAGE_OFFSET		(info->page_size - 1)
 #define KERNELBASE		(0)
-#define KVBASE			(SYMBOL(_stext))
+#define KVBASE			KERNELBASE
 #define _SECTION_SIZE_BITS	(28)
 #define _MAX_PHYSMEM_BITS	(42)
 



From mahesh at linux.vnet.ibm.com  Wed Mar 16 01:37:40 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Wed, 16 Mar 2011 11:07:40 +0530
Subject: [PATCH v1 0/6] makedumpfile: makedumpfile enhancement to
	filter out kernel data from vmcore
In-Reply-To: <20110315151247.23fc84bc.oomichi@mxs.nes.nec.co.jp>
References: <20110311075647.14587.50626.stgit@mars.in.ibm.com>
	<1823425025.382709.1299852470929.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
	<20110314114457.7e252f0d.oomichi@mxs.nes.nec.co.jp>
	<4D7EF934.3090008@linux.vnet.ibm.com>
	<20110315151247.23fc84bc.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110316053740.GA6854@in.ibm.com>

Hi Ken'inchi,

On Tue, Mar 15, 2011 at 03:12:47PM +0900, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> In my idea, offset_eraseinfo points the *file offset* of the erased
> information and size_eraseinfo is the information size.
> 
> The erased information would contain *multiple* erased symbol names.
> For example, the following is based on your above example.
> 
>  	struct S1 {
>  		int a;
>  		int b;
>  		int c;
>  	};
>  	struct S2 {
>  		struct S1 *mystruct1;
>  		struct S1 *mystruct2;
>  	};
> 
>  	struct S2 mystruct2;
> 
>  	#Filter command
>  	erase mystruct2.mystruct1.a
>  	erase mystruct2.mystruct1.c
>  	erase mystruct2.mystruct2.b
> 
> 	#The erased information
>  	erase mystruct2.mystruct1.a 4
>  	erase mystruct2.mystruct1.c 4
>  	erase mystruct2.mystruct2.b 4
> 
> 
> The dumpfile image :
> 
>        header             dump data             the erased information
> +------------------+-----------------------+-------------------------------+
> | ................ | ..................... | erase mystruct2.mystruct1.a 4 |
> | offset_eraseinfo | ..................... | erase mystruct2.mystruct1.c 4 |
> |   size_eraseinfo | ..................... | erase mystruct2.mystruct2.b 4 |
> +------------------+-------------------------------------------------------+
>                                            : offset_eraseinfo (offset in dumpfile)
>                                             <------ size_eraseinfo ------->
>                                             

Will work on the cahnge.

Thanks,
-Mahesh.
> Thanks
> Ken'ichi Ohmichi

-- 
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>


From oomichi at mxs.nes.nec.co.jp  Thu Mar 17 02:39:12 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Thu, 17 Mar 2011 15:39:12 +0900
Subject: [PATCH] makedumpfile: s390x: Fix KVBASE to correct value for
	s390x arcitecture.
In-Reply-To: <20110315170902.32471.52757.stgit@mars.in.ibm.com>
References: <20110315170902.32471.52757.stgit@mars.in.ibm.com>
Message-ID: <20110317153912.de4162a9.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Tue, 15 Mar 2011 22:39:23 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>
> From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> 
> While excluding free pages from s390x dumps taken on LPAR, makedumpfile
> fails to convert page address to pfn. The reason is, the memory for
> mem_section structure is allocated below '_stext' and since KVBASE is
> set to SYMBOL(_stext), the function is_kvaddr() fails and return NULL
> address.

Why do we need this patch ?
to support the latest kernel version of s390 ?
or to support LPAR of s390 ?

I'd like to know whether we need a similar change for the other architecture.
I will appreciate if getting a hint.


Thanks
Ken'ichi Ohmichi

> Set KVBASE to KENRELBASE(0) for s390x architecture to fix this issue.
> 
> Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> ---
> 
>  makedumpfile.h |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/makedumpfile.h b/makedumpfile.h
> index 11e1a93..4ec77b7 100644
> --- a/makedumpfile.h
> +++ b/makedumpfile.h
> @@ -615,7 +615,7 @@ do { \
>  #ifdef __s390x__
>  #define __PAGE_OFFSET		(info->page_size - 1)
>  #define KERNELBASE		(0)
> -#define KVBASE			(SYMBOL(_stext))
> +#define KVBASE			KERNELBASE
>  #define _SECTION_SIZE_BITS	(28)
>  #define _MAX_PHYSMEM_BITS	(42)
>  
> 


From caiqian at redhat.com  Thu Mar 17 05:21:29 2011
From: caiqian at redhat.com (CAI Qian)
Date: Thu, 17 Mar 2011 05:21:29 -0400 (EDT)
Subject: kdump regression related to usb3 hub update
In-Reply-To: <75962266.482150.1300351616499.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com>
Message-ID: <1569207539.482477.1300353689147.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com>

Hello Sarah and others,

There is a regression using the latest Sarah's xhci hubs-v3-rebase tree, kdump kernel reset itself (log at the end of email). The first kernel also setup using IOMMU (intel_iommu=on). Removed intel_iommu=on from the kdump kernel parameter alone did not solve the problem. This is only reproducible when the first kernel is using IOMMU.

My environment setup is:

PCI-E card -> USB3 Disk
           -> USB3 Hub -> USB3 Disk
                       -> USB2 Hub -> USB2 Disk

I have been identified one or a few of the following patches caused the problem but need more time to narrow it down.

288ead45fa6637e959015d055304f521cbbc0575
USB: remove bogus USB_PORT_FEAT_*_SPEED symbols

0eadcc09203349b11ca477ec367079b23d32ab91
usb: USB3.0 ch11 definitions

b1a72b70bbb82237b1041c78edee305503f6da31
USB: Remove bitmap #define from hcd.h

50e6c947c6340f7ba81deca99e8a37f458a00e49
USB: Fix usb_add_hcd() checkpatch errors.

0abde136582234dd720270ec3d5aeba69eae4d03
xhci: Rework port suspend structures for limited ports.

8c0d6f920004f065c2571f32b7c28e7f850e9810
xhci: Rename variables and reduce register reads.

ba764f4b37e2bcce069f6c9d96b8374ee85257ed
USB 3.0 Hub Changes

Loading usb-storage.ko module
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
Waiting 8 seconds for driver initialization.
usb 7-1: New USB device found, idVendor=046d, idProduct=08af
usb 7-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
usb 7-2: new low speed USB device number 3 using uhci_hcd
usb 7-2: New USB device found, idVendor=0624, idProduct=0307
usb 7-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 7-2: Product: Avocent DSRIQ-USB
usb 7-2: Manufacturer: Avocent
input: Avocent Avocent DSRIQ-USB as /devices/pci0000:00/0000:00:1d.2/usb7/7-2/7-2:1.0/input/input1
generic-usb 0003:0624:0307.0001: input,hidraw0: USB HID v1.10 Keyboard [Avocent Avocent DSRIQ-USB] on usb-0000:00:1d.2-2/input0
input: Avocent Avocent DSRIQ-USB as /devices/pci0000:00/0000:00:1d.2/usb7/7-2/7-2:1.1/input/input2
generic-usb 0003:0624:0307.0002: input,hidraw1: USB HID v1.10 Mouse [Avocent Avocent DSRIQ-USB] on usb-0000:00:1d.2-2/input1
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbfb000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
Loading mii.ko module
Loading v4l2-compat-ioctl32.ko module
Loading mmicrocode: CPU0 sig=0x206c2, pf=0x1, revision=0xc
icrocode.ko module
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbfa000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbf9000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbf8000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 402
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 502
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 602
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 702
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 2
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 102
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 202
DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
DRHD: handling fault status reg 302
DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000 
DMAR:[fault reason 01] Present bit in root entry is clear
<reset>
Initializing cgroup subsys cpuset
Linux version 2.6.38-rc5+ ....

Thanks.

CAI Qian


From gregkh at suse.de  Thu Mar 17 17:22:02 2011
From: gregkh at suse.de (Greg KH)
Date: Thu, 17 Mar 2011 14:22:02 -0700
Subject: [072/474] mm, x86: Saving vmcore with non-lazy freeing of vmas
In-Reply-To: <20110317213822.GA27980@kroah.com>
Message-ID: <20110317212848.172918367@clark.kroah.org>

2.6.33-longterm review patch.  If anyone has any objections, please let us know.

------------------
Content-Length: 2026
Lines: 68

From: Cliff Wickman <cpw at sgi.com>

commit 3ee48b6af49cf534ca2f481ecc484b156a41451d upstream.

During the reading of /proc/vmcore the kernel is doing
ioremap()/iounmap() repeatedly. And the buildup of un-flushed
vm_area_struct's is causing a great deal of overhead. (rb_next()
is chewing up most of that time).

This solution is to provide function set_iounmap_nonlazy(). It
causes a subsequent call to iounmap() to immediately purge the
vma area (with try_purge_vmap_area_lazy()).

With this patch we have seen the time for writing a 250MB
compressed dump drop from 71 seconds to 44 seconds.

Signed-off-by: Cliff Wickman <cpw at sgi.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: kexec at lists.infradead.org
LKML-Reference: <E1OwHZ4-0005WK-Tw at eag09.americas.sgi.com>
Signed-off-by: Ingo Molnar <mingo at elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

---
 arch/x86/include/asm/io.h       |    1 +
 arch/x86/kernel/crash_dump_64.c |    1 +
 mm/vmalloc.c                    |    9 +++++++++
 3 files changed, 11 insertions(+)

--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -172,6 +172,7 @@ static inline void __iomem *ioremap(reso
 
 extern void iounmap(volatile void __iomem *addr);
 
+extern void set_iounmap_nonlazy(void);
 
 #ifdef CONFIG_X86_32
 # include "io_32.h"
--- a/arch/x86/kernel/crash_dump_64.c
+++ b/arch/x86/kernel/crash_dump_64.c
@@ -46,6 +46,7 @@ ssize_t copy_oldmem_page(unsigned long p
 	} else
 		memcpy(buf, vaddr + offset, csize);
 
+	set_iounmap_nonlazy();
 	iounmap(vaddr);
 	return csize;
 }
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -513,6 +513,15 @@ static atomic_t vmap_lazy_nr = ATOMIC_IN
 static void purge_fragmented_blocks_allcpus(void);
 
 /*
+ * called before a call to iounmap() if the caller wants vm_area_struct's
+ * immediately freed.
+ */
+void set_iounmap_nonlazy(void)
+{
+	atomic_set(&vmap_lazy_nr, lazy_max_pages()+1);
+}
+
+/*
  * Purges all lazily-freed vmap areas.
  *
  * If sync is 0 then don't purge if there is already a purge in progress.




From gregkh at suse.de  Thu Mar 17 17:22:08 2011
From: gregkh at suse.de (Greg KH)
Date: Thu, 17 Mar 2011 14:22:08 -0700
Subject: [078/474] x86,
	kdump: Change copy_oldmem_page() to use cached addressing
In-Reply-To: <20110317213822.GA27980@kroah.com>
Message-ID: <20110317212848.821435682@clark.kroah.org>

2.6.33-longterm review patch.  If anyone has any objections, please let us know.

------------------
Content-Length: 1077
Lines: 35

From: Cliff Wickman <cpw at sgi.com>

commit 37a2f9f30a360fb03522d15c85c78265ccd80287 upstream.

The copy of /proc/vmcore to a user buffer proceeds much faster
if the kernel addresses memory as cached.

With this patch we have seen an increase in transfer rate from
less than 15MB/s to 80-460MB/s, depending on size of the
transfer. This makes a big difference in time needed to save a
system dump.

Signed-off-by: Cliff Wickman <cpw at sgi.com>
Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>
Cc: kexec at lists.infradead.org
LKML-Reference: <E1OtMLz-0001yp-Ia at eag09.americas.sgi.com>
Signed-off-by: Ingo Molnar <mingo at elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

---
 arch/x86/kernel/crash_dump_64.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/arch/x86/kernel/crash_dump_64.c
+++ b/arch/x86/kernel/crash_dump_64.c
@@ -34,7 +34,7 @@ ssize_t copy_oldmem_page(unsigned long p
 	if (!csize)
 		return 0;
 
-	vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+	vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
 	if (!vaddr)
 		return -ENOMEM;
 




From caiqian at redhat.com  Fri Mar 18 02:19:38 2011
From: caiqian at redhat.com (CAI Qian)
Date: Fri, 18 Mar 2011 02:19:38 -0400 (EDT)
Subject: Kdump failed with Intel IOMMU  (WAS Re: kdump regression related to
	usb3 hub update)
In-Reply-To: <1569207539.482477.1300353689147.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com>
Message-ID: <1130369577.497880.1300429178678.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com>

Sorry, this has nothing to do with usb3 hub update. I made a mistake that passed amd_iommu=on instead intel_iommu=on to the successful base kernel run. Hence, it passed once there and all testing for other kernels used the right parameters were failed.

The problem is still there though. Since this is the first time test this setup, not sure if this is regression or not.

CAI Qian

----- Original Message -----
> Hello Sarah and others,
> 
> There is a regression using the latest Sarah's xhci hubs-v3-rebase
> tree, kdump kernel reset itself (log at the end of email). The first
> kernel also setup using IOMMU (intel_iommu=on). Removed intel_iommu=on
> from the kdump kernel parameter alone did not solve the problem. This
> is only reproducible when the first kernel is using IOMMU.
> 
> My environment setup is:
> 
> PCI-E card -> USB3 Disk
> -> USB3 Hub -> USB3 Disk
> -> USB2 Hub -> USB2 Disk
> 
> I have been identified one or a few of the following patches caused
> the problem but need more time to narrow it down.
> 
> 288ead45fa6637e959015d055304f521cbbc0575
> USB: remove bogus USB_PORT_FEAT_*_SPEED symbols
> 
> 0eadcc09203349b11ca477ec367079b23d32ab91
> usb: USB3.0 ch11 definitions
> 
> b1a72b70bbb82237b1041c78edee305503f6da31
> USB: Remove bitmap #define from hcd.h
> 
> 50e6c947c6340f7ba81deca99e8a37f458a00e49
> USB: Fix usb_add_hcd() checkpatch errors.
> 
> 0abde136582234dd720270ec3d5aeba69eae4d03
> xhci: Rework port suspend structures for limited ports.
> 
> 8c0d6f920004f065c2571f32b7c28e7f850e9810
> xhci: Rename variables and reduce register reads.
> 
> ba764f4b37e2bcce069f6c9d96b8374ee85257ed
> USB 3.0 Hub Changes
> 
> Loading usb-storage.ko module
> Initializing USB Mass Storage driver...
> usbcore: registered new interface driver usb-storage
> USB Mass Storage support registered.
> Waiting 8 seconds for driver initialization.
> usb 7-1: New USB device found, idVendor=046d, idProduct=08af
> usb 7-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> usb 7-2: new low speed USB device number 3 using uhci_hcd
> usb 7-2: New USB device found, idVendor=0624, idProduct=0307
> usb 7-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
> usb 7-2: Product: Avocent DSRIQ-USB
> usb 7-2: Manufacturer: Avocent
> input: Avocent Avocent DSRIQ-USB as
> /devices/pci0000:00/0000:00:1d.2/usb7/7-2/7-2:1.0/input/input1
> generic-usb 0003:0624:0307.0001: input,hidraw0: USB HID v1.10 Keyboard
> [Avocent Avocent DSRIQ-USB] on usb-0000:00:1d.2-2/input0
> input: Avocent Avocent DSRIQ-USB as
> /devices/pci0000:00/0000:00:1d.2/usb7/7-2/7-2:1.1/input/input2
> generic-usb 0003:0624:0307.0002: input,hidraw1: USB HID v1.10 Mouse
> [Avocent Avocent DSRIQ-USB] on usb-0000:00:1d.2-2/input1
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbfb000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> Loading mii.ko module
> Loading v4l2-compat-ioctl32.ko module
> Loading mmicrocode: CPU0 sig=0x206c2, pf=0x1, revision=0xc
> icrocode.ko module
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbfa000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbf9000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr ffbf8000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 402
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 502
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 602
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 702
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 2
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 102
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 202
> DMAR:[DMA Write] Request device [0b:00.1] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> DRHD: handling fault status reg 302
> DMAR:[DMA Write] Request device [0b:00.0] fault addr fffff000
> DMAR:[fault reason 01] Present bit in root entry is clear
> <reset>
> Initializing cgroup subsys cpuset
> Linux version 2.6.38-rc5+ ....
> 
> Thanks.
> 
> CAI Qian


From holzheu at linux.vnet.ibm.com  Fri Mar 18 06:11:37 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 18 Mar 2011 11:11:37 +0100
Subject: [PATCH] makedumpfile: s390x: Fix KVBASE to correct value for
	s390x arcitecture.
In-Reply-To: <20110317153912.de4162a9.oomichi@mxs.nes.nec.co.jp>
References: <20110315170902.32471.52757.stgit@mars.in.ibm.com>
	<20110317153912.de4162a9.oomichi@mxs.nes.nec.co.jp>
Message-ID: <1300443097.1981.16.camel@holzheu-laptop>

Hello Ken'inchi,

On Thu, 2011-03-17 at 15:39 +0900, Ken'ichi Ohmichi wrote:
> Hi Mahesh,
> 
> On Tue, 15 Mar 2011 22:39:23 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >
> > From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> > 
> > While excluding free pages from s390x dumps taken on LPAR, makedumpfile
> > fails to convert page address to pfn. The reason is, the memory for
> > mem_section structure is allocated below '_stext' and since KVBASE is
> > set to SYMBOL(_stext), the function is_kvaddr() fails and return NULL
> > address.
> 
> Why do we need this patch ?
> to support the latest kernel version of s390 ?
> or to support LPAR of s390 ?

The problem is that on s390 depending on the kernel configuration it can
happen that memory below _stext is available for buffer allocation.
Therefore the mem_section structure has been allocated below _stext. On
s390 the kernel page tables have a 1:1 mapping from 0 to memory_end
(memory holes are possible). Therefore I think the check "> 0" is ok for
s390.

> 
> I'd like to know whether we need a similar change for the other architecture.
> I will appreciate if getting a hint.

Not sure, if other architectures use memory below _stext for buffer
allocation.

Michael




From promo at pepsi.co.uk  Sun Mar 20 11:57:41 2011
From: promo at pepsi.co.uk (PEPSI BOTTLING COMPANY PLC)
Date: Sun, 20 Mar 2011 09:57:41 -0600
Subject: You have won =?iso-8859-1?b?ozUwMCwwMDAuMDBQT1VORFM/?=
Message-ID: <20110320095741.14831vnxqz65wlx1@webmail.freedomnw.com>

You have won ?500,000.00POUNDS from Pepsi Company award 2011, Please  
provide your Full name, Age, Sex, Country,Occupation,Phone and  
Address.and send them to: Mrs. FRANCESS DAVE, Phone# :+447011150911  
+4407024015829 E MAIL: francessdavepepsi at hotmail.co.uk



From zaks_974 at yahoo.com  Mon Mar 21 09:56:21 2011
From: zaks_974 at yahoo.com (ZAKIR AHMED)
Date: Mon, 21 Mar 2011 06:56:21 -0700 (PDT)
Subject: Kexec on ARM -- Latest Status
Message-ID: <850768.5998.qm@web33205.mail.mud.yahoo.com>

Hi,

I just want to know if there is a doc OR a patch that describes that changes that has to be done for having kexec and kdump for my kernel. I am using ARM 11mpcore and linux-2.6.33

It would be of help if somebody could let me know whether ARM kernel could be made relocatable so that it could be used as the second kernel (dump kernel). Any pointers on this could be helpful?

With Regards,  Zakir Ahmed  ?  "And fear Almighty, and know that you are to meet him in the hereafter"  ?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110321/f206bba2/attachment.html>

From oomichi at mxs.nes.nec.co.jp  Mon Mar 21 23:00:32 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Tue, 22 Mar 2011 12:00:32 +0900
Subject: [PATCH] makedumpfile: s390x: Fix KVBASE to correct value for
	s390x arcitecture.
In-Reply-To: <1300443097.1981.16.camel@holzheu-laptop>
References: <20110315170902.32471.52757.stgit@mars.in.ibm.com>
	<20110317153912.de4162a9.oomichi@mxs.nes.nec.co.jp>
	<1300443097.1981.16.camel@holzheu-laptop>
Message-ID: <20110322120032.0edfbd03.oomichi@mxs.nes.nec.co.jp>


Hi Michael,

Thank you for the explanation.

On Fri, 18 Mar 2011 11:11:37 +0100
Michael Holzheu <holzheu at linux.vnet.ibm.com> wrote:
> 
> On Thu, 2011-03-17 at 15:39 +0900, Ken'ichi Ohmichi wrote:
> > Hi Mahesh,
> > 
> > On Tue, 15 Mar 2011 22:39:23 +0530
> > Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > >
> > > From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> > > 
> > > While excluding free pages from s390x dumps taken on LPAR, makedumpfile
> > > fails to convert page address to pfn. The reason is, the memory for
> > > mem_section structure is allocated below '_stext' and since KVBASE is
> > > set to SYMBOL(_stext), the function is_kvaddr() fails and return NULL
> > > address.
> > 
> > Why do we need this patch ?
> > to support the latest kernel version of s390 ?
> > or to support LPAR of s390 ?
> 
> The problem is that on s390 depending on the kernel configuration it can
> happen that memory below _stext is available for buffer allocation.
> Therefore the mem_section structure has been allocated below _stext. On
> s390 the kernel page tables have a 1:1 mapping from 0 to memory_end
> (memory holes are possible). Therefore I think the check "> 0" is ok for
> s390.

I see. And I confirmed there is the same code (kvbase is 0) in the crash
utility in the case of s390x, so this change is right.
Mahesh's patch has been merged to the git tree.

http://makedumpfile.git.sourceforge.net/git/gitweb.cgi?p=makedumpfile/makedumpfile;a=commit;h=c69f915b8163bb9209cb329a6186b7261b545a4b


Thanks
Ken'ichi Ohmichi


From indou.takao at jp.fujitsu.com  Wed Mar 23 14:40:12 2011
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Wed, 23 Mar 2011 14:40:12 -0400
Subject: [PATCH][KDUMP] Ignore spurious IPI
Message-ID: <C3CBE989BE8833indou.takao@jp.fujitsu.com>

Hi all,

I found a problem that kdump(2nd kernel) sometimes hangs up. It seems
that system panic occurs as follows.

(1)
2nd kernel boot up

(2)
A pending IPI from 1st kernel comes after unmasking interrupts at the
following point.

asmlinkage void __init start_kernel(void)
{
(snip)
    time_init();
    profile_init();
    if (!irqs_disabled())
            printk(KERN_CRIT "start_kernel(): bug: interrupts were "
                             "enabled early\n");
    early_boot_irqs_disabled = false;
    local_irq_enable(); <=======================================HERE

(3)
Kernel tries to handle the interrupt, but some data structures are not
initialized yet at this point. As a result, in the
generic_smp_call_function_single_interrupt(), NULL pointer dereference
occurs when list_replace_init() tries to access &q->list.next.

I took a look at local_apic_timer_interrupt() and found a few lines to
handle such a pending LAPIC interrupt(in this case, timer interrupt).
Therefore I made a patch to ignore spurious IPI in the same manner. I
confirmed this problem does not occur with this patch.

Any comments?

Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
---
 kernel/smp.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/kernel/smp.c b/kernel/smp.c
index 9910744..f2f561b 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -260,6 +260,12 @@ void generic_smp_call_function_single_interrupt(void)
 	 */
 	WARN_ON_ONCE(!cpu_online(smp_processor_id()));
 
+	if (unlikely(!q->list.next)) {
+		/* Pending interrupt from previous kernel(e.g. kdump), just ignore */
+		pr_warning("Spurious IPI on cpu %d\n", smp_processor_id());
+		return;
+	}
+
 	raw_spin_lock(&q->lock);
 	list_replace_init(&q->list, &list);
 	raw_spin_unlock(&q->lock);


From dgaur at cdotd.ernet.in  Tue Mar 22 04:36:23 2011
From: dgaur at cdotd.ernet.in (Deepak Gaur)
Date: Tue, 22 Mar 2011 14:06:23 +0530
Subject: KEXEC on Montavista PPC LINUX (2.6.10) with U-BOOT
Message-ID: <20110322083453.M34905@cdotd.ernet.in>

An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110322/b6a6adc3/attachment.html>

From muvarov at gmail.com  Wed Mar 23 20:17:54 2011
From: muvarov at gmail.com (Maxim Uvarov)
Date: Wed, 23 Mar 2011 17:17:54 -0700
Subject: KEXEC on Montavista PPC LINUX (2.6.10) with U-BOOT
In-Reply-To: <20110322083453.M34905@cdotd.ernet.in>
References: <20110322083453.M34905@cdotd.ernet.in>
Message-ID: <AANLkTincRC3upuXNOA7DO4k56RddKm4QbpxZGq8--tuC@mail.gmail.com>

Deepack,

it's  better to read docs which came with BSP. If your kernel is
2.6.10 then kexec tools there should be a little bit different with
main line (I synced them later). So probably you need
--start-memory-range=<addr> --end-memory-range=<addr>  to be set. It's
better to ask support if something does not work out of box in your
build. I think people here can't help you because they don't  know
internals of environment  you have (Montavista PPC LINUX).

Maxim.

2011/3/22 Deepak Gaur <dgaur at cdotd.ernet.in>:
> Hi All
>
> I have a MPC8560 based custom board with linux 2.6.10 as OS and U-BOOT as a
> bootloader.
> The compressed OS and rootfilesytem are combined in one multi image
> (ubImgae)and it resides in a flash partition as raw data. Bootloader is able
> to load the image, decompress it and execute it . The sytem comes up
> properly.
>
> In order to reduce the bootup time i was planning to use kexec to reboot the
> OS. My version of kexec is
> ./kexec -v
> kexec 1.101 released 15 February 2005
>
> I tried to load the OS+Rootfile Filesystem (with U-BOOT header) but it gave
> following output
>
> ./kexec -l ./ubImage --append=\"`cat /proc/cmdline`\"
> Invalid memory range : (nil) - (nil)
> Could not get memory layout
>
> My question is
>
> Does Kexec understand u-boot images ? Or I am missing some parameters
>
> I searched the Internet forum for this and got the guideline that os and
> initrd should be given seperately (---initrd=/boot/vmlinuz-rootfs.img)
>
> but the kexec does not recognize such an option and its help does not show
> any such option (--initrd)
>
> # ./kexec --help
> kexec 1.101 released 15 February 2005
> Usage: kexec [OPTION]... [kernel]
> Directly reboot into a new kernel
>
> -h, --help Print this help.
> -v, --version Print the version of kexec.
> -f, --force Force an immediate kexec, don't call shutdown.
> -x, --no-ifdown Don't bring down network interfaces.
> (if used, must be last option specified)
> -l, --load Load the new kernel into the current kernel.
> -p, --load-panic Load the new kernel for use on panic.
> -u, --unload Unload the current kexec target kernel.
> -e, --exec Execute a currently loaded kernel.
> -t, --type=TYPE Specify the new kernel is of this type.
> --mem-min=<addr> Specify the lowest memory addres to load code into.
> --mem-max=<addr> Specify the highest memory addres to load code into.
>
> Supported kernel file types and options:
> elf-ppc
> --command-line=STRING Set the kernel command line to STRING.
> --append=STRING Set the kernel command line to STRING.
> --gamecube=1|0 Enable/disable support for ELFs with changed
> addresses suitable for the GameCube.
> dol-ppc
> -d, --debug Enable debugging to help spot a failure.
> --command-line=STRING Set the kernel command line to STRING.
> --append=STRING Set the kernel command line to STRING.
> Architecture options:
> the following parameters should be specified:
> --start-memory-range=<addr>
> --end-memory-range=<addr>
>
> for this reason i was trying with a combined OS and Rootfs image
>
> my kernel command line is
>
> # cat /proc/cmdline
> console=ttyCPM,9600n8 wdt=1 ip=dhcp root=/dev/ram0 rw crashkernel=128M at 16M
>
> and I have compiled the kernel with all option related to KEXEC on.
>
> Please help me in understand the method for using kexec with U-BOOT as a
> bootloader. The ARCH is ppc in kernel 2.6.10.
>
> Do i need to use kexec with uncompressed OS image , but as the tool kexec
> does not recognize --initrd option, how to inform kexec abt it?
>
> with regards,
>
> Deepak Gaur
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
>
>



-- 
Best regards,
Maxim Uvarov


From benh at kernel.crashing.org  Thu Mar 24 00:33:30 2011
From: benh at kernel.crashing.org (Benjamin Herrenschmidt)
Date: Thu, 24 Mar 2011 15:33:30 +1100
Subject: [PATCH 1/2] kdump: Allow shrinking of kdump region to be
	overridden
In-Reply-To: <im6fj2$576$1@dough.gmane.org>
References: <20100825002258.GD28360@kryten> <m139u37cii.fsf@fess.ebiederm.org>
	<4D771EE6.5050404@linux.vnet.ibm.com>
	<20110309122046.GC16951@cr0.redhat.com>
	<20110309234657.264d3080@kryten>
	<20110309142108.GD16951@cr0.redhat.com>
	<20110314181315.GA16075@in.ibm.com>
	<AANLkTi=aDzCaa7_=5XTrnJCzmZPrDy3omXwDarEF8XmH@mail.gmail.com>
	<20110315165219.GA22509@in.ibm.com>  <im6fj2$576$1@dough.gmane.org>
Message-ID: <1300941210.2402.414.camel@pasglop>

On Mon, 2011-03-21 at 03:10 +0000, WANG Cong wrote:
> On Tue, 15 Mar 2011 22:22:19 +0530, Mahesh J Salgaonkar wrote:

> >> Okay, but with this patch applied, we will just ignore rtas region,
> >> right?
> > Correct.
> >> Thus, when I echo 0 to free all the 128M crashkernel memory, the final
> >> result will be 32M left, which means crash_size will still show 32M.
> >> This looks odd.
> >> 
> >> How about skipping the 32M as a whole? I mean once the region being
> >> freed has overlap with this rtas region, skip the whole rtas region,
> >> and let crash_size
> >> show 0?
> > The existing code from crash_shrink_memory() function reduces the crash
> > size to 0 when echo'ed 0. I did test this patchset and verified that
> > /sys/kernel/kexec_crash_size show 0 value.
> 
> Oh, ok.
> 
> Acked-by: WANG Cong <xiyou.wangcong at gmail.com>

So Eric, what's the right approach to get that merged ? This is a bug
gating an important delivery for us, and the patch doesn't appear
terribly invasive ? :-)

I can send it to Linus myself if you prefer and give me your Ack.

Cheers,
Ben.




From miltonm at bga.com  Thu Mar 24 10:20:32 2011
From: miltonm at bga.com (Milton Miller)
Date: Thu, 24 Mar 2011 08:20:32 -0600
Subject: [KDUMP] Ignore spurious IPI
In-Reply-To: <C3CBE989BE8833indou.takao@jp.fujitsu.com>
References: <C3CBE989BE8833indou.takao@jp.fujitsu.com>
Message-ID: <smp-ipi-supurious-single-kdump@mdm.bga.com>

On Wed, 23 Mar 2011 about 18:40:12 -0000, Takao Indoh wrote:
> Hi all,
> 
> I found a problem that kdump(2nd kernel) sometimes hangs up. It seems
> that system panic occurs as follows.
..
> (2)
> A pending IPI from 1st kernel comes after unmasking interrupts at the
> following point.
> 
> asmlinkage void __init start_kernel(void)
> {
> (snip)
>     time_init();
>     profile_init();
>     if (!irqs_disabled())
>             printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>                              "enabled early\n");
>     early_boot_irqs_disabled = false;
>     local_irq_enable(); <=======================================HERE
> 
> (3)
> Kernel tries to handle the interrupt, but some data structures are not
> initialized yet at this point. As a result, in the
> generic_smp_call_function_single_interrupt(), NULL pointer dereference
> occurs when list_replace_init() tries to access &q->list.next.
> 
[tried to match lapic timer interrupt]
> Any comments?

So this occurs because unlike device interrupts, this vector has the action
defined statically and no per-interrupt disable on your architecture?


If so, just initialize the data structure earlier -- change
init_call_single_data from early_initcall to an explict call after the
per-cpu areas are initialized.

milton


From indou.takao at jp.fujitsu.com  Thu Mar 24 17:25:18 2011
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Thu, 24 Mar 2011 17:25:18 -0400
Subject: [KDUMP] Ignore spurious IPI
In-Reply-To: <smp-ipi-supurious-single-kdump@mdm.bga.com>
References: <C3CBE989BE8833indou.takao@jp.fujitsu.com>
	<smp-ipi-supurious-single-kdump@mdm.bga.com>
Message-ID: <C4CBEA69F94DFCindou.takao@jp.fujitsu.com>

On Thu, 24 Mar 2011 08:20:32 -0600, Milton Miller wrote:

>On Wed, 23 Mar 2011 about 18:40:12 -0000, Takao Indoh wrote:
>> Hi all,
>> 
>> I found a problem that kdump(2nd kernel) sometimes hangs up. It seems
>> that system panic occurs as follows.
>..
>> (2)
>> A pending IPI from 1st kernel comes after unmasking interrupts at the
>> following point.
>> 
>> asmlinkage void __init start_kernel(void)
>> {
>> (snip)
>>     time_init();
>>     profile_init();
>>     if (!irqs_disabled())
>>             printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>>                              "enabled early\n");
>>     early_boot_irqs_disabled = false;
>>     local_irq_enable(); <=======================================HERE
>> 
>> (3)
>> Kernel tries to handle the interrupt, but some data structures are not
>> initialized yet at this point. As a result, in the
>> generic_smp_call_function_single_interrupt(), NULL pointer dereference
>> occurs when list_replace_init() tries to access &q->list.next.
>> 
>[tried to match lapic timer interrupt]
>> Any comments?
>
>So this occurs because unlike device interrupts, this vector has the action
>defined statically and no per-interrupt disable on your architecture?

I think there is not per-interrupt disable for IPI.

>If so, just initialize the data structure earlier -- change
>init_call_single_data from early_initcall to an explict call after the
>per-cpu areas are initialized.

That makes sense. I'll do this, thanks.

Thanks,
Takao Indoh


>
>milton


From xiyou.wangcong at gmail.com  Fri Mar 25 02:26:02 2011
From: xiyou.wangcong at gmail.com (WANG Cong)
Date: Fri, 25 Mar 2011 06:26:02 +0000 (UTC)
Subject: Kexec on ARM -- Latest Status
References: <850768.5998.qm@web33205.mail.mud.yahoo.com>
Message-ID: <imhchp$9u8$1@dough.gmane.org>

On Mon, 21 Mar 2011 06:56:21 -0700, ZAKIR AHMED wrote:

> Hi,
> 
> I just want to know if there is a doc OR a patch that describes that
> changes that has to be done for having kexec and kdump for my kernel. I
> am using ARM 11mpcore and linux-2.6.33
> 
> It would be of help if somebody could let me know whether ARM kernel
> could be made relocatable so that it could be used as the second kernel
> (dump kernel). Any pointers on this could be helpful?
> 

ARM doesn't have CONFIG_RELOCATABLE, so probably it doesn't
support relocating. You'd better to check this with ARM kernel developers.

Thanks.



From indou.takao at jp.fujitsu.com  Fri Mar 25 11:52:20 2011
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Fri, 25 Mar 2011 11:52:20 -0400
Subject: [PATCH] generic-ipi: Initialize call_single_queue before enabling
	interrupt
Message-ID: <C7CBEB049FD464indou.takao@jp.fujitsu.com>

Hi all,

Actually this is a v2 patch but I post with new subject.
The first post is here.

[PATCH][KDUMP] Ignore spurious IPI
http://www.gossamer-threads.com/lists/linux/kernel/1356389

The problem I found is that kdump(2nd kernel) sometimes hangs up due to
pending IPI from 1st kernel. Kernel panic occurs because IPI comes
before call_single_queue is initialized, so this patch moves
init_call_single_data() so that it can be called before
local_irq_enable().

The details of the problem is below.

(1)
2nd kernel boot up

(2)
A pending IPI from 1st kernel comes after unmasking interrupts at the
following point.

asmlinkage void __init start_kernel(void)
{
(snip)
    time_init();
    profile_init();
    if (!irqs_disabled())
            printk(KERN_CRIT "start_kernel(): bug: interrupts were "
                             "enabled early\n");
    early_boot_irqs_disabled = false;
    local_irq_enable(); <=======================================HERE

(3)
Kernel tries to handle the interrupt, but call_single_queue is not
initialized yet at this point. As a result, in the
generic_smp_call_function_single_interrupt(), NULL pointer dereference
occurs when list_replace_init() tries to access &q->list.next.

Any comments would be appreciated.

Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
---
 include/linux/smp.h |    1 +
 init/main.c         |    1 +
 kernel/smp.c        |   18 +++++++++++-------
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/include/linux/smp.h b/include/linux/smp.h
index 6dc95ca..0b81bba 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -114,6 +114,7 @@ int on_each_cpu(smp_call_func_t func, void *info, int wait);
 void smp_prepare_boot_cpu(void);
 
 extern unsigned int setup_max_cpus;
+void init_call_single_data(void);
 
 #else /* !SMP */
 
diff --git a/init/main.c b/init/main.c
index 33c37c3..02a7617 100644
--- a/init/main.c
+++ b/init/main.c
@@ -631,6 +631,7 @@ asmlinkage void __init start_kernel(void)
 		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
 				 "enabled early\n");
 	early_boot_irqs_disabled = false;
+	init_call_single_data();
 	local_irq_enable();
 
 	/* Interrupts are enabled now so all GFP allocations are safe. */
diff --git a/kernel/smp.c b/kernel/smp.c
index 7cbd0f2..f119610 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -74,9 +74,19 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = {
 	.notifier_call		= hotplug_cfd,
 };
 
-static int __cpuinit init_call_single_data(void)
+static int __cpuinit init_hotplug_cfd(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
+
+	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
+	register_cpu_notifier(&hotplug_cfd_notifier);
+
+	return 0;
+}
+early_initcall(init_hotplug_cfd);
+
+void __init init_call_single_data(void)
+{
 	int i;
 
 	for_each_possible_cpu(i) {
@@ -85,13 +95,7 @@ static int __cpuinit init_call_single_data(void)
 		raw_spin_lock_init(&q->lock);
 		INIT_LIST_HEAD(&q->list);
 	}
-
-	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
-	register_cpu_notifier(&hotplug_cfd_notifier);
-
-	return 0;
 }
-early_initcall(init_call_single_data);
 
 /*
  * csd_lock/csd_unlock used to serialize access to per-cpu csd resources



From miltonm at bga.com  Fri Mar 25 13:48:21 2011
From: miltonm at bga.com (Milton Miller)
Date: Fri, 25 Mar 2011 11:48:21 -0600
Subject: [PATCH] generic-ipi: Initialize call_single_queue before enabling
	interrupt
In-Reply-To: <C7CBEB049FD464indou.takao@jp.fujitsu.com>
References: <C7CBEB049FD464indou.takao@jp.fujitsu.com>
Message-ID: <generic-ipi-init-v2-reply@mdm.bga.com>

On Fri, 25 Mar 2011 about 11:52:20 -0400, Takao Indoh wrote:
> 
> Hi all,
> 
> Actually this is a v2 patch but I post with new subject.
> The first post is here.
> 
> [PATCH][KDUMP] Ignore spurious IPI
> http://www.gossamer-threads.com/lists/linux/kernel/1356389
> 
> The problem I found is that kdump(2nd kernel) sometimes hangs up due to
> pending IPI from 1st kernel. Kernel panic occurs because IPI comes
> before call_single_queue is initialized, so this patch moves
> init_call_single_data() so that it can be called before
> local_irq_enable().
> 

This is good background, but I generally prefer changelogs to start
by describing what is being changed and then proceed on to why, and
then the history of the patch and discussion.

> The details of the problem is below.
> 
> (1)
> 2nd kernel boot up
> 
> (2)
> A pending IPI from 1st kernel comes after unmasking interrupts at the
> following point.
> 
> asmlinkage void __init start_kernel(void)
> {
> (snip)
>     time_init();
>     profile_init();
>     if (!irqs_disabled())
>             printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>                              "enabled early\n");
>     early_boot_irqs_disabled = false;
>     local_irq_enable(); <=======================================HERE
> 

This could be described more concisely as "when irqs are first enabled
in start_kernel()".

> (3)
> Kernel tries to handle the interrupt, but call_single_queue is not
> initialized yet at this point. As a result, in the
> generic_smp_call_function_single_interrupt(), NULL pointer dereference
> occurs when list_replace_init() tries to access &q->list.next.
> 
> Any comments would be appreciated.
> 
> Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
> ---
>  include/linux/smp.h |    1 +
>  init/main.c         |    1 +
>  kernel/smp.c        |   18 +++++++++++-------
>  3 files changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/smp.h b/include/linux/smp.h
> index 6dc95ca..0b81bba 100644
> --- a/include/linux/smp.h
> +++ b/include/linux/smp.h
> @@ -114,6 +114,7 @@ int on_each_cpu(smp_call_func_t func, void *info, int wait);
>  void smp_prepare_boot_cpu(void);
>  
>  extern unsigned int setup_max_cpus;
> +void init_call_single_data(void);
>  

This no longer applys (although it did to 2.6.38).

>  #else /* !SMP */
>  

I was going to point out that this will fail on up, but it looks
like ba8dd03ac09f51a69c154b8cb508b701d713a2cd (Full conversion to
early_initcall() interface, remove old interface) only found 2 of the
previous 3 occurrances.

However, this does point out that not all CONFIG_SMP compiles are
CONFIG_USE_GENERIC_SMP_HELPERS, and you need to adjust accordingly.

[ for other reviewers no this is not a simple revert of a hunk of that
2.6.27 change, this is moving the code yet earlier ].

> diff --git a/init/main.c b/init/main.c
> index 33c37c3..02a7617 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -631,6 +631,7 @@ asmlinkage void __init start_kernel(void)
>  		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>  				 "enabled early\n");
>  	early_boot_irqs_disabled = false;
> +	init_call_single_data();
>  	local_irq_enable();
>  

1) this is too late, the point of the printk and the state variable is
to make sure interrupts are enabled exactly when we expect for the
first time.

2) please follow the naming conventions and name this xxx_init.  Actually
I prefer xxx be the name of the subsystem (call_function) instead of
the name of the data structure (call_single_data).

>  	/* Interrupts are enabled now so all GFP allocations are safe. */
> diff --git a/kernel/smp.c b/kernel/smp.c
> index 7cbd0f2..f119610 100644
> --- a/kernel/smp.c
> +++ b/kernel/smp.c
> @@ -74,9 +74,19 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = {
>  	.notifier_call		= hotplug_cfd,
>  };
>  
> -static int __cpuinit init_call_single_data(void)
> +static int __cpuinit init_hotplug_cfd(void)
>  {
>  	void *cpu = (void *)(long)smp_processor_id();
> +
> +	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
> +	register_cpu_notifier(&hotplug_cfd_notifier);
> +
> +	return 0;
> +}
> +early_initcall(init_hotplug_cfd);
> +

Why did you seperate this from the rest of the function?  I haven't
tested the patch but don't why this needs to be delayed.  If there
is some reason I don't see, please describe it in the change log.

> +void __init init_call_single_data(void)
> +{
>  	int i;
>  
>  	for_each_possible_cpu(i) {
> @@ -85,13 +95,7 @@ static int __cpuinit init_call_single_data(void)
>  		raw_spin_lock_init(&q->lock);
>  		INIT_LIST_HEAD(&q->list);
>  	}
> -
> -	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
> -	register_cpu_notifier(&hotplug_cfd_notifier);
> -
> -	return 0;
>  }
> -early_initcall(init_call_single_data);
>  
>  /*
>   * csd_lock/csd_unlock used to serialize access to per-cpu csd resources
> 

milton


From ebiederm at xmission.com  Fri Mar 25 16:49:35 2011
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Fri, 25 Mar 2011 13:49:35 -0700
Subject: reboot/kexec in 2.6.38
In-Reply-To: <20110322133034.GA15475@atrey.karlin.mff.cuni.cz> (Cyril Hrubis's
	message of "Tue, 22 Mar 2011 14:30:34 +0100")
References: <20110317064523.GA1995@ucw.cz>
	<AANLkTik1CdT4k8SJop7b-MjR27RzF7a=i7WuodNKJi+J@mail.gmail.com>
	<20110322133034.GA15475@atrey.karlin.mff.cuni.cz>
Message-ID: <m1bp0zylgg.fsf@fess.ebiederm.org>

Cyril Hrubis <metan at ucw.cz> writes:

> Hi!
>> I think it's config issue. Never heard of this.
>
> I've just compiled and booted 2.6.38. The kernel boots without problems when
> flashed in. But I've had no success with kexec, the last lines I see are:
>
> Starting new kernel

Enable early_printk to a serial port if you can.

There is definitely an issue in 2.6.38 where kdump doesn't work, that
right now looks like a memblock issue.

Eric


From indou.takao at jp.fujitsu.com  Fri Mar 25 18:07:52 2011
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Fri, 25 Mar 2011 18:07:52 -0400
Subject: [PATCH] generic-ipi: Initialize call_single_queue before enabling
	interrupt
In-Reply-To: <generic-ipi-init-v2-reply@mdm.bga.com>
References: <C7CBEB049FD464indou.takao@jp.fujitsu.com>
	<generic-ipi-init-v2-reply@mdm.bga.com>
Message-ID: <CBCBEB391604FEindou.takao@jp.fujitsu.com>

On Fri, 25 Mar 2011 11:48:21 -0600, Milton Miller wrote:

>On Fri, 25 Mar 2011 about 11:52:20 -0400, Takao Indoh wrote:
>> 
>> Hi all,
>> 
>> Actually this is a v2 patch but I post with new subject.
>> The first post is here.
>> 
>> [PATCH][KDUMP] Ignore spurious IPI
>> http://www.gossamer-threads.com/lists/linux/kernel/1356389
>> 
>> The problem I found is that kdump(2nd kernel) sometimes hangs up due to
>> pending IPI from 1st kernel. Kernel panic occurs because IPI comes
>> before call_single_queue is initialized, so this patch moves
>> init_call_single_data() so that it can be called before
>> local_irq_enable().
>> 
>
>This is good background, but I generally prefer changelogs to start
>by describing what is being changed and then proceed on to why, and
>then the history of the patch and discussion.
>
>> The details of the problem is below.
>> 
>> (1)
>> 2nd kernel boot up
>> 
>> (2)
>> A pending IPI from 1st kernel comes after unmasking interrupts at the
>> following point.
>> 
>> asmlinkage void __init start_kernel(void)
>> {
>> (snip)
>>     time_init();
>>     profile_init();
>>     if (!irqs_disabled())
>>             printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>>                              "enabled early\n");
>>     early_boot_irqs_disabled = false;
>>     local_irq_enable(); <=======================================HERE
>> 
>
>This could be described more concisely as "when irqs are first enabled
>in start_kernel()".
>
>> (3)
>> Kernel tries to handle the interrupt, but call_single_queue is not
>> initialized yet at this point. As a result, in the
>> generic_smp_call_function_single_interrupt(), NULL pointer dereference
>> occurs when list_replace_init() tries to access &q->list.next.
>> 
>> Any comments would be appreciated.
>> 
>> Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
>> ---
>>  include/linux/smp.h |    1 +
>>  init/main.c         |    1 +
>>  kernel/smp.c        |   18 +++++++++++-------
>>  3 files changed, 13 insertions(+), 7 deletions(-)
>> 
>> diff --git a/include/linux/smp.h b/include/linux/smp.h
>> index 6dc95ca..0b81bba 100644
>> --- a/include/linux/smp.h
>> +++ b/include/linux/smp.h
>> @@ -114,6 +114,7 @@ int on_each_cpu(smp_call_func_t func, void *info, int 
>> wait);
>>  void smp_prepare_boot_cpu(void);
>>  
>>  extern unsigned int setup_max_cpus;
>> +void init_call_single_data(void);
>>  
>
>This no longer applys (although it did to 2.6.38).
>
>>  #else /* !SMP */
>>  
>
>I was going to point out that this will fail on up, but it looks
>like ba8dd03ac09f51a69c154b8cb508b701d713a2cd (Full conversion to
>early_initcall() interface, remove old interface) only found 2 of the
>previous 3 occurrances.
>
>However, this does point out that not all CONFIG_SMP compiles are
>CONFIG_USE_GENERIC_SMP_HELPERS, and you need to adjust accordingly.
>
>[ for other reviewers no this is not a simple revert of a hunk of that
>2.6.27 change, this is moving the code yet earlier ].
>
>> diff --git a/init/main.c b/init/main.c
>> index 33c37c3..02a7617 100644
>> --- a/init/main.c
>> +++ b/init/main.c
>> @@ -631,6 +631,7 @@ asmlinkage void __init start_kernel(void)
>>  		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>>  				 "enabled early\n");
>>  	early_boot_irqs_disabled = false;
>> +	init_call_single_data();
>>  	local_irq_enable();
>>  
>
>1) this is too late, the point of the printk and the state variable is
>to make sure interrupts are enabled exactly when we expect for the
>first time.

Ok, so the following place is correct?

 	profile_init();
+	call_function_init();
 	if (!irqs_disabled())
 		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
 				"enabled early\n");
 	early_boot_irqs_disabled = false;
 	local_irq_enable();


>
>2) please follow the naming conventions and name this xxx_init.  Actually
>I prefer xxx be the name of the subsystem (call_function) instead of
>the name of the data structure (call_single_data).
>
>>  	/* Interrupts are enabled now so all GFP allocations are safe. */
>> diff --git a/kernel/smp.c b/kernel/smp.c
>> index 7cbd0f2..f119610 100644
>> --- a/kernel/smp.c
>> +++ b/kernel/smp.c
>> @@ -74,9 +74,19 @@ static struct notifier_block __cpuinitdata 
>> hotplug_cfd_notifier = {
>>  	.notifier_call		= hotplug_cfd,
>>  };
>>  
>> -static int __cpuinit init_call_single_data(void)
>> +static int __cpuinit init_hotplug_cfd(void)
>>  {
>>  	void *cpu = (void *)(long)smp_processor_id();
>> +
>> +	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
>> +	register_cpu_notifier(&hotplug_cfd_notifier);
>> +
>> +	return 0;
>> +}
>> +early_initcall(init_hotplug_cfd);
>> +
>
>Why did you seperate this from the rest of the function?  I haven't
>tested the patch but don't why this needs to be delayed.  If there
>is some reason I don't see, please describe it in the change log.

There is not special reason. I just thought I should minimize the change
to prevent regression because I cannot do hotplug test. Ok, next time
I'll just change the name from init_call_single_data to
call_function_init instead of separating it.

It seems that Peter Zijlstra added this hotplug code at 8969a5ed, so I
added him to Cc.

Thanks for your review.

Thanks,
Takao Indoh


>
>> +void __init init_call_single_data(void)
>> +{
>>  	int i;
>>  
>>  	for_each_possible_cpu(i) {
>> @@ -85,13 +95,7 @@ static int __cpuinit init_call_single_data(void)
>>  		raw_spin_lock_init(&q->lock);
>>  		INIT_LIST_HEAD(&q->list);
>>  	}
>> -
>> -	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
>> -	register_cpu_notifier(&hotplug_cfd_notifier);
>> -
>> -	return 0;
>>  }
>> -early_initcall(init_call_single_data);
>>  
>>  /*
>>   * csd_lock/csd_unlock used to serialize access to per-cpu csd resources
>> 
>
>milton


From christopher.leech at linux.intel.com  Mon Mar 28 15:40:49 2011
From: christopher.leech at linux.intel.com (Chris Leech)
Date: Mon, 28 Mar 2011 12:40:49 -0700
Subject: [PATCH] kexec, x86: fix kexec when boot_params.hardware_subarch != 0
Message-ID: <20110328194049.32626.74038.stgit@localhost6.localdomain6>

kexec needs to keep the subarch setting the same as the running kernel
in the boot parameters, or the kernel will die in early setup.  I ran
into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
future subarch that uses non-default early setup code.

This patch requires debugfs mounted at /sys/kernel/debug, as that's
the only way I know of to get at the running kernels boot_params.
Without debugfs mounted it falls back to the current behavior of
assuming subarch 0.

Signed-off-by: Chris Leech <christopher.leech at linux.intel.com>
---
 kexec/arch/i386/x86-linux-setup.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index f843ca4..b7f8bd8 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <errno.h>
 #include <limits.h>
 #include <sys/types.h>
@@ -396,12 +397,32 @@ out:
 		real_mode->eddbuf_entries);
 }
 
+#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
+
+void setup_subarch(struct x86_linux_param_header *real_mode)
+{
+	int data_file;
+	const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
+
+	data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
+	if (data_file < 0)
+		return;
+	if (lseek(data_file, offset, SEEK_SET) < 0)
+		goto close;
+	read(data, &real_mode->hardware_subarch, sizeof(uint32_t));
+close:
+	close(data_file);
+}
+
 void setup_linux_system_parameters(struct x86_linux_param_header *real_mode,
 					unsigned long kexec_flags)
 {
 	/* Fill in information the BIOS would usually provide */
 	struct memory_range *range;
 	int i, ranges;
+
+	/* get subarch from running kernel */
+	setup_subarch(real_mode);
 	
 	/* Default screen size */
 	real_mode->orig_x = 0;



From horms at verge.net.au  Mon Mar 28 17:40:12 2011
From: horms at verge.net.au (Simon Horman)
Date: Tue, 29 Mar 2011 06:40:12 +0900
Subject: [PATCH] kexec, x86: fix kexec when
	boot_params.hardware_subarch != 0
In-Reply-To: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
Message-ID: <20110328214012.GH4716@verge.net.au>

On Mon, Mar 28, 2011 at 12:40:49PM -0700, Chris Leech wrote:
> kexec needs to keep the subarch setting the same as the running kernel
> in the boot parameters, or the kernel will die in early setup.  I ran
> into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
> future subarch that uses non-default early setup code.
> 
> This patch requires debugfs mounted at /sys/kernel/debug, as that's
> the only way I know of to get at the running kernels boot_params.
> Without debugfs mounted it falls back to the current behavior of
> assuming subarch 0.
> 
> Signed-off-by: Chris Leech <christopher.leech at linux.intel.com>
> ---
>  kexec/arch/i386/x86-linux-setup.c |   21 +++++++++++++++++++++
>  1 files changed, 21 insertions(+), 0 deletions(-)
> 
> diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
> index f843ca4..b7f8bd8 100644
> --- a/kexec/arch/i386/x86-linux-setup.c
> +++ b/kexec/arch/i386/x86-linux-setup.c
> @@ -20,6 +20,7 @@
>  #include <string.h>
>  #include <stdarg.h>
>  #include <stdlib.h>
> +#include <stddef.h>
>  #include <errno.h>
>  #include <limits.h>
>  #include <sys/types.h>
> @@ -396,12 +397,32 @@ out:
>  		real_mode->eddbuf_entries);
>  }
>  
> +#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
> +
> +void setup_subarch(struct x86_linux_param_header *real_mode)
> +{
> +	int data_file;
> +	const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
> +
> +	data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
> +	if (data_file < 0)
> +		return;
> +	if (lseek(data_file, offset, SEEK_SET) < 0)
> +		goto close;
> +	read(data, &real_mode->hardware_subarch, sizeof(uint32_t));

Should data be data_file?

> +close:
> +	close(data_file);
> +}
> +
>  void setup_linux_system_parameters(struct x86_linux_param_header *real_mode,
>  					unsigned long kexec_flags)
>  {
>  	/* Fill in information the BIOS would usually provide */
>  	struct memory_range *range;
>  	int i, ranges;
> +
> +	/* get subarch from running kernel */
> +	setup_subarch(real_mode);
>  	
>  	/* Default screen size */
>  	real_mode->orig_x = 0;
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
> 


From christopher.leech at linux.intel.com  Mon Mar 28 17:45:57 2011
From: christopher.leech at linux.intel.com (Chris Leech)
Date: Mon, 28 Mar 2011 14:45:57 -0700
Subject: [PATCH] kexec, x86: fix kexec when
	boot_params.hardware_subarch != 0
In-Reply-To: <20110328214012.GH4716@verge.net.au>
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
	<20110328214012.GH4716@verge.net.au>
Message-ID: <20110328214557.GA5670@cleech-lnx.jf.intel.com>

On Tue, Mar 29, 2011 at 06:40:12AM +0900, Simon Horman wrote:
> > +void setup_subarch(struct x86_linux_param_header *real_mode)
> > +{
> > +	int data_file;
> > +	const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
> > +
> > +	data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
> > +	if (data_file < 0)
> > +		return;
> > +	if (lseek(data_file, offset, SEEK_SET) < 0)
> > +		goto close;
> > +	read(data, &real_mode->hardware_subarch, sizeof(uint32_t));
> 
> Should data be data_file?

Yes.  Sorry, looks like I sent an unrefreshed patch.

- Chris


From christopher.leech at linux.intel.com  Mon Mar 28 17:50:11 2011
From: christopher.leech at linux.intel.com (Chris Leech)
Date: Mon, 28 Mar 2011 14:50:11 -0700
Subject: [PATCH V2] kexec,
	x86: fix kexec when boot_params.hardware_subarch != 0
In-Reply-To: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
Message-ID: <20110328215011.30400.91252.stgit@localhost6.localdomain6>

kexec needs to keep the subarch setting the same as the running kernel
in the boot parameters, or the kernel will die in early setup.  I ran
into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
future subarch that uses non-default early setup code.

This patch requires debugfs mounted at /sys/kernel/debug, as that's
the only way I know of to get at the running kernels boot_params.
Without debugfs mounted it falls back to the current behavior of
assuming subarch 0.

Signed-off-by: Chris Leech <christopher.leech at linux.intel.com>
---
 kexec/arch/i386/x86-linux-setup.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index f843ca4..50b32be 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <errno.h>
 #include <limits.h>
 #include <sys/types.h>
@@ -396,12 +397,32 @@ out:
 		real_mode->eddbuf_entries);
 }
 
+#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
+
+void setup_subarch(struct x86_linux_param_header *real_mode)
+{
+	int data_file;
+	const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
+
+	data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
+	if (data_file < 0)
+		return;
+	if (lseek(data_file, offset, SEEK_SET) < 0)
+		goto close;
+	read(data_file, &real_mode->hardware_subarch, sizeof(uint32_t));
+close:
+	close(data_file);
+}
+
 void setup_linux_system_parameters(struct x86_linux_param_header *real_mode,
 					unsigned long kexec_flags)
 {
 	/* Fill in information the BIOS would usually provide */
 	struct memory_range *range;
 	int i, ranges;
+
+	/* get subarch from running kernel */
+	setup_subarch(real_mode);
 	
 	/* Default screen size */
 	real_mode->orig_x = 0;



From horms at verge.net.au  Mon Mar 28 18:19:04 2011
From: horms at verge.net.au (Simon Horman)
Date: Tue, 29 Mar 2011 07:19:04 +0900
Subject: [PATCH V2] kexec, x86: fix kexec when
	boot_params.hardware_subarch != 0
In-Reply-To: <20110328215011.30400.91252.stgit@localhost6.localdomain6>
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
	<20110328215011.30400.91252.stgit@localhost6.localdomain6>
Message-ID: <20110328221904.GA18357@verge.net.au>

On Mon, Mar 28, 2011 at 02:50:11PM -0700, Chris Leech wrote:
> kexec needs to keep the subarch setting the same as the running kernel
> in the boot parameters, or the kernel will die in early setup.  I ran
> into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
> future subarch that uses non-default early setup code.
> 
> This patch requires debugfs mounted at /sys/kernel/debug, as that's
> the only way I know of to get at the running kernels boot_params.
> Without debugfs mounted it falls back to the current behavior of
> assuming subarch 0.

Thanks, applied.


From xiyou.wangcong at gmail.com  Tue Mar 29 05:04:53 2011
From: xiyou.wangcong at gmail.com (WANG Cong)
Date: Tue, 29 Mar 2011 09:04:53 +0000 (UTC)
Subject: [PATCH V2] kexec,
	x86: fix kexec when boot_params.hardware_subarch != 0
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
	<20110328215011.30400.91252.stgit@localhost6.localdomain6>
Message-ID: <ims7bl$ik5$1@dough.gmane.org>

On Mon, 28 Mar 2011 14:50:11 -0700, Chris Leech wrote:

> kexec needs to keep the subarch setting the same as the running kernel
> in the boot parameters, or the kernel will die in early setup.  I ran
> into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
> future subarch that uses non-default early setup code.
> 
> This patch requires debugfs mounted at /sys/kernel/debug, as that's the
> only way I know of to get at the running kernels boot_params. Without
> debugfs mounted it falls back to the current behavior of assuming
> subarch 0.
> 
...
>  
> +#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"

A minor issue here is that you are using a hard-coded debugfs path,
debugfs can be also mounted to /debug too, so it is better that if we can 
search the path dynamically here.

Thanks.



From indou.takao at jp.fujitsu.com  Tue Mar 29 12:35:04 2011
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Tue, 29 Mar 2011 12:35:04 -0400
Subject: [PATCH v2] generic-ipi: Initialize call_single_queue before enabling
	interrupt
Message-ID: <D6CBEE2F420741indou.takao@jp.fujitsu.com>

Hi all,

This patch renames init_call_single_data() to call_function_init() and
calls it in start_kernel() so that call_single_queue can be initialized
before enabling interrupt.

There is a problem that kdump(2nd kernel) sometimes hangs up due to
pending IPI from 1st kernel. Kernel panic occurs because IPI comes
before call_single_queue is initialized. The details are as follows.
(1) 2nd kernel boot up
(2) A pending IPI from 1st kernel comes when irqs are first enabled
    in start_kernel().
(3) Kernel tries to handle the interrupt, but call_single_queue is not
    initialized yet at this point. As a result, in the
    generic_smp_call_function_single_interrupt(), NULL pointer
    dereference occurs when list_replace_init() tries to access
    &q->list.next.
Therefore this patch changes the name of init_call_single_data() to
call_function_init() and calls it before local_irq_enable() in
start_kernel().

v2:
- Rename init_call_single_data() to call_function_init() and calls it in
  start_kernel()
- Change insert position in start_kernel().
- Adjust for CONFIG_SMP/CONFIG_USE_GENERIC_SMP_HELPERS options
- Rebased to Linus's latest tree

v1:
https://lkml.org/lkml/2011/3/25/317
- Divide init_call_single_data() into two functions,
   o init_call_single_data: initialize call_single_queue
   o init_hotplug_cfd: initialize hotplug_cfd_notifier
  And call init_call_single_data before local_irq_enable() in
  start_kernel().

v0:
https://lkml.org/lkml/2011/3/23/417
- In generic_smp_call_function_single_interrupt(), check if
  call_single_queue was initialized or not, and just return if not
  initialized.

Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
---
 include/linux/smp.h |    5 ++++-
 init/main.c         |    1 +
 kernel/smp.c        |    5 +----
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/linux/smp.h b/include/linux/smp.h
index 74243c8..4fb3eac 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -85,12 +85,15 @@ int smp_call_function_any(const struct cpumask *mask,
  * Generic and arch helpers
  */
 #ifdef CONFIG_USE_GENERIC_SMP_HELPERS
+void __init call_function_init(void);
 void generic_smp_call_function_single_interrupt(void);
 void generic_smp_call_function_interrupt(void);
 void ipi_call_lock(void);
 void ipi_call_unlock(void);
 void ipi_call_lock_irq(void);
 void ipi_call_unlock_irq(void);
+#else
+static inline void call_function_init(void) { }
 #endif
 
 /*
@@ -144,7 +147,7 @@ static inline void smp_send_reschedule(int cpu) { }
 #define smp_prepare_boot_cpu()			do {} while (0)
 #define smp_call_function_many(mask, func, info, wait) \
 			(up_smp_call_function(func, info))
-static inline void init_call_single_data(void) { }
+static inline void call_function_init(void) { }
 
 static inline int
 smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
diff --git a/init/main.c b/init/main.c
index 4a9479e..12821d1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -539,6 +539,7 @@ asmlinkage void __init start_kernel(void)
 	timekeeping_init();
 	time_init();
 	profile_init();
+	call_function_init();
 	if (!irqs_disabled())
 		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
 				 "enabled early\n");
diff --git a/kernel/smp.c b/kernel/smp.c
index 73a1951..fb67dfa 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -74,7 +74,7 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = {
 	.notifier_call		= hotplug_cfd,
 };
 
-static int __cpuinit init_call_single_data(void)
+void __init call_function_init(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
 	int i;
@@ -88,10 +88,7 @@ static int __cpuinit init_call_single_data(void)
 
 	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
 	register_cpu_notifier(&hotplug_cfd_notifier);
-
-	return 0;
 }
-early_initcall(init_call_single_data);
 
 /*
  * csd_lock/csd_unlock used to serialize access to per-cpu csd resources


From horms at verge.net.au  Tue Mar 29 19:22:59 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 30 Mar 2011 08:22:59 +0900
Subject: [PATCH V2] kexec, x86: fix kexec when
	boot_params.hardware_subarch != 0
In-Reply-To: <ims7bl$ik5$1@dough.gmane.org>
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
	<20110328215011.30400.91252.stgit@localhost6.localdomain6>
	<ims7bl$ik5$1@dough.gmane.org>
Message-ID: <20110329232259.GC27905@verge.net.au>

On Tue, Mar 29, 2011 at 09:04:53AM +0000, WANG Cong wrote:
> On Mon, 28 Mar 2011 14:50:11 -0700, Chris Leech wrote:
> 
> > kexec needs to keep the subarch setting the same as the running kernel
> > in the boot parameters, or the kernel will die in early setup.  I ran
> > into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
> > future subarch that uses non-default early setup code.
> > 
> > This patch requires debugfs mounted at /sys/kernel/debug, as that's the
> > only way I know of to get at the running kernels boot_params. Without
> > debugfs mounted it falls back to the current behavior of assuming
> > subarch 0.
> > 
> ...
> >  
> > +#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
> 
> A minor issue here is that you are using a hard-coded debugfs path,
> debugfs can be also mounted to /debug too, so it is better that if we can 
> search the path dynamically here.

Do you think it would be better for the code to loop through
a few common alternatives for the path?



From horms at verge.net.au  Tue Mar 29 19:56:06 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 30 Mar 2011 08:56:06 +0900
Subject: gcc (4.6) compile warnings/errors
Message-ID: <1301442969-11811-1-git-send-email-horms@verge.net.au>

Hi,

this short series resolves a  error and some warnings
when compiling for x86_64 using gcc-4.6.



From horms at verge.net.au  Tue Mar 29 19:56:07 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 30 Mar 2011 08:56:07 +0900
Subject: [PATCH 1/3] build: Pass --no-undefined as a linker option
In-Reply-To: <1301442969-11811-1-git-send-email-horms@verge.net.au>
References: <1301442969-11811-1-git-send-email-horms@verge.net.au>
Message-ID: <1301442969-11811-2-git-send-email-horms@verge.net.au>

gcc-4.6 does not accept --no-undefined as a compiler option

Reported-by: Civil <civil.over at gmail.com>
Signed-off-by: Simon Horman <horms at verge.net.au>
---
 purgatory/Makefile |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/purgatory/Makefile b/purgatory/Makefile
index ea0c19a..ee1679c 100644
--- a/purgatory/Makefile
+++ b/purgatory/Makefile
@@ -56,8 +56,8 @@ $(PURGATORY): CPPFLAGS=$($(ARCH)_PURGATORY_EXTRA_CFLAGS) \
 			-I$(srcdir)/include \
 			-I$(shell $(CC) -print-file-name=include)
 $(PURGATORY): LDFLAGS=$($(ARCH)_PURGATORY_EXTRA_CFLAGS)\
-			--no-undefined -nostartfiles -nostdlib -nodefaultlibs \
-			-e purgatory_start -r
+			-Wl,--no-undefined -nostartfiles -nostdlib \
+			-nodefaultlibs -e purgatory_start -r
 
 $(PURGATORY): $(PURGATORY_OBJS)
 	$(MKDIR) -p $(@D)
-- 
1.7.2.3



From horms at verge.net.au  Tue Mar 29 19:56:09 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 30 Mar 2011 08:56:09 +0900
Subject: [PATCH 3/3] Don't compare signed and unsigned types
In-Reply-To: <1301442969-11811-1-git-send-email-horms@verge.net.au>
References: <1301442969-11811-1-git-send-email-horms@verge.net.au>
Message-ID: <1301442969-11811-4-git-send-email-horms@verge.net.au>

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 vmcore-dmesg/vmcore-dmesg.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
index 4c1475c..8518150 100644
--- a/vmcore-dmesg/vmcore-dmesg.c
+++ b/vmcore-dmesg/vmcore-dmesg.c
@@ -127,7 +127,7 @@ static void read_elf32(int fd)
 		exit(15);
 	}
 	ret = pread(fd, phdr32, phdrs32_size, ehdr.e_phoff);
-	if (ret != phdrs32_size) {
+	if (ret < 0 || (size_t)ret != phdrs32_size) {
 		fprintf(stderr, "Read of program header @ 0x%llu for %zu bytes failed: %s\n",
 			(unsigned long long)ehdr.e_phoff, phdrs32_size, strerror(errno));
 		exit(16);
@@ -154,7 +154,7 @@ static void read_elf64(int fd)
 	ssize_t ret, i;
 
 	ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
-	if (ret != sizeof(ehdr)) {
+	if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
 		fprintf(stderr, "Read of Elf header from %s failed: %s\n",
 			fname, strerror(errno));
 		exit(10);
@@ -198,7 +198,7 @@ static void read_elf64(int fd)
 		exit(15);
 	}
 	ret = pread(fd, phdr64, phdrs_size, ehdr.e_phoff);
-	if (ret != phdrs_size) {
+	if (ret < 0 || (size_t)ret != phdrs_size) {
 		fprintf(stderr, "Read of program header @ %llu for %zu bytes failed: %s\n",
 			(unsigned long long)(ehdr.e_phoff), phdrs_size, strerror(errno));
 		exit(16);
@@ -239,8 +239,7 @@ static void scan_vmcoreinfo(char *start, size_t size)
 	};
 
 	for (pos = start; pos <= last; pos = eol + 1) {
-		size_t len;
-		int i;
+		size_t len, i;
 		/* Find the end of the current line */
 		for (eol = pos; (eol <= last) && (*eol != '\n') ; eol++)
 			;
@@ -276,7 +275,7 @@ static void scan_notes(int fd, loff_t start, loff_t lsize)
 	size_t size;
 	ssize_t ret;
 
-	if (lsize > LONG_MAX) {
+	if (lsize > SSIZE_MAX) {
 		fprintf(stderr, "Unable to handle note section of %llu bytes\n",
 			(unsigned long long)lsize);
 		exit(20);
@@ -289,7 +288,7 @@ static void scan_notes(int fd, loff_t start, loff_t lsize)
 	}
 	last = buf + size - 1;
 	ret = pread(fd, buf, size, start);
-	if (ret != size) {
+	if (ret != (ssize_t)size) {
 		fprintf(stderr, "Cannot read note section @ 0x%llx of %zu bytes: %s\n",
 			(unsigned long long)start, size, strerror(errno));
 		exit(22);
-- 
1.7.2.3



From horms at verge.net.au  Tue Mar 29 19:56:08 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 30 Mar 2011 08:56:08 +0900
Subject: [PATCH 2/3] Remove assigned but otherwise unused variables
In-Reply-To: <1301442969-11811-1-git-send-email-horms@verge.net.au>
References: <1301442969-11811-1-git-send-email-horms@verge.net.au>
Message-ID: <1301442969-11811-3-git-send-email-horms@verge.net.au>

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/arch/x86_64/kexec-elf-x86_64.c |    3 ---
 kexec/kexec.c                        |    4 +---
 vmcore-dmesg/vmcore-dmesg.c          |    3 +--
 3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/kexec/arch/x86_64/kexec-elf-x86_64.c b/kexec/arch/x86_64/kexec-elf-x86_64.c
index 09402d9..fe4b76b 100644
--- a/kexec/arch/x86_64/kexec-elf-x86_64.c
+++ b/kexec/arch/x86_64/kexec-elf-x86_64.c
@@ -90,7 +90,6 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 	const char *append = NULL;
 	char *command_line = NULL, *modified_cmdline;
 	int command_line_len;
-	int modified_cmdline_len;
 	const char *ramdisk;
 	unsigned long entry, max_addr;
 	int arg_style;
@@ -120,7 +119,6 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 	 */
 	arg_style = ARG_STYLE_ELF;
 	modified_cmdline = 0;
-	modified_cmdline_len = 0;
 	ramdisk = 0;
 	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 		switch(opt) {
@@ -174,7 +172,6 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 						COMMAND_LINE_SIZE);
 			modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
 		}
-		modified_cmdline_len = strlen(modified_cmdline);
 	}
 
 	/* Load the ELF executable */
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 10ad41d..2515c07 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -815,9 +815,7 @@ static int my_shutdown(void)
  */
 static int my_exec(void)
 {
-	int result;
-
-	result = kexec_reboot();
+	kexec_reboot();
 	/* I have failed if I make it here */
 	fprintf(stderr, "kexec failed: %s\n", 
 		strerror(errno));
diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
index 365e293..4c1475c 100644
--- a/vmcore-dmesg/vmcore-dmesg.c
+++ b/vmcore-dmesg/vmcore-dmesg.c
@@ -79,7 +79,7 @@ static void read_elf32(int fd)
 {
 	Elf32_Ehdr ehdr32;
 	Elf32_Phdr *phdr32;
-	size_t phdrs32_size, phdrs_size;
+	size_t phdrs32_size;
 	ssize_t ret, i;
 
 	ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
@@ -114,7 +114,6 @@ static void read_elf32(int fd)
 		exit(12);
 	}
 	phdrs32_size = ehdr.e_phnum * sizeof(Elf32_Phdr);
-	phdrs_size = ehdr.e_phnum * sizeof(Elf64_Phdr);
 	phdr32 = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr));
 	if (!phdr32) {
 		fprintf(stderr, "Calloc of %u phdrs32 failed: %s\n",
-- 
1.7.2.3



From ebiederm at xmission.com  Tue Mar 29 22:37:38 2011
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Tue, 29 Mar 2011 19:37:38 -0700
Subject: gcc (4.6) compile warnings/errors
In-Reply-To: <1301442969-11811-1-git-send-email-horms@verge.net.au> (Simon
	Horman's message of "Wed, 30 Mar 2011 08:56:06 +0900")
References: <1301442969-11811-1-git-send-email-horms@verge.net.au>
Message-ID: <m139m5gwp9.fsf@fess.ebiederm.org>

Simon Horman <horms at verge.net.au> writes:

> Hi,
>
> this short series resolves a  error and some warnings
> when compiling for x86_64 using gcc-4.6.

This series seems reasonable to me.

Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>

Eric



From horms at verge.net.au  Tue Mar 29 23:07:06 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 30 Mar 2011 12:07:06 +0900
Subject: gcc (4.6) compile warnings/errors
In-Reply-To: <m139m5gwp9.fsf@fess.ebiederm.org>
References: <1301442969-11811-1-git-send-email-horms@verge.net.au>
	<m139m5gwp9.fsf@fess.ebiederm.org>
Message-ID: <20110330030705.GE28364@verge.net.au>

On Tue, Mar 29, 2011 at 07:37:38PM -0700, Eric W. Biederman wrote:
> Simon Horman <horms at verge.net.au> writes:
> 
> > Hi,
> >
> > this short series resolves a  error and some warnings
> > when compiling for x86_64 using gcc-4.6.
> 
> This series seems reasonable to me.
> 
> Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>

Thanks Eric, I have pushed the series with your Ack.


From admin at mail.pousadarecantodoprado.com.br  Wed Mar 30 03:04:41 2011
From: admin at mail.pousadarecantodoprado.com.br (Logan Eloise)
Date: Wed, 30 Mar 2011 04:04:41 -0300 (BRT)
Subject: healthcare lists, business lists, consumer lists,
	professional lists and more
Message-ID: <20110330070441.8C1F5394A7@mail.pousadarecantodoprado.com.br>

As requested, below is pricing for all our lists only until this Friday:

note: all lists are optin and were updated within the last 6 months

HEALTH RELATED LISTS
Any Individual list below $99 ea OR 2 for $159

-> Complete US Physicians Database
-> Chiropractic Doctors in the USA
-> American Holistic Medicine Providers/Clinics
-> General Dentists in the USA
-> Dentists with Specialties 
-> American Veterinarians & Veterinary Clinics
-> US Hospitals 
-> Nursing Homes int the US 
-> Pharmaceutical Company Employees
-> Physical/Occupational Therapy Clinics and Therapists in the US
-> Oncology Physicians in the US
-> US Surgery Centers
-> Massage Therapists/Therapy Clinics in America
-> Acupuncturists/clinics in the US
-> Medical Equipment Suppliers(USA)
-> Mental Health Counselors (USA)
-> Optometrists/Clinics (USA)
-> Psychologists (USA)

BUSINESS RELATED LISTS
Take any individual list below for just $99 each

-> Hotels in the USA
-> Realtors in the USA 
-> USA Business Database 
-> Manufacturer Database (USA)
-> Financial Planner Database (USA)
-> Finance & Professionals Database (USA)
-> Insurance Agents (USA)
-> Canadian Businesses
-> United Kingdom Business Database
-> Media Outlet Contacts (USA)

CONSUMER RELATED LISTS
$75 each

-> USA Consumer Database 
-> Credit Inquiries Database (USA)
-> American Homeowners

[ PROFESSIONALS LISTS ]
$75 each

-> USA Lawyers Database 
-> Criminal Attorneys in the US


Reply to this address for numbers and samples: frank.jamieson at gmx.us


  




Forward email to subtract at gmx.com to purge you from our records
  






From xiyou.wangcong at gmail.com  Wed Mar 30 11:19:50 2011
From: xiyou.wangcong at gmail.com (=?UTF-8?Q?Am=C3=A9rico_Wang?=)
Date: Wed, 30 Mar 2011 23:19:50 +0800
Subject: [PATCH v2] generic-ipi: Initialize call_single_queue before
	enabling interrupt
In-Reply-To: <D6CBEE2F420741indou.takao@jp.fujitsu.com>
References: <D6CBEE2F420741indou.takao@jp.fujitsu.com>
Message-ID: <AANLkTi=cne0mSNOV0BC3X-SGeNOPPa5MSUf3L6yLJ1-t@mail.gmail.com>

On Wed, Mar 30, 2011 at 12:35 AM, Takao Indoh
<indou.takao at jp.fujitsu.com> wrote:
> Hi all,
>
> This patch renames init_call_single_data() to call_function_init() and
> calls it in start_kernel() so that call_single_queue can be initialized
> before enabling interrupt.
>
> There is a problem that kdump(2nd kernel) sometimes hangs up due to
> pending IPI from 1st kernel. Kernel panic occurs because IPI comes
> before call_single_queue is initialized. The details are as follows.
> (1) 2nd kernel boot up
> (2) A pending IPI from 1st kernel comes when irqs are first enabled
> ? ?in start_kernel().
> (3) Kernel tries to handle the interrupt, but call_single_queue is not
> ? ?initialized yet at this point. As a result, in the
> ? ?generic_smp_call_function_single_interrupt(), NULL pointer
> ? ?dereference occurs when list_replace_init() tries to access
> ? ?&q->list.next.
> Therefore this patch changes the name of init_call_single_data() to
> call_function_init() and calls it before local_irq_enable() in
> start_kernel().
>
> v2:
> - Rename init_call_single_data() to call_function_init() and calls it in
> ?start_kernel()
> - Change insert position in start_kernel().
> - Adjust for CONFIG_SMP/CONFIG_USE_GENERIC_SMP_HELPERS options
> - Rebased to Linus's latest tree
>

Looks good to my eyes,

Reviewed-by: WANG Cong <xiyou.wangcong at gmail.com>

Thanks.


From nhorman at redhat.com  Wed Mar 30 11:48:34 2011
From: nhorman at redhat.com (Neil Horman)
Date: Wed, 30 Mar 2011 11:48:34 -0400
Subject: [PATCH v2] generic-ipi: Initialize call_single_queue before
	enabling interrupt
In-Reply-To: <D6CBEE2F420741indou.takao@jp.fujitsu.com>
References: <D6CBEE2F420741indou.takao@jp.fujitsu.com>
Message-ID: <20110330154834.GA3421@hmsreliant.think-freely.org>

On Tue, Mar 29, 2011 at 12:35:04PM -0400, Takao Indoh wrote:
> Hi all,
> 
> This patch renames init_call_single_data() to call_function_init() and
> calls it in start_kernel() so that call_single_queue can be initialized
> before enabling interrupt.
> 
> There is a problem that kdump(2nd kernel) sometimes hangs up due to
> pending IPI from 1st kernel. Kernel panic occurs because IPI comes
> before call_single_queue is initialized. The details are as follows.
> (1) 2nd kernel boot up
> (2) A pending IPI from 1st kernel comes when irqs are first enabled
>     in start_kernel().
> (3) Kernel tries to handle the interrupt, but call_single_queue is not
>     initialized yet at this point. As a result, in the
>     generic_smp_call_function_single_interrupt(), NULL pointer
>     dereference occurs when list_replace_init() tries to access
>     &q->list.next.
> Therefore this patch changes the name of init_call_single_data() to
> call_function_init() and calls it before local_irq_enable() in
> start_kernel().
> 
> v2:
> - Rename init_call_single_data() to call_function_init() and calls it in
>   start_kernel()
> - Change insert position in start_kernel().
> - Adjust for CONFIG_SMP/CONFIG_USE_GENERIC_SMP_HELPERS options
> - Rebased to Linus's latest tree
> 
> v1:
> https://lkml.org/lkml/2011/3/25/317
> - Divide init_call_single_data() into two functions,
>    o init_call_single_data: initialize call_single_queue
>    o init_hotplug_cfd: initialize hotplug_cfd_notifier
>   And call init_call_single_data before local_irq_enable() in
>   start_kernel().
> 
> v0:
> https://lkml.org/lkml/2011/3/23/417
> - In generic_smp_call_function_single_interrupt(), check if
>   call_single_queue was initialized or not, and just return if not
>   initialized.
> 
> Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
> ---
>  include/linux/smp.h |    5 ++++-
>  init/main.c         |    1 +
>  kernel/smp.c        |    5 +----
>  3 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/smp.h b/include/linux/smp.h
> index 74243c8..4fb3eac 100644
> --- a/include/linux/smp.h
> +++ b/include/linux/smp.h
> @@ -85,12 +85,15 @@ int smp_call_function_any(const struct cpumask *mask,
>   * Generic and arch helpers
>   */
>  #ifdef CONFIG_USE_GENERIC_SMP_HELPERS
> +void __init call_function_init(void);
>  void generic_smp_call_function_single_interrupt(void);
>  void generic_smp_call_function_interrupt(void);
>  void ipi_call_lock(void);
>  void ipi_call_unlock(void);
>  void ipi_call_lock_irq(void);
>  void ipi_call_unlock_irq(void);
> +#else
> +static inline void call_function_init(void) { }
>  #endif
>  
>  /*
> @@ -144,7 +147,7 @@ static inline void smp_send_reschedule(int cpu) { }
>  #define smp_prepare_boot_cpu()			do {} while (0)
>  #define smp_call_function_many(mask, func, info, wait) \
>  			(up_smp_call_function(func, info))
> -static inline void init_call_single_data(void) { }
> +static inline void call_function_init(void) { }
>  
>  static inline int
>  smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
> diff --git a/init/main.c b/init/main.c
> index 4a9479e..12821d1 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -539,6 +539,7 @@ asmlinkage void __init start_kernel(void)
>  	timekeeping_init();
>  	time_init();
>  	profile_init();
> +	call_function_init();
>  	if (!irqs_disabled())
>  		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
>  				 "enabled early\n");
> diff --git a/kernel/smp.c b/kernel/smp.c
> index 73a1951..fb67dfa 100644
> --- a/kernel/smp.c
> +++ b/kernel/smp.c
> @@ -74,7 +74,7 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = {
>  	.notifier_call		= hotplug_cfd,
>  };
>  
> -static int __cpuinit init_call_single_data(void)
> +void __init call_function_init(void)
>  {
>  	void *cpu = (void *)(long)smp_processor_id();
>  	int i;
> @@ -88,10 +88,7 @@ static int __cpuinit init_call_single_data(void)
>  
>  	hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
>  	register_cpu_notifier(&hotplug_cfd_notifier);
> -
> -	return 0;
>  }
> -early_initcall(init_call_single_data);
>  
>  /*
>   * csd_lock/csd_unlock used to serialize access to per-cpu csd resources
> 
Acked-by: Neil Horman <nhorman at tuxdriver.com>

> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From christopher.leech at linux.intel.com  Thu Mar 31 13:21:15 2011
From: christopher.leech at linux.intel.com (Chris Leech)
Date: Thu, 31 Mar 2011 17:21:15 +0000 (UTC)
Subject: [PATCH V2] kexec, x86: fix kexec
	=?utf-8?b?d2hlbglib290X3BhcmFtcy5oYXJkd2FyZV9zdWJhcmNo?= != 0
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
	<20110328215011.30400.91252.stgit@localhost6.localdomain6>
	<ims7bl$ik5$1@dough.gmane.org>
	<20110329232259.GC27905@verge.net.au>
Message-ID: <loom.20110331T191730-224@post.gmane.org>

Simon Horman <horms at ...> writes:

> 
> On Tue, Mar 29, 2011 at 09:04:53AM +0000, WANG Cong wrote:
> > On Mon, 28 Mar 2011 14:50:11 -0700, Chris Leech wrote:
> > 
> > > kexec needs to keep the subarch setting the same as the running kernel
> > > in the boot parameters, or the kernel will die in early setup.  I ran
> > > into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
> > > future subarch that uses non-default early setup code.
> > > 
> > > This patch requires debugfs mounted at /sys/kernel/debug, as that's the
> > > only way I know of to get at the running kernels boot_params. Without
> > > debugfs mounted it falls back to the current behavior of assuming
> > > subarch 0.
> > > 
> > ...
> > >  
> > > +#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
> > 
> > A minor issue here is that you are using a hard-coded debugfs path,
> > debugfs can be also mounted to /debug too, so it is better that if we can 
> > search the path dynamically here.
> 
> Do you think it would be better for the code to loop through
> a few common alternatives for the path?
> 

Not fully tested, but instead of looping through possible mount points maybe 
look through mtab in search of debugfs by fs type.

Something like this?

kexec, x86: search for debugfs mountpoint in /etc/mtab

From: Chris Leech <christopher.leech at linux.intel.com>

Signed-off-by: Chris Leech <christopher.leech at linux.intel.com>
---
 kexec/arch/i386/x86-linux-setup.c |   35 +++++++++++++++++++++++++++++++++--
 1 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-
setup.c
index 50b32be..0528cea 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -30,6 +30,7 @@
 #include <linux/fb.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <mntent.h>
 #include <x86/x86-linux.h>
 #include "../../kexec.h"
 #include "kexec-x86.h"
@@ -397,14 +398,44 @@ out:
 		real_mode->eddbuf_entries);
 }
 
-#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
+/*
+ * This really only makes sense for virtual filesystems that are only expected
+ * to be mounted once (sysfs, debugsfs, proc), as it will return the first
+ * instance listed in mtab.
+ */
+char *find_mnt_by_fsname(char *fsname)
+{
+	FILE *mtab;
+	struct mntent *mnt;
+	char *mntdir;
+
+	mtab = setmntent("/etc/mtab", "r");
+	if (!mtab)
+		return NULL;
+	for(mnt = getmntent(mtab); mnt; mnt = getmntent(mtab)) {
+		if (strcmp(mnt->mnt_fsname, fsname) == 0)
+			break;
+	}
+	mntdir = mnt ? strdup(mnt->mnt_dir) : NULL;
+	endmntent(mtab);
+	return mntdir;
+}
 
 void setup_subarch(struct x86_linux_param_header *real_mode)
 {
 	int data_file;
 	const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
+	char *debugfs_mnt;
+	char filename[PATH_MAX];
+
+	debugfs_mnt = find_mnt_by_fsname("debugfs");
+	if (!debugfs_mnt)
+		return;
+	snprintf(filename, PATH_MAX, "%s/%s", debugfs_mnt, "boot_params/data");
+	filename[PATH_MAX-1] = 0;
+	free(debugfs_mnt);
 
-	data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
+	data_file = open(filename, O_RDONLY);
 	if (data_file < 0)
 		return;
 	if (lseek(data_file, offset, SEEK_SET) < 0)






From horms at verge.net.au  Thu Mar 31 22:00:51 2011
From: horms at verge.net.au (Simon Horman)
Date: Fri, 1 Apr 2011 11:00:51 +0900
Subject: [PATCH V2] kexec, x86: fix kexec
	when?boot_params.hardware_subarch != 0
In-Reply-To: <loom.20110331T191730-224@post.gmane.org>
References: <20110328194049.32626.74038.stgit@localhost6.localdomain6>
	<20110328215011.30400.91252.stgit@localhost6.localdomain6>
	<ims7bl$ik5$1@dough.gmane.org>
	<20110329232259.GC27905@verge.net.au>
	<loom.20110331T191730-224@post.gmane.org>
Message-ID: <20110401020050.GM8362@verge.net.au>

On Thu, Mar 31, 2011 at 05:21:15PM +0000, Chris Leech wrote:
> Simon Horman <horms at ...> writes:
> 
> > 
> > On Tue, Mar 29, 2011 at 09:04:53AM +0000, WANG Cong wrote:
> > > On Mon, 28 Mar 2011 14:50:11 -0700, Chris Leech wrote:
> > > 
> > > > kexec needs to keep the subarch setting the same as the running kernel
> > > > in the boot parameters, or the kernel will die in early setup.  I ran
> > > > into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any
> > > > future subarch that uses non-default early setup code.
> > > > 
> > > > This patch requires debugfs mounted at /sys/kernel/debug, as that's the
> > > > only way I know of to get at the running kernels boot_params. Without
> > > > debugfs mounted it falls back to the current behavior of assuming
> > > > subarch 0.
> > > > 
> > > ...
> > > >  
> > > > +#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
> > > 
> > > A minor issue here is that you are using a hard-coded debugfs path,
> > > debugfs can be also mounted to /debug too, so it is better that if we can 
> > > search the path dynamically here.
> > 
> > Do you think it would be better for the code to loop through
> > a few common alternatives for the path?
> > 
> 
> Not fully tested, but instead of looping through possible mount points maybe 
> look through mtab in search of debugfs by fs type.
> 
> Something like this?

This approach looks good to me.
Could you do some more testing?

> kexec, x86: search for debugfs mountpoint in /etc/mtab
> 
> From: Chris Leech <christopher.leech at linux.intel.com>
> 
> Signed-off-by: Chris Leech <christopher.leech at linux.intel.com>
> ---
>  kexec/arch/i386/x86-linux-setup.c |   35 +++++++++++++++++++++++++++++++++--
>  1 files changed, 33 insertions(+), 2 deletions(-)
> 
> diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-
> setup.c
> index 50b32be..0528cea 100644
> --- a/kexec/arch/i386/x86-linux-setup.c
> +++ b/kexec/arch/i386/x86-linux-setup.c
> @@ -30,6 +30,7 @@
>  #include <linux/fb.h>
>  #include <unistd.h>
>  #include <dirent.h>
> +#include <mntent.h>
>  #include <x86/x86-linux.h>
>  #include "../../kexec.h"
>  #include "kexec-x86.h"
> @@ -397,14 +398,44 @@ out:
>  		real_mode->eddbuf_entries);
>  }
>  
> -#define BOOT_PARAMS_DBGFS	"/sys/kernel/debug/boot_params/data"
> +/*
> + * This really only makes sense for virtual filesystems that are only expected
> + * to be mounted once (sysfs, debugsfs, proc), as it will return the first
> + * instance listed in mtab.
> + */
> +char *find_mnt_by_fsname(char *fsname)
> +{
> +	FILE *mtab;
> +	struct mntent *mnt;
> +	char *mntdir;
> +
> +	mtab = setmntent("/etc/mtab", "r");
> +	if (!mtab)
> +		return NULL;
> +	for(mnt = getmntent(mtab); mnt; mnt = getmntent(mtab)) {
> +		if (strcmp(mnt->mnt_fsname, fsname) == 0)
> +			break;
> +	}
> +	mntdir = mnt ? strdup(mnt->mnt_dir) : NULL;
> +	endmntent(mtab);
> +	return mntdir;
> +}
>  
>  void setup_subarch(struct x86_linux_param_header *real_mode)
>  {
>  	int data_file;
>  	const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
> +	char *debugfs_mnt;
> +	char filename[PATH_MAX];
> +
> +	debugfs_mnt = find_mnt_by_fsname("debugfs");
> +	if (!debugfs_mnt)
> +		return;
> +	snprintf(filename, PATH_MAX, "%s/%s", debugfs_mnt, "boot_params/data");

It might be worth bailing out on truncation here.
Perhaps with an error message?

> +	filename[PATH_MAX-1] = 0;
> +	free(debugfs_mnt);
>  
> -	data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
> +	data_file = open(filename, O_RDONLY);
>  	if (data_file < 0)
>  		return;
>  	if (lseek(data_file, offset, SEEK_SET) < 0)


