Re: [PATCH v2] lib: sbi: Allow platforms to override local TLB operations
Anup Patel <[email protected]>
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <CAAhSdy0Qx=KVVUcBHX4t2TudLMczohF+27OXg6LyQG6dWQoVBA@mail.gmail.com> |
On Wed, Jun 17, 2026 at 5:00 PM Xiang W <[email protected]> wrote: > > Some T-Head based processors, for example the Sophgo SG2044, have a > JTLB errata that requires special handling of certain TLB maintenance > instructions (sfence.vma). > > Introduce a sbi_tlb_local_operations structure so platforms can provide > custom local TLB flush implementations. Use it to implement the JTLB > workaround on affected SoCs (currently Sophgo SG2044). > > Signed-off-by: Xiang W <[email protected]> > Signed-off-by: Han Gao <[email protected]> LGTM. Reviewed-by: Anup Patel <[email protected]> Applied this patch to the riscv/opensbi repo. As as separate patch, we should remove the get_tlbr_flush_limit() from sbi_platform_operations and instead use this new mechanism to overwrite the local TLB flush behaviour for SiFive FU540 adn FU740. Thanks, Anup > --- > include/sbi/sbi_tlb.h | 31 +++++++++++++ > lib/sbi/sbi_tlb.c | 46 +++++++++++++++++--- > platform/generic/include/thead/c9xx_errata.h | 1 + > platform/generic/thead/thead-generic.c | 31 ++++++++++++- > 4 files changed, 101 insertions(+), 8 deletions(-) > > diff --git a/include/sbi/sbi_tlb.h b/include/sbi/sbi_tlb.h > index 3936e857..0d2198ab 100644 > --- a/include/sbi/sbi_tlb.h > +++ b/include/sbi/sbi_tlb.h > @@ -54,6 +54,37 @@ do { \ > > #define SBI_TLB_INFO_SIZE sizeof(struct sbi_tlb_info) > > +/** Collection of Local TLB operations */ > +struct sbi_tlb_local_operations { > + /** Local fence.i */ > + void (*local_fence_i)(struct sbi_tlb_info *tinfo); > + > + /** Local supervisor-mode TLB flush */ > + void (*local_sfence_vma)(struct sbi_tlb_info *tinfo); > + > + /** Local supervisor-mode TLB flush with ASID */ > + void (*local_sfence_vma_asid)(struct sbi_tlb_info *tinfo); > + > + /** Local G-stage TLB flush for a specific VMID */ > + void (*local_hfence_gvma_vmid)(struct sbi_tlb_info *tinfo); > + > + /** Local G-stage TLB flush */ > + void (*local_hfence_gvma)(struct sbi_tlb_info *tinfo); > + > + /** Local VS-stage TLB flush with ASID */ > + void (*local_hfence_vvma_asid)(struct sbi_tlb_info *tinfo); > + > + /** Local VS-stage TLB flush */ > + void (*local_hfence_vvma)(struct sbi_tlb_info *tinfo); > +}; > + > +/** Get the local TLB operations */ > +const struct sbi_tlb_local_operations *sbi_tlb_get_local_operations(void); > + > +/** Set the local TLB operations */ > +void sbi_tlb_set_local_operations( > + const struct sbi_tlb_local_operations *ops); > + > void __sbi_sfence_vma_all(); > > int sbi_tlb_request(ulong hmask, ulong hbase, struct sbi_tlb_info *tinfo); > diff --git a/lib/sbi/sbi_tlb.c b/lib/sbi/sbi_tlb.c > index ada60c32..ab1e3a99 100644 > --- a/lib/sbi/sbi_tlb.c > +++ b/lib/sbi/sbi_tlb.c > @@ -29,6 +29,38 @@ static unsigned long tlb_fifo_off; > static unsigned long tlb_fifo_mem_off; > static unsigned long tlb_range_flush_limit; > > +static void sbi_tlb_local_fence_i(struct sbi_tlb_info *tinfo); > +static void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo); > +static void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo); > +static void sbi_tlb_local_hfence_gvma_vmid(struct sbi_tlb_info *tinfo); > +static void sbi_tlb_local_hfence_gvma(struct sbi_tlb_info *tinfo); > +static void sbi_tlb_local_hfence_vvma_asid(struct sbi_tlb_info *tinfo); > +static void sbi_tlb_local_hfence_vvma(struct sbi_tlb_info *tinfo); > + > +static struct sbi_tlb_local_operations default_tlb_local_ops = { > + .local_fence_i = sbi_tlb_local_fence_i, > + .local_sfence_vma = sbi_tlb_local_sfence_vma, > + .local_sfence_vma_asid = sbi_tlb_local_sfence_vma_asid, > + .local_hfence_gvma_vmid = sbi_tlb_local_hfence_gvma_vmid, > + .local_hfence_gvma = sbi_tlb_local_hfence_gvma, > + .local_hfence_vvma_asid = sbi_tlb_local_hfence_vvma_asid, > + .local_hfence_vvma = sbi_tlb_local_hfence_vvma > +}; > + > +static const struct sbi_tlb_local_operations *tlb_local_ops = > + &default_tlb_local_ops; > + > +const struct sbi_tlb_local_operations *sbi_tlb_get_local_operations(void) > +{ > + return tlb_local_ops; > +} > + > +void sbi_tlb_set_local_operations( > + const struct sbi_tlb_local_operations *ops) > +{ > + tlb_local_ops = ops; > +} > + > void __sbi_sfence_vma_all(void) > { > __asm__ __volatile("sfence.vma"); > @@ -183,25 +215,25 @@ static void tlb_entry_local_process(struct sbi_tlb_info *data) > > switch (data->type) { > case SBI_TLB_FENCE_I: > - sbi_tlb_local_fence_i(data); > + tlb_local_ops->local_fence_i(data); > break; > case SBI_TLB_SFENCE_VMA: > - sbi_tlb_local_sfence_vma(data); > + tlb_local_ops->local_sfence_vma(data); > break; > case SBI_TLB_SFENCE_VMA_ASID: > - sbi_tlb_local_sfence_vma_asid(data); > + tlb_local_ops->local_sfence_vma_asid(data); > break; > case SBI_TLB_HFENCE_GVMA_VMID: > - sbi_tlb_local_hfence_gvma_vmid(data); > + tlb_local_ops->local_hfence_gvma_vmid(data); > break; > case SBI_TLB_HFENCE_GVMA: > - sbi_tlb_local_hfence_gvma(data); > + tlb_local_ops->local_hfence_gvma(data); > break; > case SBI_TLB_HFENCE_VVMA_ASID: > - sbi_tlb_local_hfence_vvma_asid(data); > + tlb_local_ops->local_hfence_vvma_asid(data); > break; > case SBI_TLB_HFENCE_VVMA: > - sbi_tlb_local_hfence_vvma(data); > + tlb_local_ops->local_hfence_vvma(data); > break; > default: > break; > diff --git a/platform/generic/include/thead/c9xx_errata.h b/platform/generic/include/thead/c9xx_errata.h > index 40c1587b..7a419e41 100644 > --- a/platform/generic/include/thead/c9xx_errata.h > +++ b/platform/generic/include/thead/c9xx_errata.h > @@ -8,6 +8,7 @@ > */ > #define THEAD_QUIRK_ERRATA_TLB_FLUSH BIT(0) > #define THEAD_QUIRK_ERRATA_THEAD_PMU BIT(1) > +#define THEAD_QUIRK_ERRATA_JTLB BIT(2) > > void thead_register_tlb_flush_trap_handler(void); > > diff --git a/platform/generic/thead/thead-generic.c b/platform/generic/thead/thead-generic.c > index ddb4f0bf..8ec90746 100644 > --- a/platform/generic/thead/thead-generic.c > +++ b/platform/generic/thead/thead-generic.c > @@ -11,8 +11,10 @@ > #include <thead/c9xx_pmu.h> > #include <sbi/sbi_const.h> > #include <sbi/sbi_platform.h> > +#include <sbi/sbi_pmu.h> > #include <sbi/sbi_scratch.h> > #include <sbi/sbi_string.h> > +#include <sbi/sbi_tlb.h> > #include <sbi_utils/fdt/fdt_helper.h> > > struct thead_generic_quirks { > @@ -39,15 +41,38 @@ static int thead_pmu_extensions_init(struct sbi_hart_features *hfeatures) > return 0; > } > > +static void thead_jtlb_local_sfence_vma(struct sbi_tlb_info *tinfo) > +{ > + sbi_pmu_ctr_incr_fw(SBI_PMU_FW_SFENCE_VMA_RCVD); > + __asm__ __volatile__("sfence.vma"); > +} > + > +static void thead_jtlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo) > +{ > + sbi_pmu_ctr_incr_fw(SBI_PMU_FW_SFENCE_VMA_ASID_RCVD); > + /* Flush entire MM context for a given ASID */ > + __asm__ __volatile__("sfence.vma x0, %0" > + : > + : "r"(tinfo->asid) > + : "memory"); > +} > + > static int thead_generic_platform_init(const void *fdt, int nodeoff, > const struct fdt_match *match) > { > const struct thead_generic_quirks *quirks = match->data; > + static struct sbi_tlb_local_operations tlb_local_ops; > > if (quirks->errata & THEAD_QUIRK_ERRATA_TLB_FLUSH) > generic_platform_ops.early_init = thead_tlb_flush_early_init; > if (quirks->errata & THEAD_QUIRK_ERRATA_THEAD_PMU) > generic_platform_ops.extensions_init = thead_pmu_extensions_init; > + if (quirks->errata &THEAD_QUIRK_ERRATA_JTLB) { > + sbi_memcpy(&tlb_local_ops, sbi_tlb_get_local_operations(), sizeof(tlb_local_ops)); > + tlb_local_ops.local_sfence_vma = thead_jtlb_local_sfence_vma; > + tlb_local_ops.local_sfence_vma_asid = thead_jtlb_local_sfence_vma_asid; > + sbi_tlb_set_local_operations(&tlb_local_ops); > + } > > return 0; > } > @@ -60,13 +85,17 @@ static const struct thead_generic_quirks thead_pmu_quirks = { > .errata = THEAD_QUIRK_ERRATA_THEAD_PMU, > }; > > +static const struct thead_generic_quirks thead_pmu_jtlb_quirks = { > + .errata = THEAD_QUIRK_ERRATA_THEAD_PMU | THEAD_QUIRK_ERRATA_JTLB, > +}; > + > static const struct fdt_match thead_generic_match[] = { > { .compatible = "canaan,kendryte-k230", .data = &thead_pmu_quirks }, > { .compatible = "sophgo,cv1800b", .data = &thead_pmu_quirks }, > { .compatible = "sophgo,cv1812h", .data = &thead_pmu_quirks }, > { .compatible = "sophgo,sg2000", .data = &thead_pmu_quirks }, > { .compatible = "sophgo,sg2002", .data = &thead_pmu_quirks }, > - { .compatible = "sophgo,sg2044", .data = &thead_pmu_quirks }, > + { .compatible = "sophgo,sg2044", .data = &thead_pmu_jtlb_quirks }, > { .compatible = "thead,th1520", .data = &thead_th1520_quirks }, > { }, > }; > -- > 2.47.3 > -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi