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

📄 arm_cache.c

📁 Centrality Atlas II development software
💻 C
字号:
/* * $QNXLicenseC: * Copyright 2008, QNX Software Systems.  *  * Licensed under the Apache License, Version 2.0 (the "License"). You  * may not reproduce, modify or distribute this software except in  * compliance with the License. You may obtain a copy of the License  * at: http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" basis,  * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as  * contributors under the License or as licensors under other terms.   * Please review this entire file for other proprietary rights or license  * notices, as well as the QNX Development Suite License Guide at  * http://licensing.qnx.com/license-guide/ for other information. * $ */#include "startup.h"static inline unsignedarm_v7_ccsidr(int level, int icache){	unsigned	ccsidr;	// Set CSSELR for this level and cache type	__asm__ __volatile__("mcr	p15, 2, %0, c0, c0, 0" : : "r"((level << 1) | icache));	// Get CSSIDR value	__asm__ __volatile__("mrc	p15, 1, %0, c0, c0, 0" : "=r"(ccsidr));	return ccsidr;}static inline voidarm_v7_cache_size(unsigned cssidr, unsigned *nline, unsigned *lsize){	unsigned	nsets = ((cssidr >> 13) & 0x7fff) + 1;	unsigned	assoc = ((cssidr >> 3) & 0x3ff) + 1;	*nline = nsets * assoc;	*lsize = 1 << ((cssidr & 7) + 4);}voidarm_v7_add_cache(unsigned cpunum, struct cpuinfo_entry *cpu, const struct armv_cache *cache){	unsigned	clidr;	int			i;	/*	 * Read CLIDR to figure out how many cache levels are implemented	 */	__asm__ __volatile__("mrc	p15, 1, %0, c0, c0, 1" : "=r"(clidr));	for (i = 0; i < 8; i++, clidr >>= 3) {		unsigned	type = clidr & 7;		unsigned	ccsidr;		unsigned	nline;		unsigned	lsize;		unsigned	flags;		if (type == 0) {			break;		}		if (type > 4) {			crash("CLIDR reports reserved value");		}		flags = 0;		if (type & 1) {			ccsidr = arm_v7_ccsidr(i, 1);			arm_v7_cache_size(ccsidr, &nline, &lsize);			if (debug_flag) {				kprintf("CPU%d: L%d Icache: %dx%d\n", cpunum, i+1, nline, lsize);			}			/*			 * FIXME: do we need to check CTR to set CACHE_FLAG_VIRTUAL?			 */			flags = CACHE_FLAG_INSTR;		}		if ((type & 2) || type == 4) {			ccsidr = arm_v7_ccsidr(i, 0);			arm_v7_cache_size(ccsidr, &nline, &lsize);			flags = (type == 4) ? CACHE_FLAG_UNIFIED : CACHE_FLAG_DATA;			if (ccsidr & (1 << 30)) {				flags |= CACHE_FLAG_WRITEBACK;			}			if (debug_flag) {				kprintf("CPU%d: L%d Dcache: %dx%d %s\n", cpunum, i+1, nline, lsize, (flags & CACHE_FLAG_WRITEBACK) ? "WB" : "WT");			}		}		/*		 * CP15 cache operations work on all levels so only call add_cache()		 * for L1 caches.		 */		if (i == 0) {			if (flags & CACHE_FLAG_INSTR) {				cpu->ins_cache = add_cache(cpu->ins_cache,											flags,											lsize,											nline,											cache->icache_rtn);			}			else {				cpu->data_cache = add_cache(cpu->data_cache,											flags,											lsize,											nline,											cache->dcache_rtn);			}		}	}}/* * Parse the CP15 cache type register */static voidarm_cache_size(unsigned csize, unsigned *nline, unsigned *lsize){	unsigned	S = (csize >> 6) & 15;	unsigned	A = (csize >> 3) & 7;	unsigned	M = (csize >> 2) & 1;	unsigned	L = (csize & 3) + 3;	/*	 * Check if cache is absent	 */	if (A == 0 && M == 1) {		*nline = 0;		*lsize = 0;	}	else {		*nline = (M+2) << (S + 8 - L);		*lsize = 1 << L;	}}voidarm_add_cache(struct cpuinfo_entry *cpu, const struct armv_cache *cache){	unsigned	ctype;	unsigned	nline;	unsigned	lsize;	unsigned	flags;	unsigned	cpunum = cpu - lsp.cpuinfo.p;	/*	 * Use hardcoded values if there is no cache type register	 */	if (cache->dcache_config || cache->icache_config) {		const struct arm_cache_config	*config;		if (config = cache->dcache_config) {			cpu->data_cache = add_cache(cpu->data_cache,										config->flags,										config->line_size,										config->num_lines,										cache->dcache_rtn);			if (debug_flag) {				kprintf("CPU%d: %s: %dx%d %s\n", cpunum, (config->flags & CACHE_FLAG_INSTR) ? "Cache" : "Dcache", config->num_lines, config->line_size, (config->flags & CACHE_FLAG_WRITEBACK) ? "WB" : "WT");			}		}		if (config = cache->icache_config) {			cpu->ins_cache = add_cache(cpu->ins_cache,										config->flags,										config->line_size,										config->num_lines,										cache->icache_rtn);			if (debug_flag) {				kprintf("CPU%d: Icache: %dx%d\n", cpunum, config->num_lines, config->line_size);			}		}		return;	}	/*	 * Read CP15 cache type register	 */	ctype = arm_mmu_cache_type();	if (ctype & (1 << 31)) {		/*		 * ARMv7 cache handling is different		 */		arm_v7_add_cache(cpunum, cpu, cache);		return;	}		/*	 * Get Data/Unified cache size	 */	arm_cache_size(ctype >> 12, &nline, &lsize);#ifndef	FIXME	if (nline == 0)		crash("No Dcache in cache type register?");#endif	/*	 * FIXME: currently all ARM caches are virtual - this may change	 */	flags = CACHE_FLAG_VIRTUAL;	if (((ctype >> 25) & 15) != 0)		flags |= CACHE_FLAG_WRITEBACK;	if ((ctype & (1 << 24)) == 0) {		flags |= CACHE_FLAG_UNIFIED;	}	else {		flags |= CACHE_FLAG_DATA;	}	if (debug_flag) {		kprintf("CPU%d: %s: %dx%d %s\n", cpunum, (flags & CACHE_FLAG_INSTR) ? "Cache" : "Dcache", nline, lsize, (flags & CACHE_FLAG_WRITEBACK) ? "WB" : "WT");	}	cpu->data_cache = add_cache(cpu->data_cache, flags, lsize, nline, cache->dcache_rtn);	if ((flags & CACHE_FLAG_INSTR) == 0) {		/*		 * Get Instruction cache size		 */		arm_cache_size(ctype, &nline, &lsize);#ifndef	FIXME		if (nline == 0)			crash("No Icache in cache type register?");#endif		if (debug_flag) {			kprintf("CPU%d: Icache: %dx%d\n", cpunum, nline, lsize);		}		/*		 * FIXME: currently all ARM caches are virtual - this may change		 */		flags = CACHE_FLAG_VIRTUAL | CACHE_FLAG_INSTR;		cpu->ins_cache = add_cache(cpu->ins_cache, flags, lsize, nline, cache->icache_rtn);	}}__SRCVERSION("arm_cache.c $Rev: 206932 $");

⌨️ 快捷键说明

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