diff mbox series

[v2,3/5] riscv: sifive: Add SiFive alternative ports

Message ID 1615973613-22364-4-git-send-email-vincent.chen@sifive.com (mailing list archive)
State New, archived
Headers show
Series riscv: introduce alternative mechanism to apply errata patches | expand

Commit Message

Vincent Chen March 17, 2021, 9:33 a.m. UTC
Add required ports of the Alternative scheme for SiFive.

Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
---
 arch/riscv/Kconfig.erratas           | 11 ++++++
 arch/riscv/Kconfig.socs              |  1 +
 arch/riscv/errata/Makefile           |  1 +
 arch/riscv/errata/alternative.c      |  5 +++
 arch/riscv/errata/sifive/Makefile    |  1 +
 arch/riscv/errata/sifive/errata.c    | 68 ++++++++++++++++++++++++++++++++++++
 arch/riscv/include/asm/alternative.h |  3 ++
 7 files changed, 90 insertions(+)
 create mode 100644 arch/riscv/errata/sifive/Makefile
 create mode 100644 arch/riscv/errata/sifive/errata.c

Comments

Anup Patel March 17, 2021, 11:43 a.m. UTC | #1
On Wed, Mar 17, 2021 at 3:04 PM Vincent Chen <vincent.chen@sifive.com> wrote:
>
> Add required ports of the Alternative scheme for SiFive.
>
> Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> ---
>  arch/riscv/Kconfig.erratas           | 11 ++++++
>  arch/riscv/Kconfig.socs              |  1 +
>  arch/riscv/errata/Makefile           |  1 +
>  arch/riscv/errata/alternative.c      |  5 +++
>  arch/riscv/errata/sifive/Makefile    |  1 +
>  arch/riscv/errata/sifive/errata.c    | 68 ++++++++++++++++++++++++++++++++++++
>  arch/riscv/include/asm/alternative.h |  3 ++
>  7 files changed, 90 insertions(+)
>  create mode 100644 arch/riscv/errata/sifive/Makefile
>  create mode 100644 arch/riscv/errata/sifive/errata.c
>
> diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> index 4d0bafc536df..e50ab67f4830 100644
> --- a/arch/riscv/Kconfig.erratas
> +++ b/arch/riscv/Kconfig.erratas
> @@ -9,4 +9,15 @@ config RISCV_ERRATA_ALTERNATIVE
>           code patching is performed once in the boot stages. It means
>           that the overhead from this mechanism is just taken once.
>
> +config ERRATA_SIFIVE
> +       bool "SiFive errata"
> +       depends on RISCV_ERRATA_ALTERNATIVE
> +       default y

Remove the "default y" here.

Let the ERRATA Kconfig be explicitly selected from riscv/Kconfig.socs

> +       help
> +         All SiFive errata Kconfig depend on this Kconfig. Disabling
> +         this Kconfig will disable all SiFive errata. Please say "Y"
> +         here if your platform uses SiFive CPU cores.
> +
> +         Otherwise, please say "N" here to avoid unnecessary overhead.
> +
>  endmenu
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 7efcece8896c..b9eda857fc87 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -7,6 +7,7 @@ config SOC_SIFIVE
>         select CLK_SIFIVE
>         select CLK_SIFIVE_PRCI
>         select SIFIVE_PLIC
> +       select ERRATA_SIFIVE
>         help
>           This enables support for SiFive SoC platform hardware.
>
> diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> index 43e6d5424367..b8f8740a3e44 100644
> --- a/arch/riscv/errata/Makefile
> +++ b/arch/riscv/errata/Makefile
> @@ -1 +1,2 @@
>  obj-y  += alternative.o
> +obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
> index 8efa60ad69b7..3b15885db70b 100644
> --- a/arch/riscv/errata/alternative.c
> +++ b/arch/riscv/errata/alternative.c
> @@ -42,6 +42,11 @@ static void __init init_alternative(void)
>         riscv_fill_cpu_mfr_info();
>
>         switch (cpu_mfr_info.vendor_id) {
> +#ifdef CONFIG_ERRATA_SIFIVE
> +       case SIFIVE_VENDOR_ID:
> +               vendor_patch_func = sifive_errata_patch_func;
> +               break;
> +#endif
>         default:
>                 vendor_patch_func = NULL;
>         }
> diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
> new file mode 100644
> index 000000000000..2d644e19caef
> --- /dev/null
> +++ b/arch/riscv/errata/sifive/Makefile
> @@ -0,0 +1 @@
> +obj-y += errata.o
> diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> new file mode 100644
> index 000000000000..826cd391fc55
> --- /dev/null
> +++ b/arch/riscv/errata/sifive/errata.c
> @@ -0,0 +1,68 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2021 Sifive.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/bug.h>
> +#include <asm/patch.h>
> +#include <asm/alternative.h>
> +#include <asm/vendorid_list.h>
> +#include <asm/errata_list.h>
> +
> +struct errata_info_t {
> +       char name[ERRATA_STRING_LENGTH_MAX];
> +       bool (*check_func)(unsigned long  arch_id, unsigned long impid);
> +};
> +
> +static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
> +{
> +       int idx;
> +       u32 cpu_req_errata = 0;
> +
> +       for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
> +               if (errata_list[idx].check_func(archid, impid))
> +                       cpu_req_errata |= (1U << idx);
> +
> +       return cpu_req_errata;
> +}
> +
> +static void __init warn_miss_errata(u32 miss_errata)
> +{
> +       int i;
> +
> +       pr_warn("----------------------------------------------------------------\n");
> +       pr_warn("WARNING: Missing the following errata may cause potential issues\n");
> +       for (i = 0; i < ERRATA_SIFIVE_NUMBER; i++)
> +               if (miss_errata & 0x1 << i)
> +                       pr_warn("\tSiFive Errata[%d]:%s\n", i, errata_list[i].name);
> +       pr_warn("Please enable the corresponding Kconfig to apply them\n");
> +       pr_warn("----------------------------------------------------------------\n");
> +}
> +
> +void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> +                                    unsigned long archid, unsigned long impid)
> +{
> +       struct alt_entry *alt;
> +       u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> +       u32 cpu_apply_errata = 0;
> +       u32 tmp;
> +
> +       for (alt = begin; alt < end; alt++) {
> +               if (alt->vendor_id != SIFIVE_VENDOR_ID)
> +                       continue;
> +               if (alt->errata_id >= ERRATA_SIFIVE_NUMBER) {
> +                       WARN(1, "This errata id:%d is not in kernel errata list", alt->errata_id);
> +                       continue;
> +               }
> +
> +               tmp = (1U << alt->errata_id);
> +               if (cpu_req_errata & tmp) {
> +                       patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> +                       cpu_apply_errata |= tmp;
> +               }
> +       }
> +       if (cpu_apply_errata != cpu_req_errata)
> +               warn_miss_errata(cpu_req_errata - cpu_apply_errata);
> +}
> diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> index 430bc4fea133..e625d3cafbed 100644
> --- a/arch/riscv/include/asm/alternative.h
> +++ b/arch/riscv/include/asm/alternative.h
> @@ -32,5 +32,8 @@ struct errata_checkfunc_id {
>         bool (*func)(struct alt_entry *alt);
>  };
>
> +void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> +                             unsigned long archid, unsigned long impid);
> +
>  #endif
>  #endif
> --
> 2.7.4
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

Apart from the minor comment above, this patch looks good to me.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup
Vincent Chen March 22, 2021, 12:26 a.m. UTC | #2
On Wed, Mar 17, 2021 at 7:43 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Wed, Mar 17, 2021 at 3:04 PM Vincent Chen <vincent.chen@sifive.com> wrote:
> >
> > Add required ports of the Alternative scheme for SiFive.
> >
> > Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> > ---
> >  arch/riscv/Kconfig.erratas           | 11 ++++++
> >  arch/riscv/Kconfig.socs              |  1 +
> >  arch/riscv/errata/Makefile           |  1 +
> >  arch/riscv/errata/alternative.c      |  5 +++
> >  arch/riscv/errata/sifive/Makefile    |  1 +
> >  arch/riscv/errata/sifive/errata.c    | 68 ++++++++++++++++++++++++++++++++++++
> >  arch/riscv/include/asm/alternative.h |  3 ++
> >  7 files changed, 90 insertions(+)
> >  create mode 100644 arch/riscv/errata/sifive/Makefile
> >  create mode 100644 arch/riscv/errata/sifive/errata.c
> >
> > diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> > index 4d0bafc536df..e50ab67f4830 100644
> > --- a/arch/riscv/Kconfig.erratas
> > +++ b/arch/riscv/Kconfig.erratas
> > @@ -9,4 +9,15 @@ config RISCV_ERRATA_ALTERNATIVE
> >           code patching is performed once in the boot stages. It means
> >           that the overhead from this mechanism is just taken once.
> >
> > +config ERRATA_SIFIVE
> > +       bool "SiFive errata"
> > +       depends on RISCV_ERRATA_ALTERNATIVE
> > +       default y
>
> Remove the "default y" here.
>
> Let the ERRATA Kconfig be explicitly selected from riscv/Kconfig.socs
>
This is a good suggestion. I will modify it in my next version patch.
Thank you,

> > +       help
> > +         All SiFive errata Kconfig depend on this Kconfig. Disabling
> > +         this Kconfig will disable all SiFive errata. Please say "Y"
> > +         here if your platform uses SiFive CPU cores.
> > +
> > +         Otherwise, please say "N" here to avoid unnecessary overhead.
> > +
> >  endmenu
> > diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> > index 7efcece8896c..b9eda857fc87 100644
> > --- a/arch/riscv/Kconfig.socs
> > +++ b/arch/riscv/Kconfig.socs
> > @@ -7,6 +7,7 @@ config SOC_SIFIVE
> >         select CLK_SIFIVE
> >         select CLK_SIFIVE_PRCI
> >         select SIFIVE_PLIC
> > +       select ERRATA_SIFIVE
> >         help
> >           This enables support for SiFive SoC platform hardware.
> >
> > diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> > index 43e6d5424367..b8f8740a3e44 100644
> > --- a/arch/riscv/errata/Makefile
> > +++ b/arch/riscv/errata/Makefile
> > @@ -1 +1,2 @@
> >  obj-y  += alternative.o
> > +obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> > diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
> > index 8efa60ad69b7..3b15885db70b 100644
> > --- a/arch/riscv/errata/alternative.c
> > +++ b/arch/riscv/errata/alternative.c
> > @@ -42,6 +42,11 @@ static void __init init_alternative(void)
> >         riscv_fill_cpu_mfr_info();
> >
> >         switch (cpu_mfr_info.vendor_id) {
> > +#ifdef CONFIG_ERRATA_SIFIVE
> > +       case SIFIVE_VENDOR_ID:
> > +               vendor_patch_func = sifive_errata_patch_func;
> > +               break;
> > +#endif
> >         default:
> >                 vendor_patch_func = NULL;
> >         }
> > diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
> > new file mode 100644
> > index 000000000000..2d644e19caef
> > --- /dev/null
> > +++ b/arch/riscv/errata/sifive/Makefile
> > @@ -0,0 +1 @@
> > +obj-y += errata.o
> > diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> > new file mode 100644
> > index 000000000000..826cd391fc55
> > --- /dev/null
> > +++ b/arch/riscv/errata/sifive/errata.c
> > @@ -0,0 +1,68 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (C) 2021 Sifive.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/string.h>
> > +#include <linux/bug.h>
> > +#include <asm/patch.h>
> > +#include <asm/alternative.h>
> > +#include <asm/vendorid_list.h>
> > +#include <asm/errata_list.h>
> > +
> > +struct errata_info_t {
> > +       char name[ERRATA_STRING_LENGTH_MAX];
> > +       bool (*check_func)(unsigned long  arch_id, unsigned long impid);
> > +};
> > +
> > +static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
> > +{
> > +       int idx;
> > +       u32 cpu_req_errata = 0;
> > +
> > +       for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
> > +               if (errata_list[idx].check_func(archid, impid))
> > +                       cpu_req_errata |= (1U << idx);
> > +
> > +       return cpu_req_errata;
> > +}
> > +
> > +static void __init warn_miss_errata(u32 miss_errata)
> > +{
> > +       int i;
> > +
> > +       pr_warn("----------------------------------------------------------------\n");
> > +       pr_warn("WARNING: Missing the following errata may cause potential issues\n");
> > +       for (i = 0; i < ERRATA_SIFIVE_NUMBER; i++)
> > +               if (miss_errata & 0x1 << i)
> > +                       pr_warn("\tSiFive Errata[%d]:%s\n", i, errata_list[i].name);
> > +       pr_warn("Please enable the corresponding Kconfig to apply them\n");
> > +       pr_warn("----------------------------------------------------------------\n");
> > +}
> > +
> > +void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > +                                    unsigned long archid, unsigned long impid)
> > +{
> > +       struct alt_entry *alt;
> > +       u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> > +       u32 cpu_apply_errata = 0;
> > +       u32 tmp;
> > +
> > +       for (alt = begin; alt < end; alt++) {
> > +               if (alt->vendor_id != SIFIVE_VENDOR_ID)
> > +                       continue;
> > +               if (alt->errata_id >= ERRATA_SIFIVE_NUMBER) {
> > +                       WARN(1, "This errata id:%d is not in kernel errata list", alt->errata_id);
> > +                       continue;
> > +               }
> > +
> > +               tmp = (1U << alt->errata_id);
> > +               if (cpu_req_errata & tmp) {
> > +                       patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> > +                       cpu_apply_errata |= tmp;
> > +               }
> > +       }
> > +       if (cpu_apply_errata != cpu_req_errata)
> > +               warn_miss_errata(cpu_req_errata - cpu_apply_errata);
> > +}
> > diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> > index 430bc4fea133..e625d3cafbed 100644
> > --- a/arch/riscv/include/asm/alternative.h
> > +++ b/arch/riscv/include/asm/alternative.h
> > @@ -32,5 +32,8 @@ struct errata_checkfunc_id {
> >         bool (*func)(struct alt_entry *alt);
> >  };
> >
> > +void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > +                             unsigned long archid, unsigned long impid);
> > +
> >  #endif
> >  #endif
> > --
> > 2.7.4
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
>
> Apart from the minor comment above, this patch looks good to me.
>
> Reviewed-by: Anup Patel <anup@brainfault.org>
>
> Regards,
> Anup
Vincent Chen March 22, 2021, 5:40 a.m. UTC | #3
On Mon, Mar 22, 2021 at 8:26 AM Vincent Chen <vincent.chen@sifive.com> wrote:
>
> On Wed, Mar 17, 2021 at 7:43 PM Anup Patel <anup@brainfault.org> wrote:
> >
> > On Wed, Mar 17, 2021 at 3:04 PM Vincent Chen <vincent.chen@sifive.com> wrote:
> > >
> > > Add required ports of the Alternative scheme for SiFive.
> > >
> > > Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> > > ---
> > >  arch/riscv/Kconfig.erratas           | 11 ++++++
> > >  arch/riscv/Kconfig.socs              |  1 +
> > >  arch/riscv/errata/Makefile           |  1 +
> > >  arch/riscv/errata/alternative.c      |  5 +++
> > >  arch/riscv/errata/sifive/Makefile    |  1 +
> > >  arch/riscv/errata/sifive/errata.c    | 68 ++++++++++++++++++++++++++++++++++++
> > >  arch/riscv/include/asm/alternative.h |  3 ++
> > >  7 files changed, 90 insertions(+)
> > >  create mode 100644 arch/riscv/errata/sifive/Makefile
> > >  create mode 100644 arch/riscv/errata/sifive/errata.c
> > >
> > > diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> > > index 4d0bafc536df..e50ab67f4830 100644
> > > --- a/arch/riscv/Kconfig.erratas
> > > +++ b/arch/riscv/Kconfig.erratas
> > > @@ -9,4 +9,15 @@ config RISCV_ERRATA_ALTERNATIVE
> > >           code patching is performed once in the boot stages. It means
> > >           that the overhead from this mechanism is just taken once.
> > >
> > > +config ERRATA_SIFIVE
> > > +       bool "SiFive errata"
> > > +       depends on RISCV_ERRATA_ALTERNATIVE
> > > +       default y
> >
> > Remove the "default y" here.
> >
> > Let the ERRATA Kconfig be explicitly selected from riscv/Kconfig.socs
> >
> This is a good suggestion. I will modify it in my next version patch.
> Thank you,
>
Sorry, I found the "default y" may not be removed here. It is because
SiFive's customers possibly only license our Core IP. In this case, it
does not enable CONFIG_SOC_SIFIVE. Therefore, I prefer to keep the
"default y" feature. (In this patch, I have made the CONFIG_SOC_SIFIVE
select the CONFIG_SOC_SIFIVE )

> > > +       help
> > > +         All SiFive errata Kconfig depend on this Kconfig. Disabling
> > > +         this Kconfig will disable all SiFive errata. Please say "Y"
> > > +         here if your platform uses SiFive CPU cores.
> > > +
> > > +         Otherwise, please say "N" here to avoid unnecessary overhead.
> > > +
> > >  endmenu
> > > diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> > > index 7efcece8896c..b9eda857fc87 100644
> > > --- a/arch/riscv/Kconfig.socs
> > > +++ b/arch/riscv/Kconfig.socs
> > > @@ -7,6 +7,7 @@ config SOC_SIFIVE
> > >         select CLK_SIFIVE
> > >         select CLK_SIFIVE_PRCI
> > >         select SIFIVE_PLIC
> > > +       select ERRATA_SIFIVE
> > >         help
> > >           This enables support for SiFive SoC platform hardware.
> > >
> > > diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> > > index 43e6d5424367..b8f8740a3e44 100644
> > > --- a/arch/riscv/errata/Makefile
> > > +++ b/arch/riscv/errata/Makefile
> > > @@ -1 +1,2 @@
> > >  obj-y  += alternative.o
> > > +obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> > > diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
> > > index 8efa60ad69b7..3b15885db70b 100644
> > > --- a/arch/riscv/errata/alternative.c
> > > +++ b/arch/riscv/errata/alternative.c
> > > @@ -42,6 +42,11 @@ static void __init init_alternative(void)
> > >         riscv_fill_cpu_mfr_info();
> > >
> > >         switch (cpu_mfr_info.vendor_id) {
> > > +#ifdef CONFIG_ERRATA_SIFIVE
> > > +       case SIFIVE_VENDOR_ID:
> > > +               vendor_patch_func = sifive_errata_patch_func;
> > > +               break;
> > > +#endif
> > >         default:
> > >                 vendor_patch_func = NULL;
> > >         }
> > > diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
> > > new file mode 100644
> > > index 000000000000..2d644e19caef
> > > --- /dev/null
> > > +++ b/arch/riscv/errata/sifive/Makefile
> > > @@ -0,0 +1 @@
> > > +obj-y += errata.o
> > > diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> > > new file mode 100644
> > > index 000000000000..826cd391fc55
> > > --- /dev/null
> > > +++ b/arch/riscv/errata/sifive/errata.c
> > > @@ -0,0 +1,68 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * Copyright (C) 2021 Sifive.
> > > + */
> > > +
> > > +#include <linux/kernel.h>
> > > +#include <linux/string.h>
> > > +#include <linux/bug.h>
> > > +#include <asm/patch.h>
> > > +#include <asm/alternative.h>
> > > +#include <asm/vendorid_list.h>
> > > +#include <asm/errata_list.h>
> > > +
> > > +struct errata_info_t {
> > > +       char name[ERRATA_STRING_LENGTH_MAX];
> > > +       bool (*check_func)(unsigned long  arch_id, unsigned long impid);
> > > +};
> > > +
> > > +static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
> > > +{
> > > +       int idx;
> > > +       u32 cpu_req_errata = 0;
> > > +
> > > +       for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
> > > +               if (errata_list[idx].check_func(archid, impid))
> > > +                       cpu_req_errata |= (1U << idx);
> > > +
> > > +       return cpu_req_errata;
> > > +}
> > > +
> > > +static void __init warn_miss_errata(u32 miss_errata)
> > > +{
> > > +       int i;
> > > +
> > > +       pr_warn("----------------------------------------------------------------\n");
> > > +       pr_warn("WARNING: Missing the following errata may cause potential issues\n");
> > > +       for (i = 0; i < ERRATA_SIFIVE_NUMBER; i++)
> > > +               if (miss_errata & 0x1 << i)
> > > +                       pr_warn("\tSiFive Errata[%d]:%s\n", i, errata_list[i].name);
> > > +       pr_warn("Please enable the corresponding Kconfig to apply them\n");
> > > +       pr_warn("----------------------------------------------------------------\n");
> > > +}
> > > +
> > > +void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > +                                    unsigned long archid, unsigned long impid)
> > > +{
> > > +       struct alt_entry *alt;
> > > +       u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> > > +       u32 cpu_apply_errata = 0;
> > > +       u32 tmp;
> > > +
> > > +       for (alt = begin; alt < end; alt++) {
> > > +               if (alt->vendor_id != SIFIVE_VENDOR_ID)
> > > +                       continue;
> > > +               if (alt->errata_id >= ERRATA_SIFIVE_NUMBER) {
> > > +                       WARN(1, "This errata id:%d is not in kernel errata list", alt->errata_id);
> > > +                       continue;
> > > +               }
> > > +
> > > +               tmp = (1U << alt->errata_id);
> > > +               if (cpu_req_errata & tmp) {
> > > +                       patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> > > +                       cpu_apply_errata |= tmp;
> > > +               }
> > > +       }
> > > +       if (cpu_apply_errata != cpu_req_errata)
> > > +               warn_miss_errata(cpu_req_errata - cpu_apply_errata);
> > > +}
> > > diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> > > index 430bc4fea133..e625d3cafbed 100644
> > > --- a/arch/riscv/include/asm/alternative.h
> > > +++ b/arch/riscv/include/asm/alternative.h
> > > @@ -32,5 +32,8 @@ struct errata_checkfunc_id {
> > >         bool (*func)(struct alt_entry *alt);
> > >  };
> > >
> > > +void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > +                             unsigned long archid, unsigned long impid);
> > > +
> > >  #endif
> > >  #endif
> > > --
> > > 2.7.4
> > >
> > >
> > > _______________________________________________
> > > linux-riscv mailing list
> > > linux-riscv@lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> >
> > Apart from the minor comment above, this patch looks good to me.
> >
> > Reviewed-by: Anup Patel <anup@brainfault.org>
> >
> > Regards,
> > Anup
Anup Patel March 22, 2021, 6:08 a.m. UTC | #4
On Mon, Mar 22, 2021 at 11:10 AM Vincent Chen <vincent.chen@sifive.com> wrote:
>
> On Mon, Mar 22, 2021 at 8:26 AM Vincent Chen <vincent.chen@sifive.com> wrote:
> >
> > On Wed, Mar 17, 2021 at 7:43 PM Anup Patel <anup@brainfault.org> wrote:
> > >
> > > On Wed, Mar 17, 2021 at 3:04 PM Vincent Chen <vincent.chen@sifive.com> wrote:
> > > >
> > > > Add required ports of the Alternative scheme for SiFive.
> > > >
> > > > Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> > > > ---
> > > >  arch/riscv/Kconfig.erratas           | 11 ++++++
> > > >  arch/riscv/Kconfig.socs              |  1 +
> > > >  arch/riscv/errata/Makefile           |  1 +
> > > >  arch/riscv/errata/alternative.c      |  5 +++
> > > >  arch/riscv/errata/sifive/Makefile    |  1 +
> > > >  arch/riscv/errata/sifive/errata.c    | 68 ++++++++++++++++++++++++++++++++++++
> > > >  arch/riscv/include/asm/alternative.h |  3 ++
> > > >  7 files changed, 90 insertions(+)
> > > >  create mode 100644 arch/riscv/errata/sifive/Makefile
> > > >  create mode 100644 arch/riscv/errata/sifive/errata.c
> > > >
> > > > diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> > > > index 4d0bafc536df..e50ab67f4830 100644
> > > > --- a/arch/riscv/Kconfig.erratas
> > > > +++ b/arch/riscv/Kconfig.erratas
> > > > @@ -9,4 +9,15 @@ config RISCV_ERRATA_ALTERNATIVE
> > > >           code patching is performed once in the boot stages. It means
> > > >           that the overhead from this mechanism is just taken once.
> > > >
> > > > +config ERRATA_SIFIVE
> > > > +       bool "SiFive errata"
> > > > +       depends on RISCV_ERRATA_ALTERNATIVE
> > > > +       default y
> > >
> > > Remove the "default y" here.
> > >
> > > Let the ERRATA Kconfig be explicitly selected from riscv/Kconfig.socs
> > >
> > This is a good suggestion. I will modify it in my next version patch.
> > Thank you,
> >
> Sorry, I found the "default y" may not be removed here. It is because
> SiFive's customers possibly only license our Core IP. In this case, it
> does not enable CONFIG_SOC_SIFIVE. Therefore, I prefer to keep the
> "default y" feature. (In this patch, I have made the CONFIG_SOC_SIFIVE
> select the CONFIG_SOC_SIFIVE )

