📄 cache.c
字号:
/* $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;#endifvoid __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}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -