@@ -550,7 +550,7 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
return false;
}
-extern u64 nr_sfence_vma_handle_exception;
+extern u64 nr_sfence_vma_spurious_read;
extern bool tlb_caching_invalid_entries;
#define flush_tlb_fix_spurious_read_fault flush_tlb_fix_spurious_read_fault
@@ -558,8 +558,10 @@ static inline void flush_tlb_fix_spurious_read_fault(struct vm_area_struct *vma,
unsigned long address,
pte_t *ptep)
{
- if (tlb_caching_invalid_entries)
+ if (tlb_caching_invalid_entries) {
+ __sync_fetch_and_add(&nr_sfence_vma_spurious_read, 1UL);
flush_tlb_page(vma, address);
+ }
}
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
@@ -14,14 +14,18 @@
#ifdef CONFIG_MMU
extern unsigned long asid_mask;
+extern u64 nr_sfence_vma, nr_sfence_vma_all, nr_sfence_vma_all_asid;
+
static inline void local_flush_tlb_all(void)
{
+ __sync_fetch_and_add(&nr_sfence_vma_all, 1UL);
__asm__ __volatile__ ("sfence.vma" : : : "memory");
}
/* Flush one page from local TLB */
static inline void local_flush_tlb_page(unsigned long addr)
{
+ __sync_fetch_and_add(&nr_sfence_vma, 1UL);
ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory"));
}
#else /* CONFIG_MMU */
@@ -376,6 +376,8 @@ int sbi_remote_fence_i(const struct cpumask *cpu_mask)
}
EXPORT_SYMBOL(sbi_remote_fence_i);
+extern u64 nr_sfence_vma, nr_sfence_vma_all, nr_sfence_vma_all_asid;
+
/**
* sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote
* harts for the specified virtual address range.
@@ -389,6 +391,11 @@ int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
unsigned long start,
unsigned long size)
{
+ if (size == (unsigned long)-1)
+ __sync_fetch_and_add(&nr_sfence_vma_all, 1UL);
+ else
+ __sync_fetch_and_add(&nr_sfence_vma, ALIGN(size, PAGE_SIZE) / PAGE_SIZE);
+
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
cpu_mask, start, size, 0, 0);
}
@@ -410,6 +417,11 @@ int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long size,
unsigned long asid)
{
+ if (size == (unsigned long)-1)
+ __sync_fetch_and_add(&nr_sfence_vma_all_asid, 1UL);
+ else
+ __sync_fetch_and_add(&nr_sfence_vma, ALIGN(size, PAGE_SIZE) / PAGE_SIZE);
+
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
cpu_mask, start, size, asid, 0);
}
@@ -3,11 +3,16 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/sched.h>
+#include <linux/debugfs.h>
#include <asm/sbi.h>
#include <asm/mmu_context.h>
+u64 nr_sfence_vma, nr_sfence_vma_all, nr_sfence_vma_all_asid,
+ nr_sfence_vma_handle_exception, nr_sfence_vma_spurious_read;
+
static inline void local_flush_tlb_all_asid(unsigned long asid)
{
+ __sync_fetch_and_add(&nr_sfence_vma_all_asid, 1);
__asm__ __volatile__ ("sfence.vma x0, %0"
:
: "r" (asid)
@@ -17,6 +22,7 @@ static inline void local_flush_tlb_all_asid(unsigned long asid)
static inline void local_flush_tlb_page_asid(unsigned long addr,
unsigned long asid)
{
+ __sync_fetch_and_add(&nr_sfence_vma, 1);
__asm__ __volatile__ ("sfence.vma %0, %1"
:
: "r" (addr), "r" (asid)
@@ -149,3 +155,14 @@ void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
__flush_tlb_range(vma->vm_mm, start, end - start, PMD_SIZE);
}
#endif
+
+static int debugfs_nr_sfence_vma(void)
+{
+ debugfs_create_u64("nr_sfence_vma", 0444, NULL, &nr_sfence_vma);
+ debugfs_create_u64("nr_sfence_vma_all", 0444, NULL, &nr_sfence_vma_all);
+ debugfs_create_u64("nr_sfence_vma_all_asid", 0444, NULL, &nr_sfence_vma_all_asid);
+ debugfs_create_u64("nr_sfence_vma_handle_exception", 0444, NULL, &nr_sfence_vma_handle_exception);
+ debugfs_create_u64("nr_sfence_vma_spurious_read", 0444, NULL, &nr_sfence_vma_spurious_read);
+ return 0;
+}
+device_initcall(debugfs_nr_sfence_vma);
This is useful for testing/benchmarking. Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com> --- arch/riscv/include/asm/pgtable.h | 6 ++++-- arch/riscv/include/asm/tlbflush.h | 4 ++++ arch/riscv/kernel/sbi.c | 12 ++++++++++++ arch/riscv/mm/tlbflush.c | 17 +++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-)