⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-r4k.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	default:		if (!(config & MIPS_CONF_M))			panic("Don't know how to probe P-caches on this cpu.");		/*		 * So we seem to be a MIPS32 or MIPS64 CPU		 * So let's probe the I-cache ...		 */		config1 = read_c0_config1();		if ((lsize = ((config1 >> 19) & 7)))			c->icache.linesz = 2 << lsize;		else			c->icache.linesz = lsize;		c->icache.sets = 64 << ((config1 >> 22) & 7);		c->icache.ways = 1 + ((config1 >> 16) & 7);		icache_size = c->icache.sets *		              c->icache.ways *		              c->icache.linesz;		c->icache.waybit = __ffs(icache_size/c->icache.ways);		if (config & 0x8)		/* VI bit */			c->icache.flags |= MIPS_CACHE_VTAG;		/*		 * Now probe the MIPS32 / MIPS64 data cache.		 */		c->dcache.flags = 0;		if ((lsize = ((config1 >> 10) & 7)))			c->dcache.linesz = 2 << lsize;		else			c->dcache.linesz= lsize;		c->dcache.sets = 64 << ((config1 >> 13) & 7);		c->dcache.ways = 1 + ((config1 >> 7) & 7);		dcache_size = c->dcache.sets *		              c->dcache.ways *		              c->dcache.linesz;		c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);		c->options |= MIPS_CPU_PREFETCH;		break;	}	/*	 * Processor configuration sanity check for the R4000SC erratum	 * #5.  With page sizes larger than 32kB there is no possibility	 * to get a VCE exception anymore so we don't care about this	 * misconfiguration.  The case is rather theoretical anyway;	 * presumably no vendor is shipping his hardware in the "bad"	 * configuration.	 */	if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 &&	    !(config & CONF_SC) && c->icache.linesz != 16 &&	    PAGE_SIZE <= 0x8000)		panic("Improper R4000SC processor configuration detected");	/* compute a couple of other cache variables */	c->icache.waysize = icache_size / c->icache.ways;	c->dcache.waysize = dcache_size / c->dcache.ways;	c->icache.sets = c->icache.linesz ?		icache_size / (c->icache.linesz * c->icache.ways) : 0;	c->dcache.sets = c->dcache.linesz ?		dcache_size / (c->dcache.linesz * c->dcache.ways) : 0;	/*	 * R10000 and R12000 P-caches are odd in a positive way.  They're 32kB	 * 2-way virtually indexed so normally would suffer from aliases.  So	 * normally they'd suffer from aliases but magic in the hardware deals	 * with that for us so we don't need to take care ourselves.	 */	switch (c->cputype) {	case CPU_20KC:	case CPU_25KF:	case CPU_SB1:	case CPU_SB1A:		c->dcache.flags |= MIPS_CACHE_PINDEX;		break;	case CPU_R10000:	case CPU_R12000:	case CPU_R14000:		break;	case CPU_24K:	case CPU_34K:	case CPU_74K:		if ((read_c0_config7() & (1 << 16))) {			/* effectively physically indexed dcache,			   thus no virtual aliases. */			c->dcache.flags |= MIPS_CACHE_PINDEX;			break;		}	default:		if (c->dcache.waysize > PAGE_SIZE)			c->dcache.flags |= MIPS_CACHE_ALIASES;	}	switch (c->cputype) {	case CPU_20KC:		/*		 * Some older 20Kc chips doesn't have the 'VI' bit in		 * the config register.		 */		c->icache.flags |= MIPS_CACHE_VTAG;		break;	case CPU_AU1000:	case CPU_AU1500:	case CPU_AU1100:	case CPU_AU1550:	case CPU_AU1200:		c->icache.flags |= MIPS_CACHE_IC_F_DC;		break;	}#ifdef  CONFIG_CPU_LOONGSON2	/*	 * LOONGSON2 has 4 way icache, but when using indexed cache op,	 * one op will act on all 4 ways	 */	c->icache.ways = 1;#endif	printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",	       icache_size >> 10,	       cpu_has_vtag_icache ? "VIVT" : "VIPT",	       way_string[c->icache.ways], c->icache.linesz);	printk("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n",	       dcache_size >> 10, way_string[c->dcache.ways],	       (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT",	       (c->dcache.flags & MIPS_CACHE_ALIASES) ?			"cache aliases" : "no aliases",	       c->dcache.linesz);}/* * If you even _breathe_ on this function, look at the gcc output and make sure * it does not pop things on and off the stack for the cache sizing loop that * executes in KSEG1 space or else you will crash and burn badly.  You have * been warned. */static int __init probe_scache(void){	unsigned long flags, addr, begin, end, pow2;	unsigned int config = read_c0_config();	struct cpuinfo_mips *c = &current_cpu_data;	int tmp;	if (config & CONF_SC)		return 0;	begin = (unsigned long) &_stext;	begin &= ~((4 * 1024 * 1024) - 1);	end = begin + (4 * 1024 * 1024);	/*	 * This is such a bitch, you'd think they would make it easy to do	 * this.  Away you daemons of stupidity!	 */	local_irq_save(flags);	/* Fill each size-multiple cache line with a valid tag. */	pow2 = (64 * 1024);	for (addr = begin; addr < end; addr = (begin + pow2)) {		unsigned long *p = (unsigned long *) addr;		__asm__ __volatile__("nop" : : "r" (*p)); /* whee... */		pow2 <<= 1;	}	/* Load first line with zero (therefore invalid) tag. */	write_c0_taglo(0);	write_c0_taghi(0);	__asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */	cache_op(Index_Store_Tag_I, begin);	cache_op(Index_Store_Tag_D, begin);	cache_op(Index_Store_Tag_SD, begin);	/* Now search for the wrap around point. */	pow2 = (128 * 1024);	tmp = 0;	for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) {		cache_op(Index_Load_Tag_SD, addr);		__asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */		if (!read_c0_taglo())			break;		pow2 <<= 1;	}	local_irq_restore(flags);	addr -= begin;	scache_size = addr;	c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);	c->scache.ways = 1;	c->dcache.waybit = 0;		/* does not matter */	return 1;}#if defined(CONFIG_CPU_LOONGSON2)static void __init loongson2_sc_init(void){	struct cpuinfo_mips *c = &current_cpu_data;	scache_size = 512*1024;	c->scache.linesz = 32;	c->scache.ways = 4;	c->scache.waybit = 0;	c->scache.waysize = scache_size / (c->scache.ways);	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);	pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);	c->options |= MIPS_CPU_INCLUSIVE_CACHES;}#endifextern int r5k_sc_init(void);extern int rm7k_sc_init(void);extern int mips_sc_init(void);static void __init setup_scache(void){	struct cpuinfo_mips *c = &current_cpu_data;	unsigned int config = read_c0_config();	int sc_present = 0;	/*	 * Do the probing thing on R4000SC and R4400SC processors.  Other	 * processors don't have a S-cache that would be relevant to the	 * Linux memory managment.	 */	switch (c->cputype) {	case CPU_R4000SC:	case CPU_R4000MC:	case CPU_R4400SC:	case CPU_R4400MC:		sc_present = run_uncached(probe_scache);		if (sc_present)			c->options |= MIPS_CPU_CACHE_CDEX_S;		break;	case CPU_R10000:	case CPU_R12000:	case CPU_R14000:		scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);		c->scache.linesz = 64 << ((config >> 13) & 1);		c->scache.ways = 2;		c->scache.waybit= 0;		sc_present = 1;		break;	case CPU_R5000:	case CPU_NEVADA:#ifdef CONFIG_R5000_CPU_SCACHE		r5k_sc_init();#endif                return;	case CPU_RM7000:	case CPU_RM9000:#ifdef CONFIG_RM7000_CPU_SCACHE		rm7k_sc_init();#endif		return;#if defined(CONFIG_CPU_LOONGSON2)	case CPU_LOONGSON2:		loongson2_sc_init();		return;#endif	default:		if (c->isa_level == MIPS_CPU_ISA_M32R1 ||		    c->isa_level == MIPS_CPU_ISA_M32R2 ||		    c->isa_level == MIPS_CPU_ISA_M64R1 ||		    c->isa_level == MIPS_CPU_ISA_M64R2) {#ifdef CONFIG_MIPS_CPU_SCACHE			if (mips_sc_init ()) {				scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;				printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",				       scache_size >> 10,				       way_string[c->scache.ways], c->scache.linesz);			}#else			if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))				panic("Dunno how to handle MIPS32 / MIPS64 second level cache");#endif			return;		}		sc_present = 0;	}	if (!sc_present)		return;	/* compute a couple of other cache variables */	c->scache.waysize = scache_size / c->scache.ways;	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);	printk("Unified secondary cache %ldkB %s, linesize %d bytes.\n",	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);	c->options |= MIPS_CPU_INCLUSIVE_CACHES;}void au1x00_fixup_config_od(void){	/*	 * c0_config.od (bit 19) was write only (and read as 0)	 * on the early revisions of Alchemy SOCs.  It disables the bus	 * transaction overlapping and needs to be set to fix various errata.	 */	switch (read_c0_prid()) {	case 0x00030100: /* Au1000 DA */	case 0x00030201: /* Au1000 HA */	case 0x00030202: /* Au1000 HB */	case 0x01030200: /* Au1500 AB */	/*	 * Au1100 errata actually keeps silence about this bit, so we set it	 * just in case for those revisions that require it to be set according	 * to arch/mips/au1000/common/cputable.c	 */	case 0x02030200: /* Au1100 AB */	case 0x02030201: /* Au1100 BA */	case 0x02030202: /* Au1100 BC */		set_c0_config(1 << 19);		break;	}}static void __init coherency_setup(void){	change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);	/*	 * c0_status.cu=0 specifies that updates by the sc instruction use	 * the coherency mode specified by the TLB; 1 means cachable	 * coherent update on write will be used.  Not all processors have	 * this bit and; some wire it to zero, others like Toshiba had the	 * silly idea of putting something else there ...	 */	switch (current_cpu_type()) {	case CPU_R4000PC:	case CPU_R4000SC:	case CPU_R4000MC:	case CPU_R4400PC:	case CPU_R4400SC:	case CPU_R4400MC:		clear_c0_config(CONF_CU);		break;	/*	 * We need to catch the early Alchemy SOCs with	 * the write-only co_config.od bit and set it back to one...	 */	case CPU_AU1000: /* rev. DA, HA, HB */	case CPU_AU1100: /* rev. AB, BA, BC ?? */	case CPU_AU1500: /* rev. AB */		au1x00_fixup_config_od();		break;	}}void __init r4k_cache_init(void){	extern void build_clear_page(void);	extern void build_copy_page(void);	extern char __weak except_vec2_generic;	extern char __weak except_vec2_sb1;	struct cpuinfo_mips *c = &current_cpu_data;	switch (c->cputype) {	case CPU_SB1:	case CPU_SB1A:		set_uncached_handler(0x100, &except_vec2_sb1, 0x80);		break;	default:		set_uncached_handler(0x100, &except_vec2_generic, 0x80);		break;	}	probe_pcache();	setup_scache();	r4k_blast_dcache_page_setup();	r4k_blast_dcache_page_indexed_setup();	r4k_blast_dcache_setup();	r4k_blast_icache_page_setup();	r4k_blast_icache_page_indexed_setup();	r4k_blast_icache_setup();	r4k_blast_scache_page_setup();	r4k_blast_scache_page_indexed_setup();	r4k_blast_scache_setup();	/*	 * Some MIPS32 and MIPS64 processors have physically indexed caches.	 * This code supports virtually indexed processors and will be	 * unnecessarily inefficient on physically indexed processors.	 */	if (c->dcache.linesz)		shm_align_mask = max_t( unsigned long,					c->dcache.sets * c->dcache.linesz - 1,					PAGE_SIZE - 1);	else		shm_align_mask = PAGE_SIZE-1;	flush_cache_all		= cache_noop;	__flush_cache_all	= r4k___flush_cache_all;	flush_cache_mm		= r4k_flush_cache_mm;	flush_cache_page	= r4k_flush_cache_page;	flush_cache_range	= r4k_flush_cache_range;	flush_cache_sigtramp	= r4k_flush_cache_sigtramp;	flush_icache_all	= r4k_flush_icache_all;	local_flush_data_cache_page	= local_r4k_flush_data_cache_page;	flush_data_cache_page	= r4k_flush_data_cache_page;	flush_icache_range	= r4k_flush_icache_range;#ifdef CONFIG_DMA_NONCOHERENT	_dma_cache_wback_inv	= r4k_dma_cache_wback_inv;	_dma_cache_wback	= r4k_dma_cache_wback_inv;	_dma_cache_inv		= r4k_dma_cache_inv;#endif	build_clear_page();	build_copy_page();	local_r4k___flush_cache_all(NULL);	coherency_setup();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -