[Crash-utility] [PATCH] Fix x86 initialization for {hard, soft}irq_ctx

Dave Anderson anderson at redhat.com
Wed Feb 8 16:12:39 UTC 2017


----- Original Message -----
>
> Current code is setting {hard,soft}irq_ctx[] to (irq_ctx **), because
> per_cpu symbol itself is pointer of specified type (irq_ctx *).
>
> But, I wonder how this works in past, the code is expecting
> {hard,soft}_ctx[] are (irq_ctx *). This fixes by deref per_cpu in
> initialization, and set expected pointers.
>
> Tested on i386 v3.10.
>

You are correct -- apparently it never did work.  

The reason why I never noticed with RHEL kernels is that up until linux-2.6.29,
the IRQ stacks were declared as a static NR_CPUS-bounded array:
  
  #ifdef CONFIG_4KSTACKS
  /*
   * per-CPU IRQ handling contexts (thread information and stack)
   */
  union irq_ctx {
          struct thread_info      tinfo;
          u32                     stack[THREAD_SIZE/sizeof(u32)];
  };
  
  static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
  static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
  
  static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
  static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
  
  
Then in linux-2.6.30, they were changed to be per-cpu variables:
  
  #ifdef CONFIG_4KSTACKS
  /*
   * per-CPU IRQ handling contexts (thread information and stack)
   */
  union irq_ctx {
          struct thread_info      tinfo;
          u32                     stack[THREAD_SIZE/sizeof(u32)];
  } __attribute__((aligned(PAGE_SIZE)));
  
  static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
  static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
  
  static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
  static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
  
We never ran into the bug in 32-bit x86 RHEL6 (2.6.32-based) kernels because 
we did not configure CONFIG_4KSTACKS.  

Later on, the CONFIG_4KSTACKS restriction looks like it was removed, but we 
stopped supporting 32-bit x86 in RHEL7.  And nobody ever reported it from any
other x86 kernel sources.

I also note that in linux-3.15 the data structure name and variables were
changed to:
 
  struct irq_stack {
          u32                     stack[THREAD_SIZE/sizeof(u32)];
  } __aligned(THREAD_SIZE);

  DECLARE_PER_CPU(struct irq_stack *, hardirq_stack);
  DECLARE_PER_CPU(struct irq_stack *, softirq_stack);

So your patch would need more work for 3.15 and later kernels.

Thanks,
  Dave

 




> ---
>  task.c |   28 ++++++++++++++++++++++++----
>  1 file changed, 24 insertions(+), 4 deletions(-)
> 
> diff -puN task.c~ia32-irq-stack-fix task.c
> --- crash-64/task.c~ia32-irq-stack-fix	2017-02-08 17:37:33.126367767 +0900
> +++ crash-64-hirofumi/task.c	2017-02-08 17:46:06.900703326 +0900
> @@ -570,10 +570,20 @@ irqstacks_init(void)
>  	if ((hard_sp = per_cpu_symbol_search("per_cpu__hardirq_ctx"))) {
>  		if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
>  			for (i = 0; i < NR_CPUS; i++) {
> +				ulong ptr;
> +
>  				if (!kt->__per_cpu_offset[i])
>  					continue;
> -				tt->hardirq_ctx[i] = hard_sp->value +
> -					kt->__per_cpu_offset[i];
> +				ptr = hard_sp->value + kt->__per_cpu_offset[i];
> +
> +				if (!readmem(ptr, KVADDR, &ptr,
> +					     sizeof(void *), "hardirq ctx",
> +					     RETURN_ON_ERROR)) {
> +					error(INFO, "cannot read hardirq_ctx[%d] at %lx\n",
> +					      i, ptr);
> +					continue;
> +				}
> +				tt->hardirq_ctx[i] = ptr;
>  			}
>  		} else 
>  			tt->hardirq_ctx[0] = hard_sp->value;
> @@ -604,10 +614,20 @@ irqstacks_init(void)
>  	if ((soft_sp = per_cpu_symbol_search("per_cpu__softirq_ctx"))) {
>  		if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
>  			for (i = 0; i < NR_CPUS; i++) {
> +				ulong ptr;
> +
>  				if (!kt->__per_cpu_offset[i])
>  					continue;
> -				tt->softirq_ctx[i] = soft_sp->value +
> -					kt->__per_cpu_offset[i];
> +				ptr = soft_sp->value + kt->__per_cpu_offset[i];
> +
> +				if (!readmem(ptr, KVADDR, &ptr,
> +					     sizeof(void *), "softirq ctx",
> +					     RETURN_ON_ERROR)) {
> +					error(INFO, "cannot read softirq_ctx[%d] at %lx\n",
> +					      i, ptr);
> +					continue;
> +				}
> +				tt->softirq_ctx[i] = ptr;
>  			}
>  		} else 
>  			 tt->softirq_ctx[0] = soft_sp->value;
> 
> -- 
> OGAWA Hirofumi <hirofumi mail parknet co jp>




More information about the Crash-utility mailing list