Friendly reminder, if anyone has any comment on the patch :)

On 9/12/18 11:52 AM, matthias....@kernel.org wrote:
> From: Matthias Brugger <mbrug...@suse.com>
> 
> Some hardware does not implement two-level page tables so that
> the amount of contigious memory needed by the baser is bigger
> then the zone order. This is a known problem on Cavium Thunderx
> with 4K page size.
> 
> We fix this by adding an errata which allocates the memory early
> in the boot cycle, using the memblock allocator.
> 
> Signed-off-by: Matthias Brugger <mbrug...@suse.com>
> ---
>  arch/arm64/Kconfig               | 12 ++++++++
>  arch/arm64/include/asm/cpucaps.h |  3 +-
>  arch/arm64/kernel/cpu_errata.c   | 33 +++++++++++++++++++++
>  drivers/irqchip/irq-gic-v3-its.c | 50 ++++++++++++++++++++------------
>  4 files changed, 79 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 1b1a0e95c751..dfd9fe08f0b2 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -597,6 +597,18 @@ config QCOM_FALKOR_ERRATUM_E1041
>  
>         If unsure, say Y.
>  
> +config CAVIUM_ALLOC_ITS_TABLE_EARLY
> +     bool "Cavium Thunderx: Allocate the its table early"
> +     default y
> +     depends on ARM64_4K_PAGES && FORCE_MAX_ZONEORDER < 13
> +     depends on ARM_GIC_V3_ITS
> +     help
> +       Cavium Thunderx needs to allocate 16MB of ITS translation table.
> +       This can be bigger as MAX_ZONE_ORDER and need therefore be done
> +       via the memblock allocator.
> +
> +       If unsure, say Y.
> +
>  endmenu
>  
>  
> diff --git a/arch/arm64/include/asm/cpucaps.h 
> b/arch/arm64/include/asm/cpucaps.h
> index ae1f70450fb2..c98be4809b7f 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -51,7 +51,8 @@
>  #define ARM64_SSBD                           30
>  #define ARM64_MISMATCHED_CACHE_TYPE          31
>  #define ARM64_HAS_STAGE2_FWB                 32
> +#define ARM64_WORKAROUND_CAVIUM_ITS_TABLE    33
>  
> -#define ARM64_NCAPS                          33
> +#define ARM64_NCAPS                          34
>  
>  #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index dec10898d688..7908f8fa3ba8 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -411,6 +411,29 @@ static bool has_ssbd_mitigation(const struct 
> arm64_cpu_capabilities *entry,
>  }
>  #endif       /* CONFIG_ARM64_SSBD */
>  
> +#ifdef CONFIG_CAVIUM_ALLOC_ITS_TABLE_EARLY
> +#include <linux/bootmem.h>
> +extern void *its_base;
> +
> +/*
> + * Hardware that doesn't use two-level page table and exceedes
> + * the maximum order of pages that can be allocated by the buddy
> + * allocator. Try to use the memblock allocator instead.
> + * This has been observed on Cavium Thunderx machines with 4K
> + * page size.
> + */
> +static bool __init its_early_alloc(const struct arm64_cpu_capabilities *cap,
> +                    int scope)
> +{
> +     /* We need to allocate the table only once */
> +     if (scope & ARM64_CPUCAP_SCOPE_BOOT_CPU && !its_base)
> +             its_base = (void *)memblock_virt_alloc_nopanic(16 * SZ_1M,
> +                                     64 * SZ_1K);
> +
> +     return true;
> +}
> +#endif /* CONFIG_CAVIUM_ALLOC_ITS_TABLE_EARLY */
> +
>  #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)    \
>       .matches = is_affected_midr_range,                      \
>       .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
> @@ -679,6 +702,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
>               .matches = has_ssbd_mitigation,
>       },
> +#endif
> +#ifdef CONFIG_CAVIUM_ALLOC_ITS_TABLE_EARLY
> +     {
> +             /* Cavium ThunderX, pass 1.x - 2.1 */
> +             .desc = "Cavium alloc ITS table early",
> +             .capability = ARM64_WORKAROUND_CAVIUM_ITS_TABLE,
> +             .type = ARM64_CPUCAP_SCOPE_BOOT_CPU,
> +             .matches = its_early_alloc,
> +             .midr_range = MIDR_RANGE(MIDR_THUNDERX, 0, 0, 1, 1),
> +     },
>  #endif
>       {
>       }
> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
> b/drivers/irqchip/irq-gic-v3-its.c
> index c2df341ff6fa..b78546740a0d 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -87,6 +87,8 @@ struct its_baser {
>       u32             psz;
>  };
>  
> +void *its_base;
> +
>  struct its_device;
>  
>  /*
> @@ -1666,7 +1668,7 @@ static void its_write_baser(struct its_node *its, 
> struct its_baser *baser,
>       baser->val = its_read_baser(its, baser);
>  }
>  
> -static int its_setup_baser(struct its_node *its, struct its_baser *baser,
> +static int __init its_setup_baser(struct its_node *its, struct its_baser 
> *baser,
>                          u64 cache, u64 shr, u32 psz, u32 order,
>                          bool indirect)
>  {
> @@ -1675,7 +1677,6 @@ static int its_setup_baser(struct its_node *its, struct 
> its_baser *baser,
>       u64 type = GITS_BASER_TYPE(val);
>       u64 baser_phys, tmp;
>       u32 alloc_pages;
> -     void *base;
>  
>  retry_alloc_baser:
>       alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
> @@ -1687,11 +1688,22 @@ static int its_setup_baser(struct its_node *its, 
> struct its_baser *baser,
>               order = get_order(GITS_BASER_PAGES_MAX * psz);
>       }
>  
> -     base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> -     if (!base)
> -             return -ENOMEM;
> +     if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_ITS_TABLE)) {
> +             if (!its_base) {
> +                     pr_warn("ITS@%pa: %s Allocation using memblock failed 
> %pS\n",
> +                             &its->phys_base, its_base_type_string[type],
> +                             its_base);
> +                     return -ENOMEM;
> +             }
> +
> +     } else {
> +             its_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
> +                                                     order);
> +             if (!its_base)
> +                     return -ENOMEM;
> +     }
>  
> -     baser_phys = virt_to_phys(base);
> +     baser_phys = virt_to_phys(its_base);
>  
>       /* Check if the physical address of the memory is above 48bits */
>       if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) {
> @@ -1699,7 +1711,7 @@ static int its_setup_baser(struct its_node *its, struct 
> its_baser *baser,
>               /* 52bit PA is supported only when PageSize=64K */
>               if (psz != SZ_64K) {
>                       pr_err("ITS: no 52bit PA support when psz=%d\n", psz);
> -                     free_pages((unsigned long)base, order);
> +                     free_pages((unsigned long)its_base, order);
>                       return -ENXIO;
>               }
>  
> @@ -1744,7 +1756,7 @@ static int its_setup_baser(struct its_node *its, struct 
> its_baser *baser,
>               shr = tmp & GITS_BASER_SHAREABILITY_MASK;
>               if (!shr) {
>                       cache = GITS_BASER_nC;
> -                     gic_flush_dcache_to_poc(base, 
> PAGE_ORDER_TO_SIZE(order));
> +                     gic_flush_dcache_to_poc(its_base, 
> PAGE_ORDER_TO_SIZE(order));
>               }
>               goto retry_baser;
>       }
> @@ -1755,7 +1767,7 @@ static int its_setup_baser(struct its_node *its, struct 
> its_baser *baser,
>                * size and retry. If we reach 4K, then
>                * something is horribly wrong...
>                */
> -             free_pages((unsigned long)base, order);
> +             free_pages((unsigned long)its_base, order);
>               baser->base = NULL;
>  
>               switch (psz) {
> @@ -1772,19 +1784,19 @@ static int its_setup_baser(struct its_node *its, 
> struct its_baser *baser,
>               pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n",
>                      &its->phys_base, its_base_type_string[type],
>                      val, tmp);
> -             free_pages((unsigned long)base, order);
> +             free_pages((unsigned long)its_base, order);
>               return -ENXIO;
>       }
>  
>       baser->order = order;
> -     baser->base = base;
> +     baser->base = its_base;
>       baser->psz = psz;
>       tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
>  
>       pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
>               &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
>               its_base_type_string[type],
> -             (unsigned long)virt_to_phys(base),
> +             (unsigned long)virt_to_phys(its_base),
>               indirect ? "indirect" : "flat", (int)esz,
>               psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
>  
> @@ -1832,12 +1844,14 @@ static bool its_parse_indirect_baser(struct its_node 
> *its,
>        * feature is not supported by hardware.
>        */
>       new_order = max_t(u32, get_order(esz << ids), new_order);
> -     if (new_order >= MAX_ORDER) {
> -             new_order = MAX_ORDER - 1;
> -             ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
> -             pr_warn("ITS@%pa: %s Table too large, reduce ids %u->%u\n",
> -                     &its->phys_base, its_base_type_string[type],
> -                     its->device_ids, ids);
> +     if (!cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_ITS_TABLE)) {
> +             if (new_order >= MAX_ORDER) {
> +                     new_order = MAX_ORDER - 1;
> +                     ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
> +                     pr_warn("ITS@%pa: %s Table too large, reduce ids 
> %u->%u\n",
> +                             &its->phys_base, its_base_type_string[type],
> +                             its->device_ids, ids);
> +             }
>       }
>  
>       *order = new_order;
> 

Attachment: pEpkey.asc
Description: application/pgp-keys



Reply via email to