From vgoyal at redhat.com  Mon Aug  1 16:16:44 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 1 Aug 2011 16:16:44 -0400
Subject: [patch v2 01/10] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
In-Reply-To: <20110727125807.529303146@linux.vnet.ibm.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.529303146@linux.vnet.ibm.com>
Message-ID: <20110801201644.GG3805@redhat.com>

On Wed, Jul 27, 2011 at 02:55:05PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> On s390 there is a different KEXEC_CONTROL_MEMORY_LIMIT for the normal and
> the kdump kexec case. Therefore this patch introduces a new macro
> KEXEC_CRASH_CONTROL_MEMORY_LIMIT. This is set to
> KEXEC_CONTROL_MEMORY_LIMIT for all architectures that do not define
> KEXEC_CRASH_CONTROL_MEMORY_LIMIT.

Hi Michael,

Curious that why limit is different for kexec and kdump cases on s390
only.

Thanks
Vivek

> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> ---
>  include/linux/kexec.h |    4 ++++
>  kernel/kexec.c        |    2 +-
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -33,6 +33,10 @@
>  #error KEXEC_ARCH not defined
>  #endif
>  
> +#ifndef KEXEC_CRASH_CONTROL_MEMORY_LIMIT
> +#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT KEXEC_CONTROL_MEMORY_LIMIT
> +#endif
> +
>  #define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
>  #define KEXEC_CORE_NOTE_NAME "CORE"
>  #define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -498,7 +498,7 @@ static struct page *kimage_alloc_crash_c
>  	while (hole_end <= crashk_res.end) {
>  		unsigned long i;
>  
> -		if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT)
> +		if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT)
>  			break;
>  		if (hole_end > crashk_res.end)
>  			break;


From vgoyal at redhat.com  Mon Aug  1 16:31:43 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 1 Aug 2011 16:31:43 -0400
Subject: [patch v2 02/10] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110727125807.695225427@linux.vnet.ibm.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.695225427@linux.vnet.ibm.com>
Message-ID: <20110801203143.GH3805@redhat.com>

On Wed, Jul 27, 2011 at 02:55:06PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> On s390 we do not create page tables at all for the crashkernel memory.
> This requires a s390 specific version for kimage_load_crash_segment().
> Therefore this patch declares this function as "__weak". The s390 version is
> very simple. It just copies the kexec segment to real memory without using
> page tables:
> 
> int kimage_load_crash_segment(struct kimage *image,
>                               struct kexec_segment *segment)
> {
>         return copy_from_user_real((void *) segment->mem, segment->buf,
>                                    segment->bufsz);
> }
> 
> There are two main advantages of not creating page tables for the
> crashkernel memory:
> 
> a) It saves memory. We have scenarios in mind, where crashkernel
>    memory can be very large and saving page table space is important.
> b) We protect the crashkernel memory from being overwritten.
> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> ---
>  kernel/kexec.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -842,8 +842,8 @@ out:
>  	return result;
>  }
>  
> -static int kimage_load_crash_segment(struct kimage *image,
> -					struct kexec_segment *segment)
> +int __weak kimage_load_crash_segment(struct kimage *image,
> +				     struct kexec_segment *segment)

A comment here why we are making it weak should help in increasing
the code readability.

Thanks
Vivek

>  {
>  	/* For crash dumps kernels we simply copy the data from
>  	 * user space to it's destination.


From vgoyal at redhat.com  Mon Aug  1 16:36:07 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 1 Aug 2011 16:36:07 -0400
Subject: [patch v2 03/10] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110727125807.853426542@linux.vnet.ibm.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.853426542@linux.vnet.ibm.com>
Message-ID: <20110801203607.GI3805@redhat.com>

On Wed, Jul 27, 2011 at 02:55:07PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> Currently only the address of the pre-allocated ELF header is passed with
> the elfcorehdr= kernel parameter. In order to reserve memory for the header
> in the 2nd kernel also the size is required. To pass the size with this
> patch the syntax of the kernel parameter is extended as follows:
> 
> elfcorehdr=[size[KMG]@]offset[KMG]
> 
> This change is backward compatible because elfcorehdr=size is still allowed.

Generally vmcore parses elfcorehdr to figure out the sizes. kexec-tools
knows about it and relevant memory is excluded from second kernel's map
with the help of memmap= command line option.

Can you please mention that this is only s390 specific requirement as
there are no memmap= equivalent options and somehow dump tools wants
to know how big the elf header size is?

Thanks
Vivek

> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> ---
>  Documentation/kernel-parameters.txt |    6 +++---
>  include/linux/crash_dump.h          |    1 +
>  kernel/crash_dump.c                 |   11 +++++++++++
>  3 files changed, 15 insertions(+), 3 deletions(-)
> 
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -717,10 +717,10 @@ bytes respectively. Such letter suffixes
>  			See Documentation/block/as-iosched.txt and
>  			Documentation/block/deadline-iosched.txt for details.
>  
> -	elfcorehdr=	[IA64,PPC,SH,X86]
> +	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
>  			Specifies physical address of start of kernel core
> -			image elf header. Generally kexec loader will
> -			pass this option to capture kernel.
> +			image elf header and optionally the size. Generally
> +			kexec loader will pass this option to capture kernel.
>  			See Documentation/kdump/kdump.txt for details.
>  
>  	enable_mtrr_cleanup [X86]
> --- a/include/linux/crash_dump.h
> +++ b/include/linux/crash_dump.h
> @@ -10,6 +10,7 @@
>  #define ELFCORE_ADDR_ERR	(-2ULL)
>  
>  extern unsigned long long elfcorehdr_addr;
> +extern unsigned long long elfcorehdr_size;
>  
>  extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
>  						unsigned long, int);
> --- a/kernel/crash_dump.c
> +++ b/kernel/crash_dump.c
> @@ -20,8 +20,15 @@ unsigned long saved_max_pfn;
>  unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
>  
>  /*
> + * stores the size of elf header of crash image
> + */
> +unsigned long long elfcorehdr_size;
> +
> +/*
>   * elfcorehdr= specifies the location of elf core header stored by the crashed
>   * kernel. This option will be passed by kexec loader to the capture kernel.
> + *
> + * Syntax: elfcorehdr=[size[KMG]@]offset[KMG]
>   */
>  static int __init setup_elfcorehdr(char *arg)
>  {
> @@ -29,6 +36,10 @@ static int __init setup_elfcorehdr(char
>  	if (!arg)
>  		return -EINVAL;
>  	elfcorehdr_addr = memparse(arg, &end);
> +	if (*end == '@') {
> +		elfcorehdr_size = elfcorehdr_addr;
> +		elfcorehdr_addr = memparse(end + 1, &end);
> +	}
>  	return end > arg ? 0 : -EINVAL;
>  }
>  early_param("elfcorehdr", setup_elfcorehdr);


From vgoyal at redhat.com  Mon Aug  1 16:41:14 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 1 Aug 2011 16:41:14 -0400
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <20110727125808.028895659@linux.vnet.ibm.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
Message-ID: <20110801204114.GJ3805@redhat.com>

On Wed, Jul 27, 2011 at 02:55:08PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> On s390 we have the possibility to configure actions that are executed in
> case of a kernel panic. E.g. it is possible to automatically trigger an s390
> stand-alone dump. The actions are called via a panic notifier.  We also want
> to trigger kdump via the notifier call chain. Therefore this patch disables
> for s390 the direct kdump invocation in the panic() function.

Doesn't this reduce the reliability of the operation as you are assuming
that panic notifier list is fine and not corrupted.

There might be other generic notifiers registerd on panic notifier list
too. So in your case, are there multiple subsystem registering for panic
notifiers? If not, why not call crash_kexec() directly. Are there any
other actions you want to take on panic then calling crash_kexec()?

Thanks
Vivek

> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> ---
>  kernel/panic.c |    3 +++
>  1 file changed, 3 insertions(+)
> 
> --- a/kernel/panic.c
> +++ b/kernel/panic.c
> @@ -84,9 +84,12 @@ NORET_TYPE void panic(const char * fmt,
>  	/*
>  	 * If we have crashed and we have a crash kernel loaded let it handle
>  	 * everything else.
> +	 * For s390 kdump is triggered via the panic notifier call chain.
>  	 * Do we want to call this before we try to display a message?
>  	 */
> +#if !defined(CONFIG_S390)
>  	crash_kexec(NULL);
> +#endif
>  
>  	kmsg_dump(KMSG_DUMP_PANIC);
>  


From vgoyal at redhat.com  Mon Aug  1 16:54:02 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 1 Aug 2011 16:54:02 -0400
Subject: [patch v2 05/10] s390: Add PSW restart shutdown trigger
In-Reply-To: <20110727125808.172069159@linux.vnet.ibm.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.172069159@linux.vnet.ibm.com>
Message-ID: <20110801205402.GK3805@redhat.com>

On Wed, Jul 27, 2011 at 02:55:09PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> With this patch a new S390 shutdown trigger "restart" is added. If under
> z/VM "systerm restart" is entered or under the HMC the "PSW restart" button
> is pressed, the PSW located at 0 (31 bit) or 0x1a0 (64 bit) bit is loaded.
> Now we execute do_restart() that processes the restart action that is
> defined under /sys/firmware/shutdown_actions/on_restart. Currently the
> following actions are possible: reipl (default), stop, vmcmd, dump, and
> dump_reipl.

i know nothing about s390 but this sounds like a independent
functionality? I mean defining a restart trigger and associated actions
could be done even in current framework without kdump. IIUC, additional
kdump series only adds the ability to use kdump for second kernel instead
of using dump tools in case of "dump" or "dump_reipl" ?

If yes, then this patch probably does not have to be part of this series
and pushed in independetly?

Thanks
Vivek

> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> ---
>  arch/s390/include/asm/lowcore.h |   11 +++++++++--
>  arch/s390/include/asm/system.h  |    1 +
>  arch/s390/kernel/asm-offsets.c  |    1 +
>  arch/s390/kernel/entry.S        |   28 ++++++++++++++++++++++++++++
>  arch/s390/kernel/entry64.S      |   20 ++++++++++++++++++++
>  arch/s390/kernel/ipl.c          |   39 ++++++++++++++++++++++++++++++++++++++-
>  arch/s390/kernel/setup.c        |   24 +++++++++++++++++++++++-
>  arch/s390/kernel/smp.c          |    8 ++++++++
>  arch/s390/mm/maccess.c          |   16 ++++++++++++++++
>  9 files changed, 144 insertions(+), 4 deletions(-)
> 
> --- a/arch/s390/include/asm/lowcore.h
> +++ b/arch/s390/include/asm/lowcore.h
> @@ -18,6 +18,7 @@ void system_call(void);
>  void pgm_check_handler(void);
>  void mcck_int_handler(void);
>  void io_int_handler(void);
> +void psw_restart_int_handler(void);
>  
>  #ifdef CONFIG_32BIT
>  
> @@ -150,7 +151,10 @@ struct _lowcore {
>  	 */
>  	__u32	ipib;				/* 0x0e00 */
>  	__u32	ipib_checksum;			/* 0x0e04 */
> -	__u8	pad_0x0e08[0x0f00-0x0e08];	/* 0x0e08 */
> +
> +	/* 64 bit save area */
> +	__u64	save_area_64;			/* 0x0e08 */
> +	__u8	pad_0x0e10[0x0f00-0x0e10];	/* 0x0e10 */
>  
>  	/* Extended facility list */
>  	__u64	stfle_fac_list[32];		/* 0x0f00 */
> @@ -286,7 +290,10 @@ struct _lowcore {
>  	 */
>  	__u64	ipib;				/* 0x0e00 */
>  	__u32	ipib_checksum;			/* 0x0e08 */
> -	__u8	pad_0x0e0c[0x0f00-0x0e0c];	/* 0x0e0c */
> +
> +	/* 64 bit save area */
> +	__u64	save_area_64;			/* 0x0e0c */
> +	__u8	pad_0x0e14[0x0f00-0x0e14];	/* 0x0e14 */
>  
>  	/* Extended facility list */
>  	__u64	stfle_fac_list[32];		/* 0x0f00 */
> --- a/arch/s390/include/asm/system.h
> +++ b/arch/s390/include/asm/system.h
> @@ -113,6 +113,7 @@ extern void pfault_fini(void);
>  
>  extern void cmma_init(void);
>  extern int memcpy_real(void *, void *, size_t);
> +extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
>  
>  #define finish_arch_switch(prev) do {					     \
>  	set_fs(current->thread.mm_segment);				     \
> --- a/arch/s390/kernel/asm-offsets.c
> +++ b/arch/s390/kernel/asm-offsets.c
> @@ -142,6 +142,7 @@ int main(void)
>  	DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
>  	DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
>  	DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
> +	DEFINE(__LC_SAVE_AREA_64, offsetof(struct _lowcore, save_area_64));
>  #ifdef CONFIG_32BIT
>  	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
>  #else /* CONFIG_32BIT */
> --- a/arch/s390/kernel/entry.S
> +++ b/arch/s390/kernel/entry.S
> @@ -849,6 +849,34 @@ restart_crash:
>  restart_go:
>  #endif
>  
> +#
> +# PSW restart interrupt handler
> +#
> +ENTRY(psw_restart_int_handler)
> +	st	%r15,__LC_SAVE_AREA_64(%r0)	# save r15
> +	basr	%r15,0
> +0:	l	%r15,.Lrestart_stack-0b(%r15)	# load restart stack
> +	l	%r15,0(%r15)
> +	ahi	%r15,-SP_SIZE			# make room for pt_regs
> +	stm	%r0,%r14,SP_R0(%r15)		# store gprs %r0-%r14 to stack
> +	mvc	SP_R15(4,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
> +	mvc	SP_PSW(8,%r15),__LC_RST_OLD_PSW(%r0) # store restart old psw
> +	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
> +	basr	%r14,0
> +1:	l	%r14,.Ldo_restart-1b(%r14)
> +	basr	%r14,%r14
> +
> +	basr	%r14,0				# load disabled wait PSW if
> +2:	lpsw	restart_psw_crash-2b(%r14)	# do_restart returns
> +	.align 4
> +.Ldo_restart:
> +	.long	do_restart
> +.Lrestart_stack:
> +	.long	restart_stack
> +	.align 8
> +restart_psw_crash:
> +	.long	0x000a0000,0x00000000 + restart_psw_crash
> +
>  	.section .kprobes.text, "ax"
>  
>  #ifdef CONFIG_CHECK_STACK
> --- a/arch/s390/kernel/entry64.S
> +++ b/arch/s390/kernel/entry64.S
> @@ -865,6 +865,26 @@ restart_crash:
>  restart_go:
>  #endif
>  
> +#
> +# PSW restart interrupt handler
> +#
> +ENTRY(psw_restart_int_handler)
> +	stg	%r15,__LC_SAVE_AREA_64(%r0)	# save r15
> +	larl	%r15,restart_stack		# load restart stack
> +	lg	%r15,0(%r15)
> +	aghi	%r15,-SP_SIZE			# make room for pt_regs
> +	stmg	%r0,%r14,SP_R0(%r15)		# store gprs %r0-%r14 to stack
> +	mvc	SP_R15(8,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
> +	mvc	SP_PSW(16,%r15),__LC_RST_OLD_PSW(%r0)# store restart old psw
> +	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
> +	brasl	%r14,do_restart
> +
> +	larl	%r14,restart_psw_crash		# load disabled wait PSW if
> +	lpswe	0(%r14)				# do_restart returns
> +	.align 8
> +restart_psw_crash:
> +	.quad	0x0002000080000000,0x0000000000000000 + restart_psw_crash
> +
>  	.section .kprobes.text, "ax"
>  
>  #ifdef CONFIG_CHECK_STACK
> --- a/arch/s390/kernel/ipl.c
> +++ b/arch/s390/kernel/ipl.c
> @@ -45,11 +45,13 @@
>   * - halt
>   * - power off
>   * - reipl
> + * - restart
>   */
>  #define ON_PANIC_STR		"on_panic"
>  #define ON_HALT_STR		"on_halt"
>  #define ON_POFF_STR		"on_poff"
>  #define ON_REIPL_STR		"on_reboot"
> +#define ON_RESTART_STR		"on_restart"
>  
>  struct shutdown_action;
>  struct shutdown_trigger {
> @@ -1544,17 +1546,20 @@ static char vmcmd_on_reboot[128];
>  static char vmcmd_on_panic[128];
>  static char vmcmd_on_halt[128];
>  static char vmcmd_on_poff[128];
> +static char vmcmd_on_restart[128];
>  
>  DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
>  DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
>  DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
>  DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
> +DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart);
>  
>  static struct attribute *vmcmd_attrs[] = {
>  	&sys_vmcmd_on_reboot_attr.attr,
>  	&sys_vmcmd_on_panic_attr.attr,
>  	&sys_vmcmd_on_halt_attr.attr,
>  	&sys_vmcmd_on_poff_attr.attr,
> +	&sys_vmcmd_on_restart_attr.attr,
>  	NULL,
>  };
>  
> @@ -1576,6 +1581,8 @@ static void vmcmd_run(struct shutdown_tr
>  		cmd = vmcmd_on_halt;
>  	else if (strcmp(trigger->name, ON_POFF_STR) == 0)
>  		cmd = vmcmd_on_poff;
> +	else if (strcmp(trigger->name, ON_RESTART_STR) == 0)
> +		cmd = vmcmd_on_restart;
>  	else
>  		return;
>  
> @@ -1707,6 +1714,34 @@ static void do_panic(void)
>  	stop_run(&on_panic_trigger);
>  }
>  
> +/* on restart */
> +
> +static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
> +	&reipl_action};
> +
> +static ssize_t on_restart_show(struct kobject *kobj,
> +			       struct kobj_attribute *attr, char *page)
> +{
> +	return sprintf(page, "%s\n", on_restart_trigger.action->name);
> +}
> +
> +static ssize_t on_restart_store(struct kobject *kobj,
> +				struct kobj_attribute *attr,
> +				const char *buf, size_t len)
> +{
> +	return set_trigger(buf, &on_restart_trigger, len);
> +}
> +
> +static struct kobj_attribute on_restart_attr =
> +	__ATTR(on_restart, 0644, on_restart_show, on_restart_store);
> +
> +void do_restart(void)
> +{
> +	smp_send_stop();
> +	on_restart_trigger.action->fn(&on_restart_trigger);
> +	stop_run(&on_restart_trigger);
> +}
> +
>  /* on halt */
>  
>  static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
> @@ -1783,7 +1818,9 @@ static void __init shutdown_triggers_ini
>  	if (sysfs_create_file(&shutdown_actions_kset->kobj,
>  			      &on_poff_attr.attr))
>  		goto fail;
> -
> +	if (sysfs_create_file(&shutdown_actions_kset->kobj,
> +			      &on_restart_attr.attr))
> +		goto fail;
>  	return;
>  fail:
>  	panic("shutdown_triggers_init failed\n");
> --- a/arch/s390/kernel/setup.c
> +++ b/arch/s390/kernel/setup.c
> @@ -346,7 +346,7 @@ setup_lowcore(void)
>  	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
>  	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
>  	lc->restart_psw.addr =
> -		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
> +		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
>  	if (user_mode != HOME_SPACE_MODE)
>  		lc->restart_psw.mask |= PSW_ASC_HOME;
>  	lc->external_new_psw.mask = psw_kernel_bits;
> @@ -529,6 +529,27 @@ static void __init setup_memory_end(void
>  		memory_end = memory_size;
>  }
>  
> +void *restart_stack __attribute__((__section__(".data")));
> +
> +/*
> + * Setup new PSW and allocate stack for PSW restart interrupt
> + */
> +static void __init setup_restart_psw(void)
> +{
> +	psw_t psw;
> +
> +	restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);
> +	restart_stack += ASYNC_SIZE;
> +
> +	/*
> +	 * Setup restart PSW for absolute zero lowcore. This is necesary
> +	 * if PSW restart is done on an offline CPU that has lowcore zero
> +	 */
> +	psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
> +	psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
> +	copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
> +}
> +
>  static void __init
>  setup_memory(void)
>  {
> @@ -792,6 +813,7 @@ setup_arch(char **cmdline_p)
>  	setup_addressing_mode();
>  	setup_memory();
>  	setup_resources();
> +	setup_restart_psw();
>  	setup_lowcore();
>  
>          cpu_init();
> --- a/arch/s390/kernel/smp.c
> +++ b/arch/s390/kernel/smp.c
> @@ -470,6 +470,11 @@ int __cpuinit start_secondary(void *cpuv
>  	ipi_call_unlock();
>  	/* Switch on interrupts */
>  	local_irq_enable();
> +	__ctl_clear_bit(0, 28); /* Disable lowcore protection */
> +	S390_lowcore.restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
> +	S390_lowcore.restart_psw.addr =
> +		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
> +	__ctl_set_bit(0, 28); /* Enable lowcore protection */
>  	/* cpu_idle will call schedule for us */
>  	cpu_idle();
>  	return 0;
> @@ -507,6 +512,9 @@ static int __cpuinit smp_alloc_lowcore(i
>  	memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
>  	lowcore->async_stack = async_stack + ASYNC_SIZE;
>  	lowcore->panic_stack = panic_stack + PAGE_SIZE;
> +	lowcore->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
> +	lowcore->restart_psw.addr =
> +		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
>  
>  #ifndef CONFIG_64BIT
>  	if (MACHINE_HAS_IEEE) {
> --- a/arch/s390/mm/maccess.c
> +++ b/arch/s390/mm/maccess.c
> @@ -85,3 +85,19 @@ int memcpy_real(void *dest, void *src, s
>  	arch_local_irq_restore(flags);
>  	return rc;
>  }
> +
> +/*
> + * Copy memory to absolute zero
> + */
> +void copy_to_absolute_zero(void *dest, void *src, size_t count)
> +{
> +	unsigned long cr0;
> +
> +	BUG_ON((unsigned long) dest + count >= sizeof(struct _lowcore));
> +	preempt_disable();
> +	__ctl_store(cr0, 0, 0);
> +	__ctl_clear_bit(0, 28); /* disable lowcore protection */
> +	memcpy_real(dest + store_prefix(), src, count);
> +	__ctl_load(cr0, 0, 0);
> +	preempt_enable();
> +}


From holzheu at linux.vnet.ibm.com  Tue Aug  2 04:05:16 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Tue, 02 Aug 2011 10:05:16 +0200
Subject: [patch v2 05/10] s390: Add PSW restart shutdown trigger
In-Reply-To: <20110801205402.GK3805@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.172069159@linux.vnet.ibm.com>
	<20110801205402.GK3805@redhat.com>
Message-ID: <1312272316.4881.4.camel@br98xy6r>

Hello Vivek,

On Mon, 2011-08-01 at 16:54 -0400, Vivek Goyal wrote:
> On Wed, Jul 27, 2011 at 02:55:09PM +0200, Michael Holzheu wrote:
> > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > 
> > With this patch a new S390 shutdown trigger "restart" is added. If under
> > z/VM "systerm restart" is entered or under the HMC the "PSW restart" button
> > is pressed, the PSW located at 0 (31 bit) or 0x1a0 (64 bit) bit is loaded.
> > Now we execute do_restart() that processes the restart action that is
> > defined under /sys/firmware/shutdown_actions/on_restart. Currently the
> > following actions are possible: reipl (default), stop, vmcmd, dump, and
> > dump_reipl.
> 
> i know nothing about s390 but this sounds like a independent
> functionality? I mean defining a restart trigger and associated actions
> could be done even in current framework without kdump. IIUC, additional
> kdump series only adds the ability to use kdump for second kernel instead
> of using dump tools in case of "dump" or "dump_reipl" ?
> 
> If yes, then this patch probably does not have to be part of this series
> and pushed in independetly?

Yes, this is correct. We implemented the PSW restart functionality for
kdump, but it can be used independently.

We will integrate this patch upstream independently from this series.

Michael



From holzheu at linux.vnet.ibm.com  Tue Aug  2 04:37:59 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Tue, 02 Aug 2011 10:37:59 +0200
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <20110801204114.GJ3805@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
	<20110801204114.GJ3805@redhat.com>
Message-ID: <1312274279.4881.18.camel@br98xy6r>

Hello Vivek,

On Mon, 2011-08-01 at 16:41 -0400, Vivek Goyal wrote:
> On Wed, Jul 27, 2011 at 02:55:08PM +0200, Michael Holzheu wrote:
> > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > 
> > On s390 we have the possibility to configure actions that are executed in
> > case of a kernel panic. E.g. it is possible to automatically trigger an s390
> > stand-alone dump. The actions are called via a panic notifier.  We also want
> > to trigger kdump via the notifier call chain. Therefore this patch disables
> > for s390 the direct kdump invocation in the panic() function.
> 
> Doesn't this reduce the reliability of the operation as you are assuming
> that panic notifier list is fine and not corrupted.

Yes, this is correct. We have to rely that the notifier list is fine.
Probably there is still room for improvement here.

> There might be other generic notifiers registerd on panic notifier list
> too. So in your case, are there multiple subsystem registering for panic
> notifiers? If not, why not call crash_kexec() directly. Are there any
> other actions you want to take on panic then calling crash_kexec()?

We have added the panic notifier in the past in order to be able to
configure the action that should be done in case of panic using our
shutdown actions infrastructure. We can configure the action using sysfs
and we are able to configure that a stand-alone dump should be started
as action for panic.

Now with the two stage dump approach we would like to keep the
possibility to trigger a stand-alone dump even if kdump is installed.
The stand-alone dumper will be started in case of a kernel panic and
then the procedure we discussed will happen: Jump into kdump and if
program check occurs do stand-alone dump as backup.

Michael



From holzheu at linux.vnet.ibm.com  Tue Aug  2 05:08:07 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Tue, 02 Aug 2011 11:08:07 +0200
Subject: [patch v2 03/10] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110801203607.GI3805@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.853426542@linux.vnet.ibm.com>
	<20110801203607.GI3805@redhat.com>
Message-ID: <1312276087.4881.24.camel@br98xy6r>

Hello Vivek,

#On Mon, 2011-08-01 at 16:36 -0400, Vivek Goyal wrote: 
> On Wed, Jul 27, 2011 at 02:55:07PM +0200, Michael Holzheu wrote:
> > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > 
> > Currently only the address of the pre-allocated ELF header is passed with
> > the elfcorehdr= kernel parameter. In order to reserve memory for the header
> > in the 2nd kernel also the size is required. To pass the size with this
> > patch the syntax of the kernel parameter is extended as follows:
> > 
> > elfcorehdr=[size[KMG]@]offset[KMG]
> > 
> > This change is backward compatible because elfcorehdr=size is still allowed.
> 
> Generally vmcore parses elfcorehdr to figure out the sizes. kexec-tools
> knows about it and relevant memory is excluded from second kernel's map
> with the help of memmap= command line option.
> 
> Can you please mention that this is only s390 specific requirement as
> there are no memmap= equivalent options and somehow dump tools wants
> to know how big the elf header size is?

I updated the description: 

Currently only the address of the pre-allocated ELF header is passed with
the elfcorehdr= kernel parameter. In order to reserve memory for the header
in the 2nd kernel also the size is required. Current kdump architecture
backends use different methods to do that, e.g. x86 uses the memmap= kernel
parameter. On s390 there is no easy way to transfer this information.
Therefore the elfcorehdr kernel parameter is extended to also pass the size.
This now can also be used as standard mechanism by all future kdump
architecture backends.

The syntax of the kernel parameter is extended as follows:

elfcorehdr=[size[KMG]@]offset[KMG]

This change is backward compatible because elfcorehdr=size is still allowed.

Ok?

Michael



From holzheu at linux.vnet.ibm.com  Tue Aug  2 05:30:03 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Tue, 02 Aug 2011 11:30:03 +0200
Subject: [patch v2 02/10] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110801203143.GH3805@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.695225427@linux.vnet.ibm.com>
	<20110801203143.GH3805@redhat.com>
Message-ID: <1312277403.4881.26.camel@br98xy6r>

Hello Vivek,

On Mon, 2011-08-01 at 16:31 -0400, Vivek Goyal wrote:
> On Wed, Jul 27, 2011 at 02:55:06PM +0200, Michael Holzheu wrote:

[snip]

> > --- a/kernel/kexec.c
> > +++ b/kernel/kexec.c
> > @@ -842,8 +842,8 @@ out:
> >  	return result;
> >  }
> >  
> > -static int kimage_load_crash_segment(struct kimage *image,
> > -					struct kexec_segment *segment)
> > +int __weak kimage_load_crash_segment(struct kimage *image,
> > +				     struct kexec_segment *segment)
> 
> A comment here why we are making it weak should help in increasing
> the code readability.

What about the following:

/*
 * Load crash segment into memory. Architecture code can override this
 * function. E.g. this is necessary for architectures that do not
 * create page tables for crashkernel memory.
 */
int __weak kimage_load_crash_segment(struct kimage *image,

Michael



From holzheu at linux.vnet.ibm.com  Tue Aug  2 05:51:04 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Tue, 02 Aug 2011 11:51:04 +0200
Subject: [patch v2 01/10] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
In-Reply-To: <20110801201644.GG3805@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.529303146@linux.vnet.ibm.com>
	<20110801201644.GG3805@redhat.com>
Message-ID: <1312278664.4881.35.camel@br98xy6r>

Hello Vivek,

On Mon, 2011-08-01 at 16:16 -0400, Vivek Goyal wrote:
> On Wed, Jul 27, 2011 at 02:55:05PM +0200, Michael Holzheu wrote:
> > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > 
> > On s390 there is a different KEXEC_CONTROL_MEMORY_LIMIT for the normal and
> > the kdump kexec case. Therefore this patch introduces a new macro
> > KEXEC_CRASH_CONTROL_MEMORY_LIMIT. This is set to
> > KEXEC_CONTROL_MEMORY_LIMIT for all architectures that do not define
> > KEXEC_CRASH_CONTROL_MEMORY_LIMIT.
> 
> Hi Michael,
> 
> Curious that why limit is different for kexec and kdump cases on s390
> only.

The standard kexec relocate_kernel code calls a machine instruction that
must run below 2 GiB. For kdump we currently do not use the control page
at all because no segments have to be moved in that case. Perhaps I am
still missing something here?

Michael



From vgoyal at redhat.com  Tue Aug  2 14:55:01 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 2 Aug 2011 14:55:01 -0400
Subject: [patch v2 03/10] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <1312276087.4881.24.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.853426542@linux.vnet.ibm.com>
	<20110801203607.GI3805@redhat.com>
	<1312276087.4881.24.camel@br98xy6r>
Message-ID: <20110802185501.GG6399@redhat.com>

On Tue, Aug 02, 2011 at 11:08:07AM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> #On Mon, 2011-08-01 at 16:36 -0400, Vivek Goyal wrote: 
> > On Wed, Jul 27, 2011 at 02:55:07PM +0200, Michael Holzheu wrote:
> > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > 
> > > Currently only the address of the pre-allocated ELF header is passed with
> > > the elfcorehdr= kernel parameter. In order to reserve memory for the header
> > > in the 2nd kernel also the size is required. To pass the size with this
> > > patch the syntax of the kernel parameter is extended as follows:
> > > 
> > > elfcorehdr=[size[KMG]@]offset[KMG]
> > > 
> > > This change is backward compatible because elfcorehdr=size is still allowed.
> > 
> > Generally vmcore parses elfcorehdr to figure out the sizes. kexec-tools
> > knows about it and relevant memory is excluded from second kernel's map
> > with the help of memmap= command line option.
> > 
> > Can you please mention that this is only s390 specific requirement as
> > there are no memmap= equivalent options and somehow dump tools wants
> > to know how big the elf header size is?
> 
> I updated the description: 
> 
> Currently only the address of the pre-allocated ELF header is passed with
> the elfcorehdr= kernel parameter. In order to reserve memory for the header
> in the 2nd kernel also the size is required. Current kdump architecture
> backends use different methods to do that, e.g. x86 uses the memmap= kernel
> parameter. On s390 there is no easy way to transfer this information.
> Therefore the elfcorehdr kernel parameter is extended to also pass the size.
> This now can also be used as standard mechanism by all future kdump
> architecture backends.
> 
> The syntax of the kernel parameter is extended as follows:
> 
> elfcorehdr=[size[KMG]@]offset[KMG]
> 
> This change is backward compatible because elfcorehdr=size is still allowed.
> 
> Ok?

Yes, this one looks ok.

Thanks
Vivek


From vgoyal at redhat.com  Tue Aug  2 14:55:30 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 2 Aug 2011 14:55:30 -0400
Subject: [patch v2 02/10] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <1312277403.4881.26.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.695225427@linux.vnet.ibm.com>
	<20110801203143.GH3805@redhat.com>
	<1312277403.4881.26.camel@br98xy6r>
Message-ID: <20110802185530.GH6399@redhat.com>

On Tue, Aug 02, 2011 at 11:30:03AM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Mon, 2011-08-01 at 16:31 -0400, Vivek Goyal wrote:
> > On Wed, Jul 27, 2011 at 02:55:06PM +0200, Michael Holzheu wrote:
> 
> [snip]
> 
> > > --- a/kernel/kexec.c
> > > +++ b/kernel/kexec.c
> > > @@ -842,8 +842,8 @@ out:
> > >  	return result;
> > >  }
> > >  
> > > -static int kimage_load_crash_segment(struct kimage *image,
> > > -					struct kexec_segment *segment)
> > > +int __weak kimage_load_crash_segment(struct kimage *image,
> > > +				     struct kexec_segment *segment)
> > 
> > A comment here why we are making it weak should help in increasing
> > the code readability.
> 
> What about the following:
> 
> /*
>  * Load crash segment into memory. Architecture code can override this
>  * function. E.g. this is necessary for architectures that do not
>  * create page tables for crashkernel memory.
>  */
> int __weak kimage_load_crash_segment(struct kimage *image,

This looks better.

Thanks
Vivek


From vgoyal at redhat.com  Tue Aug  2 15:16:03 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 2 Aug 2011 15:16:03 -0400
Subject: [patch v2 01/10] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
In-Reply-To: <1312278664.4881.35.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.529303146@linux.vnet.ibm.com>
	<20110801201644.GG3805@redhat.com>
	<1312278664.4881.35.camel@br98xy6r>
Message-ID: <20110802191603.GI6399@redhat.com>

On Tue, Aug 02, 2011 at 11:51:04AM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Mon, 2011-08-01 at 16:16 -0400, Vivek Goyal wrote:
> > On Wed, Jul 27, 2011 at 02:55:05PM +0200, Michael Holzheu wrote:
> > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > 
> > > On s390 there is a different KEXEC_CONTROL_MEMORY_LIMIT for the normal and
> > > the kdump kexec case. Therefore this patch introduces a new macro
> > > KEXEC_CRASH_CONTROL_MEMORY_LIMIT. This is set to
> > > KEXEC_CONTROL_MEMORY_LIMIT for all architectures that do not define
> > > KEXEC_CRASH_CONTROL_MEMORY_LIMIT.
> > 
> > Hi Michael,
> > 
> > Curious that why limit is different for kexec and kdump cases on s390
> > only.
> 
> The standard kexec relocate_kernel code calls a machine instruction that
> must run below 2 GiB. For kdump we currently do not use the control page
> at all because no segments have to be moved in that case. Perhaps I am
> still missing something here?

On x86, control page is used for transition to purgatory and second kernel
and common code is used. The only step which is skipped in case of kdump
is the page copying part. As code is common for both the cases the limit
is same.

If you are not using control page at all during s390 kdump (because you
are doing all the setup in dump tools, then probably you can specify
a higher limit so control page.) So in this case you are allocating
control page but not using it?

Thanks
Vivek


From vgoyal at redhat.com  Tue Aug  2 15:21:47 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 2 Aug 2011 15:21:47 -0400
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <1312274279.4881.18.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
	<20110801204114.GJ3805@redhat.com>
	<1312274279.4881.18.camel@br98xy6r>
Message-ID: <20110802192147.GJ6399@redhat.com>

On Tue, Aug 02, 2011 at 10:37:59AM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Mon, 2011-08-01 at 16:41 -0400, Vivek Goyal wrote:
> > On Wed, Jul 27, 2011 at 02:55:08PM +0200, Michael Holzheu wrote:
> > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > 
> > > On s390 we have the possibility to configure actions that are executed in
> > > case of a kernel panic. E.g. it is possible to automatically trigger an s390
> > > stand-alone dump. The actions are called via a panic notifier.  We also want
> > > to trigger kdump via the notifier call chain. Therefore this patch disables
> > > for s390 the direct kdump invocation in the panic() function.
> > 
> > Doesn't this reduce the reliability of the operation as you are assuming
> > that panic notifier list is fine and not corrupted.
> 
> Yes, this is correct. We have to rely that the notifier list is fine.
> Probably there is still room for improvement here.
> 
> > There might be other generic notifiers registerd on panic notifier list
> > too. So in your case, are there multiple subsystem registering for panic
> > notifiers? If not, why not call crash_kexec() directly. Are there any
> > other actions you want to take on panic then calling crash_kexec()?
> 
> We have added the panic notifier in the past in order to be able to
> configure the action that should be done in case of panic using our
> shutdown actions infrastructure. We can configure the action using sysfs
> and we are able to configure that a stand-alone dump should be started
> as action for panic.
> 
> Now with the two stage dump approach we would like to keep the
> possibility to trigger a stand-alone dump even if kdump is installed.
> The stand-alone dumper will be started in case of a kernel panic and
> then the procedure we discussed will happen: Jump into kdump and if
> program check occurs do stand-alone dump as backup.

Frankly speaking this jumping to stand alone kernel by default is not
making any sense to me. Once you have already determined from /sys that
in case of crash a user has set the action to kdump, then we should
simply call crash_kexec() like other architectures and jump to stand
alone kernel only if some piece of code is corrupted and that action
failed.

What's the point of jumping to stand alone kenrel in case of panic()
and then re-enter it back to original kernel using crash_kexec(). Sound
like a very odd design choice to me.

I am now I am repeating this question umpteen time simply because
I never got a good answer except "we have to do it this way".

Thanks
Vivek


From holzheu at linux.vnet.ibm.com  Wed Aug  3 05:27:18 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Wed, 03 Aug 2011 11:27:18 +0200
Subject: [patch v2 01/10] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
In-Reply-To: <20110802191603.GI6399@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.529303146@linux.vnet.ibm.com>
	<20110801201644.GG3805@redhat.com> <1312278664.4881.35.camel@br98xy6r>
	<20110802191603.GI6399@redhat.com>
Message-ID: <1312363638.3783.17.camel@br98xy6r>

Hello Vivek,

On Tue, 2011-08-02 at 15:16 -0400, Vivek Goyal wrote:
> On Tue, Aug 02, 2011 at 11:51:04AM +0200, Michael Holzheu wrote:
> > Hello Vivek,
> > 
> > On Mon, 2011-08-01 at 16:16 -0400, Vivek Goyal wrote:
> > > On Wed, Jul 27, 2011 at 02:55:05PM +0200, Michael Holzheu wrote:
> > > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > > 
> > > > On s390 there is a different KEXEC_CONTROL_MEMORY_LIMIT for the normal and
> > > > the kdump kexec case. Therefore this patch introduces a new macro
> > > > KEXEC_CRASH_CONTROL_MEMORY_LIMIT. This is set to
> > > > KEXEC_CONTROL_MEMORY_LIMIT for all architectures that do not define
> > > > KEXEC_CRASH_CONTROL_MEMORY_LIMIT.
> > > 
> > > Hi Michael,
> > > 
> > > Curious that why limit is different for kexec and kdump cases on s390
> > > only.
> > 
> > The standard kexec relocate_kernel code calls a machine instruction that
> > must run below 2 GiB. For kdump we currently do not use the control page
> > at all because no segments have to be moved in that case. Perhaps I am
> > still missing something here?
> 
> On x86, control page is used for transition to purgatory and second kernel
> and common code is used. The only step which is skipped in case of kdump
> is the page copying part. As code is common for both the cases the limit
> is same.
> If you are not using control page at all during s390 kdump (because you
> are doing all the setup in dump tools, then probably you can specify
> a higher limit so control page.) So in this case you are allocating
> control page but not using it?

Correct, we do not use the control page for kdump, because there is
nothing to do for us. Common code is reserving the control page, we just
don't care about it.

Michael



From holzheu at linux.vnet.ibm.com  Wed Aug  3 05:50:39 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Wed, 03 Aug 2011 11:50:39 +0200
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <20110802192147.GJ6399@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
	<20110801204114.GJ3805@redhat.com> <1312274279.4881.18.camel@br98xy6r>
	<20110802192147.GJ6399@redhat.com>
Message-ID: <1312365039.3783.36.camel@br98xy6r>

Hello Vivek,

On Tue, 2011-08-02 at 15:21 -0400, Vivek Goyal wrote:
> > We have added the panic notifier in the past in order to be able to
> > configure the action that should be done in case of panic using our
> > shutdown actions infrastructure. We can configure the action using sysfs
> > and we are able to configure that a stand-alone dump should be started
> > as action for panic.
> > 
> > Now with the two stage dump approach we would like to keep the
> > possibility to trigger a stand-alone dump even if kdump is installed.
> > The stand-alone dumper will be started in case of a kernel panic and
> > then the procedure we discussed will happen: Jump into kdump and if
> > program check occurs do stand-alone dump as backup.
> 
> Frankly speaking this jumping to stand alone kernel by default is not
> making any sense to me. Once you have already determined from /sys that
> in case of crash a user has set the action to kdump, then we should
> simply call crash_kexec()

If the user has set the panic action to kdump, we jump directly to
crash_kexec(). This then works like on all other architectures.

Only if the user has specified panic action stand-alone dump, we do the
detour via the stand-alone dump tools.

> like other architectures and jump to stand
> alone kernel only if some piece of code is corrupted and that action
> failed.
> 
> What's the point of jumping to stand alone kenrel in case of panic()
> and then re-enter it back to original kernel using crash_kexec(). Sound
> like a very odd design choice to me.
> 
> I am now I am repeating this question umpteen time simply because
> I never got a good answer except "we have to do it this way".

Sometimes communication is really hard and frustrating.
... but at least we are still communicating.

Ok very last try:

* We can use the same mechanism for manual dump and automatic dump on
panic: IPL the stand-alone dump tools. kdump check and backup
stand-alone dump is implemented only in the stand-alone dump code. If we
would do it like you suggested, we would have to do it twice - in the
kernel and in the stand-alone dump tools:
- kernel: Try kdump and if kdump fails trigger standalone dump tool
- Stand-alone dump tool: Try kdump and if kdump fails do full dump

* Still the panic action is configured via sysfs as the user is already
used to on s390.

* It fits much better into our whole s390 infrastructure. Believe me, we
have discussed that here a long time. I think you do not have a full
overview here. Perhaps you just have to believe that.

Michael




From mahesh at linux.vnet.ibm.com  Wed Aug  3 06:35:38 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Wed, 03 Aug 2011 16:05:38 +0530
Subject: [PATCH v2 3/8] makedumpfile: Load the module symbol data from
	vmcore.
In-Reply-To: <20110729184208.236c4e1f.oomichi@mxs.nes.nec.co.jp>
References: <20110517200143.12740.52724.stgit@mars.in.ibm.com>
	<20110729184208.236c4e1f.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4E39247A.1070303@linux.vnet.ibm.com>

Hi Ken'ichi,

Sorry for late reply.

On 07/29/2011 03:12 PM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> This patch is almost good, and there are some cleanup points and
> error-handling points.
> 
> On Wed, 18 May 2011 01:31:53 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>>
>> 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.
> 
> [..]
> 
>> +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;
> 
> If the above num_modules is 0, makedumpfile fails without any hint
> message. How about the below change ?

Agree.

> 
> @@ -7651,13 +7651,11 @@ load_module_symbols(void)
>         unsigned int i = 0, nsym;
> 
>         head = SYMBOL(modules);
> -       if (!get_num_modules(head, &mod_st.num_modules)) {
> +       if (!get_num_modules(head, &mod_st.num_modules) ||
> +           !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) {
> ---
> 
> [..]
> 
>> +	/* Travese the list and read module symbols */
>> +	while (cur != head) {
> 
> [..]
> 
>> +		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;
> 
> In the above error case, module_init_mem should be freed.
> There are the same lacks of free, and I feel it is due to
> a large load_module_symbols() function.
> Hence I created the attached patch for making the function
> small and fixing the lacks of free.
> Can you review it ?

The attached patch looks good to me. Thanks for splitting the function.

Thanks,
-Mahesh.
> 
> 
>> +		if (mod_init_size > 0)
>> +			free(module_init_mem);
>> +	} while (cur != head);
> 
> This is the same as the begining of this loop, and it is not necessary.
> 
> 
> Thanks
> Ken'ichi Ohmichi
> 
> ---
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 3ad2bd5..92ca23b 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -7635,20 +7635,160 @@ clean_module_symbols(void)
>  }
> 
>  static int
> -load_module_symbols(void)
> +__load_module_symbol(struct module_info *modules, unsigned long addr_module)
>  {
> -	unsigned long head, cur, cur_module;
> +	int ret = FALSE;
> +	unsigned int nsym;
>  	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_struct_mem = NULL;
> +	unsigned char *module_core_mem = NULL;
>  	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;
> +
> +	/* 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, addr_module, module_struct_mem,
> +						SIZE(module))) {
> +		ERRMSG("Can't get module info.\n");
> +		goto out;
> +	}
> +
> +	module_name = (char *)(module_struct_mem + OFFSET(module.name));
> +	if (strlen(module_name) < MOD_NAME_LEN)
> +		strcpy(modules->name, module_name);
> +	else
> +		strncpy(modules->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");
> +			goto out;
> +		}
> +		if (!readmem(VADDR, mod_init, module_init_mem,
> +						mod_init_size)) {
> +			ERRMSG("Can't access module init in memory.\n");
> +			goto out;
> +		}
> +	}
> +
> +	if ((module_core_mem = calloc(1, mod_size)) == NULL) {
> +		ERRMSG("Can't allocate memory for module\n");
> +		goto out;
> +	}
> +	if (!readmem(VADDR, mod_base, module_core_mem, mod_size)) {
> +		ERRMSG("Can't access module in memory.\n");
> +		goto out;
> +	}
> +
> +	num_symtab = UINT(module_struct_mem +
> +					OFFSET(module.num_symtab));
> +	if (!num_symtab) {
> +		ERRMSG("%s: Symbol info not available\n", module_name);
> +		goto out;
> +	}
> +	modules->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);
> +		goto out;
> +	}
> +	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);
> +		goto out;
> +	}
> +	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->sym_info = calloc(num_symtab, sizeof(struct symbol_info));
> +	if (modules->sym_info == NULL) {
> +		ERRMSG("Can't allocate memory to store sym info\n");
> +		goto out;
> +	}
> +
> +	/* symbols starts from 1 */
> +	for (nsym = 1; nsym < num_symtab; nsym++) {
> +		Elf32_Sym *sym32;
> +		Elf64_Sym *sym64;
> +		/* 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 ((pointer_size * 8) == 64) {
> +			sym64 = (Elf64_Sym *) (symtab_mem
> +					+ (nsym * sizeof(Elf64_Sym)));
> +			modules->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)));
> +			modules->sym_info[nsym].value =
> +				(unsigned long long) sym32->st_value;
> +			nameptr = strtab_mem + sym32->st_name;
> +		}
> +		if (strlen(nameptr))
> +			modules->sym_info[nsym].name = strdup(nameptr);
> +		DEBUG_MSG("\t[%d] %llx %s\n", nsym,
> +					modules->sym_info[nsym].value, nameptr);
> +	}
> +	ret = TRUE;
> +out:
> +	free(module_struct_mem);
> +	free(module_core_mem);
> +	free(module_init_mem);
> +
> +	return ret;
> +}
> +
> +static int
> +load_module_symbols(void)
> +{
> +	unsigned long head, cur, cur_module;
> +	struct module_info *modules = NULL;
> +	unsigned int i = 0;
> 
>  	head = SYMBOL(modules);
>  	if (!get_num_modules(head, &mod_st.num_modules) ||
> @@ -7664,12 +7804,6 @@ load_module_symbols(void)
>  	}
>  	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;
> @@ -7678,129 +7812,9 @@ load_module_symbols(void)
>  	/* 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");
> +		if (!__load_module_symbol(&modules[i], cur_module))
>  			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;
> -			/* 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 ((pointer_size * 8) == 64) {
> -				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)) {
> @@ -7808,11 +7822,7 @@ load_module_symbols(void)
>  			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;
>  }
> 
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



From holzheu at linux.vnet.ibm.com  Wed Aug  3 06:40:44 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Wed, 03 Aug 2011 12:40:44 +0200
Subject: [patch v2 03/10] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110802185501.GG6399@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.853426542@linux.vnet.ibm.com>
	<20110801203607.GI3805@redhat.com> <1312276087.4881.24.camel@br98xy6r>
	<20110802185501.GG6399@redhat.com>
Message-ID: <1312368044.3783.39.camel@br98xy6r>

Hello Vivek,

On Tue, 2011-08-02 at 14:55 -0400, Vivek Goyal wrote:
> On Tue, Aug 02, 2011 at 11:08:07AM +0200, Michael Holzheu wrote:
> > Hello Vivek,
> > 
> > > Generally vmcore parses elfcorehdr to figure out the sizes. kexec-tools
> > > knows about it and relevant memory is excluded from second kernel's map
> > > with the help of memmap= command line option.
> > > 
> > > Can you please mention that this is only s390 specific requirement as
> > > there are no memmap= equivalent options and somehow dump tools wants
> > > to know how big the elf header size is?
> > 
> > I updated the description: 
> > 
> > Currently only the address of the pre-allocated ELF header is passed with
> > the elfcorehdr= kernel parameter. In order to reserve memory for the header
> > in the 2nd kernel also the size is required. Current kdump architecture
> > backends use different methods to do that, e.g. x86 uses the memmap= kernel
> > parameter. On s390 there is no easy way to transfer this information.
> > Therefore the elfcorehdr kernel parameter is extended to also pass the size.
> > This now can also be used as standard mechanism by all future kdump
> > architecture backends.
> > 
> > The syntax of the kernel parameter is extended as follows:
> > 
> > elfcorehdr=[size[KMG]@]offset[KMG]
> > 
> > This change is backward compatible because elfcorehdr=size is still allowed.
> > 
> > Ok?
> 
> Yes, this one looks ok.

With that description change: Do I get an "Acked-by" for this patch from
you?

Michael



From holzheu at linux.vnet.ibm.com  Wed Aug  3 06:41:28 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Wed, 03 Aug 2011 12:41:28 +0200
Subject: [patch v2 02/10] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110802185530.GH6399@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.695225427@linux.vnet.ibm.com>
	<20110801203143.GH3805@redhat.com> <1312277403.4881.26.camel@br98xy6r>
	<20110802185530.GH6399@redhat.com>
Message-ID: <1312368088.3783.40.camel@br98xy6r>

On Tue, 2011-08-02 at 14:55 -0400, Vivek Goyal wrote:
> On Tue, Aug 02, 2011 at 11:30:03AM +0200, Michael Holzheu wrote:
> > Hello Vivek,
> > 
> > On Mon, 2011-08-01 at 16:31 -0400, Vivek Goyal wrote:
> > > On Wed, Jul 27, 2011 at 02:55:06PM +0200, Michael Holzheu wrote:
> > 
> > [snip]
> > 
> > > > --- a/kernel/kexec.c
> > > > +++ b/kernel/kexec.c
> > > > @@ -842,8 +842,8 @@ out:
> > > >  	return result;
> > > >  }
> > > >  
> > > > -static int kimage_load_crash_segment(struct kimage *image,
> > > > -					struct kexec_segment *segment)
> > > > +int __weak kimage_load_crash_segment(struct kimage *image,
> > > > +				     struct kexec_segment *segment)
> > > 
> > > A comment here why we are making it weak should help in increasing
> > > the code readability.
> > 
> > What about the following:
> > 
> > /*
> >  * Load crash segment into memory. Architecture code can override this
> >  * function. E.g. this is necessary for architectures that do not
> >  * create page tables for crashkernel memory.
> >  */
> > int __weak kimage_load_crash_segment(struct kimage *image,
> 
> This looks better.

With that comment change: Do I get an "Acked-by" for this patch from
you?

Michael



From olaf at aepfle.de  Wed Aug  3 13:19:23 2011
From: olaf at aepfle.de (Olaf Hering)
Date: Wed, 3 Aug 2011 19:19:23 +0200
Subject: [PATCH] fix Xen detection for xenfs in pv_ops kernel
Message-ID: <20110803171923.GA21404@aepfle.de>

The pv_ops kernel in mainline Linux provides xenfs which has to be
mounted at /proc/xen.  It creates /proc/xen/capabilities unconditionally
which makes it impossible to distinguish PVonHVM guests from PV guests.
Use code from xen-detect.c to check wether kexec runs on a PV guest.
Without this change PVonHVM guests will be detected incorrectly as plain
PV guests.

Signed-off-by: Olaf Hering <olaf at aepfle.de>

---
 kexec/crashdump-xen.c |   79 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 77 insertions(+), 2 deletions(-)

Index: kexec-tools.git/kexec/crashdump-xen.c
===================================================================
--- kexec-tools.git.orig/kexec/crashdump-xen.c
+++ kexec-tools.git/kexec/crashdump-xen.c
@@ -10,6 +10,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <setjmp.h>
+#include <signal.h>
 #include "kexec.h"
 #include "crashdump.h"
 #include "kexec-syscall.h"
@@ -27,13 +29,86 @@ struct crash_note_info {
 
 static int xen_phys_cpus;
 static struct crash_note_info *xen_phys_notes;
+
+/* based on code from xen-detect.c */
 static int is_dom0;
+static jmp_buf xen_sigill_jmp;
+void xen_sigill_handler(int sig)
+{
+	longjmp(xen_sigill_jmp, 1);
+}
+
+static void xen_cpuid(uint32_t idx, uint32_t *regs, int pv_context)
+{
+	asm volatile (
+#ifdef __i386__
+#define R(x) "%%e"#x"x"
+#else
+#define R(x) "%%r"#x"x"
+#endif
+	"push "R(a)"; push "R(b)"; push "R(c)"; push "R(d)"\n\t"
+	"test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid\n\t"
+	"mov %%eax,(%2); mov %%ebx,4(%2)\n\t"
+	"mov %%ecx,8(%2); mov %%edx,12(%2)\n\t"
+	"pop "R(d)"; pop "R(c)"; pop "R(b)"; pop "R(a)"\n\t"
+	: : "a" (idx), "c" (pv_context), "S" (regs) : "memory" );
+}
+
+static int check_for_xen(int pv_context)
+{
+	uint32_t regs[4];
+	char signature[13];
+	uint32_t base;
+
+	for (base = 0x40000000; base < 0x40010000; base += 0x100)
+	{
+		xen_cpuid(base, regs, pv_context);
+
+		*(uint32_t *)(signature + 0) = regs[1];
+		*(uint32_t *)(signature + 4) = regs[2];
+		*(uint32_t *)(signature + 8) = regs[3];
+		signature[12] = '\0';
+
+		if (strcmp("XenVMMXenVMM", signature) == 0 && regs[0] >= (base + 2))
+			goto found;
+	}
+
+	return 0;
+
+found:
+	xen_cpuid(base + 1, regs, pv_context);
+	return regs[0];
+}
+
+static int xen_detect_pv_guest(void)
+{
+	struct sigaction act, oldact;
+	int is_pv = -1;
+
+	if (setjmp(xen_sigill_jmp))
+		return is_pv;
+
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = xen_sigill_handler;
+	sigemptyset (&act.sa_mask);
+	if (sigaction(SIGILL, &act, &oldact))
+		return is_pv;
+	if (check_for_xen(1))
+		is_pv = 1;
+	sigaction(SIGILL, &oldact, NULL);
+	return is_pv;
+}
 
+/*
+ * Return 1 if its a PV guest.
+ * This includes dom0, which is the only PV guest where kexec/kdump works.
+ * HVM guests have to be handled as native hardware.
+ */
 int xen_present(void)
 {
 	if (!is_dom0) {
-		if (access("/proc/xen/capabilities", F_OK) == 0)
-			is_dom0 = 1;
+		if (access("/proc/xen", F_OK) == 0)
+			is_dom0 = xen_detect_pv_guest();
 		else
 			is_dom0 = -1;
 	}


From olaf at aepfle.de  Wed Aug  3 13:41:59 2011
From: olaf at aepfle.de (Olaf Hering)
Date: Wed, 3 Aug 2011 19:41:59 +0200
Subject: [PATCH] fix Xen detection for xenfs in pv_ops kernel
In-Reply-To: <20110803171923.GA21404@aepfle.de>
References: <20110803171923.GA21404@aepfle.de>
Message-ID: <20110803174158.GA21782@aepfle.de>

On Wed, Aug 03, Olaf Hering wrote:

> +	"push "R(a)"; push "R(b)"; push "R(c)"; push "R(d)"\n\t"

That deserves a proper #ifdef, sorry for that.

Olaf


From olaf at aepfle.de  Wed Aug  3 14:07:05 2011
From: olaf at aepfle.de (Olaf Hering)
Date: Wed, 3 Aug 2011 20:07:05 +0200
Subject: [PATCH v2] fix Xen detection for xenfs in pv_ops kernel
Message-ID: <20110803180705.GA22296@aepfle.de>

The pv_ops kernel in mainline Linux provides xenfs which has to be
mounted at /proc/xen.  It creates /proc/xen/capabilities unconditionally
which makes it impossible to distinguish PVonHVM guests from PV guests.
Use code from xen-detect.c to check wether kexec runs on a PV guest.
Without this change PVonHVM guests will be detected incorrectly as plain
PV guests.

Signed-off-by: Olaf Hering <olaf at aepfle.de>

---
 kexec/crashdump-xen.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 84 insertions(+), 2 deletions(-)

Index: kexec-tools.git/kexec/crashdump-xen.c
===================================================================
--- kexec-tools.git.orig/kexec/crashdump-xen.c
+++ kexec-tools.git/kexec/crashdump-xen.c
@@ -10,6 +10,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <setjmp.h>
+#include <signal.h>
 #include "kexec.h"
 #include "crashdump.h"
 #include "kexec-syscall.h"
@@ -27,13 +29,93 @@ struct crash_note_info {
 
 static int xen_phys_cpus;
 static struct crash_note_info *xen_phys_notes;
+
+/* based on code from xen-detect.c */
 static int is_dom0;
+#if defined(__i386__) || defined(__x86_64__)
+static jmp_buf xen_sigill_jmp;
+void xen_sigill_handler(int sig)
+{
+	longjmp(xen_sigill_jmp, 1);
+}
+
+static void xen_cpuid(uint32_t idx, uint32_t *regs, int pv_context)
+{
+	asm volatile (
+#ifdef __i386__
+#define R(x) "%%e"#x"x"
+#else
+#define R(x) "%%r"#x"x"
+#endif
+	"push "R(a)"; push "R(b)"; push "R(c)"; push "R(d)"\n\t"
+	"test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid\n\t"
+	"mov %%eax,(%2); mov %%ebx,4(%2)\n\t"
+	"mov %%ecx,8(%2); mov %%edx,12(%2)\n\t"
+	"pop "R(d)"; pop "R(c)"; pop "R(b)"; pop "R(a)"\n\t"
+	: : "a" (idx), "c" (pv_context), "S" (regs) : "memory" );
+}
+
+static int check_for_xen(int pv_context)
+{
+	uint32_t regs[4];
+	char signature[13];
+	uint32_t base;
+
+	for (base = 0x40000000; base < 0x40010000; base += 0x100)
+	{
+		xen_cpuid(base, regs, pv_context);
+
+		*(uint32_t *)(signature + 0) = regs[1];
+		*(uint32_t *)(signature + 4) = regs[2];
+		*(uint32_t *)(signature + 8) = regs[3];
+		signature[12] = '\0';
+
+		if (strcmp("XenVMMXenVMM", signature) == 0 && regs[0] >= (base + 2))
+			goto found;
+	}
+
+	return 0;
+
+found:
+	xen_cpuid(base + 1, regs, pv_context);
+	return regs[0];
+}
+
+static int xen_detect_pv_guest(void)
+{
+	struct sigaction act, oldact;
+	int is_pv = -1;
+
+	if (setjmp(xen_sigill_jmp))
+		return is_pv;
+
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = xen_sigill_handler;
+	sigemptyset (&act.sa_mask);
+	if (sigaction(SIGILL, &act, &oldact))
+		return is_pv;
+	if (check_for_xen(1))
+		is_pv = 1;
+	sigaction(SIGILL, &oldact, NULL);
+	return is_pv;
+}
+#else
+static int xen_detect_pv_guest(void)
+{
+	return 1;
+}
+#endif
 
+/*
+ * Return 1 if its a PV guest.
+ * This includes dom0, which is the only PV guest where kexec/kdump works.
+ * HVM guests have to be handled as native hardware.
+ */
 int xen_present(void)
 {
 	if (!is_dom0) {
-		if (access("/proc/xen/capabilities", F_OK) == 0)
-			is_dom0 = 1;
+		if (access("/proc/xen", F_OK) == 0)
+			is_dom0 = xen_detect_pv_guest();
 		else
 			is_dom0 = -1;
 	}


From horms at verge.net.au  Wed Aug  3 19:44:47 2011
From: horms at verge.net.au (Simon Horman)
Date: Thu, 4 Aug 2011 08:44:47 +0900
Subject: [PATCH v2] fix Xen detection for xenfs in pv_ops kernel
In-Reply-To: <20110803180705.GA22296@aepfle.de>
References: <20110803180705.GA22296@aepfle.de>
Message-ID: <20110803234447.GN17246@verge.net.au>

On Wed, Aug 03, 2011 at 08:07:05PM +0200, Olaf Hering wrote:
> The pv_ops kernel in mainline Linux provides xenfs which has to be
> mounted at /proc/xen.  It creates /proc/xen/capabilities unconditionally
> which makes it impossible to distinguish PVonHVM guests from PV guests.
> Use code from xen-detect.c to check wether kexec runs on a PV guest.
> Without this change PVonHVM guests will be detected incorrectly as plain
> PV guests.

Thanks, applied.


From oomichi at mxs.nes.nec.co.jp  Wed Aug  3 19:54:08 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Thu, 4 Aug 2011 08:54:08 +0900
Subject: [PATCH v2 3/8] makedumpfile: Load the module symbol data from
	vmcore.
In-Reply-To: <4E39247A.1070303@linux.vnet.ibm.com>
References: <20110517200143.12740.52724.stgit@mars.in.ibm.com>
	<20110729184208.236c4e1f.oomichi@mxs.nes.nec.co.jp>
	<4E39247A.1070303@linux.vnet.ibm.com>
Message-ID: <20110804085408.927a7e7a.oomichi@mxs.nes.nec.co.jp>


Hi Mehesh,

On Wed, 03 Aug 2011 16:05:38 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > 
> >> +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;
> > 
> > If the above num_modules is 0, makedumpfile fails without any hint
> > message. How about the below change ?
> 
> Agree.

[..]

> >> +		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;
> > 
> > In the above error case, module_init_mem should be freed.
> > There are the same lacks of free, and I feel it is due to
> > a large load_module_symbols() function.
> > Hence I created the attached patch for making the function
> > small and fixing the lacks of free.
> > Can you review it ?
> 
> The attached patch looks good to me. Thanks for splitting the function.

Thank you for your review of two patches.
I have merged them into filter-out-devel branch.


Thanks
Ken'ichi Ohmichi


From mahesh at linux.vnet.ibm.com  Thu Aug  4 02:43:22 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Thu, 04 Aug 2011 12:13:22 +0530
Subject: [PATCH v2 4/8] makedumpfile: Introduce routines to get type name
	from debuginfo.
In-Reply-To: <20110801102704.efc244ac.oomichi@mxs.nes.nec.co.jp>
References: <20110517200247.12740.45844.stgit@mars.in.ibm.com>
	<20110801102704.efc244ac.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4E3A3F8A.8090204@linux.vnet.ibm.com>

Hi Ken'ichi,

On 08/01/2011 06:57 AM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> A pointer size can been gotton by sizeof(void *), and pointer (virtual 
> address) can been defined as "unsigned long".
> I think we can make this patch simple. How about the attached patch ?
> 

Yup, the patch looks simpler and good.

> 
> Thanks
> Ken'ichi Ohmichi
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 3ad2bd5..6955f64 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -34,7 +34,6 @@ struct erase_info	*erase_info = NULL;
>  unsigned long		num_erase_info = 1; /* Node 0 is unused. */
> 
>  char filename_stdout[] = FILENAME_STDOUT;
> -long pointer_size;
>  char config_buf[BUFSIZE_FGETS];
> 
>  /*
> @@ -2058,10 +2057,6 @@ 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");

[...]

> @@ -7863,8 +7849,8 @@ print_config_entry(struct config_entry *ce)
>  		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("sym_addr: %lx, ", ce->sym_addr);

Above change throws compilation warning. The sym_addr is unsigned long
long, %llx still holds good.

> +		DEBUG_MSG("addr: %lx, ", ce->addr);
>  		DEBUG_MSG("offset: %lx, ", ce->offset);
>  		DEBUG_MSG("size: %zd\n", ce->size);
> 

[...]

> @@ -1284,7 +1283,7 @@ struct config_entry {
>  	unsigned short		flag;
>  	unsigned short		nullify;
>  	unsigned long long	sym_addr;	/* Symbol address */
> -	unsigned long long	addr;		/* Symbol address or
> +	unsigned long		addr;		/* Symbol address or
>  						   value pointed by sym_addr */
>  	unsigned long long	cmp_addr;	/* for LIST_ENTRY */
>  	unsigned long		offset;
> 

I tested this patch and works fine.

Thanks,
-Mahesh.


From vgoyal at redhat.com  Thu Aug  4 16:25:18 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 4 Aug 2011 16:25:18 -0400
Subject: [patch v2 02/10] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <1312368088.3783.40.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125807.695225427@linux.vnet.ibm.com>
	<20110801203143.GH3805@redhat.com>
	<1312277403.4881.26.camel@br98xy6r>
	<20110802185530.GH6399@redhat.com>
	<1312368088.3783.40.camel@br98xy6r>
Message-ID: <20110804202518.GD429@redhat.com>

On Wed, Aug 03, 2011 at 12:41:28PM +0200, Michael Holzheu wrote:
> On Tue, 2011-08-02 at 14:55 -0400, Vivek Goyal wrote:
> > On Tue, Aug 02, 2011 at 11:30:03AM +0200, Michael Holzheu wrote:
> > > Hello Vivek,
> > > 
> > > On Mon, 2011-08-01 at 16:31 -0400, Vivek Goyal wrote:
> > > > On Wed, Jul 27, 2011 at 02:55:06PM +0200, Michael Holzheu wrote:
> > > 
> > > [snip]
> > > 
> > > > > --- a/kernel/kexec.c
> > > > > +++ b/kernel/kexec.c
> > > > > @@ -842,8 +842,8 @@ out:
> > > > >  	return result;
> > > > >  }
> > > > >  
> > > > > -static int kimage_load_crash_segment(struct kimage *image,
> > > > > -					struct kexec_segment *segment)
> > > > > +int __weak kimage_load_crash_segment(struct kimage *image,
> > > > > +				     struct kexec_segment *segment)
> > > > 
> > > > A comment here why we are making it weak should help in increasing
> > > > the code readability.
> > > 
> > > What about the following:
> > > 
> > > /*
> > >  * Load crash segment into memory. Architecture code can override this
> > >  * function. E.g. this is necessary for architectures that do not
> > >  * create page tables for crashkernel memory.
> > >  */
> > > int __weak kimage_load_crash_segment(struct kimage *image,
> > 
> > This looks better.
> 
> With that comment change: Do I get an "Acked-by" for this patch from
> you?

Yes, looks good to me.

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

Thanks
Vivek


From vgoyal at redhat.com  Thu Aug  4 17:14:32 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 4 Aug 2011 17:14:32 -0400
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <1312365039.3783.36.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
	<20110801204114.GJ3805@redhat.com>
	<1312274279.4881.18.camel@br98xy6r>
	<20110802192147.GJ6399@redhat.com>
	<1312365039.3783.36.camel@br98xy6r>
Message-ID: <20110804211432.GE429@redhat.com>

On Wed, Aug 03, 2011 at 11:50:39AM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Tue, 2011-08-02 at 15:21 -0400, Vivek Goyal wrote:
> > > We have added the panic notifier in the past in order to be able to
> > > configure the action that should be done in case of panic using our
> > > shutdown actions infrastructure. We can configure the action using sysfs
> > > and we are able to configure that a stand-alone dump should be started
> > > as action for panic.
> > > 
> > > Now with the two stage dump approach we would like to keep the
> > > possibility to trigger a stand-alone dump even if kdump is installed.
> > > The stand-alone dumper will be started in case of a kernel panic and
> > > then the procedure we discussed will happen: Jump into kdump and if
> > > program check occurs do stand-alone dump as backup.
> > 
> > Frankly speaking this jumping to stand alone kernel by default is not
> > making any sense to me. Once you have already determined from /sys that
> > in case of crash a user has set the action to kdump, then we should
> > simply call crash_kexec()
> 
> If the user has set the panic action to kdump, we jump directly to
> crash_kexec(). This then works like on all other architectures.

Ok, that's good to know that you will define panic action as kdump also
and in that case we will not jump to dump tools and directly call
crash_kexec()

> 
> Only if the user has specified panic action stand-alone dump, we do the
> detour via the stand-alone dump tools.

If a user decides to load kdump kernel to capture dump, then why does it
still make sense to set panic action as "stand-alone dump tools". One
could argue that user loaded kdump kernel but not necessarily wants
that mechanism to use, in that case dump-tools does not have to jump
to kdump kernel at all. 

> 
> > like other architectures and jump to stand
> > alone kernel only if some piece of code is corrupted and that action
> > failed.
> > 
> > What's the point of jumping to stand alone kenrel in case of panic()
> > and then re-enter it back to original kernel using crash_kexec(). Sound
> > like a very odd design choice to me.
> > 
> > I am now I am repeating this question umpteen time simply because
> > I never got a good answer except "we have to do it this way".
> 
> Sometimes communication is really hard and frustrating.
> ... but at least we are still communicating.
> 
> Ok very last try:
> 
> * We can use the same mechanism for manual dump and automatic dump on
> panic: IPL the stand-alone dump tools.

So manual dump/intervention is only required if automatic dump failed?

> kdump check and backup
> stand-alone dump is implemented only in the stand-alone dump code.

My argument is that why stand alone dump is trying to trigger kdump
at all? Shouldn't it all be part of loading kdump kernel and user
setting panic() action to kdump?

The only valid argument to try to load kdump kernel from dump tools is
the hard hang situation where we never made to panic(). Then either
that hypervisor timer or manual intervention will come into picture
and one might argue that we still will kdump a try.

Fox x86 it is relatively easy as NMI detects hard hang in the context
of first kernel and can easily call crash_kexec() without any additional
information passing.

So if it is about hard hang, i can still understand the need to jump
to crash_kexec() from dump tools. I don't know if it is possible to 
invoke crash_kexec() directly from hypervisor timer without ipling
dump tools or not.

> If we
> would do it like you suggested, we would have to do it twice - in the
> kernel and in the stand-alone dump tools:
> - kernel: Try kdump and if kdump fails trigger standalone dump tool
> - Stand-alone dump tool: Try kdump and if kdump fails do full dump

Are we not already doing above two steps? You just mentioned that 
if user specified "kdump" as panic() action, then you will call
crash_kexec() directly. Will we not jump to dump tools if kdump
fails?

Also if user specified "dump-tools" as action, then your way of things
anyway will try to execute kdump (if kernel is loaded) and if that fails
then we come back to dump tools.

So I think in current scheme of things, you already have both implemented.
> 
> * Still the panic action is configured via sysfs as the user is already
> used to on s390.

I asked the question above why it makes sense to configure panic action
as dump tools if kdump kernel is loaded.

> 
> * It fits much better into our whole s390 infrastructure. Believe me, we
> have discussed that here a long time. I think you do not have a full
> overview here. Perhaps you just have to believe that.

That's what I am talking about. So many times the answer has been "We have
to do it this way".

Sure I do not have full overview here but little explanation sometimes
help in understanding things.

Thanks
Vivek


From oomichi at mxs.nes.nec.co.jp  Thu Aug  4 20:26:59 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 5 Aug 2011 09:26:59 +0900
Subject: [PATCH v2 4/8] makedumpfile: Introduce routines to get type
	name from debuginfo.
In-Reply-To: <4E3A3F8A.8090204@linux.vnet.ibm.com>
References: <20110517200247.12740.45844.stgit@mars.in.ibm.com>
	<20110801102704.efc244ac.oomichi@mxs.nes.nec.co.jp>
	<4E3A3F8A.8090204@linux.vnet.ibm.com>
Message-ID: <20110805092659.a8a60bea.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

Thank you for your review and test.

On Thu, 04 Aug 2011 12:13:22 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> 
> On 08/01/2011 06:57 AM, Ken'ichi Ohmichi wrote:
> > 
> > Hi Mahesh,
> > 
> > A pointer size can been gotton by sizeof(void *), and pointer (virtual 
> > address) can been defined as "unsigned long".
> > I think we can make this patch simple. How about the attached patch ?
> > 
> 
> Yup, the patch looks simpler and good.
> 
> > 
> > Thanks
> > Ken'ichi Ohmichi
> > 
> > diff --git a/makedumpfile.c b/makedumpfile.c
> > index 3ad2bd5..6955f64 100644
> > --- a/makedumpfile.c
> > +++ b/makedumpfile.c
> > @@ -34,7 +34,6 @@ struct erase_info	*erase_info = NULL;
> >  unsigned long		num_erase_info = 1; /* Node 0 is unused. */
> > 
> >  char filename_stdout[] = FILENAME_STDOUT;
> > -long pointer_size;
> >  char config_buf[BUFSIZE_FGETS];
> > 
> >  /*
> > @@ -2058,10 +2057,6 @@ 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");
> 
> [...]
> 
> > @@ -7863,8 +7849,8 @@ print_config_entry(struct config_entry *ce)
> >  		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("sym_addr: %lx, ", ce->sym_addr);
> 
> Above change throws compilation warning. The sym_addr is unsigned long
> long, %llx still holds good.

Nice catch, I fixed the above.


> > +		DEBUG_MSG("addr: %lx, ", ce->addr);
> >  		DEBUG_MSG("offset: %lx, ", ce->offset);
> >  		DEBUG_MSG("size: %zd\n", ce->size);
> > 
> 
> [...]
> 
> > @@ -1284,7 +1283,7 @@ struct config_entry {
> >  	unsigned short		flag;
> >  	unsigned short		nullify;
> >  	unsigned long long	sym_addr;	/* Symbol address */
> > -	unsigned long long	addr;		/* Symbol address or
> > +	unsigned long		addr;		/* Symbol address or
> >  						   value pointed by sym_addr */
> >  	unsigned long long	cmp_addr;	/* for LIST_ENTRY */
> >  	unsigned long		offset;
> > 
> 
> I tested this patch and works fine.

Thank you.
I have merged this patch.


Thanks
Ken'ichi Ohmichi


From abel at tolna.net  Sun Aug  7 03:11:14 2011
From: abel at tolna.net (abel at tolna.net)
Date: Sun, 7 Aug 2011 07:11:14 -0000
Subject: MAIL
Message-ID: <f728c313a8b6be38b13fd8d5fe05ecbd.squirrel@webmail.tolna.net>

Dear Friend,
This is Mr. Richard Tang from Hong- Kong. I am sending you
this message concerning a Business Proposal.This business will benefit you
a lot.Please contact me;
richardtang at nba2k.com.cn
Mr. Richard Tang.




From holzheu at linux.vnet.ibm.com  Mon Aug  8 13:47:39 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Mon, 08 Aug 2011 19:47:39 +0200
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <20110804211432.GE429@redhat.com>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
	<20110801204114.GJ3805@redhat.com> <1312274279.4881.18.camel@br98xy6r>
	<20110802192147.GJ6399@redhat.com> <1312365039.3783.36.camel@br98xy6r>
	<20110804211432.GE429@redhat.com>
Message-ID: <1312825659.3537.62.camel@br98xy6r>

Hello Vivek,

On Thu, 2011-08-04 at 17:14 -0400, Vivek Goyal wrote:
> On Wed, Aug 03, 2011 at 11:50:39AM +0200, Michael Holzheu wrote:

[snip]
 
> > Only if the user has specified panic action stand-alone dump, we do the
> > detour via the stand-alone dump tools.
> 
> If a user decides to load kdump kernel to capture dump, then why does it
> still make sense to set panic action as "stand-alone dump tools". One
> could argue that user loaded kdump kernel but not necessarily wants
> that mechanism to use, in that case dump-tools does not have to jump
> to kdump kernel at all. 

The user on s390 can currently freely configure the panic action. If we
would always do kdump on panic, when kdump is active, we would have to
ensure in sysfs that the user can't change the setting any more.
Technically we could do that of course.

One use case we had in mind was that the s390 Linux administrator does
not have to learn new things when using kdump. kdump can be used as
extension of the already existing mechanism. Today users configure
stand-alone dump via sysfs. With kdump + trigger via dump tools they
could do it still the same way. And also for manual dump they just IPL
the dump tool as they are used to do it and if kdump is fine, kdump will
be triggered. Nothing new has to be learned.

If users only want to use kdump without stand-alone dump tools as on
other architectures also this is possible. Then the panic action will be
just kdump.

> > 
> > > like other architectures and jump to stand
> > > alone kernel only if some piece of code is corrupted and that action
> > > failed.
> > > 
> > > What's the point of jumping to stand alone kenrel in case of panic()
> > > and then re-enter it back to original kernel using crash_kexec(). Sound
> > > like a very odd design choice to me.
> > > 
> > > I am now I am repeating this question umpteen time simply because
> > > I never got a good answer except "we have to do it this way".
> > 
> > Sometimes communication is really hard and frustrating.
> > ... but at least we are still communicating.
> > 
> > Ok very last try:
> > 
> > * We can use the same mechanism for manual dump and automatic dump on
> > panic: IPL the stand-alone dump tools.
> 
> So manual dump/intervention is only required if automatic dump failed?

Manual intervention is required only if panic code does not make it to
the "IPL stand-alone dump tools" code.

> 
> > kdump check and backup
> > stand-alone dump is implemented only in the stand-alone dump code.
> 
> My argument is that why stand alone dump is trying to trigger kdump
> at all? Shouldn't it all be part of loading kdump kernel and user
> setting panic() action to kdump?

To summarize: Our approach was to do it in the stand-alone dump tools
code for both the manual and the automatic on panic case:

panic ------+                                 +- valid -> kdump
            +-> IPL dump tools -> try kdump --+
hard hang --+                                 +- invalid -> stand-alone dump

Your suggestion looks like the following:

panic --> try kdump +-- valid ---> kdump
                    |
                    +-- invalid -> IPL dump tools --> stand-alone dump

                                            +- valid -> kdump
hard hang --> IPL dump tools -> try kdump --+ 
                                            +- invalid -> stand-alone dump

Is that what you are suggesting? We can do it that way, too. Then
we would not need the #ifdef CONFIG_S390 in panic().

Michael



From max at stro.at  Mon Aug  8 14:43:08 2011
From: max at stro.at (maximilian attems)
Date: Mon,  8 Aug 2011 20:43:08 +0200
Subject: [PATCH] kexec-tools: include minor klibc porting
Message-ID: <1312828988-3203-1-git-send-email-max@stro.at>

These 2 "uncommon" include pathes are the first stumbling blocks
to build kexec-tools against klibc.

Of course more is needed, but this is a first step.
On the klibc step there is still stuff needed, but
it is already possible with hacks as Oppenembedded shows.

Signed-off-by: maximilian attems <max at stro.at>
---
 kexec/ifdown.c        |    2 +-
 kexec/kexec-syscall.h |    1 -
 2 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/kexec/ifdown.c b/kexec/ifdown.c
index bc7f12f..46b7bef 100644
--- a/kexec/ifdown.c
+++ b/kexec/ifdown.c
@@ -10,11 +10,11 @@ char *v_ifdown = "@(#)ifdown.c  1.11  02-Jun-1998  miquels at cistron.nl";
 #include <unistd.h>
 #include <time.h>
 #include <string.h>
+#include <errno.h>
 
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/time.h>
-#include <sys/errno.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index b082f40..f4df45c 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -2,7 +2,6 @@
 #define KEXEC_SYSCALL_H
 
 #define __LIBRARY__
-#include <syscall.h>
 #include <sys/syscall.h>
 #include <unistd.h>
 
-- 
1.7.5.4



From mahesh at linux.vnet.ibm.com  Tue Aug  9 13:42:30 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Tue, 9 Aug 2011 23:12:30 +0530
Subject: [PATCH v2 2/8] makedumpfile: Apply relocation while loading
	module debuginfo.
In-Reply-To: <20110729162104.5d611eb9.oomichi@mxs.nes.nec.co.jp>
References: <20110517200052.12740.36169.stgit@mars.in.ibm.com>
	<20110725171156.e4965f9f.oomichi@mxs.nes.nec.co.jp>
	<4E2FABA8.5000401@linux.vnet.ibm.com>
	<20110728181146.d91ee265.oomichi@mxs.nes.nec.co.jp>
	<4E313C17.7050609@linux.vnet.ibm.com>
	<20110729162104.5d611eb9.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110809174230.GA31038@in.ibm.com>

Hi Ken'ichi,

On 2011-07-29 16:21:04 Fri, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Thu, 28 Jul 2011 16:08:15 +0530
> Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > > 
> > > If adding the searching method to the blow position and removing the code
> > > from init_dwarf_info(), I guess it makes the code simple.
> > > 
> > > @ process_config_file()
> > >  9402                         if (!set_dwarf_debuginfo(config->module_name,
> > >  9403                                                                 NULL, -1)) {
> > >  9404                                 ERRMSG("Skipping to next Module section\n");
> > >  9405                                 skip_section = 1;
> > >  9406                                 free_config(config);
> > >  9407                                 continue;
> > >  9408                         }
> > >  9409                         << HERE >> 
> > 
> > This may not be the correct place to call search method. We may end up
> > calling search method multiple times for same kernel module. I think
> > moving the search method inside set_dwarf_debuginfo() routine at below
> > position is a better place:
> > 
> > @set_dwarf_debuginfo()
> > 	......
> > 	......
> > 	if (!strcmp(dwarf_info.module_name, "vmlinux") ||
> >                 !strcmp(dwarf_info.module_name, "xen-syms"))
> >                 return TRUE;
> > +	 << HERE >>
> > -        /* check to see whether module debuginfo is available */
> > -        if (!init_dwarf_info())
> > -                return FALSE;
> > -        else
> > -                clean_dwfl_info();
> > 	 return TRUE;
> > }
> > 
> > And then we can remove search routine from init_dwarf_info(). What do
> > you think?
> 
> I think the above change will be good, thanks in advance.

Please find the inline patch below that separates the search method from
init_dwarf_info() function. Please review it and let know your comments.

Thanks,
-Mahesh.
----------

makedumpfile: Move debuginfo search to set_dwarf_debuginfo() routine.

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

Move the debuginfo search logic out of init_dwarf_info() function to make
this function more simpler. Now we call search method in set_dwarf_debuginfo
when switch to different module section.

This patch also fixes a BUG where dwarf_info.module_name becomes a stale
pointer after free_config() invocation. This patch now uses strdup() to get
duplicate string and assigns it to dwarf_info.module_name.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 makedumpfile.c |  126 ++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 86 insertions(+), 40 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 35cbed9..fe8e8b0 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1186,7 +1186,60 @@ clean_dwfl_info(void)
 }
 
 /*
- * Intitialize the dwarf info.
+ * Search module debuginfo.
+ * This function searches for module debuginfo in default debuginfo path for
+ * a given module in dwarf_info.module_name.
+ *
+ * On success, dwarf_info.name_debuginfo is set to absolute path of
+ * module debuginfo.
+ */
+static int
+search_module_debuginfo(void)
+{
+	Dwfl *dwfl = NULL;
+	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,
+	};
+
+	/*
+	 * Check if We already have debuginfo file name with us. If yes,
+	 * then we don't need to proceed with search method.
+	 */
+	if (dwarf_info.name_debuginfo)
+		return TRUE;
+
+	if ((dwfl = dwfl_begin(&callbacks)) == NULL) {
+		ERRMSG("Can't create a handle for a new dwfl session.\n");
+		return FALSE;
+	}
+
+	/* Search for module debuginfo file. */
+	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);
+		dwfl_end(dwfl);
+		return FALSE;
+	}
+	dwfl_report_end(dwfl, NULL, NULL);
+	dwfl_getmodules(dwfl, &process_module, NULL, 0);
+
+	dwfl_end(dwfl);
+	clean_dwfl_info();
+
+	/* Return success if module debuginfo is found. */
+	if (dwarf_info.name_debuginfo)
+		return TRUE;
+
+	return FALSE;
+}
+
+/*
+ * Initialize the dwarf info.
  * Linux kernel module debuginfo are of ET_REL (relocatable) type.
  * This function uses dwfl API's to apply relocation before reading the
  * dwarf information from module debuginfo.
@@ -1198,51 +1251,45 @@ 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;
 
+	 /*
+	  * We already know the absolute path of debuginfo file. Fail if we
+	  * still don't have one. Ideally we should never be in this situation.
+	  */
+	if (!dwarf_info.name_debuginfo) {
+		ERRMSG("Can't find absolute path to debuginfo file.\n");
+		return FALSE;
+	}
+
 	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 (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);
+	/* 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;
+	}
+	/* Apply relocations. */
+	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;
 	}
 	dwfl_report_end(dwfl, NULL, NULL);
@@ -2522,20 +2569,19 @@ set_dwarf_debuginfo(char *mod_name, char *name_debuginfo, int fd_debuginfo)
 		if (dwarf_info.name_debuginfo)
 			free(dwarf_info.name_debuginfo);
 	}
+	if (dwarf_info.module_name)
+		free(dwarf_info.module_name);
+
 	dwarf_info.fd_debuginfo = fd_debuginfo;
 	dwarf_info.name_debuginfo = name_debuginfo;
-	dwarf_info.module_name = mod_name;
+	dwarf_info.module_name = strdup(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;
+	return search_module_debuginfo();
 }
 
 int



From vgoyal at redhat.com  Tue Aug  9 17:19:23 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 9 Aug 2011 17:19:23 -0400
Subject: [patch v2 04/10] kdump: Trigger kdump via panic notifier chain
	on s390
In-Reply-To: <1312825659.3537.62.camel@br98xy6r>
References: <20110727125504.491183728@linux.vnet.ibm.com>
	<20110727125808.028895659@linux.vnet.ibm.com>
	<20110801204114.GJ3805@redhat.com>
	<1312274279.4881.18.camel@br98xy6r>
	<20110802192147.GJ6399@redhat.com>
	<1312365039.3783.36.camel@br98xy6r>
	<20110804211432.GE429@redhat.com>
	<1312825659.3537.62.camel@br98xy6r>
Message-ID: <20110809211923.GJ6482@redhat.com>

On Mon, Aug 08, 2011 at 07:47:39PM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Thu, 2011-08-04 at 17:14 -0400, Vivek Goyal wrote:
> > On Wed, Aug 03, 2011 at 11:50:39AM +0200, Michael Holzheu wrote:
> 
> [snip]
>  
> > > Only if the user has specified panic action stand-alone dump, we do the
> > > detour via the stand-alone dump tools.
> > 
> > If a user decides to load kdump kernel to capture dump, then why does it
> > still make sense to set panic action as "stand-alone dump tools". One
> > could argue that user loaded kdump kernel but not necessarily wants
> > that mechanism to use, in that case dump-tools does not have to jump
> > to kdump kernel at all. 
> 
> The user on s390 can currently freely configure the panic action. If we
> would always do kdump on panic, when kdump is active, we would have to
> ensure in sysfs that the user can't change the setting any more.
> Technically we could do that of course.
> 
> One use case we had in mind was that the s390 Linux administrator does
> not have to learn new things when using kdump. kdump can be used as
> extension of the already existing mechanism. Today users configure
> stand-alone dump via sysfs. With kdump + trigger via dump tools they
> could do it still the same way. And also for manual dump they just IPL
> the dump tool as they are used to do it and if kdump is fine, kdump will
> be triggered. Nothing new has to be learned.
> 
> If users only want to use kdump without stand-alone dump tools as on
> other architectures also this is possible. Then the panic action will be
> just kdump.

IMHO, it makes sense to introduce a new trigger action "kdump" and let
user configure that instead of masking everything behind dump tools.

In fact, we don't have to even configure it. Like other architectures, 
we can always call crash_kexec() upon panic() if there is a crash
kernel loaded. That way, panic() path remains simple and there are
no arch specific #ifdefs.

> 
> > > 
> > > > like other architectures and jump to stand
> > > > alone kernel only if some piece of code is corrupted and that action
> > > > failed.
> > > > 
> > > > What's the point of jumping to stand alone kenrel in case of panic()
> > > > and then re-enter it back to original kernel using crash_kexec(). Sound
> > > > like a very odd design choice to me.
> > > > 
> > > > I am now I am repeating this question umpteen time simply because
> > > > I never got a good answer except "we have to do it this way".
> > > 
> > > Sometimes communication is really hard and frustrating.
> > > ... but at least we are still communicating.
> > > 
> > > Ok very last try:
> > > 
> > > * We can use the same mechanism for manual dump and automatic dump on
> > > panic: IPL the stand-alone dump tools.
> > 
> > So manual dump/intervention is only required if automatic dump failed?
> 
> Manual intervention is required only if panic code does not make it to
> the "IPL stand-alone dump tools" code.
> 
> > 
> > > kdump check and backup
> > > stand-alone dump is implemented only in the stand-alone dump code.
> > 
> > My argument is that why stand alone dump is trying to trigger kdump
> > at all? Shouldn't it all be part of loading kdump kernel and user
> > setting panic() action to kdump?
> 
> To summarize: Our approach was to do it in the stand-alone dump tools
> code for both the manual and the automatic on panic case:
> 
> panic ------+                                 +- valid -> kdump
>             +-> IPL dump tools -> try kdump --+
> hard hang --+                                 +- invalid -> stand-alone dump
> 
> Your suggestion looks like the following:
> 
> panic --> try kdump +-- valid ---> kdump
>                     |
>                     +-- invalid -> IPL dump tools --> stand-alone dump
> 
>                                             +- valid -> kdump
> hard hang --> IPL dump tools -> try kdump --+ 
>                                             +- invalid -> stand-alone dump

I think thew whole notion of jumping from dump tools to kdump is not
a very good design as it enforces us to pass additional state to dump
tools and also the awkward notion of re-enter the crashed kernel
(crash_kexec() being called from dump tools).

Is there a notion of NMI on s390. What's the x86 NMI equivalent on s390.

> Is that what you are suggesting? We can do it that way, too. Then
> we would not need the #ifdef CONFIG_S390 in panic().

How about keeping it simple in first round.

- Always use kdump for capturing dump is kdump kernel is loaded. If user
  does not want to use kdump, don't load kdump kenrel.

- Use NMI equivalent to handle the hard hang case. In case there is no
  equivalent, how about keeping it simple in first go and always use
  dump-tools to capture full dump and improve upon it in a later patchset.

  (This is no worse then today as today you don't have any filtering
   mechanism).

Thanks
Vivek


From oomichi at mxs.nes.nec.co.jp  Tue Aug  9 22:30:37 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Wed, 10 Aug 2011 11:30:37 +0900
Subject: [PATCH v2 2/8] makedumpfile: Apply relocation while loading
	module debuginfo.
In-Reply-To: <20110809174230.GA31038@in.ibm.com>
References: <20110517200052.12740.36169.stgit@mars.in.ibm.com>
	<20110725171156.e4965f9f.oomichi@mxs.nes.nec.co.jp>
	<4E2FABA8.5000401@linux.vnet.ibm.com>
	<20110728181146.d91ee265.oomichi@mxs.nes.nec.co.jp>
	<4E313C17.7050609@linux.vnet.ibm.com>
	<20110729162104.5d611eb9.oomichi@mxs.nes.nec.co.jp>
	<20110809174230.GA31038@in.ibm.com>
Message-ID: <20110810113037.c6af1d57.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Tue, 9 Aug 2011 23:12:30 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > > > 
> > > > If adding the searching method to the blow position and removing the code
> > > > from init_dwarf_info(), I guess it makes the code simple.
> > > > 
> > > > @ process_config_file()
> > > >  9402                         if (!set_dwarf_debuginfo(config->module_name,
> > > >  9403                                                                 NULL, -1)) {
> > > >  9404                                 ERRMSG("Skipping to next Module section\n");
> > > >  9405                                 skip_section = 1;
> > > >  9406                                 free_config(config);
> > > >  9407                                 continue;
> > > >  9408                         }
> > > >  9409                         << HERE >> 
> > > 
> > > This may not be the correct place to call search method. We may end up
> > > calling search method multiple times for same kernel module. I think
> > > moving the search method inside set_dwarf_debuginfo() routine at below
> > > position is a better place:
> > > 
> > > @set_dwarf_debuginfo()
> > > 	......
> > > 	......
> > > 	if (!strcmp(dwarf_info.module_name, "vmlinux") ||
> > >                 !strcmp(dwarf_info.module_name, "xen-syms"))
> > >                 return TRUE;
> > > +	 << HERE >>
> > > -        /* check to see whether module debuginfo is available */
> > > -        if (!init_dwarf_info())
> > > -                return FALSE;
> > > -        else
> > > -                clean_dwfl_info();
> > > 	 return TRUE;
> > > }
> > > 
> > > And then we can remove search routine from init_dwarf_info(). What do
> > > you think?
> > 
> > I think the above change will be good, thanks in advance.
> 
> Please find the inline patch below that separates the search method from
> init_dwarf_info() function. Please review it and let know your comments.

Thank you for the patch.
I think this patch is good, and the patch has been magerd into
filter-out-devel branch.


Thanks
Ken'ichi Ohmichi

> makedumpfile: Move debuginfo search to set_dwarf_debuginfo() routine.
> 
> From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> 
> Move the debuginfo search logic out of init_dwarf_info() function to make
> this function more simpler. Now we call search method in set_dwarf_debuginfo
> when switch to different module section.
> 
> This patch also fixes a BUG where dwarf_info.module_name becomes a stale
> pointer after free_config() invocation. This patch now uses strdup() to get
> duplicate string and assigns it to dwarf_info.module_name.
> 
> Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> ---
>  makedumpfile.c |  126 ++++++++++++++++++++++++++++++++++++++------------------
>  1 files changed, 86 insertions(+), 40 deletions(-)
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 35cbed9..fe8e8b0 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -1186,7 +1186,60 @@ clean_dwfl_info(void)
>  }
>  
>  /*
> - * Intitialize the dwarf info.
> + * Search module debuginfo.
> + * This function searches for module debuginfo in default debuginfo path for
> + * a given module in dwarf_info.module_name.
> + *
> + * On success, dwarf_info.name_debuginfo is set to absolute path of
> + * module debuginfo.
> + */
> +static int
> +search_module_debuginfo(void)
> +{
> +	Dwfl *dwfl = NULL;
> +	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,
> +	};
> +
> +	/*
> +	 * Check if We already have debuginfo file name with us. If yes,
> +	 * then we don't need to proceed with search method.
> +	 */
> +	if (dwarf_info.name_debuginfo)
> +		return TRUE;
> +
> +	if ((dwfl = dwfl_begin(&callbacks)) == NULL) {
> +		ERRMSG("Can't create a handle for a new dwfl session.\n");
> +		return FALSE;
> +	}
> +
> +	/* Search for module debuginfo file. */
> +	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);
> +		dwfl_end(dwfl);
> +		return FALSE;
> +	}
> +	dwfl_report_end(dwfl, NULL, NULL);
> +	dwfl_getmodules(dwfl, &process_module, NULL, 0);
> +
> +	dwfl_end(dwfl);
> +	clean_dwfl_info();
> +
> +	/* Return success if module debuginfo is found. */
> +	if (dwarf_info.name_debuginfo)
> +		return TRUE;
> +
> +	return FALSE;
> +}
> +
> +/*
> + * Initialize the dwarf info.
>   * Linux kernel module debuginfo are of ET_REL (relocatable) type.
>   * This function uses dwfl API's to apply relocation before reading the
>   * dwarf information from module debuginfo.
> @@ -1198,51 +1251,45 @@ 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;
>  
> +	 /*
> +	  * We already know the absolute path of debuginfo file. Fail if we
> +	  * still don't have one. Ideally we should never be in this situation.
> +	  */
> +	if (!dwarf_info.name_debuginfo) {
> +		ERRMSG("Can't find absolute path to debuginfo file.\n");
> +		return FALSE;
> +	}
> +
>  	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 (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);
> +	/* 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;
> +	}
> +	/* Apply relocations. */
> +	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;
>  	}
>  	dwfl_report_end(dwfl, NULL, NULL);
> @@ -2522,20 +2569,19 @@ set_dwarf_debuginfo(char *mod_name, char *name_debuginfo, int fd_debuginfo)
>  		if (dwarf_info.name_debuginfo)
>  			free(dwarf_info.name_debuginfo);
>  	}
> +	if (dwarf_info.module_name)
> +		free(dwarf_info.module_name);
> +
>  	dwarf_info.fd_debuginfo = fd_debuginfo;
>  	dwarf_info.name_debuginfo = name_debuginfo;
> -	dwarf_info.module_name = mod_name;
> +	dwarf_info.module_name = strdup(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;
> +	return search_module_debuginfo();
>  }
>  
>  int
> 



From horms at verge.net.au  Tue Aug  9 23:46:17 2011
From: horms at verge.net.au (Simon Horman)
Date: Wed, 10 Aug 2011 12:46:17 +0900
Subject: [PATCH] kexec-tools: include minor klibc porting
In-Reply-To: <1312828988-3203-1-git-send-email-max@stro.at>
References: <1312828988-3203-1-git-send-email-max@stro.at>
Message-ID: <20110810034617.GG27303@verge.net.au>

On Mon, Aug 08, 2011 at 08:43:08PM +0200, maximilian attems wrote:
> These 2 "uncommon" include pathes are the first stumbling blocks
> to build kexec-tools against klibc.
> 
> Of course more is needed, but this is a first step.
> On the klibc step there is still stuff needed, but
> it is already possible with hacks as Oppenembedded shows.
> 
> Signed-off-by: maximilian attems <max at stro.at>

Thanks, applied.


From blessingsoumah at itimes.com  Wed Aug 10 07:52:09 2011
From: blessingsoumah at itimes.com (blessingsoumah)
Date: Wed, 10 Aug 2011 17:22:09 +0530 (IST)
Subject: hello
Message-ID: <1587581157.825581312977129581.JavaMail.root@ims1.itimes.com>

hi
My name is miss blessing 
l saw your profile today 
and after going through 
i made up my mind to contact 
you as my friend so l will 
like you to write back to me 
through my privet email so 
that i can send you my picture 
for you to know whom am 
(soumahblessing40 at yahoo.com)


From oomichi at mxs.nes.nec.co.jp  Wed Aug 10 22:07:16 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Thu, 11 Aug 2011 11:07:16 +0900
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
Message-ID: <20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Wed, 18 May 2011 01:34:15 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> 
> 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

Thank you for the work.
I tested this feature by the above example, and confirmed the feature
works fine. Nice work :-)

There are some comments in the below lines.
Can you check them ?

> +/*
> + * 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);

"free(str);" is necessary.

> +	return NULL;
> +}

[..]

> +/*
> + * 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;

CONFIG_SKIP_SECTION is used only here, and we need to fix get_config()
for the readability. Please check my comment in get_config().

[..]

> +/*
> + * 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;

We need to change the above:

	unsigned char flag = CONFIG_NEW_CMD;
	if (skip)
		flag |= CONFIG_SKIP_SECTION;

> +
> +	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;
> +}

BTW makedumpfile.c has become a large file which is bigger than 10KLine,
and I will separate it to some files for the maintenance.


Thanks
Ken'ichi Ohmichi


From oomichi at mxs.nes.nec.co.jp  Thu Aug 11 01:17:51 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Thu, 11 Aug 2011 14:17:51 +0900
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Thu, 11 Aug 2011 11:07:16 +0900
"Ken'ichi Ohmichi" <oomichi at mxs.nes.nec.co.jp> wrote:
> 
> BTW makedumpfile.c has become a large file which is bigger than 10KLine,
> and I will separate it to some files for the maintenance.

To shrink makedumpfile.c file, I made a prototype patch.
(commit 40f5724152047a12e4ac9db51d9f9e00e7a79ebe of filter-out-devel branch)
And I'd like to see your opinion.

You added sym_in_module() call into get_symbol_addr() to look for module
symbol. And I will move the call to resolve_config_entry() because I guess
sym_in_module() is used only for resolve_config_entry():

@@ -8448,13 +7326,21 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
                                                char *base_struct_name)
 {
        char buf[BUFSIZE + 1];
+       unsigned long long symbol;

        if (ce->flag & SYMBOL_ENTRY) {
                /* find the symbol info */
                if (!ce->name)
                        return FALSE;

-               ce->sym_addr = get_symbol_addr(ce->name);
+               /*
+                * If we are looking for module symbol then traverse through
+                * mod_st.modules for symbol lookup
+                */
+               if (sym_in_module(ce->name, &symbol))
+                       ce->sym_addr = symbol;
+               else
+                       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);
---



Thanks
Ken'ichi Ohmichi


From oomichi at mxs.nes.nec.co.jp  Thu Aug 11 04:06:21 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Thu, 11 Aug 2011 17:06:21 +0900
Subject: [PATCH v2 6/8] makedumpfile: Read and process 'for' command
	from config file.
In-Reply-To: <20110517200514.12740.86690.stgit@mars.in.ibm.com>
References: <20110517200514.12740.86690.stgit@mars.in.ibm.com>
Message-ID: <20110811170621.2f931dbe.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Wed, 18 May 2011 01:35:19 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>
> 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>
> ---

Thank you for the patch.
I think this patch is good.

Acked-by: Ken'ichi Ohmichi <oomichi at mxs.nes.nec.co.jp>


Thanks
Ken'ichi Ohmichi

>  makedumpfile.c      |  533 ++++++++++++++++++++++++++++++++++++++++++++++++++-
>  makedumpfile.conf   |   67 ++++++
>  makedumpfile.conf.8 |  212 ++++++++++++++++++++
>  makedumpfile.h      |   19 ++
>  4 files changed, 814 insertions(+), 17 deletions(-)
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 1c7237a..a616bae 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;
> +}
> +
>  /*
>   * Insert the filter info node using insertion sort.
>   * If filter node for a given paddr is aready present then update the size
> @@ -8420,6 +8802,107 @@ update_filter_info(struct config_entry *filter_symbol,
>  	return TRUE;
>  }
>  
> +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;
> +}
> +
>  /*
>   * Process the config entry that has been read by get_config.
>   * return TRUE on success
> @@ -8427,7 +8910,35 @@ update_filter_info(struct config_entry *filter_symbol,
>  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.conf b/makedumpfile.conf
> index 3d47e25..03e604a 100644
> --- a/makedumpfile.conf
> +++ b/makedumpfile.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/makedumpfile.conf.8 b/makedumpfile.conf.8
> index 0a7d22a..ef0e86a 100644
> --- a/makedumpfile.conf.8
> +++ b/makedumpfile.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
> +
> +\fBmakedumpfile.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.h b/makedumpfile.h
> index 94f3521..1c61edb 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 oomichi at mxs.nes.nec.co.jp  Thu Aug 11 04:29:00 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Thu, 11 Aug 2011 17:29:00 +0900
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
	<20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110811172900.ad5c50b6.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Thu, 11 Aug 2011 14:17:51 +0900
"Ken'ichi Ohmichi" <oomichi at mxs.nes.nec.co.jp> wrote:
> > 
> > BTW makedumpfile.c has become a large file which is bigger than 10KLine,
> > and I will separate it to some files for the maintenance.
> 
> To shrink makedumpfile.c file, I made a prototype patch.
> (commit 40f5724152047a12e4ac9db51d9f9e00e7a79ebe of filter-out-devel branch)
> And I'd like to see your opinion.
> 
> You added sym_in_module() call into get_symbol_addr() to look for module
> symbol. And I will move the call to resolve_config_entry() because I guess
> sym_in_module() is used only for resolve_config_entry():
> 
> @@ -8448,13 +7326,21 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
>                                                 char *base_struct_name)
>  {
>         char buf[BUFSIZE + 1];
> +       unsigned long long symbol;
> 
>         if (ce->flag & SYMBOL_ENTRY) {
>                 /* find the symbol info */
>                 if (!ce->name)
>                         return FALSE;
> 
> -               ce->sym_addr = get_symbol_addr(ce->name);
> +               /*
> +                * If we are looking for module symbol then traverse through
> +                * mod_st.modules for symbol lookup
> +                */
> +               if (sym_in_module(ce->name, &symbol))
> +                       ce->sym_addr = symbol;
> +               else
> +                       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);
> ---

Sorry, the above mail is not clear.
My question is,
	Do you think this change is right ?


Thanks
Ken'ichi Ohmichi


From mahesh at linux.vnet.ibm.com  Thu Aug 11 07:33:06 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Thu, 11 Aug 2011 17:03:06 +0530
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4E43BDF2.8030609@linux.vnet.ibm.com>

Hi Ken'ichi,

On 08/11/2011 07:37 AM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Wed, 18 May 2011 01:34:15 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>>
>> 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
> 
> Thank you for the work.
> I tested this feature by the above example, and confirmed the feature
> works fine. Nice work :-)

Thanks :-)

> 
> There are some comments in the below lines.
> Can you check them ?
> 
>> +/*
>> + * 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);
> 
> "free(str);" is necessary.
> 

Nice catch. Agree.

>> +	return NULL;
>> +}
> 
> [..]
> 
>> +/*
>> + * 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;
> 
> CONFIG_SKIP_SECTION is used only here, and we need to fix get_config()
> for the readability. Please check my comment in get_config().
> 
> [..]
> 
>> +/*
>> + * 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;
> 
> We need to change the above:
> 
> 	unsigned char flag = CONFIG_NEW_CMD;
> 	if (skip)
> 		flag |= CONFIG_SKIP_SECTION;
>

Agree.

Thanks,
-Mahesh.


From mahesh at linux.vnet.ibm.com  Thu Aug 11 07:51:24 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Thu, 11 Aug 2011 17:21:24 +0530
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811172900.ad5c50b6.oomichi@mxs.nes.nec.co.jp>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
	<20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
	<20110811172900.ad5c50b6.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110811115124.GA2817@in.ibm.com>

On 2011-08-11 17:29:00 Thu, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Thu, 11 Aug 2011 14:17:51 +0900
> "Ken'ichi Ohmichi" <oomichi at mxs.nes.nec.co.jp> wrote:
> > > 
> > > BTW makedumpfile.c has become a large file which is bigger than 10KLine,
> > > and I will separate it to some files for the maintenance.
> > 
> > To shrink makedumpfile.c file, I made a prototype patch.
> > (commit 40f5724152047a12e4ac9db51d9f9e00e7a79ebe of filter-out-devel branch)
> > And I'd like to see your opinion.
> > 
> > You added sym_in_module() call into get_symbol_addr() to look for module
> > symbol. And I will move the call to resolve_config_entry() because I guess
> > sym_in_module() is used only for resolve_config_entry():
> > 
> > @@ -8448,13 +7326,21 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
> >                                                 char *base_struct_name)
> >  {
> >         char buf[BUFSIZE + 1];
> > +       unsigned long long symbol;
> > 
> >         if (ce->flag & SYMBOL_ENTRY) {
> >                 /* find the symbol info */
> >                 if (!ce->name)
> >                         return FALSE;
> > 
> > -               ce->sym_addr = get_symbol_addr(ce->name);
> > +               /*
> > +                * If we are looking for module symbol then traverse through
> > +                * mod_st.modules for symbol lookup
> > +                */
> > +               if (sym_in_module(ce->name, &symbol))
> > +                       ce->sym_addr = symbol;
> > +               else
> > +                       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);
> > ---
> 
> Sorry, the above mail is not clear.
> My question is,
> 	Do you think this change is right ?

My intention was to hide it under get_symbol_addr(). But yes, since it's
only used by resolve_config_entry() we can safely move it there.

Thanks,
-Mahesh.

-- 
Mahesh J Salgaonkar


From mahesh at linux.vnet.ibm.com  Thu Aug 11 08:03:48 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Thu, 11 Aug 2011 17:33:48 +0530
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
	<20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110811120348.GB2817@in.ibm.com>

On 2011-08-11 14:17:51 Thu, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Thu, 11 Aug 2011 11:07:16 +0900
> "Ken'ichi Ohmichi" <oomichi at mxs.nes.nec.co.jp> wrote:
> > 
> > BTW makedumpfile.c has become a large file which is bigger than 10KLine,
> > and I will separate it to some files for the maintenance.
> 
> To shrink makedumpfile.c file, I made a prototype patch.
> (commit 40f5724152047a12e4ac9db51d9f9e00e7a79ebe of filter-out-devel branch)
> And I'd like to see your opinion.
> 

I like the idea. The prototype patch looks good. I think we can
even separate out the module symbol load/clean up functions including all
associated functions out of makedumpfile.c. What do you think?

Thanks,
-Mahesh.

-- 
Mahesh J Salgaonkar


From oomichi at mxs.nes.nec.co.jp  Thu Aug 11 19:51:36 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 12 Aug 2011 08:51:36 +0900
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811115124.GA2817@in.ibm.com>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
	<20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
	<20110811172900.ad5c50b6.oomichi@mxs.nes.nec.co.jp>
	<20110811115124.GA2817@in.ibm.com>
Message-ID: <20110812085136.cff32f84.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Thu, 11 Aug 2011 17:21:24 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > > > 
> > > > BTW makedumpfile.c has become a large file which is bigger than 10KLine,
> > > > and I will separate it to some files for the maintenance.
> > > 
> > > To shrink makedumpfile.c file, I made a prototype patch.
> > > (commit 40f5724152047a12e4ac9db51d9f9e00e7a79ebe of filter-out-devel branch)
> > > And I'd like to see your opinion.
> > > 
> > > You added sym_in_module() call into get_symbol_addr() to look for module
> > > symbol. And I will move the call to resolve_config_entry() because I guess
> > > sym_in_module() is used only for resolve_config_entry():
> > > 
> > > @@ -8448,13 +7326,21 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
> > >                                                 char *base_struct_name)
> > >  {
> > >         char buf[BUFSIZE + 1];
> > > +       unsigned long long symbol;
> > > 
> > >         if (ce->flag & SYMBOL_ENTRY) {
> > >                 /* find the symbol info */
> > >                 if (!ce->name)
> > >                         return FALSE;
> > > 
> > > -               ce->sym_addr = get_symbol_addr(ce->name);
> > > +               /*
> > > +                * If we are looking for module symbol then traverse through
> > > +                * mod_st.modules for symbol lookup
> > > +                */
> > > +               if (sym_in_module(ce->name, &symbol))
> > > +                       ce->sym_addr = symbol;
> > > +               else
> > > +                       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);
> > > ---
> > 
> > Sorry, the above mail is not clear.
> > My question is,
> > 	Do you think this change is right ?
> 
> My intention was to hide it under get_symbol_addr(). But yes, since it's
> only used by resolve_config_entry() we can safely move it there.

Thank you for checkint it.

makedumpfile.c file has been shrunk from 10KLines to 9KLines,
and I will make the file small more.


Thanks
Ken'ichi Ohmichi


From oomichi at mxs.nes.nec.co.jp  Thu Aug 11 20:08:25 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 12 Aug 2011 09:08:25 +0900
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <4E43BDF2.8030609@linux.vnet.ibm.com>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
	<4E43BDF2.8030609@linux.vnet.ibm.com>
Message-ID: <20110812090825.962639ba.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

Thank you for checking the above also.
commit 92d2934f9e1694e7195d93f9816fbea8a657f05f fixes them.


Thanks
Ken'ichi Ohmichi

On Thu, 11 Aug 2011 17:03:06 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>
> Hi Ken'ichi,
> 
> On 08/11/2011 07:37 AM, Ken'ichi Ohmichi wrote:
> > 
> > Hi Mahesh,
> > 
> > On Wed, 18 May 2011 01:34:15 +0530
> > Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >>
> >> 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
> > 
> > Thank you for the work.
> > I tested this feature by the above example, and confirmed the feature
> > works fine. Nice work :-)
> 
> Thanks :-)
> 
> > 
> > There are some comments in the below lines.
> > Can you check them ?
> > 
> >> +/*
> >> + * 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);
> > 
> > "free(str);" is necessary.
> > 
> 
> Nice catch. Agree.
> 
> >> +	return NULL;
> >> +}
> > 
> > [..]
> > 
> >> +/*
> >> + * 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;
> > 
> > CONFIG_SKIP_SECTION is used only here, and we need to fix get_config()
> > for the readability. Please check my comment in get_config().
> > 
> > [..]
> > 
> >> +/*
> >> + * 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;
> > 
> > We need to change the above:
> > 
> > 	unsigned char flag = CONFIG_NEW_CMD;
> > 	if (skip)
> > 		flag |= CONFIG_SKIP_SECTION;
> >
> 
> Agree.
> 
> Thanks,
> -Mahesh.
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From oomichi at mxs.nes.nec.co.jp  Fri Aug 12 03:33:06 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 12 Aug 2011 16:33:06 +0900
Subject: [PATCH v2 5/8] makedumpfile: Read and process filter commands
	from config file.
In-Reply-To: <20110811120348.GB2817@in.ibm.com>
References: <20110517200407.12740.95780.stgit@mars.in.ibm.com>
	<20110811110716.7aec3c9e.oomichi@mxs.nes.nec.co.jp>
	<20110811141751.7927b2bb.oomichi@mxs.nes.nec.co.jp>
	<20110811120348.GB2817@in.ibm.com>
Message-ID: <20110812163306.95fa9fce.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Thu, 11 Aug 2011 17:33:48 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> > > 
> > > BTW makedumpfile.c has become a large file which is bigger than 10KLine,
> > > and I will separate it to some files for the maintenance.
> > 
> > To shrink makedumpfile.c file, I made a prototype patch.
> > (commit 40f5724152047a12e4ac9db51d9f9e00e7a79ebe of filter-out-devel branch)
> > And I'd like to see your opinion.
> > 
> 
> I like the idea. The prototype patch looks good. I think we can
> even separate out the module symbol load/clean up functions including all
> associated functions out of makedumpfile.c. What do you think?

Yes.
I think it is a good direction that we separete out the module symbol
load code, which is added by you, from makedumpfile.c.
And I will try it.

Thanks
Ken'ichi Ohmichi


From oomichi at mxs.nes.nec.co.jp  Fri Aug 12 04:10:13 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 12 Aug 2011 17:10:13 +0900
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in
	compressed kdump file
In-Reply-To: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
Message-ID: <20110812171013.7545b3df.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Wed, 18 May 2011 01:36:17 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -29,6 +29,8 @@ struct DumpInfo		*info = NULL;
>  struct module_sym_table	mod_st = { 0 };
>  struct filter_info	*filter_info = NULL;
>  struct filter_config	filter_config;
> +struct erase_info	*erase_info = NULL;
> +unsigned long		num_erase_info = 1; /* Node 0 is unused. */

I cannot understand erase_info[0] is unused.


> @@ -6000,10 +6007,17 @@ write_kdump_header(void)
>  			kh.size_vmcoreinfo = info->size_vmcoreinfo;
>  		}
>  	}
> -	if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
> -	    size, info->name_dumpfile))
> -		goto out;
> +	/*
> +	 * While writing dump data to STDOUT, delay the writing of sub header
> +	 * untill we gather erase info offset and size.
> +	 */
> +	if (!info->flag_flatten) {
> +		if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
> +		    size, info->name_dumpfile))
> +			goto out;
> +	}

Does makedumpfile work wrong if removing the above change ?


I'd like to check this patch carefully, and I will review the remainder
next week.


Thanks
Ken'ichi Ohmichi


> @@ -6061,12 +6075,39 @@ split_filter_info(struct filter_info *prev, unsigned long long next_paddr,
>  		return;
>  	}
>  	new->nullify = prev->nullify;
> +	new->erase_info_idx = prev->erase_info_idx;
> +	new->size_idx = prev->size_idx;
>  	new->paddr = next_paddr;
>  	new->size = size;
>  	new->next = prev->next;
>  	prev->next = new;
>  }
>  
> +void
> +update_erase_info(struct filter_info *fi)
> +{
> +	struct erase_info *ei;
> +
> +	if (!fi->erase_info_idx)
> +		return;
> +
> +	ei = &erase_info[fi->erase_info_idx];
> +
> +	if (!ei->sizes) {
> +		/* First time, allocate sizes array */
> +		ei->sizes = calloc(ei->num_sizes, sizeof(long));
> +		if (!ei->sizes) {
> +			ERRMSG("Can't allocate memory for erase info sizes\n");
> +			return;
> +		}
> +	}
> +	ei->erased = 1;
> +	if (!fi->nullify)
> +		ei->sizes[fi->size_idx] += fi->size;
> +	else
> +		ei->sizes[fi->size_idx] = -1;
> +}
> +
>  int
>  extract_filter_info(unsigned long long start_paddr,
>  			unsigned long long end_paddr,
> @@ -6100,6 +6141,7 @@ extract_filter_info(unsigned long long start_paddr,
>  			filter_info = fi->next;
>  		else
>  			prev->next = fi->next;
> +		update_erase_info(fi);
>  		free(fi);
>  		return TRUE;
>  	}
> @@ -6567,6 +6609,159 @@ out:
>  	return ret;
>  }
>  
> +/*
> + * Copy eraseinfo from input dumpfile/vmcore to output dumpfile.
> + */
> +static int
> +copy_eraseinfo(struct cache_data *cd_eraseinfo)
> +{
> +	char *buf = NULL;
> +	int ret = FALSE;
> +
> +	buf = malloc(info->size_eraseinfo);
> +	if (buf == NULL) {
> +		ERRMSG("Can't allocate memory for erase info section. %s\n",
> +		    strerror(errno));
> +		return FALSE;
> +	}
> +	if (lseek(info->fd_memory, info->offset_eraseinfo, SEEK_SET) < 0) {
> +		ERRMSG("Can't seek the dump memory(%s). %s\n",
> +		    info->name_memory, strerror(errno));
> +		goto out;
> +	}
> +	if (read(info->fd_memory, buf, info->size_eraseinfo)
> +	    != info->size_eraseinfo) {
> +		ERRMSG("Can't read the dump memory(%s). %s\n",
> +		    info->name_memory, strerror(errno));
> +		goto out;
> +	}
> +	if (!write_cache(cd_eraseinfo, buf, info->size_eraseinfo))
> +		goto out;
> +	ret = TRUE;
> +out:
> +	if (buf)
> +		free(buf);
> +	return ret;
> +}
> +
> +static int
> +update_sub_header(void)
> +{
> +	off_t offset;
> +
> +	/* seek to kdump sub header offset */
> +	offset = DISKDUMP_HEADER_BLOCKS * info->page_size;
> +
> +	info->sub_header.offset_eraseinfo = info->offset_eraseinfo;
> +	info->sub_header.size_eraseinfo = info->size_eraseinfo;
> +
> +	if (!write_buffer(info->fd_dumpfile, offset, &info->sub_header,
> +			sizeof(struct kdump_sub_header), info->name_dumpfile))
> +		return FALSE;
> +
> +	return TRUE;
> +}
> +
> +/*
> + * Traverse through eraseinfo nodes and write it to the o/p dumpfile if the
> + * node has erased flag set.
> + */
> +int
> +write_eraseinfo(struct cache_data *cd_page, unsigned long *size_out)
> +{
> +	int i, j, obuf_size = 0, ei_size = 0;
> +	int ret = FALSE;
> +	unsigned long size_eraseinfo = 0;
> +	char *obuf = NULL;
> +	char size_str[MAX_SIZE_STR_LEN];
> +
> +	for (i = 1; i < num_erase_info; i++) {
> +		if (!erase_info[i].erased)
> +			continue;
> +		for (j = 0; j < erase_info[i].num_sizes; j++) {
> +			if (erase_info[i].sizes[j] > 0)
> +				sprintf(size_str, "%ld\n",
> +						erase_info[i].sizes[j]);
> +			else if (erase_info[i].sizes[j] == -1)
> +				sprintf(size_str, "nullify\n");
> +
> +			/* Calculate the required buffer size. */
> +			ei_size = strlen("erase ") +
> +					strlen(erase_info[i].symbol_expr) + 1 +
> +					strlen(size_str) +
> +					1;
> +			/*
> +			 * If obuf is allocated in the previous run and is
> +			 * big enough to hold current erase info string then
> +			 * reuse it otherwise realloc.
> +			 */
> +			if (ei_size > obuf_size) {
> +				obuf_size = ei_size;
> +				obuf = realloc(obuf, obuf_size);
> +				if (!obuf) {
> +					ERRMSG("Can't allocate memory for"
> +						" output buffer\n");
> +					return FALSE;
> +				}
> +			}
> +			sprintf(obuf, "erase %s %s", erase_info[i].symbol_expr,
> +							size_str);
> +			DEBUG_MSG(obuf);
> +			if (!write_cache(cd_page, obuf, strlen(obuf)))
> +				goto out;
> +			size_eraseinfo += strlen(obuf);
> +		}
> +	}
> +	/*
> +	 * Write the remainder.
> +	 */
> +	if (!write_cache_bufsz(cd_page))
> +		goto out;
> +
> +	*size_out = size_eraseinfo;
> +	ret = TRUE;
> +out:
> +	if (obuf)
> +		free(obuf);
> +
> +	return ret;
> +}
> +
> +int
> +write_kdump_eraseinfo(struct cache_data *cd_page)
> +{
> +	off_t offset_eraseinfo;
> +	unsigned long size_eraseinfo;
> +
> +	DEBUG_MSG("Writing erase info...\n");
> +	offset_eraseinfo = cd_page->offset;
> +
> +	/*
> +	 * In case of refiltering copy the existing eraseinfo from input
> +	 * dumpfile to o/p dumpfile.
> +	 */
> +	if (info->offset_eraseinfo && info->size_eraseinfo) {
> +		if (!copy_eraseinfo(cd_page))
> +			return FALSE;
> +	}
> +
> +	/* Initialize eraseinfo offset with new offset value. */
> +	info->offset_eraseinfo = offset_eraseinfo;
> +
> +	if (!write_eraseinfo(cd_page, &size_eraseinfo))
> +		return FALSE;
> +
> +	info->size_eraseinfo += size_eraseinfo;
> +	DEBUG_MSG("offset_eraseinfo: %lx, size_eraseinfo: %ld\n",
> +			info->offset_eraseinfo, info->size_eraseinfo);
> +
> +	/* Update the erase info offset and size in kdump sub header */
> +	if (!update_sub_header())
> +		return FALSE;
> +
> +	return TRUE;
> +}
> +
>  int
>  write_kdump_bitmap(void)
>  {
> @@ -7391,6 +7586,8 @@ writeout_dumpfile(void)
>  			goto out;
>  		if (!write_kdump_pages(&cd_header, &cd_page))
>  			goto out;
> +		if (!write_kdump_eraseinfo(&cd_page))
> +			goto out;
>  		if (!write_kdump_bitmap())
>  			goto out;
>  	}
> @@ -7781,6 +7978,8 @@ free_config_entry(struct config_entry *ce)
>  			free(p->name);
>  		if (p->type_name)
>  			free(p->type_name);
> +		if (p->symbol_expr)
> +			free(p->symbol_expr);
>  		free(p);
>  	}
>  }
> @@ -8129,6 +8328,13 @@ read_filter_entry(struct config *config, int line)
>  									line);
>  		return FALSE;
>  	}
> +
> +	/*
> +	 * Save the symbol expression string for generation of eraseinfo data
> +	 * later while writing dumpfile.
> +	 */
> +	config->filter_symbol[idx]->symbol_expr = strdup(token);
> +
>  	if (config->iter_entry) {
>  		if (strcmp(config->filter_symbol[idx]->name,
>  				config->iter_entry->name)) {
> @@ -8726,8 +8932,11 @@ resolve_list_entry(struct config_entry *ce, unsigned long long base_addr,
>   * Insert the filter info node using insertion sort.
>   * If filter node for a given paddr is aready present then update the size
>   * and delete the fl_info node passed.
> + *
> + * Return 1 on successfull insertion.
> + * Return 0 if filter node with same paddr is found.
>   */
> -void
> +int
>  insert_filter_info(struct filter_info *fl_info)
>  {
>  	struct filter_info *prev = NULL;
> @@ -8735,7 +8944,7 @@ insert_filter_info(struct filter_info *fl_info)
>  
>  	if (!ptr) {
>  		filter_info = fl_info;
> -		return;
> +		return 1;
>  	}
>  
>  	while (ptr) {
> @@ -8748,7 +8957,7 @@ insert_filter_info(struct filter_info *fl_info)
>  		if (fl_info->size > ptr->size)
>  			ptr->size = fl_info->size;
>  		free(fl_info);
> -		return;
> +		return 0;
>  	}
>  
>  	if (prev) {
> @@ -8759,7 +8968,80 @@ insert_filter_info(struct filter_info *fl_info)
>  		fl_info->next = filter_info;
>  		filter_info = fl_info;
>  	}
> -	return;
> +	return 1;
> +}
> +
> +/*
> + * Create an erase info node for each erase command. One node per erase
> + * command even if it is part of loop construct.
> + * For erase commands that are not part of loop construct, the num_sizes will
> + * always be 1
> + * For erase commands that are part of loop construct, the num_sizes may be
> + * 1 or >1 depending on number iterations. This function will called multiple
> + * times depending on iterations. At first invokation create a node and
> + * increment num_sizes for subsequent invokations.
> + *
> + * The valid erase info node starts from index value 1. (index 0 is invalid
> + * index).
> + *
> + *            Index 0     1        2        3
> + *             +------+--------+--------+--------+
> + * erase_info->|Unused|        |        |        |......
> + *             +------+--------+--------+--------+
> + *                        |        .        .        .....
> + *                        V
> + *                   +---------+
> + *                   | char*   |----> Original erase command string
> + *                   +---------+
> + *                   |num_sizes|
> + *                   +---------+      +--+--+--+
> + *                   | sizes   |----> |  |  |  |... Sizes array of num_sizes
> + *                   +---------+      +--+--+--+
> + *
> + * On success, return the index value of erase node for given erase command.
> + * On failure, return 0.
> + */
> +static int
> +add_erase_info_node(struct config_entry *filter_symbol)
> +{
> +	int idx = filter_symbol->erase_info_idx;
> +
> +	/*
> +	 * Check if node is already created, if yes, increment the num_sizes.
> +	 */
> +	if (idx) {
> +		erase_info[idx].num_sizes++;
> +		return idx;
> +	}
> +
> +	/* Allocate a new node. */
> +	DEBUG_MSG("Allocating new erase info node for command \"%s\"\n",
> +			filter_symbol->symbol_expr);
> +	idx = num_erase_info++;
> +	erase_info = realloc(erase_info,
> +			sizeof(struct erase_info) * num_erase_info);
> +	if (!erase_info) {
> +		ERRMSG("Can't get memory to create erase information.\n");
> +		return 0;
> +	}
> +
> +	memset(&erase_info[idx], 0, sizeof(struct erase_info));
> +	erase_info[idx].symbol_expr = filter_symbol->symbol_expr;
> +	erase_info[idx].num_sizes = 1;
> +
> +	filter_symbol->symbol_expr = NULL;
> +	filter_symbol->erase_info_idx = idx;
> +
> +	return idx;
> +}
> +
> +/* Return the index value in sizes array for given erase command index. */
> +static inline int
> +get_size_index(int ei_idx)
> +{
> +	if (ei_idx)
> +		return erase_info[ei_idx].num_sizes - 1;
> +	return 0;
>  }
>  
>  int
> @@ -8798,7 +9080,10 @@ update_filter_info(struct config_entry *filter_symbol,
>  	fl_info->size = size;
>  	fl_info->nullify = filter_symbol->nullify;
>  
> -	insert_filter_info(fl_info);
> +	if (insert_filter_info(fl_info)) {
> +		fl_info->erase_info_idx = add_erase_info_node(filter_symbol);
> +		fl_info->size_idx = get_size_index(fl_info->erase_info_idx);
> +	}
>  	return TRUE;
>  }
>  
> @@ -9049,6 +9334,7 @@ void
>  clear_filter_info(void)
>  {
>  	struct filter_info *prev, *fi = filter_info;
> +	int i;
>  
>  	/* Delete filter_info nodes that are left out. */
>  	while (fi) {
> @@ -9057,6 +9343,13 @@ clear_filter_info(void)
>  		free(prev);
>  	}
>  	filter_info = NULL;
> +	if (erase_info) {
> +		for (i = 1; i < num_erase_info; i++) {
> +			free(erase_info[i].symbol_expr);
> +			free(erase_info[i].sizes);
> +		}
> +		free(erase_info);
> +	}
>  }
>  
>  int
> @@ -9245,6 +9538,8 @@ store_splitting_info(void)
>  		}
>  		SPLITTING_START_PFN(i) = kh.start_pfn;
>  		SPLITTING_END_PFN(i)   = kh.end_pfn;
> +		SPLITTING_OFFSET_EI(i) = kh.offset_eraseinfo;
> +		SPLITTING_SIZE_EI(i)   = kh.size_eraseinfo;
>  	}
>  	return TRUE;
>  }
> @@ -9452,6 +9747,7 @@ reassemble_kdump_pages(void)
>  	struct cache_data cd_pd, cd_data;
>  	struct timeval tv_start;
>  	char *data = NULL;
> +	unsigned long data_buf_size = info->page_size;
>  
>  	initialize_2nd_bitmap(&bitmap2);
>  
> @@ -9465,7 +9761,7 @@ reassemble_kdump_pages(void)
>  		free_cache_data(&cd_pd);
>  		return FALSE;
>  	}
> -	if ((data = malloc(info->page_size)) == NULL) {
> +	if ((data = malloc(data_buf_size)) == NULL) {
>  		ERRMSG("Can't allcate memory for page data.\n");
>  		free_cache_data(&cd_pd);
>  		free_cache_data(&cd_data);
> @@ -9570,6 +9866,49 @@ reassemble_kdump_pages(void)
>  	if (!write_cache_bufsz(&cd_data))
>  		goto out;
>  
> +	info->offset_eraseinfo = cd_data.offset;
> +	/* Copy eraseinfo from split dumpfiles to o/p dumpfile */
> +	for (i = 0; i < info->num_dumpfile; i++) {
> +		if (!SPLITTING_SIZE_EI(i))
> +			continue;
> +
> +		if (SPLITTING_SIZE_EI(i) > data_buf_size) {
> +			data_buf_size = SPLITTING_SIZE_EI(i);
> +			if ((data = realloc(data, data_buf_size)) == NULL) {
> +				ERRMSG("Can't allcate memory for eraseinfo"
> +					" data.\n");
> +				goto out;
> +			}
> +		}
> +		if ((fd = open(SPLITTING_DUMPFILE(i), O_RDONLY)) < 0) {
> +			ERRMSG("Can't open a file(%s). %s\n",
> +			    SPLITTING_DUMPFILE(i), strerror(errno));
> +			goto out;
> +		}
> +		if (lseek(fd, SPLITTING_OFFSET_EI(i), SEEK_SET) < 0) {
> +			ERRMSG("Can't seek a file(%s). %s\n",
> +			    SPLITTING_DUMPFILE(i), strerror(errno));
> +			goto out;
> +		}
> +		if (read(fd, data, SPLITTING_SIZE_EI(i)) !=
> +						SPLITTING_SIZE_EI(i)) {
> +			ERRMSG("Can't read a file(%s). %s\n",
> +			    SPLITTING_DUMPFILE(i), strerror(errno));
> +			goto out;
> +		}
> +		if (!write_cache(&cd_data, data, SPLITTING_SIZE_EI(i)))
> +			goto out;
> +		info->size_eraseinfo += SPLITTING_SIZE_EI(i);
> +
> +		close(fd);
> +		fd = 0;
> +	}
> +	if (!write_cache_bufsz(&cd_data))
> +		goto out;
> +
> +	if (!update_sub_header())
> +		goto out;
> +
>  	print_progress(PROGRESS_COPY, num_dumpable, num_dumpable);
>  	print_execution_time(PROGRESS_COPY, &tv_start);
>  
> diff --git a/makedumpfile.h b/makedumpfile.h
> index 1c61edb..2e4b902 100644
> --- a/makedumpfile.h
> +++ b/makedumpfile.h
> @@ -434,6 +434,8 @@ do { \
>  #define SPLITTING_FD_BITMAP(i)	info->splitting_info[i].fd_bitmap
>  #define SPLITTING_START_PFN(i)	info->splitting_info[i].start_pfn
>  #define SPLITTING_END_PFN(i)	info->splitting_info[i].end_pfn
> +#define SPLITTING_OFFSET_EI(i)	info->splitting_info[i].offset_eraseinfo
> +#define SPLITTING_SIZE_EI(i)	info->splitting_info[i].size_eraseinfo
>  
>  /*
>   * kernel version
> @@ -499,6 +501,8 @@ do { \
>  #define XEN_ELFNOTE_CRASH_INFO	(0x1000001)
>  #define SIZE_XEN_CRASH_INFO_V2	(sizeof(unsigned long) * 10)
>  
> +#define MAX_SIZE_STR_LEN (21)
> +
>  /*
>   * The value of dependence on machine
>   */
> @@ -841,6 +845,8 @@ struct splitting_info {
>  	int 			fd_bitmap;
>  	unsigned long long	start_pfn;
>  	unsigned long long	end_pfn;
> +	off_t			offset_eraseinfo;
> +	unsigned long		size_eraseinfo;
>  } splitting_info_t;
>  
>  struct DumpInfo {
> @@ -905,6 +911,7 @@ struct DumpInfo {
>  	struct dump_bitmap 		*bitmap1;
>  	struct dump_bitmap 		*bitmap2;
>  	struct disk_dump_header		*dump_header;
> +	struct kdump_sub_header		sub_header;
>  
>  	/*
>  	 * ELF header info:
> @@ -973,6 +980,12 @@ struct DumpInfo {
>  	unsigned long		size_note;
>  
>  	/*
> +	 * erased information in dump memory image info:
> +	 */
> +	off_t			offset_eraseinfo;
> +	unsigned long		size_eraseinfo;
> +
> +	/*
>  	 * for Xen extraction
>  	 */
>  	off_t			offset_xen_crash_info;
> @@ -1280,12 +1293,27 @@ struct dwarf_info {
>  extern struct dwarf_info	dwarf_info;
>  
>  /*
> + * Erase information, original symbol expressions.
> + */
> +struct erase_info {
> +	char		*symbol_expr;
> +	int		num_sizes;
> +	long		*sizes;
> +	int		erased;		/* 1= erased, 0= Not erased */
> +};
> +
> +/*
>   * Filtering information
>   */
>  struct filter_info {
>  	unsigned long long      address;
>  	unsigned long long      paddr;
>  	long			size;
> +
> +	/* direct access to update erase information node */
> +	int			erase_info_idx;	/* 0= invalid index */
> +	int			size_idx;
> +
>  	struct filter_info      *next;
>  	unsigned short          nullify;
>  };
> @@ -1293,6 +1321,7 @@ struct filter_info {
>  struct config_entry {
>  	char			*name;
>  	char			*type_name;
> +	char			*symbol_expr;	/* original symbol expression */
>  	unsigned short		flag;
>  	unsigned short		nullify;
>  	unsigned long long	sym_addr;	/* Symbol address */
> @@ -1305,6 +1334,7 @@ struct config_entry {
>  	long			index;
>  	long			size;
>  	int			line;	/* Line number in config file. */
> +	int			erase_info_idx;	/* 0= invalid index */
>  	struct config_entry	*refer_to;
>  	struct config_entry	*next;
>  };
> 



From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:49 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:49 +0200
Subject: [patch v3 0/8] kdump: Patch series for s390 support (version 3)
Message-ID: <20110812134849.748973593@linux.vnet.ibm.com>

Hello Vivek,

I updated the patch series according to our last discussions. As you requested,
I removed the "#if !defined(CONFIG_S390)" in the panic function.

The semantics is now as follows:

If kdump is loaded, kdump is always triggered for panic and PSW restart
(s390 NMI). If kdump is not loaded, the s390 shutdown actions defined
under /sys/firmware are executed as we are doing it already today.

I also added again patches for stand-alone dump integration:

For s390 we add a parameter to the purgatory entry point. When "0" is passed,
purgatory only returns the result of the checksum test. When "1" is passed,
purgatory triggers kdump. So we call purgatory twice. First for checking and
second time for execution. You can argue that it would be better to call
purgatory only once and it returns only, if checksums are invalid.
Unfortunately this would be very hard to implement for us, because we
switch to the boot CPU before kdump is finally triggered and after that
currently it is not possible to return from the called function.

panic --------+
              +--- crash_kexec()
              |    call_s390_shutdown_actions() -> stand-alone dump
PSW restart --+

crash_kexec +--> kdump loaded? --> machine_kexec()
            |
            +--> kdump not loaded --> return

machine_kexec +-> purgatory(0)==0 -> switch to IPL cpu -> purgatory(1) -> kdump
              |
              +-> purgatory(0)!=0 -> return

See patches [6] and [8] for details.

Does that sound ok for you?

Michael

Patch overview:
---------------
[1-3] common code changes (could you please ACC patches [1] and [3]?)
[4]   s390 kdump preparation patch
[5]   s390 kdump backend
[6]   s390 stand-alone dump/shutdown actions integration
[7]   kexec-tools: s390 kdump backend for kexec-tools
[8]   kexec-tools: s390 stand-alone dump/shutdown actions integration

History: v1->v2:
----------------
Main changes compared to version 1:
1. We use purgatory code
2. We use pre-allocated ELF core header
3. Registers are saved in old kernel
4. Removed meminfo


From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:53 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:53 +0200
Subject: [patch v3 4/8] s390: Add real memory access functions
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.485280669@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-arch-maccess.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/c156ffe9/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:55 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:55 +0200
Subject: [patch v3 6/8] s390: Do first kdump checksum test before really
	starting kdump
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.816664005@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-arch-backend-entry.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/aa0f2dda/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:50 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:50 +0200
Subject: [patch v3 1/8] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.021058020@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-common-control-limit.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/4aef6e9c/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:51 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:51 +0200
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.166585439@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-common-load_crash_segment.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/8f341203/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:57 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:57 +0200
Subject: [patch v3 8/8] kexec-tools: Allow to call verify_sha256_digest() from
	kernel
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134908.120804811@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: kexec-tools-s390-kdump-entry.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/7126e309/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:52 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:52 +0200
Subject: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.325789470@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-common-elfcorehdr-parm.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/8a5daece/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:56 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:56 +0200
Subject: [patch v3 7/8] kexec-tools: Add s390 kdump support
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.971000326@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: kexec-tools-s390-kdump.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/8cff4ee2/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 12 09:48:54 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 12 Aug 2011 15:48:54 +0200
Subject: [patch v3 5/8] s390: kdump backend code
References: <20110812134849.748973593@linux.vnet.ibm.com>
Message-ID: <20110812134907.651658120@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-arch-backend.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110812/2420c405/attachment.ksh>

From william_rose55 at yahoo.com  Fri Aug 12 14:25:00 2011
From: william_rose55 at yahoo.com (Rose)
Date: Fri, 12 Aug 2011 20:25:00 +0200
Subject: =?UTF-8?Q?HELLO=20my=20=20=E4=BD=A0=E5=A5=BD=EF=BC=8C=E6=88=91?=
Message-ID: <20110812202500.3D7EFB8D@centrum.sk>


HELLO
My name is Rose,i and became intrested in you, i will also like to know you more,and i want you to send an email to my email address so i can give you my picture for you to know whom i am. Here is my email address(william_rose55 at yahoo.com)I believe we can move from here!
I am waiting for your mail to my email address above..
(Remeber the distance or colour does not matter but love matters alot in life)
Thanks Rose? please contact me now through my email address
(william_rose55 at yahoo.com)


From oomichi at mxs.nes.nec.co.jp  Mon Aug 15 01:54:51 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Mon, 15 Aug 2011 14:54:51 +0900
Subject: [UPDATED PATCH v2 8/8] makedumpfile: Add erase information in
	ELF formatted dumpfile
In-Reply-To: <20110715091602.GA719@in.ibm.com>
References: <20110517200715.12740.67863.stgit@mars.in.ibm.com>
	<20110715091602.GA719@in.ibm.com>
Message-ID: <20110815145451.44f9d605.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Fri, 15 Jul 2011 14:46:02 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> @@ -4647,6 +4650,15 @@ write_cache_bufsz(struct cache_data *cd)
>  }
>  
>  int
> +write_cache_zero(struct cache_data *cd, size_t size)
> +{
> +	memset(cd->buf + cd->buf_size, 0, size);
> +	cd->buf_size += size;
> +
> +	return write_cache_bufsz(cd);
> +}

if cd->buf_size is a little smaller than cd->cache_size and
the argument "size" is bigger than info->page_size, the above
a SIGSEGV happens at the above memset().

Previous write_cache_bufsze() call will avoid that :
---
 int
 write_cache_zero(struct cache_data *cd, size_t size)
 {
+	if (!write_cache_bufsz(cd))
+		return FALSE;

	memset(cd->buf + cd->buf_size, 0, size);
	cd->buf_size += size;

	return write_cache_bufsz(cd);
 }
---

>  /*
> + * ELF note section for erase information
> + *
> + * According to elf.h the unused values are 0x15(21) through 0xff. The value
> + * range 0x1XX, 0x2XX and 0x3XX is been used for PPC, i386 and s390
> + * respectively.
> + *
> + * Using 0xff to be on safer side so that any new Elf Note addition in elf.h
> + * after 0x15 value would not clash.
> + */
> +#ifndef NT_ERASE_INFO
> +#define NT_ERASE_INFO (0xff)	/* Contains erased information. */
> +#endif
> +#define ERASEINFO_NOTE_NAME		"ERASEINFO"
> +#define ERASEINFO_NOTE_NAME_BYTES	(sizeof(ERASEINFO_NOTE_NAME))

I feel NT_ERASE_INFO(0xff) is not safe and we can use ERASEINFO_NOTE_NAME
instead.


Thanks
Ken'ichi Ohmichi


From holzheu at linux.vnet.ibm.com  Mon Aug 15 09:24:26 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Mon, 15 Aug 2011 15:24:26 +0200
Subject: [PATCH] makedumpfile: Support line mode terminals
Message-ID: <1313414666.9445.3.camel@br98xy6r>

From: Michael Holzheu <holzheu at linux.vnet.ibm.com>

On S390 we have line mode terminals that do not have the ability to
position the cursor. When using kdump the output of makedumpfile will be shown
on such terminals. Currently the output looks very strange because the '\r'
control character is ignored. It looks like the following:

 Checking for memory holes          : [  0 %]  Checking for memory holes        
  : [100 %]  Copying data                       : [ 33 %]  Copying data         
              : [ 65 %]  Copying data                       : [ 96 %]  Copying d
ata                       : [100 %]   

For those line mode terminals the TERM environment variable is set to "dumb".
With this patch makedumpfile checks the TERM variable and in case of "dumb"
instead of using '\r' each progress message is printed into a separate line.
The output will then look like the following:

Checking for memory holes          : [  0 %]
Checking for memory holes          : [100 %]
Copying data                       : [ 11 %]
Copying data                       : [ 44 %]
Copying data                       : [ 75 %]
Copying data                       : [100 %]

Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
---
 makedumpfile.c |   22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -29,6 +29,7 @@ struct DumpInfo		*info = NULL;
 
 char filename_stdout[] = FILENAME_STDOUT;
 int message_level;
+static int dumb_term;
 
 /*
  * Forward declarations
@@ -5661,9 +5662,14 @@ print_progress(const char *msg, unsigned
 		progress = current * 100 / end;
 	} else
 		progress = 100;
-
-	PROGRESS_MSG("\r");
-	PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3d %%] ", msg, progress);
+	if (dumb_term) {
+		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3d %%]\n",
+			     msg, progress);
+	} else {
+		PROGRESS_MSG("\r");
+		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3d %%] ",
+			     msg, progress);
+	}
 }
 
 unsigned long long
@@ -7825,11 +7831,21 @@ static struct option longopts[] = {
 	{0, 0, 0, 0}
 };
 
+static void setup_term(void)
+{
+	char *term_str = getenv("TERM");
+
+	if (term_str && strcmp(term_str, "dumb") == 0)
+		dumb_term = 1;
+}
+
 int
 main(int argc, char *argv[])
 {
 	int i, opt, flag_debug = FALSE;
 
+	setup_term();
+
 	if ((info = calloc(1, sizeof(struct DumpInfo))) == NULL) {
 		ERRMSG("Can't allocate memory for the pagedesc cache. %s.\n",
 		    strerror(errno));




From vgoyal at redhat.com  Mon Aug 15 10:40:30 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 15 Aug 2011 10:40:30 -0400
Subject: kdump and SMP system kernel
In-Reply-To: <9C7BACB01B839A499792154E76C9ADE555DE65CE87@MX19A.corp.emc.com>
References: <9C7BACB01B839A499792154E76C9ADE555DE65CE87@MX19A.corp.emc.com>
Message-ID: <20110815144030.GD10154@redhat.com>

On Mon, Aug 15, 2011 at 10:27:30AM -0400, dmitry.krivenok at emc.com wrote:
> Hello Vivek and Maneesh,
> I've read your document Documentation/kdump/kdump.txt and built system and dump-capture
> kernels with the options mentioned there.
> 
> Then I booted the new system kernel and registered a "panic handler" using the following command
> kexec -p /boot/linux-3.0.0-capture --initrd=/boot/initrd-3.0.0-capture --append="root=/dev/mapper/myvg-root 3 irqpoll maxcpus=1 reset_devices"
> 
> Finally, I simulated a panic using
> echo c > /proc/sysrq-trigger
> 
> Unfortunately, the dump-capture kernel wasn't functional (it was booting very slowly, I saw lots of messages
> like "ata2: lost interrupt", my keyboard didn't work at all and I couldn't access the system via the network).
> 
> I investigated this problem and tried lots of combinations of boot parameters for dump-capture kernel, but
> nothing helped. Then I tried to tune boot parameters of system kernel and found that if I specify "maxcpus=1"
> for system kernel, then dump-capture kernel always boots successfully and I have access to correct /proc/vmcore.
> 
> The problem is that I'm debugging a problem which only occurs on SMP kernel and I never see it on the kernel
> booted with "maxcpus=1".
> 
> So I just want to clarify - is it possible to use kexec/kdump with SMP system kernel?
> Is it intended to work at all?
> 
> Thanks in advance!
> 
> P.S.
> I'm using Arch Linux with vanilla kernel 3.0.0 and kexec-tools 2.0.2-3 running in VM on VmWare ESX server.

Yes it is supposed to work on SMP machines. maxcpus=1 in second kernel 
will make sure that it brings up only the cpu we crashed on. You can
also try using nr_cpus=1 on latest kernels.

It sounds like an issue with disk driver initialization and could have
something do to with hypervisor also. Not sure. Does it work on bare
metal.

P.S. Maneesh is no more with IBM so above id is not valid. I am not sure
what's new id. Some of these issues you can copy on kexec-tools mailing
list. I am ccing the list now.


Thanks
Vivek


From dmitry.krivenok at emc.com  Mon Aug 15 10:56:17 2011
From: dmitry.krivenok at emc.com (dmitry.krivenok at emc.com)
Date: Mon, 15 Aug 2011 10:56:17 -0400
Subject: kdump and SMP system kernel
In-Reply-To: <20110815144030.GD10154@redhat.com>
References: <9C7BACB01B839A499792154E76C9ADE555DE65CE87@MX19A.corp.emc.com>
	<20110815144030.GD10154@redhat.com>
Message-ID: <9C7BACB01B839A499792154E76C9ADE555DE65CE99@MX19A.corp.emc.com>

I tried nr_cpus=1, but it didn't help.

I haven't tried the test on bare metal, but I'm going to try it 
on my laptop later today. I'll let you know if it works.

Thanks,
Dmitry

-----Original Message-----
From: Vivek Goyal [mailto:vgoyal at redhat.com] 
Sent: Monday, August 15, 2011 6:41 PM
To: Krivenok, Dmitry
Cc: Kexec Mailing List
Subject: Re: kdump and SMP system kernel

On Mon, Aug 15, 2011 at 10:27:30AM -0400, dmitry.krivenok at emc.com wrote:
> Hello Vivek and Maneesh,
> I've read your document Documentation/kdump/kdump.txt and built system and dump-capture
> kernels with the options mentioned there.
> 
> Then I booted the new system kernel and registered a "panic handler" using the following command
> kexec -p /boot/linux-3.0.0-capture --initrd=/boot/initrd-3.0.0-capture --append="root=/dev/mapper/myvg-root 3 irqpoll maxcpus=1 reset_devices"
> 
> Finally, I simulated a panic using
> echo c > /proc/sysrq-trigger
> 
> Unfortunately, the dump-capture kernel wasn't functional (it was booting very slowly, I saw lots of messages
> like "ata2: lost interrupt", my keyboard didn't work at all and I couldn't access the system via the network).
> 
> I investigated this problem and tried lots of combinations of boot parameters for dump-capture kernel, but
> nothing helped. Then I tried to tune boot parameters of system kernel and found that if I specify "maxcpus=1"
> for system kernel, then dump-capture kernel always boots successfully and I have access to correct /proc/vmcore.
> 
> The problem is that I'm debugging a problem which only occurs on SMP kernel and I never see it on the kernel
> booted with "maxcpus=1".
> 
> So I just want to clarify - is it possible to use kexec/kdump with SMP system kernel?
> Is it intended to work at all?
> 
> Thanks in advance!
> 
> P.S.
> I'm using Arch Linux with vanilla kernel 3.0.0 and kexec-tools 2.0.2-3 running in VM on VmWare ESX server.

Yes it is supposed to work on SMP machines. maxcpus=1 in second kernel 
will make sure that it brings up only the cpu we crashed on. You can
also try using nr_cpus=1 on latest kernels.

It sounds like an issue with disk driver initialization and could have
something do to with hypervisor also. Not sure. Does it work on bare
metal.

P.S. Maneesh is no more with IBM so above id is not valid. I am not sure
what's new id. Some of these issues you can copy on kexec-tools mailing
list. I am ccing the list now.


Thanks
Vivek



From oomichi at mxs.nes.nec.co.jp  Mon Aug 15 21:00:35 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Tue, 16 Aug 2011 10:00:35 +0900
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in
	compressed kdump file
In-Reply-To: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
Message-ID: <20110816100035.e27d97c0.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Wed, 18 May 2011 01:36:17 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> @@ -9452,6 +9747,7 @@ reassemble_kdump_pages(void)
>  	struct cache_data cd_pd, cd_data;
>  	struct timeval tv_start;
>  	char *data = NULL;
> +	unsigned long data_buf_size = info->page_size;
>  
>  	initialize_2nd_bitmap(&bitmap2);
>  
> @@ -9465,7 +9761,7 @@ reassemble_kdump_pages(void)
>  		free_cache_data(&cd_pd);
>  		return FALSE;
>  	}
> -	if ((data = malloc(info->page_size)) == NULL) {
> +	if ((data = malloc(data_buf_size)) == NULL) {
>  		ERRMSG("Can't allcate memory for page data.\n");
>  		free_cache_data(&cd_pd);
>  		free_cache_data(&cd_data);
> @@ -9570,6 +9866,49 @@ reassemble_kdump_pages(void)
>  	if (!write_cache_bufsz(&cd_data))
>  		goto out;
>  
> +	info->offset_eraseinfo = cd_data.offset;
> +	/* Copy eraseinfo from split dumpfiles to o/p dumpfile */
> +	for (i = 0; i < info->num_dumpfile; i++) {
> +		if (!SPLITTING_SIZE_EI(i))
> +			continue;
> +
> +		if (SPLITTING_SIZE_EI(i) > data_buf_size) {
> +			data_buf_size = SPLITTING_SIZE_EI(i);
> +			if ((data = realloc(data, data_buf_size)) == NULL) {
> +				ERRMSG("Can't allcate memory for eraseinfo"
> +					" data.\n");
> +				goto out;
> +			}
> +		}
> +		if ((fd = open(SPLITTING_DUMPFILE(i), O_RDONLY)) < 0) {
> +			ERRMSG("Can't open a file(%s). %s\n",
> +			    SPLITTING_DUMPFILE(i), strerror(errno));
> +			goto out;
> +		}
> +		if (lseek(fd, SPLITTING_OFFSET_EI(i), SEEK_SET) < 0) {
> +			ERRMSG("Can't seek a file(%s). %s\n",
> +			    SPLITTING_DUMPFILE(i), strerror(errno));
> +			goto out;
> +		}
> +		if (read(fd, data, SPLITTING_SIZE_EI(i)) !=
> +						SPLITTING_SIZE_EI(i)) {
> +			ERRMSG("Can't read a file(%s). %s\n",
> +			    SPLITTING_DUMPFILE(i), strerror(errno));
> +			goto out;
> +		}
> +		if (!write_cache(&cd_data, data, SPLITTING_SIZE_EI(i)))
> +			goto out;
> +		info->size_eraseinfo += SPLITTING_SIZE_EI(i);
> +
> +		close(fd);
> +		fd = 0;
> +	}
> +	if (!write_cache_bufsz(&cd_data))
> +		goto out;
> +
> +	if (!update_sub_header())
> +		goto out;

The above update_sub_header() breaks "--reassemble" option if a dumpfile
does not contain eraseinfo data :

---
# makedumpfile --split -d30 vmcore dump.1 dump.2
Copying data                       : [100 %]
Copying data                       : [100 %]

The dumpfiles are saved to dump.1, and dump.2.

makedumpfile Completed.
# makedumpfile --reassemble dump.1 dump.2 dump.3
Copying data                       : [100 %]
The dumpfile is saved to dump.3.

makedumpfile Completed.
# crash vmlinux dump.3
[..]

crash: page excluded: kernel virtual address: ffffffff8040b220  type: "cpu_possible_mask"
#
---

The cause is that info->sub_header, which is written in update_sub_header(),
is filled with 0x0.
The following change fixes this problem:

---
@@ -9378,6 +9680,7 @@ reassemble_kdump_header(void)
                    info->name_dumpfile, strerror(errno));
                return FALSE;
        }
+       memcpy(&info->sub_header, &kh, sizeof(kh));

        /*
         * Write dump bitmap to both a dumpfile and a bitmap file.
---

Thanks
Ken'ichi Ohmichi


From mahesh at linux.vnet.ibm.com  Tue Aug 16 06:16:09 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Tue, 16 Aug 2011 15:46:09 +0530
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in	compressed
	kdump file
In-Reply-To: <20110816100035.e27d97c0.oomichi@mxs.nes.nec.co.jp>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
	<20110816100035.e27d97c0.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4E4A4369.1000008@linux.vnet.ibm.com>

Hi Ken'ichi,

On 08/16/2011 06:30 AM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Wed, 18 May 2011 01:36:17 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>> @@ -9452,6 +9747,7 @@ reassemble_kdump_pages(void)
>>  	struct cache_data cd_pd, cd_data;
>>  	struct timeval tv_start;
>>  	char *data = NULL;
>> +	unsigned long data_buf_size = info->page_size;
>>  
>>  	initialize_2nd_bitmap(&bitmap2);
>>  
>> @@ -9465,7 +9761,7 @@ reassemble_kdump_pages(void)
>>  		free_cache_data(&cd_pd);
>>  		return FALSE;
>>  	}
>> -	if ((data = malloc(info->page_size)) == NULL) {
>> +	if ((data = malloc(data_buf_size)) == NULL) {
>>  		ERRMSG("Can't allcate memory for page data.\n");
>>  		free_cache_data(&cd_pd);
>>  		free_cache_data(&cd_data);
>> @@ -9570,6 +9866,49 @@ reassemble_kdump_pages(void)
>>  	if (!write_cache_bufsz(&cd_data))
>>  		goto out;
>>  
>> +	info->offset_eraseinfo = cd_data.offset;
>> +	/* Copy eraseinfo from split dumpfiles to o/p dumpfile */
>> +	for (i = 0; i < info->num_dumpfile; i++) {
>> +		if (!SPLITTING_SIZE_EI(i))
>> +			continue;
>> +
>> +		if (SPLITTING_SIZE_EI(i) > data_buf_size) {
>> +			data_buf_size = SPLITTING_SIZE_EI(i);
>> +			if ((data = realloc(data, data_buf_size)) == NULL) {
>> +				ERRMSG("Can't allcate memory for eraseinfo"
>> +					" data.\n");
>> +				goto out;
>> +			}
>> +		}
>> +		if ((fd = open(SPLITTING_DUMPFILE(i), O_RDONLY)) < 0) {
>> +			ERRMSG("Can't open a file(%s). %s\n",
>> +			    SPLITTING_DUMPFILE(i), strerror(errno));
>> +			goto out;
>> +		}
>> +		if (lseek(fd, SPLITTING_OFFSET_EI(i), SEEK_SET) < 0) {
>> +			ERRMSG("Can't seek a file(%s). %s\n",
>> +			    SPLITTING_DUMPFILE(i), strerror(errno));
>> +			goto out;
>> +		}
>> +		if (read(fd, data, SPLITTING_SIZE_EI(i)) !=
>> +						SPLITTING_SIZE_EI(i)) {
>> +			ERRMSG("Can't read a file(%s). %s\n",
>> +			    SPLITTING_DUMPFILE(i), strerror(errno));
>> +			goto out;
>> +		}
>> +		if (!write_cache(&cd_data, data, SPLITTING_SIZE_EI(i)))
>> +			goto out;
>> +		info->size_eraseinfo += SPLITTING_SIZE_EI(i);
>> +
>> +		close(fd);
>> +		fd = 0;
>> +	}
>> +	if (!write_cache_bufsz(&cd_data))
>> +		goto out;
>> +
>> +	if (!update_sub_header())
>> +		goto out;
> 
> The above update_sub_header() breaks "--reassemble" option if a dumpfile
> does not contain eraseinfo data :

My bad. Thanks for catching it.

Thanks,
-Mahesh.

> 
> ---
> # makedumpfile --split -d30 vmcore dump.1 dump.2
> Copying data                       : [100 %]
> Copying data                       : [100 %]
> 
> The dumpfiles are saved to dump.1, and dump.2.
> 
> makedumpfile Completed.
> # makedumpfile --reassemble dump.1 dump.2 dump.3
> Copying data                       : [100 %]
> The dumpfile is saved to dump.3.
> 
> makedumpfile Completed.
> # crash vmlinux dump.3
> [..]
> 
> crash: page excluded: kernel virtual address: ffffffff8040b220  type: "cpu_possible_mask"
> #
> ---
> 
> The cause is that info->sub_header, which is written in update_sub_header(),
> is filled with 0x0.
> The following change fixes this problem:
> 
> ---
> @@ -9378,6 +9680,7 @@ reassemble_kdump_header(void)
>                     info->name_dumpfile, strerror(errno));
>                 return FALSE;
>         }
> +       memcpy(&info->sub_header, &kh, sizeof(kh));
> 
>         /*
>          * Write dump bitmap to both a dumpfile and a bitmap file.
> ---
> 
> Thanks
> Ken'ichi Ohmichi
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



From mahesh at linux.vnet.ibm.com  Tue Aug 16 07:21:16 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Tue, 16 Aug 2011 16:51:16 +0530
Subject: [UPDATED PATCH v2 8/8] makedumpfile: Add erase information in
	ELF formatted dumpfile
In-Reply-To: <20110815145451.44f9d605.oomichi@mxs.nes.nec.co.jp>
References: <20110517200715.12740.67863.stgit@mars.in.ibm.com>
	<20110715091602.GA719@in.ibm.com>
	<20110815145451.44f9d605.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4E4A52AC.2060407@linux.vnet.ibm.com>

On 08/15/2011 11:24 AM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Fri, 15 Jul 2011 14:46:02 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>> @@ -4647,6 +4650,15 @@ write_cache_bufsz(struct cache_data *cd)
>>  }
>>  
>>  int
>> +write_cache_zero(struct cache_data *cd, size_t size)
>> +{
>> +	memset(cd->buf + cd->buf_size, 0, size);
>> +	cd->buf_size += size;
>> +
>> +	return write_cache_bufsz(cd);
>> +}
> 
> if cd->buf_size is a little smaller than cd->cache_size and
> the argument "size" is bigger than info->page_size, the above
> a SIGSEGV happens at the above memset().
> 
> Previous write_cache_bufsze() call will avoid that :
> ---
>  int
>  write_cache_zero(struct cache_data *cd, size_t size)
>  {
> +	if (!write_cache_bufsz(cd))
> +		return FALSE;
> 
> 	memset(cd->buf + cd->buf_size, 0, size);
> 	cd->buf_size += size;
> 
> 	return write_cache_bufsz(cd);
>  }
> ---

Nice catch. Agree.

> 
>>  /*
>> + * ELF note section for erase information
>> + *
>> + * According to elf.h the unused values are 0x15(21) through 0xff. The value
>> + * range 0x1XX, 0x2XX and 0x3XX is been used for PPC, i386 and s390
>> + * respectively.
>> + *
>> + * Using 0xff to be on safer side so that any new Elf Note addition in elf.h
>> + * after 0x15 value would not clash.
>> + */
>> +#ifndef NT_ERASE_INFO
>> +#define NT_ERASE_INFO (0xff)	/* Contains erased information. */
>> +#endif
>> +#define ERASEINFO_NOTE_NAME		"ERASEINFO"
>> +#define ERASEINFO_NOTE_NAME_BYTES	(sizeof(ERASEINFO_NOTE_NAME))
> 
> I feel NT_ERASE_INFO(0xff) is not safe and we can use ERASEINFO_NOTE_NAME
> instead.

Do you mean having n_type set to '0' and just using
'ERASEINFO_NOTE_NAME' to identify the eraseinfo note? if Yes, then I
think I am ok with that.

Thanks,
-Mahesh.


From oomichi at mxs.nes.nec.co.jp  Tue Aug 16 23:49:41 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Wed, 17 Aug 2011 12:49:41 +0900
Subject: [UPDATED PATCH v2 8/8] makedumpfile: Add erase information in
	ELF formatted dumpfile
In-Reply-To: <4E4A52AC.2060407@linux.vnet.ibm.com>
References: <20110517200715.12740.67863.stgit@mars.in.ibm.com>
	<20110715091602.GA719@in.ibm.com>
	<20110815145451.44f9d605.oomichi@mxs.nes.nec.co.jp>
	<4E4A52AC.2060407@linux.vnet.ibm.com>
Message-ID: <20110817124941.445ca9b7.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Tue, 16 Aug 2011 16:51:16 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >>  /*
> >> + * ELF note section for erase information
> >> + *
> >> + * According to elf.h the unused values are 0x15(21) through 0xff. The value
> >> + * range 0x1XX, 0x2XX and 0x3XX is been used for PPC, i386 and s390
> >> + * respectively.
> >> + *
> >> + * Using 0xff to be on safer side so that any new Elf Note addition in elf.h
> >> + * after 0x15 value would not clash.
> >> + */
> >> +#ifndef NT_ERASE_INFO
> >> +#define NT_ERASE_INFO (0xff)	/* Contains erased information. */
> >> +#endif
> >> +#define ERASEINFO_NOTE_NAME		"ERASEINFO"
> >> +#define ERASEINFO_NOTE_NAME_BYTES	(sizeof(ERASEINFO_NOTE_NAME))
> > 
> > I feel NT_ERASE_INFO(0xff) is not safe and we can use ERASEINFO_NOTE_NAME
> > instead.
> 
> Do you mean having n_type set to '0' and just using
> 'ERASEINFO_NOTE_NAME' to identify the eraseinfo note?

Yes, that is I wanted to say. thanks.

> if Yes, then I think I am ok with that.

OK, I have merged the above change(commit: 8b8f13e6e84ad628a54bbe2d930aa15224ef5d92)
into the filter-out-devel branch.


Thanks
Ken'ichi Ohmichi


From adrian.wenl at gmail.com  Wed Aug 17 02:21:33 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Wed, 17 Aug 2011 14:21:33 +0800
Subject: makedumpfile cross compile for ARM?
Message-ID: <CALZhoSQ5dXghiq618_5D-uXnhc_8UU60xeouALARRiWDxmoBXA@mail.gmail.com>

Hi,

Does anyone know how to cross compile makedumpfile for the arm?
I try to build out binary from qemu, but it works only under qemu env,
while I copy it to the board, it run fail and report Segamatation
fault.

So I want to have another try with cross compile, however it seems to
me that makedumpfile doesn't support this from the look of its
Makefile.
Does anyone know any patch to fix this?

Thanks,
Lei


From vgoyal at redhat.com  Wed Aug 17 17:05:55 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Wed, 17 Aug 2011 17:05:55 -0400
Subject: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110812134907.325789470@linux.vnet.ibm.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.325789470@linux.vnet.ibm.com>
Message-ID: <20110817210554.GD14813@redhat.com>

On Fri, Aug 12, 2011 at 03:48:52PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> Currently only the address of the pre-allocated ELF header is passed with
> the elfcorehdr= kernel parameter. In order to reserve memory for the header
> in the 2nd kernel also the size is required. Current kdump architecture
> backends use different methods to do that, e.g. x86 uses the memmap= kernel
> parameter. On s390 there is no easy way to transfer this information.
> Therefore the elfcorehdr kernel parameter is extended to also pass the size.
> This now can also be used as standard mechanism by all future kdump
> architecture backends.

Michael,

This version looks much better. A quick question. Who parses this
elfcorehdr= parameter in s390 and how do we make sure these headers are not
overwritten.

Thanks
Vivek


From mahesh at linux.vnet.ibm.com  Thu Aug 18 04:14:12 2011
From: mahesh at linux.vnet.ibm.com (Mahesh Jagannath Salgaonkar)
Date: Thu, 18 Aug 2011 13:44:12 +0530
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in compressed
	kdump file
In-Reply-To: <20110812171013.7545b3df.oomichi@mxs.nes.nec.co.jp>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
	<20110812171013.7545b3df.oomichi@mxs.nes.nec.co.jp>
Message-ID: <4E4CC9D4.7040306@linux.vnet.ibm.com>

Hi Ken'ichi,

On 08/12/2011 01:40 PM, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Wed, 18 May 2011 01:36:17 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>> --- a/makedumpfile.c
>> +++ b/makedumpfile.c
>> @@ -29,6 +29,8 @@ struct DumpInfo		*info = NULL;
>>  struct module_sym_table	mod_st = { 0 };
>>  struct filter_info	*filter_info = NULL;
>>  struct filter_config	filter_config;
>> +struct erase_info	*erase_info = NULL;
>> +unsigned long		num_erase_info = 1; /* Node 0 is unused. */
> 
> I cannot understand erase_info[0] is unused.

I did this to avoid the explicit need of initializing erase_info_idx
member from struct config_entry and struct filter_info with some other
invalid value, instead I thought I will use '0' as invalid index.

Do you think I should change this patch to use '-1' as invalid index?

> 
> 
>> @@ -6000,10 +6007,17 @@ write_kdump_header(void)
>>  			kh.size_vmcoreinfo = info->size_vmcoreinfo;
>>  		}
>>  	}
>> -	if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
>> -	    size, info->name_dumpfile))
>> -		goto out;
>> +	/*
>> +	 * While writing dump data to STDOUT, delay the writing of sub header
>> +	 * untill we gather erase info offset and size.
>> +	 */
>> +	if (!info->flag_flatten) {
>> +		if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
>> +		    size, info->name_dumpfile))
>> +			goto out;
>> +	}
> 
> Does makedumpfile work wrong if removing the above change ?
> 

Hmm.. while implementing this patch I thought we may run into issues if
we write sub_header data twice for flattened case. But it seems the '-R'
option rearranges the data properly.

I agree that we dont need above change. Thanks for catching this.

Thanks,
-Mahesh.


From holzheu at linux.vnet.ibm.com  Thu Aug 18 04:47:59 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Thu, 18 Aug 2011 10:47:59 +0200
Subject: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110817210554.GD14813@redhat.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.325789470@linux.vnet.ibm.com>
	<20110817210554.GD14813@redhat.com>
Message-ID: <1313657279.3528.6.camel@br98xy6r>

Hello Vivek,

On Wed, 2011-08-17 at 17:05 -0400, Vivek Goyal wrote:
> On Fri, Aug 12, 2011 at 03:48:52PM +0200, Michael Holzheu wrote:
> > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > 
> > Currently only the address of the pre-allocated ELF header is passed with
> > the elfcorehdr= kernel parameter. In order to reserve memory for the header
> > in the 2nd kernel also the size is required. Current kdump architecture
> > backends use different methods to do that, e.g. x86 uses the memmap= kernel
> > parameter. On s390 there is no easy way to transfer this information.
> > Therefore the elfcorehdr kernel parameter is extended to also pass the size.
> > This now can also be used as standard mechanism by all future kdump
> > architecture backends.
> 
> Michael,
> 
> This version looks much better. A quick question. Who parses this
> elfcorehdr= parameter in s390 and how do we make sure these headers are not
> overwritten.

The parameter is parsed in common code (kernel/crash_dump.c) in
early_param("elfcorehdr", setup_elfcorehdr), as it is already currently
the case.

We use address and size of the ELF core header to reserve the header
memory in setup.c (see patch #8):

+#ifdef CONFIG_CRASH_DUMP
+       if (is_kdump_kernel())
+               reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+                               PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif

Does that answer your question?

Michael



From vgoyal at redhat.com  Thu Aug 18 13:15:41 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 18 Aug 2011 13:15:41 -0400
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110812134907.166585439@linux.vnet.ibm.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
Message-ID: <20110818171541.GC15413@redhat.com>

On Fri, Aug 12, 2011 at 03:48:51PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> On s390 we do not create page tables at all for the crashkernel memory.
> This requires a s390 specific version for kimage_load_crash_segment().
> Therefore this patch declares this function as "__weak". The s390 version is
> very simple. It just copies the kexec segment to real memory without using
> page tables:
> 
> int kimage_load_crash_segment(struct kimage *image,
>                               struct kexec_segment *segment)
> {
>         return copy_from_user_real((void *) segment->mem, segment->buf,
>                                    segment->bufsz);
> }
> 
> There are two main advantages of not creating page tables for the
> crashkernel memory:
> 
> a) It saves memory. We have scenarios in mind, where crashkernel
>    memory can be very large and saving page table space is important.
> b) We protect the crashkernel memory from being overwritten.

Michael,

Thinking more about it. Can't we provide a arch specific version of
kmap() and kunmap() so that we create temporary mappings to copy
the pages and then these are torn off. That way you don't waste space
as well you don't have the risk of overwritting the loaded kernel.

Exporting the knowledge of generic kexec segments to arch code sounds
like little odd choice.

Thanks
Vivek


From vgoyal at redhat.com  Thu Aug 18 13:28:15 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 18 Aug 2011 13:28:15 -0400
Subject: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <1313657279.3528.6.camel@br98xy6r>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.325789470@linux.vnet.ibm.com>
	<20110817210554.GD14813@redhat.com>
	<1313657279.3528.6.camel@br98xy6r>
Message-ID: <20110818172815.GD15413@redhat.com>

On Thu, Aug 18, 2011 at 10:47:59AM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Wed, 2011-08-17 at 17:05 -0400, Vivek Goyal wrote:
> > On Fri, Aug 12, 2011 at 03:48:52PM +0200, Michael Holzheu wrote:
> > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > 
> > > Currently only the address of the pre-allocated ELF header is passed with
> > > the elfcorehdr= kernel parameter. In order to reserve memory for the header
> > > in the 2nd kernel also the size is required. Current kdump architecture
> > > backends use different methods to do that, e.g. x86 uses the memmap= kernel
> > > parameter. On s390 there is no easy way to transfer this information.
> > > Therefore the elfcorehdr kernel parameter is extended to also pass the size.
> > > This now can also be used as standard mechanism by all future kdump
> > > architecture backends.
> > 
> > Michael,
> > 
> > This version looks much better. A quick question. Who parses this
> > elfcorehdr= parameter in s390 and how do we make sure these headers are not
> > overwritten.
> 
> The parameter is parsed in common code (kernel/crash_dump.c) in
> early_param("elfcorehdr", setup_elfcorehdr), as it is already currently
> the case.
> 
> We use address and size of the ELF core header to reserve the header
> memory in setup.c (see patch #8):
> 
> +#ifdef CONFIG_CRASH_DUMP
> +       if (is_kdump_kernel())
> +               reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
> +                               PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
> +#endif
> 
> Does that answer your question?

Yes it does. Thanks.

It brings up few more questions about rest of the memory mangement.

So kdump kernel is loaded in reserved area but does not run from there.
It reloads itself into lower memory areas and swaps the contents of
lower memory with reserved memory? If yes, how does it, kernel or
purgatory?

How does kernel come to know about how much memory is to be swapped
and how do you bound the memory usage of second kernel so that it
does not try to use other memory which has not been swapped into
reserved area.

Thanks
Vivek 


From holzheu at linux.vnet.ibm.com  Thu Aug 18 13:56:46 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Thu, 18 Aug 2011 19:56:46 +0200
Subject: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110818172815.GD15413@redhat.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.325789470@linux.vnet.ibm.com>
	<20110817210554.GD14813@redhat.com> <1313657279.3528.6.camel@br98xy6r>
	<20110818172815.GD15413@redhat.com>
Message-ID: <1313690206.3528.32.camel@br98xy6r>

Hello Vivek,

On Thu, 2011-08-18 at 13:28 -0400, Vivek Goyal wrote:
> > The parameter is parsed in common code (kernel/crash_dump.c) in
> > early_param("elfcorehdr", setup_elfcorehdr), as it is already currently
> > the case.
> > 
> > We use address and size of the ELF core header to reserve the header
> > memory in setup.c (see patch #8):
> > 
> > +#ifdef CONFIG_CRASH_DUMP
> > +       if (is_kdump_kernel())
> > +               reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
> > +                               PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
> > +#endif
> > 
> > Does that answer your question?
> 
> Yes it does. Thanks.
> 
> It brings up few more questions about rest of the memory mangement.
> 
> So kdump kernel is loaded in reserved area but does not run from there.
> It reloads itself into lower memory areas and swaps the contents of
> lower memory with reserved memory? If yes, how does it, kernel or
> purgatory?

With the v3 patch series purgatory does that (see
purgatory-s390.c/post_verification_setup_arch()):

> How does kernel come to know about how much memory is to be swapped

2nd kernel knows crash_base and crash_base because kexec tools told him
that. We do it like registering the ramdisk. See kexec-image.c:

+               if (info->kexec_flags & KEXEC_ON_CRASH) {
+                       tmp = krnl_buffer + OLDMEM_BASE_OFFS;
+                       *tmp = crash_base;
+
+                       tmp = krnl_buffer + OLDMEM_SIZE_OFFS;
+                       *tmp = crash_end - crash_base + 1;
+               }

> and how do you bound the memory usage of second kernel so that it
> does not try to use other memory which has not been swapped into
> reserved area.

See kernel patches setup.c:

+/*
+ * Make sure that oldmem, where the dump is stored, is protected
+ */
+static void reserve_oldmem(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+       if (!is_kdump_kernel())
+               return;
+
+       reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM);
+       reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE,
+                             CHUNK_OLDMEM);
+       if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size)
+               saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
+       else
+               saved_max_pfn = PFN_DOWN(real_memory_size) - 1;
+#endif
+}

Michael












From oomichi at mxs.nes.nec.co.jp  Thu Aug 18 20:31:09 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 19 Aug 2011 09:31:09 +0900
Subject: [PATCH] makedumpfile: Support line mode terminals
In-Reply-To: <1313414666.9445.3.camel@br98xy6r>
References: <1313414666.9445.3.camel@br98xy6r>
Message-ID: <20110819093109.ed9252ed.oomichi@mxs.nes.nec.co.jp>


Hi Michael,

On Mon, 15 Aug 2011 15:24:26 +0200
Michael Holzheu <holzheu at linux.vnet.ibm.com> wrote:
>
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> On S390 we have line mode terminals that do not have the ability to
> position the cursor. When using kdump the output of makedumpfile will be shown
> on such terminals. Currently the output looks very strange because the '\r'
> control character is ignored. It looks like the following:
> 
>  Checking for memory holes          : [  0 %]  Checking for memory holes        
>   : [100 %]  Copying data                       : [ 33 %]  Copying data         
>               : [ 65 %]  Copying data                       : [ 96 %]  Copying d
> ata                       : [100 %]   
> 
> For those line mode terminals the TERM environment variable is set to "dumb".
> With this patch makedumpfile checks the TERM variable and in case of "dumb"
> instead of using '\r' each progress message is printed into a separate line.
> The output will then look like the following:
> 
> Checking for memory holes          : [  0 %]
> Checking for memory holes          : [100 %]
> Copying data                       : [ 11 %]
> Copying data                       : [ 44 %]
> Copying data                       : [ 75 %]
> Copying data                       : [100 %]
> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>

Thank you for the patch, and it has been merged to devel tree.

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

Acked-by: Ken'ichi Ohmichi <oomichi at mxs.nes.nec.co.jp>


Thanks
Ken'ichi Ohmichi

> ---
>  makedumpfile.c |   22 +++++++++++++++++++---
>  1 file changed, 19 insertions(+), 3 deletions(-)
> 
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -29,6 +29,7 @@ struct DumpInfo		*info = NULL;
>  
>  char filename_stdout[] = FILENAME_STDOUT;
>  int message_level;
> +static int dumb_term;
>  
>  /*
>   * Forward declarations
> @@ -5661,9 +5662,14 @@ print_progress(const char *msg, unsigned
>  		progress = current * 100 / end;
>  	} else
>  		progress = 100;
> -
> -	PROGRESS_MSG("\r");
> -	PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3d %%] ", msg, progress);
> +	if (dumb_term) {
> +		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3d %%]\n",
> +			     msg, progress);
> +	} else {
> +		PROGRESS_MSG("\r");
> +		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3d %%] ",
> +			     msg, progress);
> +	}
>  }
>  
>  unsigned long long
> @@ -7825,11 +7831,21 @@ static struct option longopts[] = {
>  	{0, 0, 0, 0}
>  };
>  
> +static void setup_term(void)
> +{
> +	char *term_str = getenv("TERM");
> +
> +	if (term_str && strcmp(term_str, "dumb") == 0)
> +		dumb_term = 1;
> +}
> +
>  int
>  main(int argc, char *argv[])
>  {
>  	int i, opt, flag_debug = FALSE;
>  
> +	setup_term();
> +
>  	if ((info = calloc(1, sizeof(struct DumpInfo))) == NULL) {
>  		ERRMSG("Can't allocate memory for the pagedesc cache. %s.\n",
>  		    strerror(errno));
> 
> 


From nathanm2 at us.ibm.com  Thu Aug 18 18:21:30 2011
From: nathanm2 at us.ibm.com (Nathan D Miller)
Date: Thu, 18 Aug 2011 17:21:30 -0500
Subject: Bootloaders with early kdump support?
Message-ID: <OF087F73E2.5ECF6BE5-ON862578F0.0079BA5A-862578F0.007AD1A0@us.ibm.com>


Greetings-

Vivek made the following statement a few months ago:

> On a side note, few months back there were folks who were trying
> to enhance bootloaders to be able to prepare basic environment so
> that a kdump kernel can boot even in the event of early first
> kernel boot.

Any idea which bootloaders?  Which folks?

I'm curious how one would go about implementing such a thing.  What
parameters would the bootloader need to supply to the kernel?

Thanks,
Nate
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110818/ae44d025/attachment.html>

From horms at verge.net.au  Thu Aug 18 21:14:32 2011
From: horms at verge.net.au (Simon Horman)
Date: Fri, 19 Aug 2011 10:14:32 +0900
Subject: [patch 0/3] kdump: Add external kdump entry point for s390
	stand-alone dump tools
In-Reply-To: <20110729123944.562622201@linux.vnet.ibm.com>
References: <20110729123944.562622201@linux.vnet.ibm.com>
Message-ID: <20110819011431.GB20747@verge.net.au>

On Fri, Jul 29, 2011 at 02:39:44PM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> I finished the patches that add the stand-alone dump tools support on
> top of the recently sent v2 patch series. The following three patches
> implement the program check idea that we have discussed recently:
> 
> [1] kdump: Add new machine_kexec_finish() architecture callback
> [2] s390: Add external kdump entry point for s390 stand-alone dump tools
> [3] kexec-tools: Emit program check on s390 for checksum failure

Hi Michael,

in general I am fine with these patches and happy to merge them
although I am a little unclear about the status of the kernel side of
things. Please let me know if you would like me to merge the kexec-tools
patches now or wait a bit (for an updated version?).

Also, if you could give me any pointers on how to obtain an s390
cross-compiling environment for x86_64 I would be most grateful.


From oomichi at mxs.nes.nec.co.jp  Fri Aug 19 01:39:30 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 19 Aug 2011 14:39:30 +0900
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in
	compressed kdump file
In-Reply-To: <4E4CC9D4.7040306@linux.vnet.ibm.com>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
	<20110812171013.7545b3df.oomichi@mxs.nes.nec.co.jp>
	<4E4CC9D4.7040306@linux.vnet.ibm.com>
Message-ID: <20110819143930.b025fb1d.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

On Thu, 18 Aug 2011 13:44:12 +0530
Mahesh Jagannath Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >> --- a/makedumpfile.c
> >> +++ b/makedumpfile.c
> >> @@ -29,6 +29,8 @@ struct DumpInfo		*info = NULL;
> >>  struct module_sym_table	mod_st = { 0 };
> >>  struct filter_info	*filter_info = NULL;
> >>  struct filter_config	filter_config;
> >> +struct erase_info	*erase_info = NULL;
> >> +unsigned long		num_erase_info = 1; /* Node 0 is unused. */
> > 
> > I cannot understand erase_info[0] is unused.
> 
> I did this to avoid the explicit need of initializing erase_info_idx
> member from struct config_entry and struct filter_info with some other
> invalid value, instead I thought I will use '0' as invalid index.

Thank you for the explanation. I can understand your thought.
I think current code is right and we don't need to change the code.
Sorry about my noise.


> >> @@ -6000,10 +6007,17 @@ write_kdump_header(void)
> >>  			kh.size_vmcoreinfo = info->size_vmcoreinfo;
> >>  		}
> >>  	}
> >> -	if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
> >> -	    size, info->name_dumpfile))
> >> -		goto out;
> >> +	/*
> >> +	 * While writing dump data to STDOUT, delay the writing of sub header
> >> +	 * untill we gather erase info offset and size.
> >> +	 */
> >> +	if (!info->flag_flatten) {
> >> +		if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
> >> +		    size, info->name_dumpfile))
> >> +			goto out;
> >> +	}
> > 
> > Does makedumpfile work wrong if removing the above change ?
> > 
> 
> Hmm.. while implementing this patch I thought we may run into issues if
> we write sub_header data twice for flattened case. But it seems the '-R'
> option rearranges the data properly.
> 
> I agree that we dont need above change. Thanks for catching this.

OK, I will revert the above change.


Thanks
Ken'ichi Ohmichi


From oomichi at mxs.nes.nec.co.jp  Fri Aug 19 02:16:59 2011
From: oomichi at mxs.nes.nec.co.jp (Ken'ichi Ohmichi)
Date: Fri, 19 Aug 2011 15:16:59 +0900
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in
	compressed kdump file
In-Reply-To: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
Message-ID: <20110819151659.6cfd324b.oomichi@mxs.nes.nec.co.jp>


Hi Mahesh,

Sorry about many responses of this patch.

On Wed, 18 May 2011 01:36:17 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>
> From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> 
> Include the erase information in the makedumpfile generated dumpfile. The
> erased information contains only effective lines from the filter
> configuration file. This patch supports inclusion of erase information in
> kdump compressed, flatten and split dumpfiles. On re-filtering, the erase
> information from input dumpfile (if any) will be carried over to resulting
> dumpfile.
> 
> This patch introduces new members offset_eraseinfo, size_eraseinfo into the
> sub header in compressed kdump file.
> 
> 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

While testing this feature, I noticed the description format of
makedumpfile.conf is different from the one of eraseinfo.
The former contains "size", but the later does not.

I feel the same format will be useful.
Are there any reasons of different formats ?


Thanks
Ken'ichi Ohmichi


From holzheu at linux.vnet.ibm.com  Fri Aug 19 08:53:20 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 14:53:20 +0200
Subject: [patch 0/3] kdump: Add external kdump entry point for s390
	stand-alone dump tools
In-Reply-To: <20110819011431.GB20747@verge.net.au>
References: <20110729123944.562622201@linux.vnet.ibm.com>
	<20110819011431.GB20747@verge.net.au>
Message-ID: <1313758400.3858.12.camel@br98xy6r>

Hello Simon,

On Fri, 2011-08-19 at 10:14 +0900, Simon Horman wrote:
> On Fri, Jul 29, 2011 at 02:39:44PM +0200, Michael Holzheu wrote:
> > Hello Vivek,
> > 
> > I finished the patches that add the stand-alone dump tools support on
> > top of the recently sent v2 patch series. The following three patches
> > implement the program check idea that we have discussed recently:
> > 
> > [1] kdump: Add new machine_kexec_finish() architecture callback
> > [2] s390: Add external kdump entry point for s390 stand-alone dump tools
> > [3] kexec-tools: Emit program check on s390 for checksum failure
> 
> Hi Michael,
> 
> in general I am fine with these patches and happy to merge them

That's good news.

> although I am a little unclear about the status of the kernel side of
> things. Please let me know if you would like me to merge the kexec-tools
> patches now or wait a bit (for an updated version?).

I think that we are almost done with the discussion. I will send you my
current kexec-tools patches and would be glad, if you could integrate
them now.


From adrian.wenl at gmail.com  Fri Aug 19 09:07:36 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 19 Aug 2011 21:07:36 +0800
Subject: Bootloaders with early kdump support?
In-Reply-To: <OF087F73E2.5ECF6BE5-ON862578F0.0079BA5A-862578F0.007AD1A0@us.ibm.com>
References: <OF087F73E2.5ECF6BE5-ON862578F0.0079BA5A-862578F0.007AD1A0@us.ibm.com>
Message-ID: <CALZhoSSnHcfuTaKv6FCrONhh5DXtfO+JV6hOQzWfKhYG5WYeDg@mail.gmail.com>

Hi Nathan,

On Fri, Aug 19, 2011 at 6:21 AM, Nathan D Miller <nathanm2 at us.ibm.com> wrote:
> Greetings-
>
> Vivek made the following statement a few months ago:
>
>> On a side note, few months back there were folks who were trying
>> to enhance bootloaders to be able to prepare basic environment so
>> that a kdump kernel can boot even in the event of early first
>> kernel boot.
>
> Any idea which bootloaders? ?Which folks?
>
> I'm curious how one would go about implementing such a thing. ?What
> parameters would the bootloader need to supply to the kernel?

Actually I ask a similar question for it, but sightly different at
that I try to trigger
the dump kernel at the moment the first kernel unable to trigger. Core hang, or
very bad dead lock all could lead to this...

I recently make some patches to both the kernel and kexec tools side, and basic
idea is:
1) Move copy kernel relocation code to the stage of
machine_kexec_prepare() from original
in machine_kexec()
2) Provide a new supported flags for kexec_load api to support
crash_update method. In this
method,  I would call crash_setup_regs(), crash_save_vmcoreinfo() and
machine_crash_update().
3) Add patch to kexec to support the new supported flags. This new
made method could be called
as a daemon in the kernel, and the info pass to the crash kernel could
be gotten updated to
the point of dead lock.
4) After kernel meet core hang, we reset the board and while enter the
uboot, we let the uboot to
directly transfer the control to the crash kernel. Since crash kernel
is already loaded, and reloaction
code and parameter all has been set up. There is no more effort for
the bootloader, just transferring
control would do the all good.

Best regards,
Lei


From holzheu at linux.vnet.ibm.com  Fri Aug 19 09:09:49 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 15:09:49 +0200
Subject: [patch 0/2] s390: Patch series for s390 kdump support
Message-ID: <20110819130949.289522258@linux.vnet.ibm.com>

Hello Simon,

The following two patches add s390 kdump support (64 bit only) to the
kexec-tools:
[0] Add s390 kdump support
[1] Allow to call verify_sha256_digest() from kernel

Thanks!

Michael


From holzheu at linux.vnet.ibm.com  Fri Aug 19 09:09:51 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 15:09:51 +0200
Subject: [patch 2/2] kexec-tools: Allow to call verify_sha256_digest() from
	kernel
References: <20110819130949.289522258@linux.vnet.ibm.com>
Message-ID: <20110819131212.181608175@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: kexec-tools-s390-kdump-entry.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110819/0247f7e4/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 19 09:09:50 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 15:09:50 +0200
Subject: [patch 1/2] kexec-tools: Add s390 kdump support
References: <20110819130949.289522258@linux.vnet.ibm.com>
Message-ID: <20110819131211.988753361@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: kexec-tools-s390-kdump.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110819/161e6004/attachment.ksh>

From vgoyal at redhat.com  Fri Aug 19 09:20:19 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 19 Aug 2011 09:20:19 -0400
Subject: [patch 0/3] kdump: Add external kdump entry point for s390
	stand-alone dump tools
In-Reply-To: <1313758400.3858.12.camel@br98xy6r>
References: <20110729123944.562622201@linux.vnet.ibm.com>
	<20110819011431.GB20747@verge.net.au>
	<1313758400.3858.12.camel@br98xy6r>
Message-ID: <20110819132019.GA18656@redhat.com>

On Fri, Aug 19, 2011 at 02:53:20PM +0200, Michael Holzheu wrote:

[...]
> > although I am a little unclear about the status of the kernel side of
> > things. Please let me know if you would like me to merge the kexec-tools
> > patches now or wait a bit (for an updated version?).
> 
> I think that we are almost done with the discussion. I will send you my
> current kexec-tools patches and would be glad, if you could integrate
> them now.

I guess kexec-tools integration will make more sense once kernel patches
show up atleast in one maintainer's subtree.

Also in kernel patches, atleast we need to resolve the issue of arch
specific kmap(), kunmap() calls so that we don't have to make
kimage_load_crash_segment() arch specific.

Thanks
Vivek


From holzheu at linux.vnet.ibm.com  Fri Aug 19 09:27:52 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 15:27:52 +0200
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110818171541.GC15413@redhat.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
	<20110818171541.GC15413@redhat.com>
Message-ID: <1313760472.3858.26.camel@br98xy6r>

Hello Vivek,

On Thu, 2011-08-18 at 13:15 -0400, Vivek Goyal wrote:
> On Fri, Aug 12, 2011 at 03:48:51PM +0200, Michael Holzheu wrote:
> > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > 
> > On s390 we do not create page tables at all for the crashkernel memory.
> > This requires a s390 specific version for kimage_load_crash_segment().
> > Therefore this patch declares this function as "__weak". The s390 version is
> > very simple. It just copies the kexec segment to real memory without using
> > page tables:
> > 
> > int kimage_load_crash_segment(struct kimage *image,
> >                               struct kexec_segment *segment)
> > {
> >         return copy_from_user_real((void *) segment->mem, segment->buf,
> >                                    segment->bufsz);
> > }
> > 
> > There are two main advantages of not creating page tables for the
> > crashkernel memory:
> > 
> > a) It saves memory. We have scenarios in mind, where crashkernel
> >    memory can be very large and saving page table space is important.
> > b) We protect the crashkernel memory from being overwritten.
> 
> Michael,
> 
> Thinking more about it. Can't we provide a arch specific version of
> kmap() and kunmap() so that we create temporary mappings to copy
> the pages and then these are torn off.

Isn't kmap/kunmap() used for higmem? These functions are called from
many different functions in the Linux kernel, not only for kdump. I
would assume that creating and removing mappings with these functions is
not what a caller would expect and probably would break the Linux kernel
at many other places, no?

Perhaps we can finish this discussion after my vacation. I will change
my patch series that we even do not need this patch...

So only two common code patches are remaining. I will send the common
code patches again and will ask Andrew Morton to integrate them in the
next merge window. The s390 patches will be integrated by Martin.

Michael



From holzheu at linux.vnet.ibm.com  Fri Aug 19 09:36:38 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 15:36:38 +0200
Subject: [patch 0/3] kdump: Add external kdump entry point for s390
	stand-alone dump tools
In-Reply-To: <20110819132019.GA18656@redhat.com>
References: <20110729123944.562622201@linux.vnet.ibm.com>
	<20110819011431.GB20747@verge.net.au>
	<1313758400.3858.12.camel@br98xy6r>
	<20110819132019.GA18656@redhat.com>
Message-ID: <1313760998.3858.32.camel@br98xy6r>

Hello Vivek,

On Fri, 2011-08-19 at 09:20 -0400, Vivek Goyal wrote:
> On Fri, Aug 19, 2011 at 02:53:20PM +0200, Michael Holzheu wrote:
> 
> [...]
> > > although I am a little unclear about the status of the kernel side of
> > > things. Please let me know if you would like me to merge the kexec-tools
> > > patches now or wait a bit (for an updated version?).
> > 
> > I think that we are almost done with the discussion. I will send you my
> > current kexec-tools patches and would be glad, if you could integrate
> > them now.
> 
> I guess kexec-tools integration will make more sense once kernel patches
> show up atleast in one maintainer's subtree.

The s390 kexec-tools kdump code will inactive as long a kernel shows
"Crash kernel" in /proc/iomem. So IMHO there is little risk to integrate
the code.

> Also in kernel patches, atleast we need to resolve the issue of arch
> specific kmap(), kunmap() calls so that we don't have to make
> kimage_load_crash_segment() arch specific.

As I told in my last mail we will do this later. So I think there are
currently no more open issues, correct?

Michael




From vgoyal at redhat.com  Fri Aug 19 09:48:36 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 19 Aug 2011 09:48:36 -0400
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <1313760472.3858.26.camel@br98xy6r>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
	<20110818171541.GC15413@redhat.com>
	<1313760472.3858.26.camel@br98xy6r>
Message-ID: <20110819134836.GB18656@redhat.com>

On Fri, Aug 19, 2011 at 03:27:52PM +0200, Michael Holzheu wrote:
> Hello Vivek,
> 
> On Thu, 2011-08-18 at 13:15 -0400, Vivek Goyal wrote:
> > On Fri, Aug 12, 2011 at 03:48:51PM +0200, Michael Holzheu wrote:
> > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > 
> > > On s390 we do not create page tables at all for the crashkernel memory.
> > > This requires a s390 specific version for kimage_load_crash_segment().
> > > Therefore this patch declares this function as "__weak". The s390 version is
> > > very simple. It just copies the kexec segment to real memory without using
> > > page tables:
> > > 
> > > int kimage_load_crash_segment(struct kimage *image,
> > >                               struct kexec_segment *segment)
> > > {
> > >         return copy_from_user_real((void *) segment->mem, segment->buf,
> > >                                    segment->bufsz);
> > > }
> > > 
> > > There are two main advantages of not creating page tables for the
> > > crashkernel memory:
> > > 
> > > a) It saves memory. We have scenarios in mind, where crashkernel
> > >    memory can be very large and saving page table space is important.
> > > b) We protect the crashkernel memory from being overwritten.
> > 
> > Michael,
> > 
> > Thinking more about it. Can't we provide a arch specific version of
> > kmap() and kunmap() so that we create temporary mappings to copy
> > the pages and then these are torn off.
> 
> Isn't kmap/kunmap() used for higmem? These functions are called from
> many different functions in the Linux kernel, not only for kdump. I
> would assume that creating and removing mappings with these functions is
> not what a caller would expect and probably would break the Linux kernel
> at many other places, no?

[CCing linux-mm]

Yes it is being used for highmem pages. If arch has not defined kmap()
then generic definition is just returning page_address(page), expecting
that page will be mapped.

I was wondering that what will be broken if arch decides to extend this
to create temporary mappings for pages which are not HIGHMEM but do
not have any mapping. (Like this special case of s390).

I guess memory management guys can give a better answer here. As a layman,
kmap() seems to be the way to get a kernel mapping for any page frame
and if one is not already there, then arch might create one on the fly,
like we do for HIGHMEM pages. So the question is can be extend this
to also cover pages which are not highmem but do not have any mappings
on s390.

> 
> Perhaps we can finish this discussion after my vacation. I will change
> my patch series that we even do not need this patch...

So how are you planning to get rid of this patch without modifying kmap(),
kunmap() implementation for s390?

> 
> So only two common code patches are remaining. I will send the common
> code patches again and will ask Andrew Morton to integrate them in the
> next merge window.The s390 patches will be integrated by Martin.

I am fine with merge of other 2 common patches. Once you repost the
series, I will ack those.

Thanks
Vivek


From holzheu at linux.vnet.ibm.com  Fri Aug 19 10:02:34 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 16:02:34 +0200
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110819134836.GB18656@redhat.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
	<20110818171541.GC15413@redhat.com> <1313760472.3858.26.camel@br98xy6r>
	<20110819134836.GB18656@redhat.com>
Message-ID: <1313762554.3858.37.camel@br98xy6r>

Hello Vivek,

On Fri, 2011-08-19 at 09:48 -0400, Vivek Goyal wrote:

[snip]

> > > Michael,
> > > 
> > > Thinking more about it. Can't we provide a arch specific version of
> > > kmap() and kunmap() so that we create temporary mappings to copy
> > > the pages and then these are torn off.
> > 
> > Isn't kmap/kunmap() used for higmem? These functions are called from
> > many different functions in the Linux kernel, not only for kdump. I
> > would assume that creating and removing mappings with these functions is
> > not what a caller would expect and probably would break the Linux kernel
> > at many other places, no?
> 
> [CCing linux-mm]
> 
> Yes it is being used for highmem pages. If arch has not defined kmap()
> then generic definition is just returning page_address(page), expecting
> that page will be mapped.
> 
> I was wondering that what will be broken if arch decides to extend this
> to create temporary mappings for pages which are not HIGHMEM but do
> not have any mapping. (Like this special case of s390).

At least we have significant additional overhead for all the other
places where kmap/kunmap is called.

> I guess memory management guys can give a better answer here. As a layman,
> kmap() seems to be the way to get a kernel mapping for any page frame
> and if one is not already there, then arch might create one on the fly,
> like we do for HIGHMEM pages. So the question is can be extend this
> to also cover pages which are not highmem but do not have any mappings
> on s390.
> 
> > 
> > Perhaps we can finish this discussion after my vacation. I will change
> > my patch series that we even do not need this patch...
> 
> So how are you planning to get rid of this patch without modifying kmap(),
> kunmap() implementation for s390?

I will update my patch series that we do not remove page tables for
crashkernel memory. So everything will be as on other architectures.

I hope that we can find a good solution after my vacation. Perhaps then
I have enough energy again :-)

> > So only two common code patches are remaining. I will send the common
> > code patches again and will ask Andrew Morton to integrate them in the
> > next merge window.The s390 patches will be integrated by Martin.
> 
> I am fine with merge of other 2 common patches. Once you repost the
> series, I will ack those.

Great! I will resend the patches and contact Andrew Morton.

Thanks!

Michael



From holzheu at linux.vnet.ibm.com  Fri Aug 19 10:18:57 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 16:18:57 +0200
Subject: [patch 0/2] kdump: Common code changes for s390 kdump support
Message-ID: <20110819141857.052232873@linux.vnet.ibm.com>

Hello Andrew,

I had a long discussion with Vivek Goyal on the s390 kdump support (thanks
Vivek for all the time!). As a result of this, here are two common code
patches that are required for the s390 port. Could you please integrate them
upstream in the next merge window? The s390 specific part will be integrated
by our s390 maintainer Martin Schwidefsky.

I will be on vacation for the next two weeks. Therefore if you have comments
or questions, please contact also Martin Schwidefsky and Heiko Carstens.

Thanks

   Michael


From holzheu at linux.vnet.ibm.com  Fri Aug 19 10:18:59 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 16:18:59 +0200
Subject: [patch 2/2] kdump: Add size to elfcorehdr kernel parameter
References: <20110819141857.052232873@linux.vnet.ibm.com>
Message-ID: <20110819141940.335341157@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-common-elfcorehdr-parm.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110819/13b9fc4a/attachment.ksh>

From holzheu at linux.vnet.ibm.com  Fri Aug 19 10:18:58 2011
From: holzheu at linux.vnet.ibm.com (Michael Holzheu)
Date: Fri, 19 Aug 2011 16:18:58 +0200
Subject: [patch 1/2] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
References: <20110819141857.052232873@linux.vnet.ibm.com>
Message-ID: <20110819141940.177788593@linux.vnet.ibm.com>

An embedded and charset-unspecified text was scrubbed...
Name: s390-kdump-common-control-limit.patch
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110819/3154ca2b/attachment.ksh>

From vgoyal at redhat.com  Fri Aug 19 10:24:03 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 19 Aug 2011 10:24:03 -0400
Subject: [patch 1/2] kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT
In-Reply-To: <20110819141940.177788593@linux.vnet.ibm.com>
References: <20110819141857.052232873@linux.vnet.ibm.com>
	<20110819141940.177788593@linux.vnet.ibm.com>
Message-ID: <20110819142403.GF18656@redhat.com>

On Fri, Aug 19, 2011 at 04:18:58PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> On s390 there is a different KEXEC_CONTROL_MEMORY_LIMIT for the normal and
> the kdump kexec case. Therefore this patch introduces a new macro
> KEXEC_CRASH_CONTROL_MEMORY_LIMIT. This is set to
> KEXEC_CONTROL_MEMORY_LIMIT for all architectures that do not define
> KEXEC_CRASH_CONTROL_MEMORY_LIMIT.
> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>

Looks good to me. 

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

Vivek

> ---
>  include/linux/kexec.h |    4 ++++
>  kernel/kexec.c        |    2 +-
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -33,6 +33,10 @@
>  #error KEXEC_ARCH not defined
>  #endif
>  
> +#ifndef KEXEC_CRASH_CONTROL_MEMORY_LIMIT
> +#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT KEXEC_CONTROL_MEMORY_LIMIT
> +#endif
> +
>  #define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
>  #define KEXEC_CORE_NOTE_NAME "CORE"
>  #define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -498,7 +498,7 @@ static struct page *kimage_alloc_crash_c
>  	while (hole_end <= crashk_res.end) {
>  		unsigned long i;
>  
> -		if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT)
> +		if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT)
>  			break;
>  		if (hole_end > crashk_res.end)
>  			break;


From vgoyal at redhat.com  Fri Aug 19 10:25:02 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 19 Aug 2011 10:25:02 -0400
Subject: [patch 2/2] kdump: Add size to elfcorehdr kernel parameter
In-Reply-To: <20110819141940.335341157@linux.vnet.ibm.com>
References: <20110819141857.052232873@linux.vnet.ibm.com>
	<20110819141940.335341157@linux.vnet.ibm.com>
Message-ID: <20110819142502.GG18656@redhat.com>

On Fri, Aug 19, 2011 at 04:18:59PM +0200, Michael Holzheu wrote:
> From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> 
> Currently only the address of the pre-allocated ELF header is passed with
> the elfcorehdr= kernel parameter. In order to reserve memory for the header
> in the 2nd kernel also the size is required. Current kdump architecture
> backends use different methods to do that, e.g. x86 uses the memmap= kernel
> parameter. On s390 there is no easy way to transfer this information.
> Therefore the elfcorehdr kernel parameter is extended to also pass the size.
> This now can also be used as standard mechanism by all future kdump
> architecture backends.
> 
> The syntax of the kernel parameter is extended as follows:
> 
> elfcorehdr=[size[KMG]@]offset[KMG]
> 
> This change is backward compatible because elfcorehdr=size is still allowed.
> 
> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>

Looks good to me.

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

Vivek

> ---
>  Documentation/kernel-parameters.txt |    6 +++---
>  include/linux/crash_dump.h          |    1 +
>  kernel/crash_dump.c                 |   11 +++++++++++
>  3 files changed, 15 insertions(+), 3 deletions(-)
> 
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -727,10 +727,10 @@ bytes respectively. Such letter suffixes
>  			See Documentation/block/as-iosched.txt and
>  			Documentation/block/deadline-iosched.txt for details.
>  
> -	elfcorehdr=	[IA-64,PPC,SH,X86]
> +	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
>  			Specifies physical address of start of kernel core
> -			image elf header. Generally kexec loader will
> -			pass this option to capture kernel.
> +			image elf header and optionally the size. Generally
> +			kexec loader will pass this option to capture kernel.
>  			See Documentation/kdump/kdump.txt for details.
>  
>  	enable_mtrr_cleanup [X86]
> --- a/include/linux/crash_dump.h
> +++ b/include/linux/crash_dump.h
> @@ -10,6 +10,7 @@
>  #define ELFCORE_ADDR_ERR	(-2ULL)
>  
>  extern unsigned long long elfcorehdr_addr;
> +extern unsigned long long elfcorehdr_size;
>  
>  extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
>  						unsigned long, int);
> --- a/kernel/crash_dump.c
> +++ b/kernel/crash_dump.c
> @@ -20,8 +20,15 @@ unsigned long saved_max_pfn;
>  unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
>  
>  /*
> + * stores the size of elf header of crash image
> + */
> +unsigned long long elfcorehdr_size;
> +
> +/*
>   * elfcorehdr= specifies the location of elf core header stored by the crashed
>   * kernel. This option will be passed by kexec loader to the capture kernel.
> + *
> + * Syntax: elfcorehdr=[size[KMG]@]offset[KMG]
>   */
>  static int __init setup_elfcorehdr(char *arg)
>  {
> @@ -29,6 +36,10 @@ static int __init setup_elfcorehdr(char
>  	if (!arg)
>  		return -EINVAL;
>  	elfcorehdr_addr = memparse(arg, &end);
> +	if (*end == '@') {
> +		elfcorehdr_size = elfcorehdr_addr;
> +		elfcorehdr_addr = memparse(end + 1, &end);
> +	}
>  	return end > arg ? 0 : -EINVAL;
>  }
>  early_param("elfcorehdr", setup_elfcorehdr);


From schwidefsky at de.ibm.com  Fri Aug 19 10:28:54 2011
From: schwidefsky at de.ibm.com (Martin Schwidefsky)
Date: Fri, 19 Aug 2011 16:28:54 +0200
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110819134836.GB18656@redhat.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
	<20110818171541.GC15413@redhat.com>
	<1313760472.3858.26.camel@br98xy6r>
	<20110819134836.GB18656@redhat.com>
Message-ID: <20110819162854.64bd7201@mschwide>

On Fri, 19 Aug 2011 09:48:36 -0400
Vivek Goyal <vgoyal at redhat.com> wrote:

> On Fri, Aug 19, 2011 at 03:27:52PM +0200, Michael Holzheu wrote:
> > Hello Vivek,
> > 
> > On Thu, 2011-08-18 at 13:15 -0400, Vivek Goyal wrote:
> > > On Fri, Aug 12, 2011 at 03:48:51PM +0200, Michael Holzheu wrote:
> > > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > > 
> > > > On s390 we do not create page tables at all for the crashkernel memory.
> > > > This requires a s390 specific version for kimage_load_crash_segment().
> > > > Therefore this patch declares this function as "__weak". The s390 version is
> > > > very simple. It just copies the kexec segment to real memory without using
> > > > page tables:
> > > > 
> > > > int kimage_load_crash_segment(struct kimage *image,
> > > >                               struct kexec_segment *segment)
> > > > {
> > > >         return copy_from_user_real((void *) segment->mem, segment->buf,
> > > >                                    segment->bufsz);
> > > > }
> > > > 
> > > > There are two main advantages of not creating page tables for the
> > > > crashkernel memory:
> > > > 
> > > > a) It saves memory. We have scenarios in mind, where crashkernel
> > > >    memory can be very large and saving page table space is important.
> > > > b) We protect the crashkernel memory from being overwritten.
> > > 
> > > Michael,
> > > 
> > > Thinking more about it. Can't we provide a arch specific version of
> > > kmap() and kunmap() so that we create temporary mappings to copy
> > > the pages and then these are torn off.
> > 
> > Isn't kmap/kunmap() used for higmem? These functions are called from
> > many different functions in the Linux kernel, not only for kdump. I
> > would assume that creating and removing mappings with these functions is
> > not what a caller would expect and probably would break the Linux kernel
> > at many other places, no?
> 
> [CCing linux-mm]
> 
> Yes it is being used for highmem pages. If arch has not defined kmap()
> then generic definition is just returning page_address(page), expecting
> that page will be mapped.
> 
> I was wondering that what will be broken if arch decides to extend this
> to create temporary mappings for pages which are not HIGHMEM but do
> not have any mapping. (Like this special case of s390).
> 
> I guess memory management guys can give a better answer here. As a layman,
> kmap() seems to be the way to get a kernel mapping for any page frame
> and if one is not already there, then arch might create one on the fly,
> like we do for HIGHMEM pages. So the question is can be extend this
> to also cover pages which are not highmem but do not have any mappings
> on s390.

Imho it would be wrong to misuse kmap/kunmap to get around a minor problem
with the memory for the crash kernel. These functions are used to provide
accessibility to highmem pages in the kernel address space. The highmem
area is "normal" memory with corresponding struct page elements (the
functions do take a struct page * as argument after all). They are not
usable to map arbitrary page frames.

And we definitely don't want to make the memory management any slower by
defining non-trivial kmap/kunmap functions.

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.



From vgoyal at redhat.com  Fri Aug 19 10:37:48 2011
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 19 Aug 2011 10:37:48 -0400
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110819162854.64bd7201@mschwide>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
	<20110818171541.GC15413@redhat.com>
	<1313760472.3858.26.camel@br98xy6r>
	<20110819134836.GB18656@redhat.com>
	<20110819162854.64bd7201@mschwide>
Message-ID: <20110819143748.GI18656@redhat.com>

On Fri, Aug 19, 2011 at 04:28:54PM +0200, Martin Schwidefsky wrote:
> On Fri, 19 Aug 2011 09:48:36 -0400
> Vivek Goyal <vgoyal at redhat.com> wrote:
> 
> > On Fri, Aug 19, 2011 at 03:27:52PM +0200, Michael Holzheu wrote:
> > > Hello Vivek,
> > > 
> > > On Thu, 2011-08-18 at 13:15 -0400, Vivek Goyal wrote:
> > > > On Fri, Aug 12, 2011 at 03:48:51PM +0200, Michael Holzheu wrote:
> > > > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > > > 
> > > > > On s390 we do not create page tables at all for the crashkernel memory.
> > > > > This requires a s390 specific version for kimage_load_crash_segment().
> > > > > Therefore this patch declares this function as "__weak". The s390 version is
> > > > > very simple. It just copies the kexec segment to real memory without using
> > > > > page tables:
> > > > > 
> > > > > int kimage_load_crash_segment(struct kimage *image,
> > > > >                               struct kexec_segment *segment)
> > > > > {
> > > > >         return copy_from_user_real((void *) segment->mem, segment->buf,
> > > > >                                    segment->bufsz);
> > > > > }
> > > > > 
> > > > > There are two main advantages of not creating page tables for the
> > > > > crashkernel memory:
> > > > > 
> > > > > a) It saves memory. We have scenarios in mind, where crashkernel
> > > > >    memory can be very large and saving page table space is important.
> > > > > b) We protect the crashkernel memory from being overwritten.
> > > > 
> > > > Michael,
> > > > 
> > > > Thinking more about it. Can't we provide a arch specific version of
> > > > kmap() and kunmap() so that we create temporary mappings to copy
> > > > the pages and then these are torn off.
> > > 
> > > Isn't kmap/kunmap() used for higmem? These functions are called from
> > > many different functions in the Linux kernel, not only for kdump. I
> > > would assume that creating and removing mappings with these functions is
> > > not what a caller would expect and probably would break the Linux kernel
> > > at many other places, no?
> > 
> > [CCing linux-mm]
> > 
> > Yes it is being used for highmem pages. If arch has not defined kmap()
> > then generic definition is just returning page_address(page), expecting
> > that page will be mapped.
> > 
> > I was wondering that what will be broken if arch decides to extend this
> > to create temporary mappings for pages which are not HIGHMEM but do
> > not have any mapping. (Like this special case of s390).
> > 
> > I guess memory management guys can give a better answer here. As a layman,
> > kmap() seems to be the way to get a kernel mapping for any page frame
> > and if one is not already there, then arch might create one on the fly,
> > like we do for HIGHMEM pages. So the question is can be extend this
> > to also cover pages which are not highmem but do not have any mappings
> > on s390.
> 
> Imho it would be wrong to misuse kmap/kunmap to get around a minor problem
> with the memory for the crash kernel. These functions are used to provide
> accessibility to highmem pages in the kernel address space. The highmem
> area is "normal" memory with corresponding struct page elements (the
> functions do take a struct page * as argument after all). They are not
> usable to map arbitrary page frames.

Same is the case with crashkernel memory in s390 where these are
normal pages, just that these are not mapped in linearly mapped region.

The only exception to highmem pages is that linearly mapped region is
not big enough in certain arches, so we left them unmapped.

> 
> And we definitely don't want to make the memory management any slower by
> defining non-trivial kmap/kunmap functions.

if we continue to return page_address() and only go into else loop if page
is not mapped, then there should not be any slow down for exisitng cases
where memory is mapped?

Anyway, this was just a thought. I am not too particular about it and
michael has agreed to get rid of code which was removing mappings for
crashkernel area. So for the time we don't need above.

Thanks
Vivek


From schwidefsky at de.ibm.com  Fri Aug 19 10:44:32 2011
From: schwidefsky at de.ibm.com (Martin Schwidefsky)
Date: Fri, 19 Aug 2011 16:44:32 +0200
Subject: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak
In-Reply-To: <20110819143748.GI18656@redhat.com>
References: <20110812134849.748973593@linux.vnet.ibm.com>
	<20110812134907.166585439@linux.vnet.ibm.com>
	<20110818171541.GC15413@redhat.com>
	<1313760472.3858.26.camel@br98xy6r>
	<20110819134836.GB18656@redhat.com>
	<20110819162854.64bd7201@mschwide>
	<20110819143748.GI18656@redhat.com>
Message-ID: <20110819164432.2bda197c@mschwide>

On Fri, 19 Aug 2011 10:37:48 -0400
Vivek Goyal <vgoyal at redhat.com> wrote:

> On Fri, Aug 19, 2011 at 04:28:54PM +0200, Martin Schwidefsky wrote:
> > On Fri, 19 Aug 2011 09:48:36 -0400
> > Vivek Goyal <vgoyal at redhat.com> wrote:
> > 
> > > On Fri, Aug 19, 2011 at 03:27:52PM +0200, Michael Holzheu wrote:
> > > > Hello Vivek,
> > > > 
> > > > On Thu, 2011-08-18 at 13:15 -0400, Vivek Goyal wrote:
> > > > > On Fri, Aug 12, 2011 at 03:48:51PM +0200, Michael Holzheu wrote:
> > > > > > From: Michael Holzheu <holzheu at linux.vnet.ibm.com>
> > > > > > 
> > > > > > On s390 we do not create page tables at all for the crashkernel memory.
> > > > > > This requires a s390 specific version for kimage_load_crash_segment().
> > > > > > Therefore this patch declares this function as "__weak". The s390 version is
> > > > > > very simple. It just copies the kexec segment to real memory without using
> > > > > > page tables:
> > > > > > 
> > > > > > int kimage_load_crash_segment(struct kimage *image,
> > > > > >                               struct kexec_segment *segment)
> > > > > > {
> > > > > >         return copy_from_user_real((void *) segment->mem, segment->buf,
> > > > > >                                    segment->bufsz);
> > > > > > }
> > > > > > 
> > > > > > There are two main advantages of not creating page tables for the
> > > > > > crashkernel memory:
> > > > > > 
> > > > > > a) It saves memory. We have scenarios in mind, where crashkernel
> > > > > >    memory can be very large and saving page table space is important.
> > > > > > b) We protect the crashkernel memory from being overwritten.
> > > > > 
> > > > > Michael,
> > > > > 
> > > > > Thinking more about it. Can't we provide a arch specific version of
> > > > > kmap() and kunmap() so that we create temporary mappings to copy
> > > > > the pages and then these are torn off.
> > > > 
> > > > Isn't kmap/kunmap() used for higmem? These functions are called from
> > > > many different functions in the Linux kernel, not only for kdump. I
> > > > would assume that creating and removing mappings with these functions is
> > > > not what a caller would expect and probably would break the Linux kernel
> > > > at many other places, no?
> > > 
> > > [CCing linux-mm]
> > > 
> > > Yes it is being used for highmem pages. If arch has not defined kmap()
> > > then generic definition is just returning page_address(page), expecting
> > > that page will be mapped.
> > > 
> > > I was wondering that what will be broken if arch decides to extend this
> > > to create temporary mappings for pages which are not HIGHMEM but do
> > > not have any mapping. (Like this special case of s390).
> > > 
> > > I guess memory management guys can give a better answer here. As a layman,
> > > kmap() seems to be the way to get a kernel mapping for any page frame
> > > and if one is not already there, then arch might create one on the fly,
> > > like we do for HIGHMEM pages. So the question is can be extend this
> > > to also cover pages which are not highmem but do not have any mappings
> > > on s390.
> > 
> > Imho it would be wrong to misuse kmap/kunmap to get around a minor problem
> > with the memory for the crash kernel. These functions are used to provide
> > accessibility to highmem pages in the kernel address space. The highmem
> > area is "normal" memory with corresponding struct page elements (the
> > functions do take a struct page * as argument after all). They are not
> > usable to map arbitrary page frames.
> 
> Same is the case with crashkernel memory in s390 where these are
> normal pages, just that these are not mapped in linearly mapped region.
> 
> The only exception to highmem pages is that linearly mapped region is
> not big enough in certain arches, so we left them unmapped.

Well, the crashkernel memory in s390 is addressable without a page table
but is not included in the mem_map array (no struct page). For the highmem
page it is the other way round, the are not addressable without a page table
entry but they are included in mem_map. That makes all the difference, no?
 
> > 
> > And we definitely don't want to make the memory management any slower by
> > defining non-trivial kmap/kunmap functions.
> 
> if we continue to return page_address() and only go into else loop if page
> is not mapped, then there should not be any slow down for exisitng cases
> where memory is mapped?
> 
> Anyway, this was just a thought. I am not too particular about it and
> michael has agreed to get rid of code which was removing mappings for
> crashkernel area. So for the time we don't need above.

Then we can use the standard kimage_load_crash_segment function. But we
should think about adding code that protects the crash kernel memory,
e.g. by making the memory area read-only in the kernel page table. One
reason why we wanted to exclude the crash kernel memory from the memory
that is seen by the Linux kernel is protection from wild stores.

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.



From akpm at linux-foundation.org  Fri Aug 19 18:03:53 2011
From: akpm at linux-foundation.org (Andrew Morton)
Date: Fri, 19 Aug 2011 15:03:53 -0700
Subject: [patch 0/2] kdump: Common code changes for s390 kdump support
In-Reply-To: <20110819141857.052232873@linux.vnet.ibm.com>
References: <20110819141857.052232873@linux.vnet.ibm.com>
Message-ID: <20110819150353.bf58c7e0.akpm@linux-foundation.org>

On Fri, 19 Aug 2011 16:18:57 +0200
Michael Holzheu <holzheu at linux.vnet.ibm.com> wrote:

> I had a long discussion with Vivek Goyal on the s390 kdump support (thanks
> Vivek for all the time!). As a result of this, here are two common code
> patches that are required for the s390 port. Could you please integrate them
> upstream in the next merge window? The s390 specific part will be integrated
> by our s390 maintainer Martin Schwidefsky.

The patches look OK to me.  I suggest that they be carried in Martin's
tree, alongside the s390 kdump support.  That will somewhat simplify
things during the merge window, and will greatly simplify getting the
entire feature into linux-next.

You can put my acked-by's on them if you like.

> I will be on vacation for the next two weeks. Therefore if you have comments
> or questions, please contact also Martin Schwidefsky and Heiko Carstens.

I'll put the patches into my tree (and hence linux-next) now, because I
need the typing practice ;) I'll drop them again if/when they turn up
in linux-next's s390 tree.



From horms at verge.net.au  Sat Aug 20 05:21:57 2011
From: horms at verge.net.au (Simon Horman)
Date: Sat, 20 Aug 2011 18:21:57 +0900
Subject: [patch 0/2] s390: Patch series for s390 kdump support
In-Reply-To: <20110819130949.289522258@linux.vnet.ibm.com>
References: <20110819130949.289522258@linux.vnet.ibm.com>
Message-ID: <20110820092157.GA24619@verge.net.au>

On Fri, Aug 19, 2011 at 03:09:49PM +0200, Michael Holzheu wrote:
> Hello Simon,
> 
> The following two patches add s390 kdump support (64 bit only) to the
> kexec-tools:
> [0] Add s390 kdump support
> [1] Allow to call verify_sha256_digest() from kernel

Thanks, applied.



From dkiper at net-space.pl  Sun Aug 21 09:50:29 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Sun, 21 Aug 2011 15:50:29 +0200
Subject: [PATCH 0/4] kexec-tools: Xen fixes and cleanups
Message-ID: <20110821135029.GA17323@router-fw-old.local.net-space.pl>

Hi,

I am sending some Xen specific fixes and cleanups for kexec-tools.
These patches applies to current kexec-tools git tree.

Full list of fixes and cleanups:
  - xen: Take into account Xen control interface changes since Xen Ver. 4.1,
  - kexec: Export compare_ranges() function from firmware_memmap.c module,
  - kexec/arch/i386: Rename fixup_memory_ranges_sysfs() to fixup_memory_ranges(),
  - kexec/arch/i386: Add get_memory_ranges_xen() function.

Daniel


From dkiper at net-space.pl  Sun Aug 21 09:51:39 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Sun, 21 Aug 2011 15:51:39 +0200
Subject: [PATCH 1/4] xen: Take into account Xen control interface changes
	since Xen Ver. 4.1
Message-ID: <20110821135139.GB17323@router-fw-old.local.net-space.pl>

xc_interface_open() receive three arguments instead of void and returns
pointer to xc_interface type instead of int since Xen Ver. 4.1. Take into
account that and allow kexec-tools compilation with all versions of Xen.

Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
---
 kexec/crashdump-xen.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/kexec/crashdump-xen.c b/kexec/crashdump-xen.c
