Linux MIPS Architecture development
 help / color / mirror / Atom feed
From: Brian Murphy <brian@murphy.dk>
Cc: linux-mips@oss.sgi.com
Subject: Re: [2.5 patch] R5K SC support
Date: Tue, 06 Aug 2002 21:38:20 +0200	[thread overview]
Message-ID: <3D5025AC.9020203@murphy.dk> (raw)
In-Reply-To: 20020715144315.A4837@dea.linux-mips.net

[-- Attachment #1: Type: text/plain, Size: 1098 bytes --]

Ralf Baechle wrote:

>>+static void r5k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size)
>>+static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
>>
>
>You can hook the second level cache support into the bcache hook.  That's
>working because unlike the R4000SC the R5000's second level cache does not
>have the additional constraint of the primary caches always being a subset
>of the second level caches.
>
>Arch/mips/sgi-ip22/ip22-sc.c is an example how this can be done.
>
>
>
This is all very fine in theory but the R5000 cache routines are 
automatically
selected by the R4000 secondary setup routines which pick out the incorrect
flush_range function and wback_inv and inv functions. These do not call
board cache routines at all.

It must be that the secondary cache for the ip22 architecture with an R5000
is not flagged as having a secondary cache in a way that the R4000 
secondary
cache routines can detect.

On the other hand with the application of this (attached) patch the 
cache is
detected correctly and appropriate routines are selected.

/Brian

[-- Attachment #2: r5k-sc.patch --]
[-- Type: text/plain, Size: 6258 bytes --]

Index: arch/mips/mm/c-r4k.c
===================================================================
RCS file: /cvs/linux-mips/arch/mips/mm/c-r4k.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- arch/mips/mm/c-r4k.c	18 Jul 2002 17:35:18 -0000	1.1
+++ arch/mips/mm/c-r4k.c	18 Jul 2002 17:41:34 -0000	1.2
@@ -36,6 +36,7 @@
 
 /* Secondary cache (if present) parameters. */
 static unsigned int scache_size, sc_lsize;	/* Again, in bytes */
+static int sc_present = 0;
 
 #include <asm/cacheops.h>
 #include <asm/r4kcache.h>
@@ -1195,6 +1196,126 @@
 #endif
 }
 
+static void r5k_flush_cache_range(struct mm_struct *mm,
+				  unsigned long start,
+				  unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if (mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if (vma) {
+		if (mm->context != current->active_mm->context) {
+			_flush_cache_all();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			__save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while (start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if (pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache32_page(start);
+					if (text)
+						blast_icache32_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			__restore_flags(flags);
+		}
+	}
+}
+
+static void
+r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+	if (size >= scache_size) {
+		blast_r5000_scache();
+		return;
+	}
+
+	/* We assume the address is in KSEG0. On the R5000 we
+	 * cannot invalidate less than a page at a time, and
+	 * there is no Hit_xxx cache operations.
+	 */
+	a = addr & ~(PAGE_SIZE - 1);
+	end = (addr + size - 1) & ~(PAGE_SIZE - 1);
+	while (a <= end) {
+		blast_r5000_scache_page_indexed(a);	/* Page_Invalidate */
+		a += PAGE_SIZE;
+	}
+}
+
+static void
+r5k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+	if (size >= dcache_size) {
+		blast_dcache32();
+	} else {
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size - 1) & ~(dc_lsize - 1);
+		while (a <= end) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			a += dc_lsize;
+		}
+	}
+	if (sc_present)
+		r5k_dma_cache_inv_sc(addr, size);
+}
+
+static void
+r5k_dma_cache_inv(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+	if (size >= dcache_size) {
+		blast_dcache32();
+	} else {
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size - 1) & ~(dc_lsize - 1);
+		while (a <= end) {
+			invalidate_dcache_line(a); /* Hit_Invalidate_D */
+			a += dc_lsize;
+		}
+	}
+	if (sc_present)
+		r5k_dma_cache_inv_sc(addr, size);
+}
+
+static void
+r5k_dma_cache_wback(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+	if (size >= dcache_size) {
+		blast_dcache32();
+	} else {
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size - 1) & ~(dc_lsize - 1);
+		while (a <= end) {
+			flush_dcache_line_wb(a); /* Hit_Writeback_D */
+			a += dc_lsize;
+		}
+	}
+}
+
 /* Detect and size the various r4k caches. */
 static void __init probe_icache(unsigned long config)
 {
@@ -1374,7 +1495,7 @@
 	_dma_cache_inv = r4k_dma_cache_inv_pc;
 }
 