If you are using SiFive IP for your <xyz> SOC then your
CONFIG_SOC_<xyz> in Kconfig option should select
ERRATA_SIFIVE

Basically, SOC Kconfig options should explicitly select required
ERRATA configs so that if someone wants to disable ERRATs from
menuconfig then it can be easily done without knowledge of which
SOCs need which ERRATAs.

Regards,
Anup

>
> > > > +       help
> > > > +         All SiFive errata Kconfig depend on this Kconfig. Disabling
> > > > +         this Kconfig will disable all SiFive errata. Please say "Y"
> > > > +         here if your platform uses SiFive CPU cores.
> > > > +
> > > > +         Otherwise, please say "N" here to avoid unnecessary overhead.
> > > > +
> > > >  endmenu
> > > > diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> > > > index 7efcece8896c..b9eda857fc87 100644
> > > > --- a/arch/riscv/Kconfig.socs
> > > > +++ b/arch/riscv/Kconfig.socs
> > > > @@ -7,6 +7,7 @@ config SOC_SIFIVE
> > > >         select CLK_SIFIVE
> > > >         select CLK_SIFIVE_PRCI
> > > >         select SIFIVE_PLIC
> > > > +       select ERRATA_SIFIVE
> > > >         help
> > > >           This enables support for SiFive SoC platform hardware.
> > > >
> > > > diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> > > > index 43e6d5424367..b8f8740a3e44 100644
> > > > --- a/arch/riscv/errata/Makefile
> > > > +++ b/arch/riscv/errata/Makefile
> > > > @@ -1 +1,2 @@
> > > >  obj-y  += alternative.o
> > > > +obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> > > > diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
> > > > index 8efa60ad69b7..3b15885db70b 100644
> > > > --- a/arch/riscv/errata/alternative.c
> > > > +++ b/arch/riscv/errata/alternative.c
> > > > @@ -42,6 +42,11 @@ static void __init init_alternative(void)
> > > >         riscv_fill_cpu_mfr_info();
> > > >
> > > >         switch (cpu_mfr_info.vendor_id) {
> > > > +#ifdef CONFIG_ERRATA_SIFIVE
> > > > +       case SIFIVE_VENDOR_ID:
> > > > +               vendor_patch_func = sifive_errata_patch_func;
> > > > +               break;
> > > > +#endif
> > > >         default:
> > > >                 vendor_patch_func = NULL;
> > > >         }
> > > > diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
> > > > new file mode 100644
> > > > index 000000000000..2d644e19caef
> > > > --- /dev/null
> > > > +++ b/arch/riscv/errata/sifive/Makefile
> > > > @@ -0,0 +1 @@
> > > > +obj-y += errata.o
> > > > diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> > > > new file mode 100644
> > > > index 000000000000..826cd391fc55
> > > > --- /dev/null
> > > > +++ b/arch/riscv/errata/sifive/errata.c
> > > > @@ -0,0 +1,68 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-only
> > > > +/*
> > > > + * Copyright (C) 2021 Sifive.
> > > > + */
> > > > +
> > > > +#include <linux/kernel.h>
> > > > +#include <linux/string.h>
> > > > +#include <linux/bug.h>
> > > > +#include <asm/patch.h>
> > > > +#include <asm/alternative.h>
> > > > +#include <asm/vendorid_list.h>
> > > > +#include <asm/errata_list.h>
> > > > +
> > > > +struct errata_info_t {
> > > > +       char name[ERRATA_STRING_LENGTH_MAX];
> > > > +       bool (*check_func)(unsigned long  arch_id, unsigned long impid);
> > > > +};
> > > > +
> > > > +static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
> > > > +{
> > > > +       int idx;
> > > > +       u32 cpu_req_errata = 0;
> > > > +
> > > > +       for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
> > > > +               if (errata_list[idx].check_func(archid, impid))
> > > > +                       cpu_req_errata |= (1U << idx);
> > > > +
> > > > +       return cpu_req_errata;
> > > > +}
> > > > +
> > > > +static void __init warn_miss_errata(u32 miss_errata)
> > > > +{
> > > > +       int i;
> > > > +
> > > > +       pr_warn("----------------------------------------------------------------\n");
> > > > +       pr_warn("WARNING: Missing the following errata may cause potential issues\n");
> > > > +       for (i = 0; i < ERRATA_SIFIVE_NUMBER; i++)
> > > > +               if (miss_errata & 0x1 << i)
> > > > +                       pr_warn("\tSiFive Errata[%d]:%s\n", i, errata_list[i].name);
> > > > +       pr_warn("Please enable the corresponding Kconfig to apply them\n");
> > > > +       pr_warn("----------------------------------------------------------------\n");
> > > > +}
> > > > +
> > > > +void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > > +                                    unsigned long archid, unsigned long impid)
> > > > +{
> > > > +       struct alt_entry *alt;
> > > > +       u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> > > > +       u32 cpu_apply_errata = 0;
> > > > +       u32 tmp;
> > > > +
> > > > +       for (alt = begin; alt < end; alt++) {
> > > > +               if (alt->vendor_id != SIFIVE_VENDOR_ID)
> > > > +                       continue;
> > > > +               if (alt->errata_id >= ERRATA_SIFIVE_NUMBER) {
> > > > +                       WARN(1, "This errata id:%d is not in kernel errata list", alt->errata_id);
> > > > +                       continue;
> > > > +               }
> > > > +
> > > > +               tmp = (1U << alt->errata_id);
> > > > +               if (cpu_req_errata & tmp) {
> > > > +                       patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> > > > +                       cpu_apply_errata |= tmp;
> > > > +               }
> > > > +       }
> > > > +       if (cpu_apply_errata != cpu_req_errata)
> > > > +               warn_miss_errata(cpu_req_errata - cpu_apply_errata);
> > > > +}
> > > > diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> > > > index 430bc4fea133..e625d3cafbed 100644
> > > > --- a/arch/riscv/include/asm/alternative.h
> > > > +++ b/arch/riscv/include/asm/alternative.h
> > > > @@ -32,5 +32,8 @@ struct errata_checkfunc_id {
> > > >         bool (*func)(struct alt_entry *alt);
> > > >  };
> > > >
> > > > +void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > > +                             unsigned long archid, unsigned long impid);
> > > > +
> > > >  #endif
> > > >  #endif
> > > > --
> > > > 2.7.4
> > > >
> > > >
> > > > _______________________________________________
> > > > linux-riscv mailing list
> > > > linux-riscv@lists.infradead.org
> > > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> > >
> > > Apart from the minor comment above, this patch looks good to me.
> > >
> > > Reviewed-by: Anup Patel <anup@brainfault.org>
> > >
> > > Regards,
> > > Anup
Vincent Chen March 22, 2021, 7:50 a.m. UTC | #5
On Mon, Mar 22, 2021 at 2:08 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Mon, Mar 22, 2021 at 11:10 AM Vincent Chen <vincent.chen@sifive.com> wrote:
> >
> > On Mon, Mar 22, 2021 at 8:26 AM Vincent Chen <vincent.chen@sifive.com> wrote:
> > >
> > > On Wed, Mar 17, 2021 at 7:43 PM Anup Patel <anup@brainfault.org> wrote:
> > > >
> > > > On Wed, Mar 17, 2021 at 3:04 PM Vincent Chen <vincent.chen@sifive.com> wrote:
> > > > >
> > > > > Add required ports of the Alternative scheme for SiFive.
> > > > >
> > > > > Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> > > > > ---
> > > > >  arch/riscv/Kconfig.erratas           | 11 ++++++
> > > > >  arch/riscv/Kconfig.socs              |  1 +
> > > > >  arch/riscv/errata/Makefile           |  1 +
> > > > >  arch/riscv/errata/alternative.c      |  5 +++
> > > > >  arch/riscv/errata/sifive/Makefile    |  1 +
> > > > >  arch/riscv/errata/sifive/errata.c    | 68 ++++++++++++++++++++++++++++++++++++
> > > > >  arch/riscv/include/asm/alternative.h |  3 ++
> > > > >  7 files changed, 90 insertions(+)
> > > > >  create mode 100644 arch/riscv/errata/sifive/Makefile
> > > > >  create mode 100644 arch/riscv/errata/sifive/errata.c
> > > > >
> > > > > diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> > > > > index 4d0bafc536df..e50ab67f4830 100644
> > > > > --- a/arch/riscv/Kconfig.erratas
> > > > > +++ b/arch/riscv/Kconfig.erratas
> > > > > @@ -9,4 +9,15 @@ config RISCV_ERRATA_ALTERNATIVE
> > > > >           code patching is performed once in the boot stages. It means
> > > > >           that the overhead from this mechanism is just taken once.
> > > > >
> > > > > +config ERRATA_SIFIVE
> > > > > +       bool "SiFive errata"
> > > > > +       depends on RISCV_ERRATA_ALTERNATIVE
> > > > > +       default y
> > > >
> > > > Remove the "default y" here.
> > > >
> > > > Let the ERRATA Kconfig be explicitly selected from riscv/Kconfig.socs
> > > >
> > > This is a good suggestion. I will modify it in my next version patch.
> > > Thank you,
> > >
> > Sorry, I found the "default y" may not be removed here. It is because
> > SiFive's customers possibly only license our Core IP. In this case, it
> > does not enable CONFIG_SOC_SIFIVE. Therefore, I prefer to keep the
> > "default y" feature. (In this patch, I have made the CONFIG_SOC_SIFIVE
> > select the CONFIG_SOC_SIFIVE )
>
> If you are using SiFive IP for your <xyz> SOC then your
> CONFIG_SOC_<xyz> in Kconfig option should select
> ERRATA_SIFIVE
>
> Basically, SOC Kconfig options should explicitly select required
> ERRATA configs so that if someone wants to disable ERRATs from
> menuconfig then it can be easily done without knowledge of which
> SOCs need which ERRATAs.
>
> Regards,
> Anup
>
I got it. I will remove it in my next version patch.
Thank you for the explanation.

