[PATCH] LoongArch: Add tlb_flush_threshold for tlb flush range

From: Bibo Mao
Date: Thu Sep 07 2023 - 21:29:16 EST


There is calculation in function flush_tlb_range to decide flush tlb
entries one by one or flush the whole tlbs. Instead the calculation can be
done during cpu probe stage rather than runtime flush period.

This patch adds percpu variable tlb_flush_threshold during cpu probe
stage, and removes unused percpu variabled like tlbsizemtlb,
tlbsizestlbsets/tlbsizestlbways etc.

Also this patch fixes function __update_hugetlb, it should be
effective for CONFIG_TRANSPARENT_HUGEPAGE also.

Signed-off-by: Bibo Mao <maobibo@xxxxxxxxxxx>
---
arch/loongarch/include/asm/cpu-info.h | 4 +---
arch/loongarch/kernel/cpu-probe.c | 31 ++++++++++++++++-----------
arch/loongarch/mm/tlb.c | 11 +++-------
3 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/arch/loongarch/include/asm/cpu-info.h b/arch/loongarch/include/asm/cpu-info.h
index 900589cb159d..523827216c1b 100644
--- a/arch/loongarch/include/asm/cpu-info.h
+++ b/arch/loongarch/include/asm/cpu-info.h
@@ -47,9 +47,7 @@ struct cpuinfo_loongarch {
unsigned int cputype;
int isa_level;
int tlbsize;
- int tlbsizemtlb;
- int tlbsizestlbsets;
- int tlbsizestlbways;
+ int tlb_flush_threshold;
int cache_leaves_present; /* number of cache_leaves[] elements */
struct cache_desc cache_leaves[CACHE_LEAVES_MAX];
int core; /* physical core number in package */
diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c
index e925579c7a71..ffa0a1b1ae29 100644
--- a/arch/loongarch/kernel/cpu-probe.c
+++ b/arch/loongarch/kernel/cpu-probe.c
@@ -88,7 +88,7 @@ static void set_isa(struct cpuinfo_loongarch *c, unsigned int isa)

static void cpu_probe_common(struct cpuinfo_loongarch *c)
{
- unsigned int config;
+ unsigned int config, stlbsets, stlbways, mtlbs;
unsigned long asid_mask;

c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR |
@@ -173,28 +173,35 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
c->ksave_mask &= ~(EXC_KSAVE_MASK | PERCPU_KSAVE_MASK | KVM_KSAVE_MASK);

config = read_csr_prcfg3();
+ stlbsets = 0;
+ c->tlbsize = 0;
switch (config & CSR_CONF3_TLBTYPE) {
case 0:
- c->tlbsizemtlb = 0;
- c->tlbsizestlbsets = 0;
- c->tlbsizestlbways = 0;
+ mtlbs = 0;
+ stlbsets = 0;
+ stlbways = 0;
c->tlbsize = 0;
break;
case 1:
- c->tlbsizemtlb = ((config & CSR_CONF3_MTLBSIZE) >> CSR_CONF3_MTLBSIZE_SHIFT) + 1;
- c->tlbsizestlbsets = 0;
- c->tlbsizestlbways = 0;
- c->tlbsize = c->tlbsizemtlb + c->tlbsizestlbsets * c->tlbsizestlbways;
+ mtlbs = ((config & CSR_CONF3_MTLBSIZE) >> CSR_CONF3_MTLBSIZE_SHIFT) + 1;
+ stlbsets = 0;
+ stlbways = 0;
+ c->tlbsize = mtlbs + stlbsets * stlbways;
break;
case 2:
- c->tlbsizemtlb = ((config & CSR_CONF3_MTLBSIZE) >> CSR_CONF3_MTLBSIZE_SHIFT) + 1;
- c->tlbsizestlbsets = 1 << ((config & CSR_CONF3_STLBIDX) >> CSR_CONF3_STLBIDX_SHIFT);
- c->tlbsizestlbways = ((config & CSR_CONF3_STLBWAYS) >> CSR_CONF3_STLBWAYS_SHIFT) + 1;
- c->tlbsize = c->tlbsizemtlb + c->tlbsizestlbsets * c->tlbsizestlbways;
+ mtlbs = ((config & CSR_CONF3_MTLBSIZE) >> CSR_CONF3_MTLBSIZE_SHIFT) + 1;
+ stlbsets = 1 << ((config & CSR_CONF3_STLBIDX) >> CSR_CONF3_STLBIDX_SHIFT);
+ stlbways = ((config & CSR_CONF3_STLBWAYS) >> CSR_CONF3_STLBWAYS_SHIFT) + 1;
+ c->tlbsize = mtlbs + stlbsets * stlbways;
break;
default:
pr_warn("Warning: unknown TLB type\n");
}
+
+ if (stlbsets)
+ c->tlb_flush_threshold = c->tlbsize / 8;
+ else
+ c->tlb_flush_threshold = c->tlbsize / 2;
}

#define MAX_NAME_LEN 32
diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c
index eb8572e201ea..d87627cb9e29 100644
--- a/arch/loongarch/mm/tlb.c
+++ b/arch/loongarch/mm/tlb.c
@@ -66,9 +66,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
start = round_down(start, PAGE_SIZE << 1);
end = round_up(end, PAGE_SIZE << 1);
size = (end - start) >> (PAGE_SHIFT + 1);
- if (size <= (current_cpu_data.tlbsizestlbsets ?
- current_cpu_data.tlbsize / 8 :
- current_cpu_data.tlbsize / 2)) {
+ if (size <= current_cpu_data.tlb_flush_threshold) {
int asid = cpu_asid(cpu, mm);

while (start < end) {
@@ -91,10 +89,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
local_irq_save(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
- if (size <= (current_cpu_data.tlbsizestlbsets ?
- current_cpu_data.tlbsize / 8 :
- current_cpu_data.tlbsize / 2)) {
-
+ if (size <= current_cpu_data.tlb_flush_threshold) {
start &= (PAGE_MASK << 1);
end += ((PAGE_SIZE << 1) - 1);
end &= (PAGE_MASK << 1);
@@ -136,7 +131,7 @@ void local_flush_tlb_one(unsigned long page)

static void __update_hugetlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
{
-#ifdef CONFIG_HUGETLB_PAGE
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
int idx;
unsigned long lo;
unsigned long flags;

base-commit: 744a759492b5c57ff24a6e8aabe47b17ad8ee964
--
2.27.0