📄 arm_cache.c
字号:
/* * $QNXLicenseC: * Copyright 2007, 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"/* * -------------------------------------------------------------------------- * CPU cache configuration * -------------------------------------------------------------------------- *//* * ARM720T has an 8K unified cache */const struct arm_cache_config arm720_cache_config = { CACHE_FLAG_UNIFIED|CACHE_FLAG_VIRTUAL, 16, 512,};const struct arm_cache_info arm720_cache = { &arm720_cache_config, // dcache_config &cache_720, // dcache_rtn 0, // icache_config 0 // icache_rtn};/* * SA1100/SA1110 has a 16K instruction + 8K data cache */const struct arm_cache_config sa11x0_dcache_config = { CACHE_FLAG_DATA|CACHE_FLAG_VIRTUAL|CACHE_FLAG_WRITEBACK, 32, 256,};const struct arm_cache_config sa11x0_icache_config = { CACHE_FLAG_INSTR|CACHE_FLAG_VIRTUAL, 32, 512,};const struct arm_cache_info sa11x0_cache = { &sa11x0_dcache_config, // dcache_config &cache_sa_d, // dcache_rtn &sa11x0_icache_config, // icache_config &cache_sa_i // icache_rtn};/* * ARM92x has separate I and D caches, sizes read from cache type register */const struct arm_cache_info arm92x_cache = { 0, // dcache_config &cache_920_d, // dcache_rtn 0, // icache_config &cache_920_i // icache_rtn};/* * ARM925 has separate I and D caches, sizes read from cache type register */const struct arm_cache_info arm925_cache = { 0, // dcache_config &cache_925_d, // dcache_rtn 0, // icache_config &cache_925_i // icache_rtn};/* * ARM102x has separate I and D caches, sizes read from cache type register */const struct arm_cache_info arm102x_cache = { 0, // dcache_config &cache_1020_d, // dcache_rtn 0, // icache_config &cache_1020_i // icache_rtn};/* * Xscale has separate I and D caches, sizes read from cache type register */const struct arm_cache_info xscale_cache = { 0, // dcache_config &cache_sa2_d, // dcache_rtn 0, // icache_config &cache_sa2_i // icache_rtn};/* * ARM1136 has separate I and D caches, sizes read from cache type register */const struct arm_cache_info arm1136_cache = { 0, // dcache_config &cache_1136_d, // dcache_rtn 0, // icache_config &cache_1136_i // icache_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 arm_cache_info *cache){ unsigned ctype; unsigned nline; unsigned lsize; unsigned flags; /* * 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(CACHE_LIST_END, config->flags, config->line_size, config->num_lines, cache->dcache_rtn); if (debug_flag) { kprintf("%s: %dx%d %s\n", (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(CACHE_LIST_END, config->flags, config->line_size, config->num_lines, cache->icache_rtn); if (debug_flag) { kprintf("Icache: %dx%d\n", config->num_lines, config->line_size); } } return; } /* * Read CP15 cache type register */ __asm__ __volatile__( "mrc p15, 0, %0, c0, c0, 1" : "=r" (ctype) ); /* * 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("%s: %dx%d %s\n", (flags & CACHE_FLAG_INSTR) ? "Cache" : "Dcache", nline, lsize, (flags & CACHE_FLAG_WRITEBACK) ? "WB" : "WT"); } cpu->data_cache = add_cache(CACHE_LIST_END, 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("Icache: %dx%d\n", nline, lsize); } /* * FIXME: currently all ARM caches are virtual - this may change */ flags = CACHE_FLAG_VIRTUAL | CACHE_FLAG_INSTR; cpu->ins_cache = add_cache(CACHE_LIST_END, flags, lsize, nline, cache->icache_rtn); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -