patch-2.4.0-test12 linux/arch/parisc/kernel/cache.c
Next file: linux/arch/parisc/kernel/ccio-dma.c
Previous file: linux/arch/parisc/kernel/Makefile
Back to the patch index
Back to the overall index
- Lines: 254
- Date:
Tue Dec 5 12:29:39 2000
- Orig file:
v2.4.0-test11/linux/arch/parisc/kernel/cache.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/cache.c linux/arch/parisc/kernel/cache.c
@@ -0,0 +1,253 @@
+/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
+ *
+ * Cache and TLB management
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/pdc.h>
+#include <asm/cache.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+struct pdc_cache_info cache_info;
+#ifndef __LP64__
+static struct pdc_btlb_info btlb_info;
+#endif
+
+
+void __flush_page_to_ram(unsigned long address)
+{
+ __flush_dcache_range(address, PAGE_SIZE);
+ __flush_icache_range(address, PAGE_SIZE);
+}
+
+
+
+void flush_data_cache(void)
+{
+ register unsigned long base = cache_info.dc_base;
+ register unsigned long count = cache_info.dc_count;
+ register unsigned long loop = cache_info.dc_loop;
+ register unsigned long stride = cache_info.dc_stride;
+ register unsigned long addr;
+ register long i, j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ fdce(addr);
+}
+
+static inline void flush_data_tlb_space(void)
+{
+ unsigned long base = cache_info.dt_off_base;
+ unsigned long count = cache_info.dt_off_count;
+ unsigned long stride = cache_info.dt_off_stride;
+ unsigned long loop = cache_info.dt_loop;
+
+ unsigned long addr;
+ long i,j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ pdtlbe(addr);
+}
+
+
+
+void flush_data_tlb(void)
+{
+ unsigned long base = cache_info.dt_sp_base;
+ unsigned long count = cache_info.dt_sp_count;
+ unsigned long stride = cache_info.dt_sp_stride;
+ unsigned long space;
+ unsigned long old_sr1;
+ long i;
+
+ old_sr1 = mfsp(1);
+
+ for(i=0,space=base; i<count; i++, space+=stride) {
+ mtsp(space,1);
+ flush_data_tlb_space();
+ }
+
+ mtsp(old_sr1, 1);
+}
+
+static inline void flush_instruction_tlb_space(void)
+{
+ unsigned long base = cache_info.it_off_base;
+ unsigned long count = cache_info.it_off_count;
+ unsigned long stride = cache_info.it_off_stride;
+ unsigned long loop = cache_info.it_loop;
+
+ unsigned long addr;
+ long i,j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ pitlbe(addr);
+}
+
+void flush_instruction_tlb(void)
+{
+ unsigned long base = cache_info.it_sp_base;
+ unsigned long count = cache_info.it_sp_count;
+ unsigned long stride = cache_info.it_sp_stride;
+ unsigned long space;
+ unsigned long old_sr1;
+ unsigned int i;
+
+ old_sr1 = mfsp(1);
+
+ for(i=0,space=base; i<count; i++, space+=stride) {
+ mtsp(space,1);
+ flush_instruction_tlb_space();
+ }
+
+ mtsp(old_sr1, 1);
+}
+
+
+void __flush_tlb_space(unsigned long space)
+{
+ unsigned long old_sr1;
+
+ old_sr1 = mfsp(1);
+ mtsp(space, 1);
+
+ flush_data_tlb_space();
+ flush_instruction_tlb_space();
+
+ mtsp(old_sr1, 1);
+}
+
+
+void flush_instruction_cache(void)
+{
+ register unsigned long base = cache_info.ic_base;
+ register unsigned long count = cache_info.ic_count;
+ register unsigned long loop = cache_info.ic_loop;
+ register unsigned long stride = cache_info.ic_stride;
+ register unsigned long addr;
+ register long i, j;
+ unsigned long old_sr1;
+
+ old_sr1 = mfsp(1);
+ mtsp(0,1);
+
+ /*
+ * Note: fice instruction has 3 bit space field, so one must
+ * be specified (otherwise you are justing using whatever
+ * happens to be in sr0).
+ */
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ fice(addr);
+
+ mtsp(old_sr1, 1);
+}
+
+/* not yet ... fdc() needs to be implemented in cache.h !
+void flush_datacache_range( unsigned int base, unsigned int end )
+{
+ register long offset,offset_add;
+ offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) *
+ cache_info.dc_conf.cc_line ) << 4;
+ for (offset=base; offset<=end; offset+=offset_add)
+ fdc(space,offset);
+ fdc(space,end);
+}
+*/
+
+/* flushes code and data-cache */
+void flush_all_caches(void)
+{
+ flush_instruction_cache();
+ flush_data_cache();
+
+ flush_instruction_tlb();
+ flush_data_tlb();
+
+ asm volatile("sync");
+ asm volatile("syncdma");
+ asm volatile("sync");
+}
+
+int get_cache_info(char *buffer)
+{
+ char *p = buffer;
+
+ p += sprintf(p, "I-cache\t\t: %ld KB\n",
+ cache_info.ic_size/1024 );
+ p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n",
+ cache_info.dc_size/1024,
+ (cache_info.dc_conf.cc_wt ? "WT":"WB"),
+ (cache_info.dc_conf.cc_sh ? " - shared I/D":"")
+ );
+
+ p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
+ cache_info.it_size,
+ cache_info.dt_size,
+ cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
+ );
+
+#ifndef __LP64__
+ /* BTLB - Block TLB */
+ if (btlb_info.max_size==0) {
+ p += sprintf(p, "BTLB\t\t: not supported\n" );
+ } else {
+ p += sprintf(p,
+ "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
+ "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
+ "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
+ btlb_info.max_size, (int)4096,
+ btlb_info.max_size>>8,
+ btlb_info.fixed_range_info.num_i,
+ btlb_info.fixed_range_info.num_d,
+ btlb_info.fixed_range_info.num_comb,
+ btlb_info.variable_range_info.num_i,
+ btlb_info.variable_range_info.num_d,
+ btlb_info.variable_range_info.num_comb
+ );
+ }
+#endif
+
+ return p - buffer;
+}
+
+
+void __init
+cache_init(void)
+{
+ if(pdc_cache_info(&cache_info)<0)
+ panic("cache_init: pdc_cache_info failed");
+
+#if 0
+ printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
+ cache_info.ic_size,
+ cache_info.dc_size,
+ cache_info.it_size,
+ sizeof (struct pdc_cache_info) / sizeof (long),
+ sizeof (struct pdc_cache_cf)
+ );
+#endif
+#ifndef __LP64__
+ if(pdc_btlb_info(&btlb_info)<0) {
+ memset(&btlb_info, 0, sizeof btlb_info);
+ }
+#endif
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)