From 6384423f49c804dbca02add1945e0ccf922cb522 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 22 Aug 2019 00:51:49 -0700 Subject: RISC-V: Do not invoke SBI call if cpumask is empty SBI calls are expensive. If cpumask is empty, there is no need to trap via SBI as no remote tlb flushing is required. Signed-off-by: Atish Patra Reviewed-by: Christoph Hellwig Signed-off-by: Paul Walmsley --- arch/riscv/mm/tlbflush.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 24cd33d2c48f..9ecaf73cd051 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -14,6 +14,9 @@ static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start, { struct cpumask hmask; + if (cpumask_empty(cmask)) + return; + riscv_cpuid_to_hartid_mask(cmask, &hmask); sbi_remote_sfence_vma(hmask.bits, start, size); } -- cgit v1.2.3 From 31738ede9b339c90216b8fd10da0b1567a041f06 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 22 Aug 2019 00:51:50 -0700 Subject: RISC-V: Issue a local tlbflush if possible. In RISC-V, tlb flush happens via SBI which is expensive. If the local cpu is the only cpu in cpumask, there is no need to invoke a SBI call. Just do a local flush and return. Signed-off-by: Atish Patra Reviewed-by: Christoph Hellwig Signed-off-by: Paul Walmsley --- arch/riscv/mm/tlbflush.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 9ecaf73cd051..3531d4647323 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -2,6 +2,7 @@ #include #include +#include #include void flush_tlb_all(void) @@ -9,16 +10,30 @@ void flush_tlb_all(void) sbi_remote_sfence_vma(NULL, 0, -1); } +/* + * This function must not be called with cmask being null. + * Kernel may panic if cmask is NULL. + */ static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start, unsigned long size) { struct cpumask hmask; + unsigned int cpuid; if (cpumask_empty(cmask)) return; - riscv_cpuid_to_hartid_mask(cmask, &hmask); - sbi_remote_sfence_vma(hmask.bits, start, size); + cpuid = get_cpu(); + + if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) { + /* local cpu is the only cpu present in cpumask */ + local_flush_tlb_all(); + } else { + riscv_cpuid_to_hartid_mask(cmask, &hmask); + sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size); + } + + put_cpu(); } void flush_tlb_mm(struct mm_struct *mm) -- cgit v1.2.3 From 6efb16b1d5514865d0f7a01910648568ad3225d8 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 22 Aug 2019 00:51:51 -0700 Subject: RISC-V: Issue a tlb page flush if possible If tlbflush request is for page only, there is no need to do a complete local tlb shootdown. Just do a local tlb flush for the given address. Signed-off-by: Atish Patra Reviewed-by: Christoph Hellwig Signed-off-by: Paul Walmsley --- arch/riscv/mm/tlbflush.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 3531d4647323..720b443c4528 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -27,7 +27,10 @@ static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start, if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) { /* local cpu is the only cpu present in cpumask */ - local_flush_tlb_all(); + if (size <= PAGE_SIZE) + local_flush_tlb_page(start); + else + local_flush_tlb_all(); } else { riscv_cpuid_to_hartid_mask(cmask, &hmask); sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size); -- cgit v1.2.3