index b347764..9dfabf8 100644
--- a/kexec/crashdump-xen.c
+++ b/kexec/crashdump-xen.c
@@ -126,19 +126,32 @@ unsigned long xen_architecture(struct crash_elf_info *elf_info)
 {
 	unsigned long machine = elf_info->machine;
 #ifdef HAVE_LIBXENCTRL
-	int xc, rc;
+	int rc;
 	xen_capabilities_info_t capabilities;
+#ifdef XENCTRL_HAS_XC_INTERFACE
+	xc_interface *xc;
+#else
+	int xc;
+#endif
 
 	if (!xen_present())
 		goto out;
 
 	memset(capabilities, '0', XEN_CAPABILITIES_INFO_LEN);
 
+#ifdef XENCTRL_HAS_XC_INTERFACE
+	xc = xc_interface_open(NULL, NULL, 0);
+	if ( !xc ) {
+		fprintf(stderr, "failed to open xen control interface.\n");
+		goto out;
+	}
+#else
 	xc = xc_interface_open();
 	if ( xc == -1 ) {
 		fprintf(stderr, "failed to open xen control interface.\n");
 		goto out;
 	}
+#endif
 
 	rc = xc_version(xc, XENVER_capabilities, &capabilities[0]);
 	if ( rc == -1 ) {
-- 
1.5.6.5


From dkiper at net-space.pl  Sun Aug 21 09:52:42 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Sun, 21 Aug 2011 15:52:42 +0200
Subject: [PATCH 2/4] kexec: Export compare_ranges() function from
	firmware_memmap.c module
Message-ID: <20110821135242.GC17323@router-fw-old.local.net-space.pl>

Export compare_ranges() function from firmware_memmap.c module.
It is generic function and it could be used by other modules.

Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
---
 kexec/firmware_memmap.c |   14 ++------------
 kexec/firmware_memmap.h |   13 +++++++++++++
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/kexec/firmware_memmap.c b/kexec/firmware_memmap.c
index d8afed5..9598933 100644
--- a/kexec/firmware_memmap.c
+++ b/kexec/firmware_memmap.c
@@ -179,18 +179,8 @@ static int parse_memmap_entry(const char *entry, struct memory_range *range)
 	return 0;
 }
 
-/**
- * Compares two memory ranges according to their start address. This function
- * can be used with qsort() as @c compar function.
- *
- * @param[in] first a pointer to the first memory range
- * @param[in] second a pointer to the second memory range
- * @return 0 if @p first and @p second have the same start address,
- *         a value less then 0 if the start address of @p first is less than
- *         the start address of @p second, and a value greater than 0 if
- *         the opposite is in case.
- */
-static int compare_ranges(const void *first, const void *second)
+/* documentation: firmware_memmap.h */
+int compare_ranges(const void *first, const void *second)
 {
 	const struct memory_range *first_range = first;
 	const struct memory_range *second_range = second;
diff --git a/kexec/firmware_memmap.h b/kexec/firmware_memmap.h
index adb03c3..eac0ddb 100644
--- a/kexec/firmware_memmap.h
+++ b/kexec/firmware_memmap.h
@@ -39,6 +39,19 @@
  */
 
 /**
+ * Compares two memory ranges according to their start address. This function
+ * can be used with qsort() as @c compar function.
+ *
+ * @param[in] first a pointer to the first memory range
+ * @param[in] second a pointer to the second memory range
+ * @return 0 if @p first and @p second have the same start address,
+ *         a value less then 0 if the start address of @p first is less than
+ *         the start address of @p second, and a value greater than 0 if
+ *         the opposite is in case.
+ */
+int compare_ranges(const void *first, const void *second);
+
+/**
  * Checks if the kernel provides the /sys/firmware/memmap interface.
  * It makes sense to use that function in advance before calling
  * get_firmware_memmap_ranges() because the latter function prints an error
-- 
1.5.6.5


From dkiper at net-space.pl  Sun Aug 21 09:54:00 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Sun, 21 Aug 2011 15:54:00 +0200
Subject: [PATCH 3/4] kexec/arch/i386: Rename fixup_memory_ranges_sysfs() to
	fixup_memory_ranges()
Message-ID: <20110821135400.GD17323@router-fw-old.local.net-space.pl>

Rename fixup_memory_ranges_sysfs() to fixup_memory_ranges().
It is generic function and it could be used to fixup memory
ranges from other sources than sysfs (e.g. Xen).

Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
---
 kexec/arch/i386/kexec-x86-common.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c
index 474e680..8f59c6c 100644
--- a/kexec/arch/i386/kexec-x86-common.c
+++ b/kexec/arch/i386/kexec-x86-common.c
@@ -149,7 +149,7 @@ static void remove_range(struct memory_range *range, int nr_ranges, int index)
  *
  * @return 0 on success, any other value on failure.
  */
-static int fixup_memory_ranges_sysfs(struct memory_range **range, int *ranges)
+static int fixup_memory_ranges(struct memory_range **range, int *ranges)
 {
 	int i;
 	int j;
@@ -162,7 +162,7 @@ again:
 	for (i = 0; i < (nr_ranges-1); i++) {
 		j = i+1;
 		if (rp[i].start > rp[j].start) {
-			fprintf(stderr, "sysfs memory out of order!!\n");
+			fprintf(stderr, "memory out of order!!\n");
 			return 1;
 		}
 
@@ -252,7 +252,7 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
 	if (!efi_map_added() && !xen_present() && have_sys_firmware_memmap()) {
 		ret = get_memory_ranges_sysfs(range, ranges);
 		if (!ret)
-			ret = fixup_memory_ranges_sysfs(range, ranges);
+			ret = fixup_memory_ranges(range, ranges);
 	} else
 		ret = get_memory_ranges_proc_iomem(range, ranges);
 
-- 
1.5.6.5


From dkiper at net-space.pl  Sun Aug 21 09:54:59 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Sun, 21 Aug 2011 15:54:59 +0200
Subject: [PATCH 4/4] kexec/arch/i386: Add get_memory_ranges_xen() function
Message-ID: <20110821135459.GE17323@router-fw-old.local.net-space.pl>

get_memory_ranges_sysfs() and get_memory_ranges_proc_iomem()
are unreliable under Xen. Proper machine memory map could be
obtained under Xen by calling __HYPERVISOR_memory_op hypercall
with XENMEM_machine_memory_map argument. get_memory_ranges_xen()
does that. It is implemented using ioctl() or libxenctrl interface.
This solution is compatible with 3.x and 4.x Xen versions.

Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
---
 configure.ac                       |    3 +
 kexec/arch/i386/kexec-x86-common.c |  203 ++++++++++++++++++++++++++++++++++--
 2 files changed, 197 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index 172a52a..0d09bba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,9 @@ if test "$with_xen" = yes ; then
 	AC_CHECK_HEADER(xenctrl.h,
 		AC_CHECK_LIB(xenctrl, xc_version, ,
 		AC_MSG_NOTICE([Xen support disabled])))
+	if test "$ac_cv_lib_xenctrl_xc_version" = yes ; then
+		AC_CHECK_FUNCS(xc_get_machine_memory_map)
+	fi
 fi
 
 dnl ---Sanity checks
diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c
index 8f59c6c..609d35d 100644
--- a/kexec/arch/i386/kexec-x86-common.c
+++ b/kexec/arch/i386/kexec-x86-common.c
@@ -17,6 +17,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define _XOPEN_SOURCE	600
+#define _BSD_SOURCE
+
+#include <fcntl.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <errno.h>
@@ -24,12 +28,29 @@
 #include <string.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
 #include "../../firmware_memmap.h"
 #include "../../crashdump.h"
 #include "kexec-x86.h"
 
+#ifdef HAVE_LIBXENCTRL
+#ifdef HAVE_XC_GET_MACHINE_MEMORY_MAP
+#include <xenctrl.h>
+#else
+#define __XEN_TOOLS__	1
+#include <x86/x86-linux.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/sys/privcmd.h>
+#endif /* HAVE_XC_GET_MACHINE_MEMORY_MAP */
+#endif /* HAVE_LIBXENCTRL */
+
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /**
@@ -129,6 +150,172 @@ static int get_memory_ranges_sysfs(struct memory_range **range, int *ranges)
 	return 0;
 }
 
+#ifdef HAVE_LIBXENCTRL
+static unsigned e820_to_kexec_type(uint32_t type)
+{
+	switch (type) {
+		case E820_RAM:
+			return RANGE_RAM;
+		case E820_ACPI:
+			return RANGE_ACPI;
+		case E820_NVS:
+			return RANGE_ACPI_NVS;
+		case E820_RESERVED:
+		default:
+			return RANGE_RESERVED;
+	}
+}
+
+/**
+ * Memory map detection for Xen.
+ *
+ * @param[out] range pointer that will be set to an array that holds the
+ *             memory ranges
+ * @param[out] ranges number of ranges valid in @p range
+ *
+ * @return 0 on success, any other value on failure.
+ */
+#ifdef HAVE_XC_GET_MACHINE_MEMORY_MAP
+static int get_memory_ranges_xen(struct memory_range **range, int *ranges)
+{
+	int rc, ret = -1;
+	struct e820entry e820entries[MAX_MEMORY_RANGES];
+	unsigned int i;
+#ifdef XENCTRL_HAS_XC_INTERFACE
+	xc_interface *xc;
+#else
+	int xc;
+#endif
+
+#ifdef XENCTRL_HAS_XC_INTERFACE
+	xc = xc_interface_open(NULL, NULL, 0);
+
+	if (!xc) {
+		fprintf(stderr, "%s: Failed to open Xen control interface\n", __func__);
+		goto err;
+	}
+#else
+	xc = xc_interface_open();
+
+	if (xc == -1) {
+		fprintf(stderr, "%s: Failed to open Xen control interface\n", __func__);
+		goto err;
+	}
+#endif
+
+	rc = xc_get_machine_memory_map(xc, e820entries, MAX_MEMORY_RANGES);
+
+	if (rc < 0) {
+		fprintf(stderr, "%s: xc_get_machine_memory_map: %s\n", __func__, strerror(rc));
+		goto err;
+	}
+
+	for (i = 0; i < rc; ++i) {
+		memory_range[i].start = e820entries[i].addr;
+		memory_range[i].end = e820entries[i].addr + e820entries[i].size;
+		memory_range[i].type = e820_to_kexec_type(e820entries[i].type);
+	}
+
+	qsort(memory_range, rc, sizeof(struct memory_range), compare_ranges);
+
+	*range = memory_range;
+	*ranges = rc;
+
+	ret = 0;
+
+err:
+	xc_interface_close(xc);
+
+	return ret;
+}
+#else
+static int get_memory_ranges_xen(struct memory_range **range, int *ranges)
+{
+	int fd, rc, ret = -1;
+	privcmd_hypercall_t hypercall;
+	struct e820entry *e820entries = NULL;
+	struct xen_memory_map *xen_memory_map = NULL;
+	unsigned int i;
+
+	fd = open("/proc/xen/privcmd", O_RDWR);
+
+	if (fd == -1) {
+		fprintf(stderr, "%s: open(/proc/xen/privcmd): %m\n", __func__);
+		goto err;
+	}
+
+	rc = posix_memalign((void **)&e820entries, sysconf(_SC_PAGESIZE),
+			    sizeof(struct e820entry) * MAX_MEMORY_RANGES);
+
+	if (rc) {
+		fprintf(stderr, "%s: posix_memalign(e820entries): %s\n", __func__, strerror(rc));
+		e820entries = NULL;
+		goto err;
+	}
+
+	rc = posix_memalign((void **)&xen_memory_map, sysconf(_SC_PAGESIZE),
+			    sizeof(struct xen_memory_map));
+
+	if (rc) {
+		fprintf(stderr, "%s: posix_memalign(xen_memory_map): %s\n", __func__, strerror(rc));
+		xen_memory_map = NULL;
+		goto err;
+	}
+
+	if (mlock(e820entries, sizeof(struct e820entry) * MAX_MEMORY_RANGES) == -1) {
+		fprintf(stderr, "%s: mlock(e820entries): %m\n", __func__);
+		goto err;
+	}
+
+	if (mlock(xen_memory_map, sizeof(struct xen_memory_map)) == -1) {
+		fprintf(stderr, "%s: mlock(xen_memory_map): %m\n", __func__);
+		goto err;
+	}
+
+	xen_memory_map->nr_entries = MAX_MEMORY_RANGES;
+	set_xen_guest_handle(xen_memory_map->buffer, e820entries);
+
+	hypercall.op = __HYPERVISOR_memory_op;
+	hypercall.arg[0] = XENMEM_machine_memory_map;
+	hypercall.arg[1] = (__u64)xen_memory_map;
+
+	rc = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, &hypercall);
+
+	if (rc == -1) {
+		fprintf(stderr, "%s: ioctl(IOCTL_PRIVCMD_HYPERCALL): %m\n", __func__);
+		goto err;
+	}
+
+	for (i = 0; i < xen_memory_map->nr_entries; ++i) {
+		memory_range[i].start = e820entries[i].addr;
+		memory_range[i].end = e820entries[i].addr + e820entries[i].size;
+		memory_range[i].type = e820_to_kexec_type(e820entries[i].type);
+	}
+
+	qsort(memory_range, xen_memory_map->nr_entries, sizeof(struct memory_range), compare_ranges);
+
+	*range = memory_range;
+	*ranges = xen_memory_map->nr_entries;
+
+	ret = 0;
+
+err:
+	munlock(xen_memory_map, sizeof(struct xen_memory_map));
+	munlock(e820entries, sizeof(struct e820entry) * MAX_MEMORY_RANGES);
+	free(xen_memory_map);
+	free(e820entries);
+	close(fd);
+
+	return ret;
+}
+#endif /* HAVE_XC_GET_MACHINE_MEMORY_MAP */
+#else
+static int get_memory_ranges_xen(struct memory_range **range, int *ranges)
+{
+	return 0;
+}
+#endif /* HAVE_LIBXENCTRL */
+
 static void remove_range(struct memory_range *range, int nr_ranges, int index)
 {
 	int i, j;
@@ -242,23 +429,21 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
 {
 	int ret, i;
 
-	/*
-	 * When using Xen, /sys/firmware/memmap (i.e., the E820 map) is
-	 * wrong, it just provides one large memory are and that cannot
-	 * be used for Kdump. Use always the /proc/iomem interface there
-	 * even if we have /sys/firmware/memmap. Without that, /proc/vmcore
-	 * is empty in the kdump kernel.
-	 */
 	if (!efi_map_added() && !xen_present() && have_sys_firmware_memmap()) {
 		ret = get_memory_ranges_sysfs(range, ranges);
 		if (!ret)
 			ret = fixup_memory_ranges(range, ranges);
+	} else if (xen_present()) {
+		ret = get_memory_ranges_xen(range, ranges);
+		if (!ret)
+			ret = fixup_memory_ranges(range, ranges);
 	} else
 		ret = get_memory_ranges_proc_iomem(range, ranges);
 
 	/*
-	 * both get_memory_ranges_sysfs() and get_memory_ranges_proc_iomem()
-	 * have already printed an error message, so fail silently here
+	 * get_memory_ranges_sysfs(), get_memory_ranges_proc_iomem() and
+	 * get_memory_ranges_xen() have already printed an error message,
+	 * so fail silently here.
 	 */
 	if (ret != 0)
 		return ret;
-- 
1.5.6.5


From horms at verge.net.au  Sun Aug 21 18:47:38 2011
From: horms at verge.net.au (Simon Horman)
Date: Mon, 22 Aug 2011 07:47:38 +0900
Subject: [PATCH 0/4] kexec-tools: Xen fixes and cleanups
In-Reply-To: <20110821135029.GA17323@router-fw-old.local.net-space.pl>
References: <20110821135029.GA17323@router-fw-old.local.net-space.pl>
Message-ID: <20110821224737.GF2300@verge.net.au>

On Sun, Aug 21, 2011 at 03:50:29PM +0200, Daniel Kiper wrote:
> Hi,
> 
> I am sending some Xen specific fixes and cleanups for kexec-tools.
> These patches applies to current kexec-tools git tree.
> 
> Full list of fixes and cleanups:
>   - xen: Take into account Xen control interface changes since Xen Ver. 4.1,
>   - kexec: Export compare_ranges() function from firmware_memmap.c module,
>   - kexec/arch/i386: Rename fixup_memory_ranges_sysfs() to fixup_memory_ranges(),
>   - kexec/arch/i386: Add get_memory_ranges_xen() function.

Thanks Daniel,

all applied.



From konrad.wilk at oracle.com  Sun Aug 21 23:56:50 2011
From: konrad.wilk at oracle.com (Konrad Rzeszutek Wilk)
Date: Sun, 21 Aug 2011 23:56:50 -0400
Subject: [PATCH 1/4] xen: Take into account Xen control interface changes
	since Xen Ver. 4.1
In-Reply-To: <20110821135139.GB17323@router-fw-old.local.net-space.pl>
References: <20110821135139.GB17323@router-fw-old.local.net-space.pl>
Message-ID: <201108212356.50589.konrad.wilk@oracle.com>

> xc_interface_open() receive three arguments instead of void and returns
> pointer to xc_interface type instead of int since Xen Ver. 4.1. Take into
> account that and allow kexec-tools compilation with all versions of Xen.
> 
> Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
> ---
>  kexec/crashdump-xen.c |   15 ++++++++++++++-
>  1 files changed, 14 insertions(+), 1 deletions(-)
> 
> diff --git a/kexec/crashdump-xen.c b/kexec/crashdump-xen.c
> index b347764..9dfabf8 100644
> --- a/kexec/crashdump-xen.c
> +++ b/kexec/crashdump-xen.c
> @@ -126,19 +126,32 @@ unsigned long xen_architecture(struct crash_elf_info 
*elf_info)
>  {
>  	unsigned long machine = elf_info->machine;
>  #ifdef HAVE_LIBXENCTRL
> -	int xc, rc;
> +	int rc;
>  	xen_capabilities_info_t capabilities;
> +#ifdef XENCTRL_HAS_XC_INTERFACE
> +	xc_interface *xc;
> +#else
> +	int xc;
> +#endif

Where is the #endif for HAVE_LIBXENCTRL?

>  
>  	if (!xen_present())
>  		goto out;
>  
>  	memset(capabilities, '0', XEN_CAPABILITIES_INFO_LEN);
>  
> +#ifdef XENCTRL_HAS_XC_INTERFACE
> +	xc = xc_interface_open(NULL, NULL, 0);
> +	if ( !xc ) {
> +		fprintf(stderr, "failed to open xen control interface.\n");
> +		goto out;
> +	}
> +#else
>  	xc = xc_interface_open();
>  	if ( xc == -1 ) {
>  		fprintf(stderr, "failed to open xen control interface.\n");
>  		goto out;
>  	}
> +#endif
>  
>  	rc = xc_version(xc, XENVER_capabilities, &capabilities[0]);
>  	if ( rc == -1 ) {
> -- 
> 1.5.6.5
> 


From konrad.wilk at oracle.com  Mon Aug 22 00:01:24 2011
From: konrad.wilk at oracle.com (Konrad Rzeszutek Wilk)
Date: Mon, 22 Aug 2011 00:01:24 -0400
Subject: [PATCH 4/4] kexec/arch/i386: Add get_memory_ranges_xen() function
In-Reply-To: <20110821135459.GE17323@router-fw-old.local.net-space.pl>
References: <20110821135459.GE17323@router-fw-old.local.net-space.pl>
Message-ID: <201108220001.24399.konrad.wilk@oracle.com>

> get_memory_ranges_sysfs() and get_memory_ranges_proc_iomem()
> are unreliable under Xen. Proper machine memory map could be
> obtained under Xen by calling __HYPERVISOR_memory_op hypercall
> with XENMEM_machine_memory_map argument. get_memory_ranges_xen()
> does that. It is implemented using ioctl() or libxenctrl interface.
> This solution is compatible with 3.x and 4.x Xen versions.
> 
> Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
> ---
>  configure.ac                       |    3 +
>  kexec/arch/i386/kexec-x86-common.c |  203 
++++++++++++++++++++++++++++++++++--
>  2 files changed, 197 insertions(+), 9 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 172a52a..0d09bba 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -157,6 +157,9 @@ if test "$with_xen" = yes ; then
>  	AC_CHECK_HEADER(xenctrl.h,
>  		AC_CHECK_LIB(xenctrl, xc_version, ,
>  		AC_MSG_NOTICE([Xen support disabled])))
> +	if test "$ac_cv_lib_xenctrl_xc_version" = yes ; then
> +		AC_CHECK_FUNCS(xc_get_machine_memory_map)
> +	fi
>  fi
>  
>  dnl ---Sanity checks
> diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-
common.c
> index 8f59c6c..609d35d 100644
> --- a/kexec/arch/i386/kexec-x86-common.c
> +++ b/kexec/arch/i386/kexec-x86-common.c
> @@ -17,6 +17,10 @@
>   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>   */
>  
> +#define _XOPEN_SOURCE	600
> +#define _BSD_SOURCE
> +
> +#include <fcntl.h>
>  #include <stddef.h>
>  #include <stdio.h>
>  #include <errno.h>
> @@ -24,12 +28,29 @@
>  #include <string.h>
>  #include <limits.h>
>  #include <stdlib.h>
> +#include <stdio.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
>  #include "../../kexec.h"
>  #include "../../kexec-syscall.h"
>  #include "../../firmware_memmap.h"
>  #include "../../crashdump.h"
>  #include "kexec-x86.h"
>  
> +#ifdef HAVE_LIBXENCTRL
> +#ifdef HAVE_XC_GET_MACHINE_MEMORY_MAP
> +#include <xenctrl.h>
> +#else
> +#define __XEN_TOOLS__	1
> +#include <x86/x86-linux.h>
> +#include <xen/xen.h>
> +#include <xen/memory.h>
> +#include <xen/sys/privcmd.h>
> +#endif /* HAVE_XC_GET_MACHINE_MEMORY_MAP */
> +#endif /* HAVE_LIBXENCTRL */
> +
>  static struct memory_range memory_range[MAX_MEMORY_RANGES];
>  
>  /**
> @@ -129,6 +150,172 @@ static int get_memory_ranges_sysfs(struct memory_range 
**range, int *ranges)
>  	return 0;
>  }
>  
> +#ifdef HAVE_LIBXENCTRL
> +static unsigned e820_to_kexec_type(uint32_t type)
> +{
> +	switch (type) {
> +		case E820_RAM:
> +			return RANGE_RAM;
> +		case E820_ACPI:
> +			return RANGE_ACPI;
> +		case E820_NVS:
> +			return RANGE_ACPI_NVS;
> +		case E820_RESERVED:

For E820_UNUSABLE you want to do that too?

> +		default:
> +			return RANGE_RESERVED;

Or should E820_UNUSABLE returne its own type of RANGE?
> 


From schwidefsky at de.ibm.com  Mon Aug 22 02:34:59 2011
From: schwidefsky at de.ibm.com (Martin Schwidefsky)
Date: Mon, 22 Aug 2011 08:34:59 +0200
Subject: [patch 0/2] kdump: Common code changes for s390 kdump support
In-Reply-To: <20110819150353.bf58c7e0.akpm@linux-foundation.org>
References: <20110819141857.052232873@linux.vnet.ibm.com>
	<20110819150353.bf58c7e0.akpm@linux-foundation.org>
Message-ID: <20110822083459.2cc52fc8@mschwide>

On Fri, 19 Aug 2011 15:03:53 -0700
Andrew Morton <akpm at linux-foundation.org> wrote:

> On Fri, 19 Aug 2011 16:18:57 +0200
> Michael Holzheu <holzheu at linux.vnet.ibm.com> wrote:
> 
> > I had a long discussion with Vivek Goyal on the s390 kdump support (thanks
> > Vivek for all the time!). As a result of this, here are two common code
> > patches that are required for the s390 port. Could you please integrate them
> > upstream in the next merge window? The s390 specific part will be integrated
> > by our s390 maintainer Martin Schwidefsky.
> 
> The patches look OK to me.  I suggest that they be carried in Martin's
> tree, alongside the s390 kdump support.  That will somewhat simplify
> things during the merge window, and will greatly simplify getting the
> entire feature into linux-next.
> 
> You can put my acked-by's on them if you like.
> 
> > I will be on vacation for the next two weeks. Therefore if you have comments
> > or questions, please contact also Martin Schwidefsky and Heiko Carstens.
> 
> I'll put the patches into my tree (and hence linux-next) now, because I
> need the typing practice ;) I'll drop them again if/when they turn up
> in linux-next's s390 tree.

Ok, sounds reasonable to me. I'll take them via the s390 tree and add
you acked-by. Thanks Andrew. 


-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.



From belerajendra753 at gmail.com  Mon Aug 22 02:24:45 2011
From: belerajendra753 at gmail.com (Rajendra Bele)
Date: Mon, 22 Aug 2011 12:09:45 +0545
Subject: [Xen-devel] [PATCH 1/4] xen: Take into account Xen control
	interface changes since Xen Ver. 4.1
In-Reply-To: <20110821135139.GB17323@router-fw-old.local.net-space.pl>
References: <20110821135139.GB17323@router-fw-old.local.net-space.pl>
Message-ID: <CAJRmKy8=f+x6bU0XQOuqgVcX-u1oMvk-hdsWGsrgOj3H+sepxQ@mail.gmail.com>

Dear Friends,
I am pursuing Ph.D. in virtualization,
I want to study detail architecture and implementation of Xen
As I wanted to start from scratch ,can you suggest some guidance or resource
for it.
Thanking you
Rajendra Bele
Pune,India

On Sun, Aug 21, 2011 at 7:36 PM, Daniel Kiper <dkiper at net-space.pl> wrote:

> xc_interface_open() receive three arguments instead of void and returns
> pointer to xc_interface type instead of int since Xen Ver. 4.1. Take into
> account that and allow kexec-tools compilation with all versions of Xen.
>
> Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
> ---
>  kexec/crashdump-xen.c |   15 ++++++++++++++-
>  1 files changed, 14 insertions(+), 1 deletions(-)
>
> diff --git a/kexec/crashdump-xen.c b/kexec/crashdump-xen.c
> index b347764..9dfabf8 100644
> --- a/kexec/crashdump-xen.c
> +++ b/kexec/crashdump-xen.c
> @@ -126,19 +126,32 @@ unsigned long xen_architecture(struct crash_elf_info
> *elf_info)
>  {
>        unsigned long machine = elf_info->machine;
>  #ifdef HAVE_LIBXENCTRL
> -       int xc, rc;
> +       int rc;
>        xen_capabilities_info_t capabilities;
> +#ifdef XENCTRL_HAS_XC_INTERFACE
> +       xc_interface *xc;
> +#else
> +       int xc;
> +#endif
>
>        if (!xen_present())
>                goto out;
>
>        memset(capabilities, '0', XEN_CAPABILITIES_INFO_LEN);
>
> +#ifdef XENCTRL_HAS_XC_INTERFACE
> +       xc = xc_interface_open(NULL, NULL, 0);
> +       if ( !xc ) {
> +               fprintf(stderr, "failed to open xen control interface.\n");
> +               goto out;
> +       }
> +#else
>        xc = xc_interface_open();
>        if ( xc == -1 ) {
>                fprintf(stderr, "failed to open xen control interface.\n");
>                goto out;
>        }
> +#endif
>
>        rc = xc_version(xc, XENVER_capabilities, &capabilities[0]);
>        if ( rc == -1 ) {
> --
> 1.5.6.5
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel at lists.xensource.com
> http://lists.xensource.com/xen-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20110822/da5c25b9/attachment.html>

From mahesh at linux.vnet.ibm.com  Mon Aug 22 07:57:58 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Mon, 22 Aug 2011 17:27:58 +0530
Subject: [PATCH v2 7/8] makedumpfile: Add erased information in
	compressed kdump file
In-Reply-To: <20110819151659.6cfd324b.oomichi@mxs.nes.nec.co.jp>
References: <20110517200608.12740.68790.stgit@mars.in.ibm.com>
	<20110819151659.6cfd324b.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110822115757.GA23157@in.ibm.com>

On 2011-08-19 15:16:59 Fri, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> Sorry about many responses of this patch.
> 
> On Wed, 18 May 2011 01:36:17 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >
> > From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> > 
> > Include the erase information in the makedumpfile generated dumpfile. The
> > erased information contains only effective lines from the filter
> > configuration file. This patch supports inclusion of erase information in
> > kdump compressed, flatten and split dumpfiles. On re-filtering, the erase
> > information from input dumpfile (if any) will be carried over to resulting
> > dumpfile.
> > 
> > This patch introduces new members offset_eraseinfo, size_eraseinfo into the
> > sub header in compressed kdump file.
> > 
> > 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
> 
> While testing this feature, I noticed the description format of
> makedumpfile.conf is different from the one of eraseinfo.
> The former contains "size", but the later does not.
> 
> Are there any reasons of different formats ?

There is no specific reason, since it is just an information I thought we
can follow a simple format.

> I feel the same format will be useful.

Sure, will make the change.

Thanks,
-Mahesh.

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

-- 
Mahesh J Salgaonkar


From dkiper at net-space.pl  Mon Aug 22 09:25:25 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Mon, 22 Aug 2011 15:25:25 +0200
Subject: [PATCH 1/4] xen: Take into account Xen control interface changes
	since Xen Ver. 4.1
In-Reply-To: <201108212356.50589.konrad.wilk@oracle.com>
References: <20110821135139.GB17323@router-fw-old.local.net-space.pl>
	<201108212356.50589.konrad.wilk@oracle.com>
Message-ID: <20110822132525.GB27902@router-fw-old.local.net-space.pl>

On Sun, Aug 21, 2011 at 11:56:50PM -0400, Konrad Rzeszutek Wilk wrote:
> > xc_interface_open() receive three arguments instead of void and returns
> > pointer to xc_interface type instead of int since Xen Ver. 4.1. Take into
> > account that and allow kexec-tools compilation with all versions of Xen.
> >
> > Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
> > ---
> >  kexec/crashdump-xen.c |   15 ++++++++++++++-
> >  1 files changed, 14 insertions(+), 1 deletions(-)
> >
> > diff --git a/kexec/crashdump-xen.c b/kexec/crashdump-xen.c
> > index b347764..9dfabf8 100644
> > --- a/kexec/crashdump-xen.c
> > +++ b/kexec/crashdump-xen.c
> > @@ -126,19 +126,32 @@ unsigned long xen_architecture(struct crash_elf_info
> *elf_info)
> >  {
> >  	unsigned long machine = elf_info->machine;
> >  #ifdef HAVE_LIBXENCTRL
> > -	int xc, rc;
> > +	int rc;
> >  	xen_capabilities_info_t capabilities;
> > +#ifdef XENCTRL_HAS_XC_INTERFACE
> > +	xc_interface *xc;
> > +#else
> > +	int xc;
> > +#endif
>
> Where is the #endif for HAVE_LIBXENCTRL?

At the end of this function. It is not included in this patch.

Daniel


From dkiper at net-space.pl  Mon Aug 22 10:07:45 2011
From: dkiper at net-space.pl (Daniel Kiper)
Date: Mon, 22 Aug 2011 16:07:45 +0200
Subject: [PATCH 4/4] kexec/arch/i386: Add get_memory_ranges_xen() function
In-Reply-To: <201108220001.24399.konrad.wilk@oracle.com>
References: <20110821135459.GE17323@router-fw-old.local.net-space.pl>
	<201108220001.24399.konrad.wilk@oracle.com>
Message-ID: <20110822140745.GC27902@router-fw-old.local.net-space.pl>

On Mon, Aug 22, 2011 at 12:01:24AM -0400, Konrad Rzeszutek Wilk wrote:

[...]

> > +#ifdef HAVE_LIBXENCTRL
> > +static unsigned e820_to_kexec_type(uint32_t type)
> > +{
> > +	switch (type) {
> > +		case E820_RAM:
> > +			return RANGE_RAM;
> > +		case E820_ACPI:
> > +			return RANGE_ACPI;
> > +		case E820_NVS:
> > +			return RANGE_ACPI_NVS;
> > +		case E820_RESERVED:
>
> For E820_UNUSABLE you want to do that too?
>
> > +		default:
> > +			return RANGE_RESERVED;
>
> Or should E820_UNUSABLE returne its own type of RANGE?

Kexec does not differentiate between E820_RESERVED and E820_UNUSABLE
(please look into kexec/firmware_memmap.c, parse_memmap_entry()).
It treats both as RANGE_RESERVED. RANGE_UNUSABLE is not defined.
In this situation I stated that it is not worth to change that
and I have mapped all undefined types to RANGE_RESERVED. It means
that E820_UNUSABLE is mapped to RANGE_RESERVED.

Daniel


From suzuki at in.ibm.com  Tue Aug 23 02:10:40 2011
From: suzuki at in.ibm.com (Suzuki K. Poulose)
Date: Tue, 23 Aug 2011 11:40:40 +0530
Subject: [PATCH] kexec:ppc: Fix compilation failure
Message-ID: <20110823061020.14928.83952.stgit@suzukikp.in.ibm.com>

commit 1ea7cfd435aba0e095886db367e9616271f56c28 broke the ppc build as it removes
the declaration for two variables in use by the elf_ppc_load(). This patch reverts
the particular hunk.

Signed-off-by: Suzuki K. Poulose <suzuki at in.ibm.com>
Reported-by: Josh Boyer <jwboyer at gmail.com>
---

 kexec/arch/ppc/kexec-elf-ppc.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index 39f1833..314eb1e 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -187,6 +187,8 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	char *fixup_nodes[FIXUP_ENTRYS + 1];
 	int cur_fixup = 0;
 	int opt;
+	char *blob_buf = NULL;
+	off_t blob_size = 0;
 
 	command_line = NULL;
 	dtb = NULL;



From horms at verge.net.au  Tue Aug 23 02:59:50 2011
From: horms at verge.net.au (Simon Horman)
Date: Tue, 23 Aug 2011 15:59:50 +0900
Subject: [PATCH] kexec:ppc: Fix compilation failure
In-Reply-To: <20110823061020.14928.83952.stgit@suzukikp.in.ibm.com>
References: <20110823061020.14928.83952.stgit@suzukikp.in.ibm.com>
Message-ID: <20110823065947.GA26169@verge.net.au>

On Tue, Aug 23, 2011 at 11:40:40AM +0530, Suzuki K. Poulose wrote:
> commit 1ea7cfd435aba0e095886db367e9616271f56c28 broke the ppc build as it removes
> the declaration for two variables in use by the elf_ppc_load(). This patch reverts
> the particular hunk.
> 
> Signed-off-by: Suzuki K. Poulose <suzuki at in.ibm.com>
> Reported-by: Josh Boyer <jwboyer at gmail.com>

Sorry about that, I have pushed your change.


From mahesh at linux.vnet.ibm.com  Tue Aug 30 14:16:42 2011
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Tue, 30 Aug 2011 23:46:42 +0530
Subject: [PATCH v2 6/8] makedumpfile: Read and process 'for' command
	from config file.
In-Reply-To: <20110811170621.2f931dbe.oomichi@mxs.nes.nec.co.jp>
References: <20110517200514.12740.86690.stgit@mars.in.ibm.com>
	<20110811170621.2f931dbe.oomichi@mxs.nes.nec.co.jp>
Message-ID: <20110830181642.GA21808@in.ibm.com>

On 2011-08-11 17:06:21 Thu, Ken'ichi Ohmichi wrote:
> 
> Hi Mahesh,
> 
> On Wed, 18 May 2011 01:35:19 +0530
> Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
> >
> > 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>
> > ---
> 
> Thank you for the patch.
> I think this patch is good.
> 
> Acked-by: Ken'ichi Ohmichi <oomichi at mxs.nes.nec.co.jp>
> 
> 
> Thanks
> Ken'ichi Ohmichi

Hi Ken'ichi,

As I told you earlier I found few BUGs w.r.t patch 6/8 that processes loop
construct. Please find the patch below that fixes those BUGs. Please review.

Thanks,
-Mahesh.

-------

[PATCH] makedumpfile: Fix array traversal for array of structure and char type.

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

Introduce new function get_next_list_entry() that returns config entry
for each element in the LIST entry. This approach improves the handling
of LIST entry. With this change the function get_config_symbol_addr()
no longer required to handle LIST entry separately.

This patch fixes following BUGs:

- If the loop construct is used for array of structures (non-pointer), then
the array index value is not incremented resulting in an infinite loop. This
patch fixes this BUG.
- The loop construct used for array of char* (pointer) silently fails and
does not filter the strings.
- Corrected 2nd argument while calling get_structure_size().
- Fixed dwarf_info.c:get_data_array_length() to handle array of const data
type.
  e.g.
	<1><1a49df3>: Abbrev Number: 90 (DW_TAG_variable)
	   <1a49df4>   DW_AT_name        : policycap_names
	   <1a49df8>   DW_AT_decl_file   : 1
	   <1a49df9>   DW_AT_decl_line   : 43
	   <1a49dfa>   DW_AT_type        : <0x1a49e08>
	<1><1a49e08>: Abbrev Number: 7 (DW_TAG_const_type)
	   <1a49e09>   DW_AT_type        : <0x1a49de3>
	<1><1a49de3>: Abbrev Number: 4 (DW_TAG_array_type)
	   <1a49de4>   DW_AT_type        : <0x1a3b276>
	   <1a49de8>   DW_AT_sibling     : <0x1a49df3>


Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 dwarf_info.c   |    8 ++
 makedumpfile.c |  292 +++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 188 insertions(+), 112 deletions(-)

diff --git a/dwarf_info.c b/dwarf_info.c
index 744ecf7..46dcd8e 100644
--- a/dwarf_info.c
+++ b/dwarf_info.c
@@ -328,6 +328,14 @@ get_data_array_length(Dwarf_Die *die)
 		return FALSE;
 	}
 	tag = dwarf_tag(&die_type);
+	if (tag == DW_TAG_const_type) {
+		/* This array is of const type. Get the die type again */
+		if (!get_die_type(&die_type, &die_type)) {
+			ERRMSG("Can't get CU die of DW_AT_type.\n");
+			return FALSE;
+		}
+		tag = dwarf_tag(&die_type);
+	}
 	if (tag != DW_TAG_array_type) {
 		/*
 		 * This kernel doesn't have the member of array.
diff --git a/makedumpfile.c b/makedumpfile.c
index 599950d..1a88171 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -6763,11 +6763,27 @@ read_pointer_value(unsigned long long addr)
 	return val;
 }
 
+static long
+get_strlen(unsigned long long addr)
+{
+	char buf[BUFSIZE + 1];
+	long len = 0;
+
+	/*
+	 * Determine the string length for 'char' pointer.
+	 * BUFSIZE(1024) is the upper limit for string length.
+	 */
+	if (readmem(VADDR, addr, buf, BUFSIZE)) {
+		buf[BUFSIZE] = '\0';
+		len = strlen(buf);
+	}
+	return len;
+}
+
 int
 resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 						char *base_struct_name)
 {
-	char buf[BUFSIZE + 1];
 	unsigned long long symbol;
 
 	if (ce->flag & SYMBOL_ENTRY) {
@@ -6866,7 +6882,7 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 		 * 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)
+		if (((ce->type_flag & (TYPE_BASE | TYPE_ARRAY)) == TYPE_BASE)
 					&& (strcmp(ce->type_name, "void")))
 			return FALSE;
 
@@ -6905,17 +6921,14 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 			ce->size = 0;
 
 	}
-	if ((ce->type_flag & TYPE_BASE) && (ce->type_flag & TYPE_PTR)) {
+	if ((ce->type_flag & TYPE_BASE) && (ce->type_flag & TYPE_PTR)
+					&& !(ce->type_flag & TYPE_ARRAY)) {
 		/*
 		 * 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 (!strcmp(ce->type_name, "char"))
+			ce->size = get_strlen(ce->addr);
 	}
 	if (!ce->next && (ce->flag & SIZE_ENTRY)) {
 		void *val;
@@ -6968,80 +6981,11 @@ get_config_symbol_addr(struct config_entry *ce,
 			unsigned long long base_addr,
 			char *base_struct_name)
 {
-	unsigned 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 * get_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;
@@ -7083,6 +7027,116 @@ get_config_symbol_size(struct config_entry *ce,
 	}
 }
 
+int
+get_next_list_entry(struct config_entry *ce, unsigned long long base_addr,
+			char *base_struct_name, struct config_entry *out_ce)
+{
+	unsigned long addr = 0;
+
+	/* This function only deals with LIST_ENTRY config entry. */
+	if (!(ce->flag & LIST_ENTRY))
+		return FALSE;
+
+	if (!(ce->flag & ENTRY_RESOLVED)) {
+		if (!resolve_config_entry(ce, base_addr, base_struct_name))
+			return FALSE;
+	}
+
+	if (!ce->next) {
+		/* leaf node. */
+		if (ce->type_flag & TYPE_ARRAY) {
+			if (ce->index == ce->array_length)
+				return FALSE;
+
+			if (ce->type_flag & TYPE_PTR) {
+				/* Array of pointers.
+				 *
+				 * Array may contain NULL pointers at some
+				 * indexes. Hence jump to the next non-null
+				 * address value.
+				 */
+				while (ce->index < ce->array_length) {
+					addr = read_pointer_value(ce->addr +
+						(ce->index * get_pointer_size()));
+					if (addr)
+						break;
+					ce->index++;
+				}
+				if (ce->index == ce->array_length)
+					return FALSE;
+				out_ce->sym_addr = ce->addr + (ce->index *
+							get_pointer_size());
+				out_ce->addr = addr;
+				if (!strcmp(ce->type_name, "char"))
+					out_ce->size = get_strlen(addr);
+				else
+					out_ce->size = ce->size;
+			}
+			else {
+				out_ce->sym_addr = ce->addr +
+							(ce->index * ce->size);
+				out_ce->addr = out_ce->sym_addr;
+				out_ce->size = ce->size;
+			}
+			ce->index++;
+		}
+		else {
+			if (ce->addr == ce->cmp_addr)
+				return FALSE;
+
+			out_ce->addr = ce->addr;
+			/* Set the leaf node as unresolved, so that
+			 * it will be resolved every time when
+			 * get_next_list_entry is called untill
+			 * it hits the exit condiftion.
+			 */
+			ce->flag &= ~ENTRY_RESOLVED;
+		}
+		return TRUE;
+	}
+	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.
+		 */
+		if (!(ce->type_flag & TYPE_LIST_HEAD)) {
+			if (!ce->addr || ce->addr == ce->next->cmp_addr)
+				return FALSE;
+
+			if (!ce->next->cmp_addr) {
+				/* safeguard against circular
+				 * link-list
+				 */
+				ce->next->cmp_addr = ce->addr;
+			}
+
+			out_ce->addr = ce->addr;
+			out_ce->sym_addr = ce->sym_addr;
+			out_ce->size = ce->size;
+
+			ce->sym_addr = ce->next->sym_addr;
+			ce->addr = ce->next->addr;
+
+			/* Force resolution of traversal node */
+			if (ce->addr && !resolve_config_entry(ce->next,
+					ce->addr, ce->type_name))
+				return FALSE;
+
+			return TRUE;
+		}
+		else {
+			ce->sym_addr = ce->next->sym_addr;
+			ce->addr = ce->next->addr;
+		}
+	}
+
+	if (ce->next && ce->addr)
+		return get_next_list_entry(ce->next, ce->addr,
+						ce->type_name, out_ce);
+	return FALSE;
+}
+
 static int
 resolve_list_entry(struct config_entry *ce, unsigned long long base_addr,
 			char *base_struct_name, char **out_type_name,
@@ -7308,31 +7362,14 @@ initialize_iteration_entry(struct config_entry *ie,
 								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);
+		/*
+		 * For list_head find out the size of the StructName and
+		 * populate ie->size now. For array and link list we get the
+		 * size info from config entry returned by
+		 * get_next_list_entry().
+		 */
+		ie->size = get_structure_size(ie->type_name, 0);
 		if (ie->size == FAILED_DWARFINFO) {
 			ERRMSG("Config error at %d: "
 				"Can't get size for type: %s.\n",
@@ -7345,8 +7382,7 @@ initialize_iteration_entry(struct config_entry *ie,
 				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;
 
@@ -7356,6 +7392,34 @@ initialize_iteration_entry(struct config_entry *ie,
 				ie->next->line, ie->next->name);
 			return FALSE;
 		}
+		ie->type_flag = TYPE_STRUCT;
+	}
+	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;
+			}
+		}
+		/*
+		 * Set type flag for iteration entry. The iteration entry holds
+		 * individual element from array/list, hence strip off the
+		 * array type flag bit.
+		 */
+		ie->type_name = strdup(type_name);
+		ie->type_flag = type_flag;
+		ie->type_flag &= ~TYPE_ARRAY;
 	}
 	return TRUE;
 }
@@ -7363,25 +7427,29 @@ initialize_iteration_entry(struct config_entry *ie,
 int
 list_entry_empty(struct config_entry *le, struct config_entry *ie)
 {
-	unsigned long long addr;
+	struct config_entry ce;
 
 	/* 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)
+
+	memset(&ce, 0, sizeof(struct config_entry));
+	/* get next available entry from LIST entry. */
+	if (!get_next_list_entry(le, 0, NULL, &ce))
 		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);
+		ie->next->addr = ce.addr;
+		ie->addr = ce.addr - ie->next->offset;
+	}
+	else {
+		ie->addr = ce.addr;
+		ie->sym_addr = ce.sym_addr;
+		ie->size = ce.size;
 	}
-	else
-		ie->addr = addr;
 	return FALSE;
 }
 


-- 
Mahesh J Salgaonkar



