Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/arch/arm/kernel/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  cacheinfo.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  ARM cacheinfo support
 *
 *  Copyright (C) 2023 Linaro Ltd.
 *  Copyright (C) 2015 ARM Ltd.
 *  All Rights Reserved
 */


#include <linux/bitfield.h>
#include <linux/cacheinfo.h>
#include <linux/of.h>

#include <asm/cachetype.h>
#include <asm/cputype.h>
#include <asm/system_info.h>

/* Ctypen, bits[3(n - 1) + 2 : 3(n - 1)], for n = 1 to 7 */
#define CLIDR_CTYPE_SHIFT(level) (3 * (level - 1))
#define CLIDR_CTYPE_MASK(level)  (7 << CLIDR_CTYPE_SHIFT(level))
#define CLIDR_CTYPE(clidr, level) \
 (((clidr) & CLIDR_CTYPE_MASK(level)) >> CLIDR_CTYPE_SHIFT(level))

#define MAX_CACHE_LEVEL   7 /* Max 7 level supported */

#define CTR_FORMAT_MASK GENMASK(31, 29)
#define CTR_FORMAT_ARMV6 0
#define CTR_FORMAT_ARMV7 4
#define CTR_CWG_MASK GENMASK(27, 24)
#define CTR_DSIZE_LEN_MASK GENMASK(13, 12)
#define CTR_ISIZE_LEN_MASK GENMASK(1, 0)

/* Also valid for v7m */
static inline int cache_line_size_cp15(void)
{
 u32 ctr = read_cpuid_cachetype();
 u32 format = FIELD_GET(CTR_FORMAT_MASK, ctr);

 if (format == CTR_FORMAT_ARMV7) {
  u32 cwg = FIELD_GET(CTR_CWG_MASK, ctr);

  return cwg ? 4 << cwg : ARCH_DMA_MINALIGN;
 } else if (WARN_ON_ONCE(format != CTR_FORMAT_ARMV6)) {
  return ARCH_DMA_MINALIGN;
 }

 return 8 << max(FIELD_GET(CTR_ISIZE_LEN_MASK, ctr),
   FIELD_GET(CTR_DSIZE_LEN_MASK, ctr));
}

int cache_line_size(void)
{
 if (coherency_max_size != 0)
  return coherency_max_size;

 /* CP15 is optional / implementation defined before ARMv6 */
 if (cpu_architecture() < CPU_ARCH_ARMv6)
  return ARCH_DMA_MINALIGN;

 return cache_line_size_cp15();
}
EXPORT_SYMBOL_GPL(cache_line_size);

static inline enum cache_type get_cache_type(int level)
{
 u32 clidr;

 if (level > MAX_CACHE_LEVEL)
  return CACHE_TYPE_NOCACHE;

 clidr = read_clidr();

 return CLIDR_CTYPE(clidr, level);
}

static void ci_leaf_init(struct cacheinfo *this_leaf,
    enum cache_type type, unsigned int level)
{
 this_leaf->level = level;
 this_leaf->type = type;
}

static int detect_cache_level(unsigned int *level_p, unsigned int *leaves_p)
{
 unsigned int ctype, level, leaves;
 u32 ctr, format;

 /* CLIDR is not present before ARMv7/v7m */
 if (cpu_architecture() < CPU_ARCH_ARMv7)
  return -EOPNOTSUPP;

 /* Don't try reading CLIDR if CTR declares old format */
 ctr = read_cpuid_cachetype();
 format = FIELD_GET(CTR_FORMAT_MASK, ctr);
 if (format != CTR_FORMAT_ARMV7)
  return -EOPNOTSUPP;

 for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
  ctype = get_cache_type(level);
  if (ctype == CACHE_TYPE_NOCACHE) {
   level--;
   break;
  }
  /* Separate instruction and data caches */
  leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
 }

 *level_p = level;
 *leaves_p = leaves;

 return 0;
}

int early_cache_level(unsigned int cpu)
{
 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);

 return detect_cache_level(&this_cpu_ci->num_levels, &this_cpu_ci->num_leaves);
}

int init_cache_level(unsigned int cpu)
{
 unsigned int level, leaves;
 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 int fw_level;
 int ret;

 ret = detect_cache_level(&level, &leaves);
 if (ret)
  return ret;

 fw_level = of_find_last_cache_level(cpu);

 if (level < fw_level) {
  /*
 * some external caches not specified in CLIDR_EL1
 * the information may be available in the device tree
 * only unified external caches are considered here
 */

  leaves += (fw_level - level);
  level = fw_level;
 }

 this_cpu_ci->num_levels = level;
 this_cpu_ci->num_leaves = leaves;
 return 0;
}

int populate_cache_leaves(unsigned int cpu)
{
 unsigned int level, idx;
 enum cache_type type;
 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 struct cacheinfo *this_leaf = this_cpu_ci->info_list;
 unsigned int arch = cpu_architecture();

 /* CLIDR is not present before ARMv7/v7m */
 if (arch < CPU_ARCH_ARMv7)
  return -EOPNOTSUPP;

 for (idx = 0, level = 1; level <= this_cpu_ci->num_levels &&
      idx < this_cpu_ci->num_leaves; idx++, level++) {
  type = get_cache_type(level);
  if (type == CACHE_TYPE_SEPARATE) {
   ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
   ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
  } else {
   ci_leaf_init(this_leaf++, type, level);
  }
 }

 return 0;
}

Messung V0.5
C=92 H=92 G=91

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.