Re: [PATCH 3/4] sparc64: convert spinlock_t to raw_spinlock_t in mmu_context_t

From: Kirill Tkhai
Date: Tue Feb 11 2014 - 16:24:27 EST




06.01.2014, 07:56, "Allen Pais" <allen.pais@xxxxxxxxxx>:
> In the attempt of get PREEMPT_RT working on sparc64 using
> linux-stable-rt version 3.10.22-rt19+, the kernel crash
> with the following trace:
>
> [ 1487.027884] I7: <rt_mutex_setprio+0x3c/0x2c0>
> [ 1487.027885] Call Trace:
> [ 1487.027887]  [00000000004967dc] rt_mutex_setprio+0x3c/0x2c0
> [ 1487.027892]  [00000000004afe20] task_blocks_on_rt_mutex+0x180/0x200
> [ 1487.027895]  [0000000000819114] rt_spin_lock_slowlock+0x94/0x300
> [ 1487.027897]  [0000000000817ebc] __schedule+0x39c/0x53c
> [ 1487.027899]  [00000000008185fc] schedule+0x1c/0xc0
> [ 1487.027908]  [000000000048fff4] smpboot_thread_fn+0x154/0x2e0
> [ 1487.027913]  [000000000048753c] kthread+0x7c/0xa0
> [ 1487.027920]  [00000000004060c4] ret_from_syscall+0x1c/0x2c
> [ 1487.027922]  [0000000000000000]           (null)
>
> Thomas debugged this issue and pointed to switch_mm
>
>         spin_lock_irqsave(&mm->context.lock, flags);
>
> context.lock needs to be a raw_spinlock.
>
> Acked-by: David S. Miller <davem@xxxxxxxxxxxxx>
> Signed-off-by: Allen Pais <allen.pais@xxxxxxxxxx>
> ---
>  arch/sparc/include/asm/mmu_64.h         |    2 +-
>  arch/sparc/include/asm/mmu_context_64.h |    8 ++++----
>  arch/sparc/kernel/smp_64.c              |    4 ++--
>  arch/sparc/mm/init_64.c                 |    4 ++--
>  arch/sparc/mm/tsb.c                     |   16 ++++++++--------
>  5 files changed, 17 insertions(+), 17 deletions(-)
>
> diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h
> index 76092c4..e945ddb 100644
> --- a/arch/sparc/include/asm/mmu_64.h
> +++ b/arch/sparc/include/asm/mmu_64.h
> @@ -90,7 +90,7 @@ struct tsb_config {
>  #endif
>
>  typedef struct {
> - spinlock_t lock;
> + raw_spinlock_t lock;
>          unsigned long sparc64_ctx_val;
>          unsigned long huge_pte_count;
>          struct page *pgtable_page;
> diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h
> index 3d528f0..3a85624 100644
> --- a/arch/sparc/include/asm/mmu_context_64.h
> +++ b/arch/sparc/include/asm/mmu_context_64.h
> @@ -77,7 +77,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
>          if (unlikely(mm == &init_mm))
>                  return;
>
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>          ctx_valid = CTX_VALID(mm->context);
>          if (!ctx_valid)
>                  get_new_mmu_context(mm);
> @@ -125,7 +125,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
>                  __flush_tlb_mm(CTX_HWBITS(mm->context),
>                                 SECONDARY_CONTEXT);
>          }
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>  }
>
>  #define deactivate_mm(tsk,mm) do { } while (0)
> @@ -136,7 +136,7 @@ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm
>          unsigned long flags;
>          int cpu;
>
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>          if (!CTX_VALID(mm->context))
>                  get_new_mmu_context(mm);
>          cpu = smp_processor_id();
> @@ -146,7 +146,7 @@ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm
>          load_secondary_context(mm);
>          __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
>          tsb_context_switch(mm);
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>  }
>
>  #endif /* !(__ASSEMBLY__) */
> diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
> index 77539ed..f42e1a7 100644
> --- a/arch/sparc/kernel/smp_64.c
> +++ b/arch/sparc/kernel/smp_64.c
> @@ -975,12 +975,12 @@ void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *reg
>          if (unlikely(!mm || (mm == &init_mm)))
>                  return;
>
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>
>          if (unlikely(!CTX_VALID(mm->context)))
>                  get_new_mmu_context(mm);
>
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>
>          load_secondary_context(mm);
>          __flush_tlb_mm(CTX_HWBITS(mm->context),
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 04fd55a..bd5253d 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -350,7 +350,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
>
>          mm = vma->vm_mm;
>
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>
>  #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
>          if (mm->context.huge_pte_count && is_hugetlb_pte(pte))
> @@ -361,7 +361,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
>                  __update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
>                                          address, pte_val(pte));
>
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>  }

We also should do the same in update_mmu_cache_pmd().

>
>  void flush_dcache_page(struct page *page)
> diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
> index 2cc3bce..d84d4ea 100644
> --- a/arch/sparc/mm/tsb.c
> +++ b/arch/sparc/mm/tsb.c
> @@ -73,7 +73,7 @@ void flush_tsb_user(struct tlb_batch *tb)
>          struct mm_struct *mm = tb->mm;
>          unsigned long nentries, base, flags;
>
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>
>          base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
>          nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
> @@ -90,14 +90,14 @@ void flush_tsb_user(struct tlb_batch *tb)
>                  __flush_tsb_one(tb, HPAGE_SHIFT, base, nentries);
>          }
>  #endif
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>  }
>
>  void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
>  {
>          unsigned long nentries, base, flags;
>
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>
>          base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
>          nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
> @@ -114,7 +114,7 @@ void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
>                  __flush_tsb_one_entry(base, vaddr, HPAGE_SHIFT, nentries);
>          }
>  #endif
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>  }
>
>  #define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_8K
> @@ -392,7 +392,7 @@ retry_tsb_alloc:
>           * the lock and ask all other cpus running this address space
>           * to run tsb_context_switch() to see the new TSB table.
>           */
> - spin_lock_irqsave(&mm->context.lock, flags);
> + raw_spin_lock_irqsave(&mm->context.lock, flags);
>
>          old_tsb = mm->context.tsb_block[tsb_index].tsb;
>          old_cache_index =
> @@ -407,7 +407,7 @@ retry_tsb_alloc:
>           */
>          if (unlikely(old_tsb &&
>                       (rss < mm->context.tsb_block[tsb_index].tsb_rss_limit))) {
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>
>                  kmem_cache_free(tsb_caches[new_cache_index], new_tsb);
>                  return;
> @@ -433,7 +433,7 @@ retry_tsb_alloc:
>          mm->context.tsb_block[tsb_index].tsb = new_tsb;
>          setup_tsb_params(mm, tsb_index, new_size);
>
> - spin_unlock_irqrestore(&mm->context.lock, flags);
> + raw_spin_unlock_irqrestore(&mm->context.lock, flags);
>
>          /* If old_tsb is NULL, we're being invoked for the first time
>           * from init_new_context().
> @@ -459,7 +459,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
>  #endif
>          unsigned int i;
>
> - spin_lock_init(&mm->context.lock);
> + raw_spin_lock_init(&mm->context.lock);
>
>          mm->context.sparc64_ctx_val = 0UL;
>
> --
> 1.7.10.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/