From: Hartvig Ekner <hartvig@ekner.info>
To: Linux MIPS mailing list <linux-mips@linux-mips.org>
Subject: Cache flush statistics patch to c-mips32.c
Date: Wed, 02 Apr 2003 21:16:20 +0200 [thread overview]
Message-ID: <3E8B3703.3D9B09D5@ekner.info> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1159 bytes --]
Below is a patch with some cache statistics counters added to c-mips32.c.
They are turned on by the local define DEBUG_COUNTERS in case somebody wants to
play with them.
A sample output:
[root@au01 root]# more /proc/cmips32_cache_stats
Cache statistics from c-mips32.c:
mips32_flush_cache_all_pc: 83384 mips32_flush_cache_all_sc: 0
mips32_flush_cache_range_pc: 37276 mips32_flush_cache_range_sc: 0
mips32_flush_cache_mm_pc: 2121 mips32_flush_cache_mm_sc: 0
mips32_flush_cache_page_pc: 36282 mips32_flush_cache_page_sc: 0
mips32_flush_icache_all: 0 mips32_flush_icache_page_s: 0
mips32_flush_icache_range: 4 mips32_flush_icache_page: 93545
mips32_flush_data_cache_page: 31905 mips32_flush_cache_sigtramp: 2467
dma_cache_wback_inv_pc: 7029 dma_cache_wback_inv_sc: 0
dma_cache_inv_pc: 0 dma_cache_inv_sc: 0
These counts are from a system which has just booted, nothing else. While running
some programs, the flush_cache_all is called up to 400 times pr. second (!).
/Hartvig
[-- Attachment #1.2: Type: text/html, Size: 2498 bytes --]
[-- Attachment #2: cmips32_patch --]
[-- Type: text/plain, Size: 12169 bytes --]
Index: c-mips32.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/c-mips32.c,v
retrieving revision 1.3.2.17
diff -u -r1.3.2.17 c-mips32.c
--- c-mips32.c 31 Mar 2003 23:29:06 -0000 1.3.2.17
+++ c-mips32.c 2 Apr 2003 19:01:35 -0000
@@ -17,6 +17,10 @@
*
* MIPS32 CPU variant specific MMU/Cache routines.
*/
+
+#undef DEBUG_CACHE /* Control debug printk's */
+#undef DEBUG_COUNTERS /* Control statistics counters */
+
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -32,6 +36,40 @@
#include <asm/system.h>
#include <asm/mmu_context.h>
+
+#ifndef DEBUG_COUNTERS
+#define DEBUG_INCCNT(cnt)
+#else
+
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+
+#define DEBUG_INCCNT(cnt) cnt++
+
+static int cnt_mips32_flush_cache_all_sc = 0; /* All the bean counters */
+static int cnt_mips32_flush_cache_all_pc = 0;
+static int cnt_mips32_flush_cache_range_sc = 0;
+static int cnt_mips32_flush_cache_range_pc = 0;
+static int cnt_mips32_flush_cache_mm_sc = 0;
+static int cnt_mips32_flush_cache_mm_pc = 0;
+static int cnt_mips32_flush_cache_page_sc = 0;
+static int cnt_mips32_flush_cache_page_pc = 0;
+
+static int cnt_mips32_flush_icache_all = 0;
+static int cnt_mips32_flush_icache_page_s = 0;
+static int cnt_mips32_flush_icache_range = 0;
+static int cnt_mips32_flush_icache_page = 0;
+static int cnt_mips32_flush_data_cache_page = 0;
+static int cnt_mips32_flush_cache_sigtramp = 0;
+
+static int cnt_dma_cache_wback_inv_pc = 0;
+static int cnt_dma_cache_wback_inv_sc = 0;
+static int cnt_dma_cache_inv_pc = 0;
+static int cnt_dma_cache_inv_sc = 0;
+
+#endif
+
+
/* Primary cache parameters. */
int icache_size, dcache_size; /* Size in bytes */
int ic_lsize, dc_lsize; /* LineSize in bytes */
@@ -42,7 +80,6 @@
#include <asm/cacheops.h>
#include <asm/mips32_cache.h>
-#undef DEBUG_CACHE
/*
* Dummy cache handling routines for machines without boardcaches
@@ -62,6 +99,8 @@
{
unsigned long flags;
+ DEBUG_INCCNT(cnt_mips32_flush_cache_all_sc);
+
local_irq_save(flags);
blast_dcache(); blast_icache(); blast_scache();
local_irq_restore(flags);
@@ -71,6 +110,8 @@
{
unsigned long flags;
+ DEBUG_INCCNT(cnt_mips32_flush_cache_all_pc);
+
local_irq_save(flags);
blast_dcache(); blast_icache();
local_irq_restore(flags);
@@ -84,6 +125,8 @@
struct vm_area_struct *vma;
unsigned long flags;
+ DEBUG_INCCNT(cnt_mips32_flush_cache_range_sc);
+
if (cpu_context(smp_processor_id(), mm) == 0)
return;
@@ -119,6 +162,8 @@
unsigned long start,
unsigned long end)
{
+ DEBUG_INCCNT(cnt_mips32_flush_cache_range_pc);
+
if (cpu_context(smp_processor_id(), mm) != 0) {
unsigned long flags;
@@ -138,6 +183,8 @@
*/
static void mips32_flush_cache_mm_sc(struct mm_struct *mm)
{
+ DEBUG_INCCNT(cnt_mips32_flush_cache_mm_sc);
+
if (cpu_context(smp_processor_id(), mm) != 0) {
#ifdef DEBUG_CACHE
printk("cmm[%d]", cpu_context(smp_processor_id(), mm));
@@ -148,6 +195,8 @@
static void mips32_flush_cache_mm_pc(struct mm_struct *mm)
{
+ DEBUG_INCCNT(cnt_mips32_flush_cache_mm_pc);
+
if (cpu_context(smp_processor_id(), mm) != 0) {
#ifdef DEBUG_CACHE
printk("cmm[%d]", cpu_context(smp_processor_id(), mm));
@@ -164,6 +213,8 @@
pmd_t *pmdp;
pte_t *ptep;
+ DEBUG_INCCNT(cnt_mips32_flush_cache_page_sc);
+
/*
* If ownes no valid ASID yet, cannot possibly have gotten
* this page into the cache.
@@ -212,6 +263,8 @@
pmd_t *pmdp;
pte_t *ptep;
+ DEBUG_INCCNT(cnt_mips32_flush_cache_page_pc);
+
/*
* If ownes no valid ASID yet, cannot possibly have gotten
* this page into the cache.
@@ -251,17 +304,20 @@
}
}
-static void mips32_flush_data_cache_page(unsigned long addr)
+static void mips32_flush_icache_all(void)
{
- if (sc_lsize)
- blast_scache_page(addr);
- else
- blast_dcache_page(addr);
+ DEBUG_INCCNT(cnt_mips32_flush_icache_all);
+
+ if (mips_cpu.icache.flags | MIPS_CACHE_VTAG_CACHE) {
+ blast_icache();
+ }
}
static void
mips32_flush_icache_page_s(struct vm_area_struct *vma, struct page *page)
{
+ DEBUG_INCCNT(cnt_mips32_flush_icache_page_s);
+
/*
* We did an scache flush therefore PI is already clean.
*/
@@ -270,12 +326,16 @@
static void
mips32_flush_icache_range(unsigned long start, unsigned long end)
{
+ DEBUG_INCCNT(cnt_mips32_flush_icache_range);
+
flush_cache_all();
}
static void
mips32_flush_icache_page(struct vm_area_struct *vma, struct page *page)
{
+ DEBUG_INCCNT(cnt_mips32_flush_icache_page);
+
/*
* If there's no context yet, or the page isn't executable, no icache
* flush is needed.
@@ -290,15 +350,45 @@
flush_cache_all();
}
+static void mips32_flush_data_cache_page(unsigned long addr)
+{
+ DEBUG_INCCNT(cnt_mips32_flush_data_cache_page);
+
+ if (sc_lsize)
+ blast_scache_page(addr);
+ else
+ blast_dcache_page(addr);
+}
+
+
+/*
+ * While we're protected against bad userland addresses we don't care
+ * very much about what happens in that case. Usually a segmentation
+ * fault will dump the process later on anyway ...
+ */
+static void mips32_flush_cache_sigtramp(unsigned long addr)
+{
+ DEBUG_INCCNT(cnt_mips32_flush_cache_sigtramp);
+
+ protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
+ protected_flush_icache_line(addr & ~(ic_lsize - 1));
+}
+
+
/*
* Writeback and invalidate the primary cache dcache before DMA.
*/
+
+#ifdef CONFIG_NONCOHERENT_IO
+
static void
mips32_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
{
unsigned long end, a;
unsigned long flags;
+ DEBUG_INCCNT(cnt_dma_cache_wback_inv_pc);
+
if (size >= dcache_size) {
blast_dcache();
} else {
@@ -320,6 +410,8 @@
{
unsigned long end, a;
+ DEBUG_INCCNT(cnt_dma_cache_wback_inv_sc);
+
if (size >= scache_size) {
blast_scache();
return;
@@ -340,6 +432,8 @@
unsigned long end, a;
unsigned long flags;
+ DEBUG_INCCNT(cnt_dma_cache_inv_pc);
+
if (size >= dcache_size) {
blast_dcache();
} else {
@@ -362,6 +456,8 @@
{
unsigned long end, a;
+ DEBUG_INCCNT(cnt_dma_cache_inv_sc);
+
if (size >= scache_size) {
blast_scache();
return;
@@ -379,26 +475,11 @@
static void
mips32_dma_cache_wback(unsigned long addr, unsigned long size)
{
- panic("mips32_dma_cache called - should not happen.");
+ panic("mips32_dma_cache_wback called - should not happen.");
}
-/*
- * While we're protected against bad userland addresses we don't care
- * very much about what happens in that case. Usually a segmentation
- * fault will dump the process later on anyway ...
- */
-static void mips32_flush_cache_sigtramp(unsigned long addr)
-{
- protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
- protected_flush_icache_line(addr & ~(ic_lsize - 1));
-}
+#endif
-static void mips32_flush_icache_all(void)
-{
- if (mips_cpu.icache.flags | MIPS_CACHE_VTAG_CACHE) {
- blast_icache();
- }
-}
/* Detect and size the various caches. */
static void __init probe_icache(unsigned long config)
@@ -586,36 +667,40 @@
static void __init setup_noscache_funcs(void)
{
- _clear_page = (void *)mips32_clear_page_dc;
- _copy_page = (void *)mips32_copy_page_dc;
- _flush_cache_all = mips32_flush_cache_all_pc;
- ___flush_cache_all = mips32_flush_cache_all_pc;
- _flush_cache_mm = mips32_flush_cache_mm_pc;
- _flush_cache_range = mips32_flush_cache_range_pc;
- _flush_cache_page = mips32_flush_cache_page_pc;
+ _clear_page = (void *) mips32_clear_page_dc;
+ _copy_page = (void *) mips32_copy_page_dc;
+ _flush_cache_all = mips32_flush_cache_all_pc;
+ ___flush_cache_all = mips32_flush_cache_all_pc;
+ _flush_cache_mm = mips32_flush_cache_mm_pc;
+ _flush_cache_range = mips32_flush_cache_range_pc;
+ _flush_cache_page = mips32_flush_cache_page_pc;
- _flush_icache_page = mips32_flush_icache_page;
+ _flush_icache_page = mips32_flush_icache_page;
+#ifdef CONFIG_NONCOHERENT_IO
_dma_cache_wback_inv = mips32_dma_cache_wback_inv_pc;
- _dma_cache_wback = mips32_dma_cache_wback;
- _dma_cache_inv = mips32_dma_cache_inv_pc;
+ _dma_cache_wback = mips32_dma_cache_wback;
+ _dma_cache_inv = mips32_dma_cache_inv_pc;
+#endif
}
static void __init setup_scache_funcs(void)
{
- _flush_cache_all = mips32_flush_cache_all_sc;
- ___flush_cache_all = mips32_flush_cache_all_sc;
- _flush_cache_mm = mips32_flush_cache_mm_sc;
- _flush_cache_range = mips32_flush_cache_range_sc;
- _flush_cache_page = mips32_flush_cache_page_sc;
- _clear_page = (void *)mips32_clear_page_sc;
- _copy_page = (void *)mips32_copy_page_sc;
+ _clear_page = (void *) mips32_clear_page_sc;
+ _copy_page = (void *) mips32_copy_page_sc;
+ _flush_cache_all = mips32_flush_cache_all_sc;
+ ___flush_cache_all = mips32_flush_cache_all_sc;
+ _flush_cache_mm = mips32_flush_cache_mm_sc;
+ _flush_cache_range = mips32_flush_cache_range_sc;
+ _flush_cache_page = mips32_flush_cache_page_sc;
- _flush_icache_page = mips32_flush_icache_page_s;
+ _flush_icache_page = mips32_flush_icache_page_s;
+#ifdef CONFIG_NONCOHERENT_IO
_dma_cache_wback_inv = mips32_dma_cache_wback_inv_sc;
- _dma_cache_wback = mips32_dma_cache_wback;
- _dma_cache_inv = mips32_dma_cache_inv_sc;
+ _dma_cache_wback = mips32_dma_cache_wback;
+ _dma_cache_inv = mips32_dma_cache_inv_sc;
+#endif
}
typedef int (*probe_func_t)(unsigned long);
@@ -669,10 +754,89 @@
shm_align_mask = max_t(unsigned long, mips_cpu.dcache.sets * dc_lsize,
PAGE_SIZE) - 1;
- _flush_cache_sigtramp = mips32_flush_cache_sigtramp;
- _flush_icache_range = mips32_flush_icache_range; /* Ouch */
+ _flush_icache_all = mips32_flush_icache_all;
+ _flush_icache_range = mips32_flush_icache_range; /* Ouch */
_flush_data_cache_page = mips32_flush_data_cache_page;
- _flush_icache_all = mips32_flush_icache_all;
+ _flush_cache_sigtramp = mips32_flush_cache_sigtramp;
__flush_cache_all();
}
+
+
+
+#ifdef DEBUG_COUNTERS
+
+static int cmips32_read_proc(char *buf, char **start, off_t fpos,
+ int length, int *eof, void *data)
+{
+ int len;
+ char *p = buf;
+
+ p += sprintf(p, "\nCache statistics from c-mips32.c:\n\n");
+
+ p += sprintf(p, "mips32_flush_cache_all_pc: %8d "
+ "mips32_flush_cache_all_sc: %8d\n",
+ cnt_mips32_flush_cache_all_pc,
+ cnt_mips32_flush_cache_all_sc);
+ p += sprintf(p, "mips32_flush_cache_range_pc: %8d "
+ "mips32_flush_cache_range_sc: %8d\n",
+ cnt_mips32_flush_cache_range_pc,
+ cnt_mips32_flush_cache_range_sc);
+ p += sprintf(p, "mips32_flush_cache_mm_pc: %8d "
+ "mips32_flush_cache_mm_sc: %8d\n",
+ cnt_mips32_flush_cache_mm_pc,
+ cnt_mips32_flush_cache_mm_sc);
+ p += sprintf(p, "mips32_flush_cache_page_pc: %8d "
+ "mips32_flush_cache_page_sc: %8d\n\n",
+ cnt_mips32_flush_cache_page_pc,
+ cnt_mips32_flush_cache_page_sc);
+
+ p += sprintf(p, "mips32_flush_icache_all: %8d "
+ "mips32_flush_icache_page_s: %8d\n",
+ cnt_mips32_flush_icache_all,
+ cnt_mips32_flush_icache_page_s);
+ p += sprintf(p, "mips32_flush_icache_range: %8d "
+ "mips32_flush_icache_page: %8d\n",
+ cnt_mips32_flush_icache_range,
+ cnt_mips32_flush_icache_page);
+ p += sprintf(p, "mips32_flush_data_cache_page:%8d "
+ "mips32_flush_cache_sigtramp: %8d\n\n",
+ cnt_mips32_flush_data_cache_page,
+ cnt_mips32_flush_cache_sigtramp);
+
+ p += sprintf(p, "dma_cache_wback_inv_pc: %8d "
+ "dma_cache_wback_inv_sc: %8d\n",
+ cnt_dma_cache_wback_inv_pc,
+ cnt_dma_cache_wback_inv_sc);
+ p += sprintf(p, "dma_cache_inv_pc: %8d "
+ "dma_cache_inv_sc: %8d\n\n",
+ cnt_dma_cache_inv_pc,
+ cnt_dma_cache_inv_sc);
+
+ len = p - buf;
+ if (fpos >= len) {
+ /* Nothing to return... */
+ *start = buf;
+ *eof = 1;
+ return 0;
+ }
+
+ *start = buf + fpos;
+ if ((len -= fpos) > length)
+ return length;
+
+ *eof = 1;
+ return len;
+}
+
+static int __init cmips32_init_module(void)
+{
+ create_proc_read_entry ("cmips32_cache_stats", 0, NULL,
+ cmips32_read_proc, NULL);
+
+ return 0;
+}
+
+module_init(cmips32_init_module);
+
+#endif
next reply other threads:[~2003-04-02 19:08 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-04-02 19:16 Hartvig Ekner [this message]
2003-04-02 20:05 ` Cache flush statistics patch to c-mips32.c Ralf Baechle
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3E8B3703.3D9B09D5@ekner.info \
--to=hartvig@ekner.info \
--cc=linux-mips@linux-mips.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox