From 2632c96530cacaea51f987a91922ea9fd1d7017b Mon Sep 17 00:00:00 2001 From: Sanath Kumar Date: Thu, 11 Aug 2016 18:01:31 -0500 Subject: [PATCH] sparc64: Use HW supported number of context ID bits Orabug: 24449941 Number of context IDs supported by the hardware is reported via machine descriptor for sun4v systems. For systems > T3, 16 bits are used to represent context ID in the HW. For these systems the context ID wrap around happens if there are more that 65536 processes running simultaneously. For systems older than that 13 bits are used and the context ID wraps around if there are 8192 processes running simultaneously. Reviewed-by: Babu Moger Acked-by: Rob Gardner Signed-off-by: Sanath Kumar Signed-off-by: Allen Pais --- arch/sparc/include/asm/mdesc.h | 1 + arch/sparc/include/asm/mmu_64.h | 6 ++-- arch/sparc/include/asm/mmu_context_64.h | 1 + arch/sparc/kernel/mdesc.c | 37 +++++++++++++++++++++++++ arch/sparc/mm/init_64.c | 7 +++-- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h index d4821f062fda..9018564700c0 100644 --- a/arch/sparc/include/asm/mdesc.h +++ b/arch/sparc/include/asm/mdesc.h @@ -94,6 +94,7 @@ int mdesc_get_node_info(struct mdesc_handle *hp, u64 node, void mdesc_fill_in_cpu_data(cpumask_t *mask); void mdesc_populate_present_mask(cpumask_t *mask); void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask); +extern void mdesc_get_mmu_ctx_bits(cpumask_t *mask, unsigned long *ctx_bits); void sun4v_mdesc_init(void); diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h index 67b32556bc79..b7e86bd2d01c 100644 --- a/arch/sparc/include/asm/mmu_64.h +++ b/arch/sparc/include/asm/mmu_64.h @@ -5,9 +5,11 @@ #include #include -#define CTX_NR_BITS 13 +#define MAX_CTX_NR_BITS 16 +#define DEFAULT_CTX_NR_BITS 13 -#define TAG_CONTEXT_BITS ((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL)) +#define MAX_CTX_NR (_AC(1, UL) << MAX_CTX_NR_BITS) +#define TAG_CONTEXT_BITS ((_AC(1, UL) << ctx_nr_bits) - _AC(1, UL)) /* UltraSPARC-III+ and later have a feature whereby you can * select what page size the various Data-TLB instances in the diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h index fc66ba82923c..9e73e485bb7d 100644 --- a/arch/sparc/include/asm/mmu_context_64.h +++ b/arch/sparc/include/asm/mmu_context_64.h @@ -15,6 +15,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) extern spinlock_t ctx_alloc_lock; extern unsigned long tlb_context_cache; +extern unsigned long ctx_nr_bits; extern unsigned long mmu_context_bmap[]; void get_new_mmu_context(struct mm_struct *mm); diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 84a8b875d8e8..af177d81d3d7 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Unlike the OBP device tree, the machine description is a full-on * DAG. An arbitrary number of ARCs are possible from one @@ -1125,6 +1126,42 @@ void mdesc_populate_present_mask(cpumask_t *mask) mdesc_iterate_over_cpus(record_one_cpu, NULL, mask); } +static void * __init get_one_mmu_ctx_bits(struct mdesc_handle *hp, u64 mp, + int cpuid, void *arg) +{ + const u64 *ctx_md = mdesc_get_property(hp, mp, "mmu-#context-bits", + NULL); + unsigned long *ctx_bits = arg; + u64 val = DEFAULT_CTX_NR_BITS; + + if (ctx_md && *ctx_md) + val = *ctx_md; + + if (!*ctx_bits) + *ctx_bits = val; + + /* The previous cpu must report the same number of context-bits */ + if (*ctx_bits != val) { + printk_once(KERN_WARNING "Inconsistent context-bits reported by MD\n"); + *ctx_bits = DEFAULT_CTX_NR_BITS; + } else { + *ctx_bits = val; + } + + if (*ctx_bits > MAX_CTX_NR_BITS) { + printk_once(KERN_WARNING "Unsupported number of context-bits reported by MD\n"); + *ctx_bits = DEFAULT_CTX_NR_BITS; + } + + return NULL; +} + +void __init mdesc_get_mmu_ctx_bits(cpumask_t *mask, unsigned long *ctx_bits) +{ + *ctx_bits = 0; + mdesc_iterate_over_cpus(get_one_mmu_ctx_bits, ctx_bits, mask); +} + static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) { const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL); diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 086aa0901391..a494b91b19de 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -56,6 +56,7 @@ #include "init_64.h" +unsigned long ctx_nr_bits = DEFAULT_CTX_NR_BITS; unsigned long kern_linear_pte_xor[4] __read_mostly; static unsigned long page_cache4v_flag; @@ -925,7 +926,6 @@ EXPORT_SYMBOL(__flush_dcache_range); /* get_new_mmu_context() uses "cache + 1". */ DEFINE_SPINLOCK(ctx_alloc_lock); unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; -#define MAX_CTX_NR (1UL << CTX_NR_BITS) #define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR) DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR); @@ -948,9 +948,9 @@ void get_new_mmu_context(struct mm_struct *mm) spin_lock(&ctx_alloc_lock); orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK); ctx = (tlb_context_cache + 1) & CTX_NR_MASK; - new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx); + new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << ctx_nr_bits, ctx); new_version = 0; - if (new_ctx >= (1 << CTX_NR_BITS)) { + if (new_ctx >= (1UL << ctx_nr_bits)) { new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1); if (new_ctx >= ctx) { int i; @@ -2645,6 +2645,7 @@ void __init paging_init(void) mdesc_fill_in_cpu_data(cpu_all_mask); #endif mdesc_get_page_sizes(cpu_all_mask, &cpu_pgsz_mask); + mdesc_get_mmu_ctx_bits(cpu_all_mask, &ctx_nr_bits); sun4v_linear_pte_xor_finalize(); -- 2.50.1