-static void __init setup_scache_funcs(void)
+static void __init setup_scache_funcs_r4k(void)
 {
 	switch(sc_lsize) {
 	case 16:
@@ -1457,19 +1578,36 @@
 	_dma_cache_inv = r4k_dma_cache_inv_sc;
 }
 
+static void __init setup_scache_funcs_r5k(void) {
+	_clear_page = r4k_clear_page_d32;
+	_copy_page = r4k_copy_page_d32;
+	_flush_cache_all = r4k_flush_cache_all_d32i32;
+	_flush_cache_range = r5k_flush_cache_range;
+	_flush_cache_mm = r4k_flush_cache_mm_d32i32;
+	_flush_page_to_ram = r4k_flush_page_to_ram_d32;
+
+	___flush_cache_all = _flush_cache_all;
+	_flush_icache_page = r4k_flush_icache_page_p;
+	_dma_cache_wback_inv = r5k_dma_cache_wback_inv;
+	_dma_cache_wback = r5k_dma_cache_wback;
+	_dma_cache_inv = r5k_dma_cache_inv;
+}
+
 typedef int (*probe_func_t)(unsigned long);
 
 static inline void __init setup_scache(unsigned int config)
 {
 	probe_func_t probe_scache_kseg1;
-	int sc_present = 0;
 
 	/* Maybe the cpu knows about a l2 cache? */
 	probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
 	sc_present = probe_scache_kseg1(config);
 
 	if (sc_present) {
-		setup_scache_funcs();
+		if (mips_cpu.cputype == CPU_R5000)
+			setup_scache_funcs_r5k();
+		else
+			setup_scache_funcs_r4k();
 		return;
 	}
 
Index: include/asm-mips/r4kcache.h
===================================================================
RCS file: /cvs/linux-mips/include/asm-mips/r4kcache.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- include/asm-mips/r4kcache.h	18 Jul 2002 17:34:01 -0000	1.1
+++ include/asm-mips/r4kcache.h	18 Jul 2002 17:41:35 -0000	1.2
@@ -76,6 +76,19 @@
 		  "i" (Hit_Writeback_Inv_D));
 }
 
+extern inline void flush_dcache_line_wb(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Writeback_D));
+}
+
 static inline void invalidate_dcache_line(unsigned long addr)
 {
 	__asm__ __volatile__(
@@ -606,6 +619,40 @@
 static inline void blast_scache128_page_indexed(unsigned long page)
 {
 	cache128_unroll32(page,Index_Writeback_Inv_SD);
+}
+
+
+#define cache_unroll(base,op)	        	\
+	__asm__ __volatile__("	         	\
+		.set noreorder;		        \
+		.set mips3;		        \
+                cache %1, (%0);	                \
+		.set mips0;			\
+		.set reorder"			\
+		:				\
+		: "r" (base),			\
+		  "i" (op));
+
+extern inline void blast_r5000_scache(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		cache_unroll(start,Page_Invalidate);
+		start += 128*sc_lsize;
+	}
+}
+
+extern inline void blast_r5000_scache_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		cache_unroll(start,Page_Invalidate);
+		start += 128*sc_lsize;
+	}
 }
 
 #endif /* !(_MIPS_R4KCACHE_H) */

  reply	other threads:[~2002-08-06 19:37 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-07-14 21:12 [2.5 patch] R5K SC support Vivien Chappelier
2002-07-15 12:43 ` Ralf Baechle
2002-08-06 19:38   ` Brian Murphy [this message]
2002-08-07 12:11     ` Maciej W. Rozycki

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=3D5025AC.9020203@murphy.dk \
    --to=brian@murphy.dk \
    --cc=linux-mips@oss.sgi.com \
    /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