[PATCH] riscv: kasan: use local_tlb_flush_all() to avoid uninitialized __sbi_rfence

Vincent Chen vincent.chen at sifive.com
Tue Jul 21 04:58:21 EDT 2020


On Tue, Jul 21, 2020 at 12:18 PM Palmer Dabbelt <palmer at dabbelt.com> wrote:
>
> On Thu, 09 Jul 2020 19:40:54 PDT (-0700), vincent.chen at sifive.com wrote:
> > It fails to boot the v5.8-rc4 kernel with CONFIG_KASAN because kasan_init
> > and kasan_early_init use uninitialized __sbi_rfence as executing the
> > tlb_flush_all(). Actually, at this moment, only the CPU which is
> > responsible for the system initialization enables the MMU. Other CPUs are
> > parking at the .Lsecondary_start. Hence the tlb_flush_all() is able to be
> > replaced by local_tlb_flush_all() to avoid using uninitialized
> > __sbi_rfence.
> >
> > Signed-off-by: Vincent Chen <vincent.chen at sifive.com>
> > ---
> >  arch/riscv/mm/kasan_init.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
> > index 4a8b61806633..87b4ab3d3c77 100644
> > --- a/arch/riscv/mm/kasan_init.c
> > +++ b/arch/riscv/mm/kasan_init.c
> > @@ -44,7 +44,7 @@ asmlinkage void __init kasan_early_init(void)
> >                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
> >                               __pgprot(_PAGE_TABLE)));
> >
> > -     flush_tlb_all();
> > +     local_flush_tlb_all();
> >  }
> >
> >  static void __init populate(void *start, void *end)
> > @@ -79,7 +79,7 @@ static void __init populate(void *start, void *end)
> >                       pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
> >                               __pgprot(_PAGE_TABLE)));
> >
> > -     flush_tlb_all();
> > +     local_flush_tlb_all();
> >       memset(start, 0, end - start);
> >  }
>
> Can we just move the sbi_init() call before the kasan_init() call?  I feel like
> the SBI should be initialized directly after paging, as probing really doesn't
> have any dependencies.

The kasan_early_init() which is called before page_init() also uses
__sbi_rfence. Hence we need to move sbi_init() before the
kasan_early_init() not just before the kasan_init. I have tried to use
this solution to resolve this bug, and it could work on QEMU actually.
However, I think the solution replacing flush_tlb_all() with
local_flush_tlb_all() not only can resolve this problem but also can
lightly improve performance by reducing one SBI call. Therefore, the
patch uses local_flush_tlb_all() to solve this bug.



More information about the linux-riscv mailing list