The cacheattr area contains information about the configuration of the on-chip and off-chip cache system. It also contains the control() callout used for cache control operations. This entry is filled by the library routines init_cpuinfo() and init_cacheattr().
Note that init_cpuinfo() deals with caches implemented on the CPU itself; init_cacheattr() handles board-level caches.
Each entry in the cacheattr area consists of the following:
Member | Description |
---|---|
next | index to next lower level entry |
line_size | size of cache line in bytes |
num_lines | number of cache lines |
flags | See below |
control | callout supplied by startup code (see below). |
The total number of bytes described by a particular cacheattr entry is defined by line_size × num_lines.
The flags parameter is a bitmapped variable consisting of the following:
This constant: | Means that the cache: |
---|---|
CACHE_FLAG_INSTR | Holds instructions. |
CACHE_FLAG_DATA | Holds data. |
CACHE_FLAG_UNIFIED | Holds both instructions and data. |
CACHE_FLAG_SHARED | Is shared between multiple processors in an SMP system. |
CACHE_FLAG_SNOOPED | Implements a bus-snooping protocol. |
CACHE_FLAG_VIRTUAL | Is virtually tagged. |
CACHE_FLAG_WRITEBACK | Does write-back, not write-through. |
CACHE_FLAG_CTRL_PHYS | Takes physical addresses via its control() function. |
CACHE_FLAG_SUBSET | Obeys the subset property. This means that one cache level caches something from another level as well. As you go up each cache level, if something is in a particular level, it will also be in all the lower-level caches as well. This impacts the flushing operations of the cache in that a "subsetted" level can be effectively "ignored" by the control() function, since it knows that the operation will be performed on the lower-level cache. |
CACHE_FLAG_NONCOHERENT | Is noncoherent on SMP. |
CACHE_FLAG_NONISA | Doesn't obey ISA cache instructions. |
The cacheattr entries are organized in a linked list, with the next member indicating the index of the next lower cache entry. This was done because some architectures will have separate instruction and data caches at one level, but a unified cache at another level. This linking allows the system page to efficiently contain the information. Note that the entry into the cacheattr tables is done through the cpuinfo's ins_cache and data_cache. Since the cpuinfo is an array indexed by the CPU number for SMP systems, it's possible to construct a description of caches for CPUs with different cache architectures. Here's a diagram showing a two-processor system, with separate L1 instruction and data caches as well as a unified L2 cache:
Given the above memory layout, here's what the cpuinfo and cacheattr fields will look like:
/* * CPUINFO */ cpuinfo [0].ins_cache = 0; cpuinfo [0].data_cache = 1; cpuinfo [1].ins_cache = 0; cpuinfo [1].data_cache = 1; /* * CACHEATTR */ cacheattr [0].next = 2; cacheattr [0].linesize = linesize; cacheattr [0].numlines = numlines; cacheattr [0].flags = CACHE_FLAG_INSTR; cacheattr [1].next = 2; cacheattr [1].linesize = linesize; cacheattr [1].numlines = numlines; cacheattr [1].flags = CACHE_FLAG_DATA; cacheattr [2].next = CACHE_LIST_END; cacheattr [2].linesize = linesize; cacheattr [2].numlines = numlines; cacheattr [2].flags = CACHE_FLAG_UNIFIED;
Note that the actual values chosen for linesize and numlines will, of course, depend on the actual configuration of the caches present on the system.