Best regards,
Vincent

> >
> > > > > +       help
> > > > > +         All SiFive errata Kconfig depend on this Kconfig. Disabling
> > > > > +         this Kconfig will disable all SiFive errata. Please say "Y"
> > > > > +         here if your platform uses SiFive CPU cores.
> > > > > +
> > > > > +         Otherwise, please say "N" here to avoid unnecessary overhead.
> > > > > +
> > > > >  endmenu
> > > > > diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> > > > > index 7efcece8896c..b9eda857fc87 100644
> > > > > --- a/arch/riscv/Kconfig.socs
> > > > > +++ b/arch/riscv/Kconfig.socs
> > > > > @@ -7,6 +7,7 @@ config SOC_SIFIVE
> > > > >         select CLK_SIFIVE
> > > > >         select CLK_SIFIVE_PRCI
> > > > >         select SIFIVE_PLIC
> > > > > +       select ERRATA_SIFIVE
> > > > >         help
> > > > >           This enables support for SiFive SoC platform hardware.
> > > > >
> > > > > diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> > > > > index 43e6d5424367..b8f8740a3e44 100644
> > > > > --- a/arch/riscv/errata/Makefile
> > > > > +++ b/arch/riscv/errata/Makefile
> > > > > @@ -1 +1,2 @@
> > > > >  obj-y  += alternative.o
> > > > > +obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> > > > > diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
> > > > > index 8efa60ad69b7..3b15885db70b 100644
> > > > > --- a/arch/riscv/errata/alternative.c
> > > > > +++ b/arch/riscv/errata/alternative.c
> > > > > @@ -42,6 +42,11 @@ static void __init init_alternative(void)
> > > > >         riscv_fill_cpu_mfr_info();
> > > > >
> > > > >         switch (cpu_mfr_info.vendor_id) {
> > > > > +#ifdef CONFIG_ERRATA_SIFIVE
> > > > > +       case SIFIVE_VENDOR_ID:
> > > > > +               vendor_patch_func = sifive_errata_patch_func;
> > > > > +               break;
> > > > > +#endif
> > > > >         default:
> > > > >                 vendor_patch_func = NULL;
> > > > >         }
> > > > > diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
> > > > > new file mode 100644
> > > > > index 000000000000..2d644e19caef
> > > > > --- /dev/null
> > > > > +++ b/arch/riscv/errata/sifive/Makefile
> > > > > @@ -0,0 +1 @@
> > > > > +obj-y += errata.o
> > > > > diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> > > > > new file mode 100644
> > > > > index 000000000000..826cd391fc55
> > > > > --- /dev/null
> > > > > +++ b/arch/riscv/errata/sifive/errata.c
> > > > > @@ -0,0 +1,68 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0-only
> > > > > +/*
> > > > > + * Copyright (C) 2021 Sifive.
> > > > > + */
> > > > > +
> > > > > +#include <linux/kernel.h>
> > > > > +#include <linux/string.h>
> > > > > +#include <linux/bug.h>
> > > > > +#include <asm/patch.h>
> > > > > +#include <asm/alternative.h>
> > > > > +#include <asm/vendorid_list.h>
> > > > > +#include <asm/errata_list.h>
> > > > > +
> > > > > +struct errata_info_t {
> > > > > +       char name[ERRATA_STRING_LENGTH_MAX];
> > > > > +       bool (*check_func)(unsigned long  arch_id, unsigned long impid);
> > > > > +};
> > > > > +
> > > > > +static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
> > > > > +{
> > > > > +       int idx;
> > > > > +       u32 cpu_req_errata = 0;
> > > > > +
> > > > > +       for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
> > > > > +               if (errata_list[idx].check_func(archid, impid))
> > > > > +                       cpu_req_errata |= (1U << idx);
> > > > > +
> > > > > +       return cpu_req_errata;
> > > > > +}
> > > > > +
> > > > > +static void __init warn_miss_errata(u32 miss_errata)
> > > > > +{
> > > > > +       int i;
> > > > > +
> > > > > +       pr_warn("----------------------------------------------------------------\n");
> > > > > +       pr_warn("WARNING: Missing the following errata may cause potential issues\n");
> > > > > +       for (i = 0; i < ERRATA_SIFIVE_NUMBER; i++)
> > > > > +               if (miss_errata & 0x1 << i)
> > > > > +                       pr_warn("\tSiFive Errata[%d]:%s\n", i, errata_list[i].name);
> > > > > +       pr_warn("Please enable the corresponding Kconfig to apply them\n");
> > > > > +       pr_warn("----------------------------------------------------------------\n");
> > > > > +}
> > > > > +
> > > > > +void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > > > +                                    unsigned long archid, unsigned long impid)
> > > > > +{
> > > > > +       struct alt_entry *alt;
> > > > > +       u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> > > > > +       u32 cpu_apply_errata = 0;
> > > > > +       u32 tmp;
> > > > > +
> > > > > +       for (alt = begin; alt < end; alt++) {
> > > > > +               if (alt->vendor_id != SIFIVE_VENDOR_ID)
> > > > > +                       continue;
> > > > > +               if (alt->errata_id >= ERRATA_SIFIVE_NUMBER) {
> > > > > +                       WARN(1, "This errata id:%d is not in kernel errata list", alt->errata_id);
> > > > > +                       continue;
> > > > > +               }
> > > > > +
> > > > > +               tmp = (1U << alt->errata_id);
> > > > > +               if (cpu_req_errata & tmp) {
> > > > > +                       patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> > > > > +                       cpu_apply_errata |= tmp;
> > > > > +               }
> > > > > +       }
> > > > > +       if (cpu_apply_errata != cpu_req_errata)
> > > > > +               warn_miss_errata(cpu_req_errata - cpu_apply_errata);
> > > > > +}
> > > > > diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> > > > > index 430bc4fea133..e625d3cafbed 100644
> > > > > --- a/arch/riscv/include/asm/alternative.h
> > > > > +++ b/arch/riscv/include/asm/alternative.h
> > > > > @@ -32,5 +32,8 @@ struct errata_checkfunc_id {
> > > > >         bool (*func)(struct alt_entry *alt);
> > > > >  };
> > > > >
> > > > > +void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > > > +                             unsigned long archid, unsigned long impid);
> > > > > +
> > > > >  #endif
> > > > >  #endif
> > > > > --
> > > > > 2.7.4
> > > > >
> > > > >
> > > > > _______________________________________________
> > > > > linux-riscv mailing list
> > > > > linux-riscv@lists.infradead.org
> > > > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> > > >
> > > > Apart from the minor comment above, this patch looks good to me.
> > > >
> > > > Reviewed-by: Anup Patel <anup@brainfault.org>
> > > >
> > > > Regards,
> > > > Anup
diff mbox series

Patch

diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
index 4d0bafc536df..e50ab67f4830 100644
--- a/arch/riscv/Kconfig.erratas
+++ b/arch/riscv/Kconfig.erratas
@@ -9,4 +9,15 @@  config RISCV_ERRATA_ALTERNATIVE
 	  code patching is performed once in the boot stages. It means
 	  that the overhead from this mechanism is just taken once.
 
+config ERRATA_SIFIVE
+	bool "SiFive errata"
+	depends on RISCV_ERRATA_ALTERNATIVE
+	default y
+	help
+	  All SiFive errata Kconfig depend on this Kconfig. Disabling
+	  this Kconfig will disable all SiFive errata. Please say "Y"
+	  here if your platform uses SiFive CPU cores.
+
+	  Otherwise, please say "N" here to avoid unnecessary overhead.
+
 endmenu
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 7efcece8896c..b9eda857fc87 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -7,6 +7,7 @@  config SOC_SIFIVE
 	select CLK_SIFIVE
 	select CLK_SIFIVE_PRCI
 	select SIFIVE_PLIC
+	select ERRATA_SIFIVE
 	help
 	  This enables support for SiFive SoC platform hardware.
 
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
index 43e6d5424367..b8f8740a3e44 100644
--- a/arch/riscv/errata/Makefile
+++ b/arch/riscv/errata/Makefile
@@ -1 +1,2 @@ 
 obj-y	+= alternative.o
+obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
index 8efa60ad69b7..3b15885db70b 100644
--- a/arch/riscv/errata/alternative.c
+++ b/arch/riscv/errata/alternative.c
@@ -42,6 +42,11 @@  static void __init init_alternative(void)
 	riscv_fill_cpu_mfr_info();
 
 	switch (cpu_mfr_info.vendor_id) {
+#ifdef CONFIG_ERRATA_SIFIVE
+	case SIFIVE_VENDOR_ID:
+		vendor_patch_func = sifive_errata_patch_func;
+		break;
+#endif
 	default:
 		vendor_patch_func = NULL;
 	}
diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
new file mode 100644
index 000000000000..2d644e19caef
--- /dev/null
+++ b/arch/riscv/errata/sifive/Makefile
@@ -0,0 +1 @@ 
+obj-y += errata.o
diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
new file mode 100644
index 000000000000..826cd391fc55
--- /dev/null
+++ b/arch/riscv/errata/sifive/errata.c
@@ -0,0 +1,68 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Sifive.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/bug.h>
+#include <asm/patch.h>
+#include <asm/alternative.h>
+#include <asm/vendorid_list.h>
+#include <asm/errata_list.h>
+
+struct errata_info_t {
+	char name[ERRATA_STRING_LENGTH_MAX];
+	bool (*check_func)(unsigned long  arch_id, unsigned long impid);
+};
+
+static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
+{
+	int idx;
+	u32 cpu_req_errata = 0;
+
+	for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
+		if (errata_list[idx].check_func(archid, impid))
+			cpu_req_errata |= (1U << idx);
+
+	return cpu_req_errata;
+}
+
+static void __init warn_miss_errata(u32 miss_errata)
+{
+	int i;
+
+	pr_warn("----------------------------------------------------------------\n");
+	pr_warn("WARNING: Missing the following errata may cause potential issues\n");
+	for (i = 0; i < ERRATA_SIFIVE_NUMBER; i++)
+		if (miss_errata & 0x1 << i)
+			pr_warn("\tSiFive Errata[%d]:%s\n", i, errata_list[i].name);
+	pr_warn("Please enable the corresponding Kconfig to apply them\n");
+	pr_warn("----------------------------------------------------------------\n");
+}
+
+void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+				     unsigned long archid, unsigned long impid)
+{
+	struct alt_entry *alt;
+	u32 cpu_req_errata = sifive_errata_probe(archid, impid);
+	u32 cpu_apply_errata = 0;
+	u32 tmp;
+
+	for (alt = begin; alt < end; alt++) {
+		if (alt->vendor_id != SIFIVE_VENDOR_ID)
+			continue;
+		if (alt->errata_id >= ERRATA_SIFIVE_NUMBER) {
+			WARN(1, "This errata id:%d is not in kernel errata list", alt->errata_id);
+			continue;
+		}
+
+		tmp = (1U << alt->errata_id);
+		if (cpu_req_errata & tmp) {
+			patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
+			cpu_apply_errata |= tmp;
+		}
+	}
+	if (cpu_apply_errata != cpu_req_errata)
+		warn_miss_errata(cpu_req_errata - cpu_apply_errata);
+}
diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
index 430bc4fea133..e625d3cafbed 100644
--- a/arch/riscv/include/asm/alternative.h
+++ b/arch/riscv/include/asm/alternative.h
@@ -32,5 +32,8 @@  struct errata_checkfunc_id {
 	bool (*func)(struct alt_entry *alt);
 };
 
+void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+			      unsigned long archid, unsigned long impid);
+
 #endif
 #endif