[PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
Suzuki K Poulose
Suzuki.Poulose at arm.com
Mon Jan 30 08:47:26 PST 2017
On 30/01/17 16:25, Sudeep Holla wrote:
> The number of sets described for each cache level in the CCSIDR is
> limited to 32K and the associativity is limited to 1024 ways.
>
> As part of the ARM8.3 extensions, an alternative format for the
> CCSIDR_EL1 is introduced for AArch64, and for AArch32, a new CCSIDR2
> register is introduced to hold the upper 32 bits of this information,
> and the CCSIDR register format is changed. An identification registers
> are also added to identify the presence for this functionality.
>
> This patch adds support for the alternative format of CCSIDR_EL1.
>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Suzuki K Poulose <suzuki.poulose at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---
> arch/arm64/include/asm/cachetype.h | 58 +++++++++++++++++++++++--------------
> arch/arm64/include/asm/cpufeature.h | 9 ++++++
> arch/arm64/include/asm/sysreg.h | 1 +
> arch/arm64/kernel/cacheinfo.c | 26 ++++++++++++-----
> arch/arm64/kernel/cpufeature.c | 1 +
> 5 files changed, 67 insertions(+), 28 deletions(-)
>
> diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
> index f5588692f1d4..180b3288aa3f 100644
> --- a/arch/arm64/include/asm/cachetype.h
> +++ b/arch/arm64/include/asm/cachetype.h
> @@ -40,9 +40,17 @@
> extern unsigned long __icache_flags;
>
> /*
> - * NumSets, bits[27:13] - (Number of sets in cache) - 1
> - * Associativity, bits[12:3] - (Associativity of cache) - 1
> - * LineSize, bits[2:0] - (Log2(Number of words in cache line)) - 2
> + * +---------------+---------+---------+------------------------------+
> + * | Property | v1 | v2 | Calculation |
> + * +---------------+---------+---------+------------------------------+
> + * | Attributes | [31:28] | NA | |
> + * +---------------+---------+---------+------------------------------+
> + * | NumSets | [27:13] | [55:32] | Number of sets in cache - 1 |
> + * +---------------+---------+---------+------------------------------+
> + * | Associativity | [12: 3] | [23: 3] | Associativity of cache - 1 |
> + * +---------------+---------+---------+------------------------------+
> + * | LineSize | [ 2: 0] | [ 2: 0] | Log2(Words in cache line) - 2|
> + * +---------------+---------+---------+------------------------------+
> */
> #define CCSIDR_EL1_WRITE_THROUGH BIT(31)
> #define CCSIDR_EL1_WRITE_BACK BIT(30)
> @@ -50,19 +58,32 @@ extern unsigned long __icache_flags;
> #define CCSIDR_EL1_WRITE_ALLOCATE BIT(28)
> #define CCSIDR_EL1_LINESIZE_MASK 0x7
> #define CCSIDR_EL1_LINESIZE(x) ((x) & CCSIDR_EL1_LINESIZE_MASK)
> -#define CCSIDR_EL1_ASSOCIATIVITY_SHIFT 3
> -#define CCSIDR_EL1_ASSOCIATIVITY_MASK 0x3ff
> -#define CCSIDR_EL1_ASSOCIATIVITY(x) \
> - (((x) >> CCSIDR_EL1_ASSOCIATIVITY_SHIFT) & CCSIDR_EL1_ASSOCIATIVITY_MASK)
> -#define CCSIDR_EL1_NUMSETS_SHIFT 13
> -#define CCSIDR_EL1_NUMSETS_MASK 0x7fff
> -#define CCSIDR_EL1_NUMSETS(x) \
> - (((x) >> CCSIDR_EL1_NUMSETS_SHIFT) & CCSIDR_EL1_NUMSETS_MASK)
> -
> -#define CACHE_LINESIZE(x) (16 << CCSIDR_EL1_LINESIZE(x))
> -#define CACHE_NUMSETS(x) (CCSIDR_EL1_NUMSETS(x) + 1)
> -#define CACHE_ASSOCIATIVITY(x) (CCSIDR_EL1_ASSOCIATIVITY(x) + 1)
> -
> +#define CCSIDR_EL1_V1_ASSOCIATIVITY_SHIFT 3
> +#define CCSIDR_EL1_V1_ASSOCIATIVITY_MASK 0x3ff
> +#define CCSIDR_EL1_V2_ASSOCIATIVITY_SHIFT 3
> +#define CCSIDR_EL1_V2_ASSOCIATIVITY_MASK 0x1fffff
> +#define CCSIDR_EL1_V1_NUMSETS_SHIFT 13
> +#define CCSIDR_EL1_V1_NUMSETS_MASK 0x7fff
> +#define CCSIDR_EL1_V2_NUMSETS_SHIFT 32
> +#define CCSIDR_EL1_V2_NUMSETS_MASK 0xffffff
> +
> +#define CCSIDR_EL1_V1_ATTRIBUTE_MASK 0xf0000000
> +#define CCSIDR_EL1_V2_ATTRIBUTE_MASK 0x0 /* Not supported */
> +#define CCSIDR_EL1_ATTRIBUTES(v, x) ((x) & CCSIDR_EL1_V##v##_ATTRIBUTE_MASK)
> +#define CCSIDR_EL1_ASSOCIATIVITY(v, x) \
> + (((x) >> CCSIDR_EL1_V##v##_ASSOCIATIVITY_SHIFT) & CCSIDR_EL1_V##v##_ASSOCIATIVITY_MASK)
> +#define CCSIDR_EL1_NUMSETS(v, x) \
> + (((x) >> CCSIDR_EL1_V##v##_NUMSETS_SHIFT) & CCSIDR_EL1_V##v##_NUMSETS_MASK)
> +
> +#define CACHE_LINESIZE(x) (16 << CCSIDR_EL1_LINESIZE(x))
> +#define CACHE_NUMSETS_V1(x) (CCSIDR_EL1_NUMSETS(1, x) + 1)
> +#define CACHE_ASSOCIATIVITY_V1(x) (CCSIDR_EL1_ASSOCIATIVITY(1, x) + 1)
> +#define CACHE_ATTRIBUTES_V1(x) (CCSIDR_EL1_ATTRIBUTES(1, x))
> +#define CACHE_NUMSETS_V2(x) (CCSIDR_EL1_NUMSETS(2, x) + 1)
> +#define CACHE_ASSOCIATIVITY_V2(x) (CCSIDR_EL1_ASSOCIATIVITY(2, x) + 1)
> +#define CACHE_ATTRIBUTES_V2(x) (CCSIDR_EL1_ATTRIBUTES(2, x))
> +
> +extern int icache_get_numsets(void);
> extern u64 __attribute_const__ cache_get_ccsidr(u64 csselr);
>
> /* Helpers for Level 1 Instruction cache csselr = 1L */
> @@ -71,11 +92,6 @@ static inline int icache_get_linesize(void)
> return CACHE_LINESIZE(cache_get_ccsidr(1L));
> }
>
> -static inline int icache_get_numsets(void)
> -{
> - return CACHE_NUMSETS(cache_get_ccsidr(1L));
> -}
> -
> /*
> * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
> * permitted in the I-cache.
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index b4989df48670..076a22ade503 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -185,6 +185,11 @@ static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
> return val == ID_AA64PFR0_EL0_32BIT_64BIT;
> }
>
> +static inline bool id_aa64mmfr2_ccsidr_64b_format(u64 mmfr2)
> +{
> + return cpuid_feature_extract_unsigned_field(mmfr2, ID_AA64MMFR2_CCIDX_SHIFT) == 0x1;
> +}
> +
> void __init setup_cpu_features(void);
>
> void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> @@ -224,6 +229,10 @@ static inline bool system_uses_ttbr0_pan(void)
> !cpus_have_cap(ARM64_HAS_PAN);
> }
>
> +static inline bool cpu_supports_ccsidr_64b_format(void)
> +{
> + return id_aa64mmfr2_ccsidr_64b_format(read_system_reg(SYS_ID_AA64MMFR2_EL1));
read_system_reg() gives you the system wide safe value for the register, which could
be different from that of the current CPU. You have to use read_sysreg_s(), to read
a register on the CPU (which aren't yet recognized by GAS).
Sorry, the names are a bit confusing, which can easily cause such issues. May be we should
rename some of them.
> +}
> #endif /* __ASSEMBLY__ */
>
> #endif
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 98ae03f8eedd..c72dfe8807ca 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -183,6 +183,7 @@
> #define ID_AA64MMFR1_VMIDBITS_16 2
>
> /* id_aa64mmfr2 */
> +#define ID_AA64MMFR2_CCIDX_SHIFT 20
> #define ID_AA64MMFR2_LVA_SHIFT 16
> #define ID_AA64MMFR2_IESB_SHIFT 12
> #define ID_AA64MMFR2_LSM_SHIFT 8
> diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c
> index 3f2250fc391b..888b38f1709f 100644
> --- a/arch/arm64/kernel/cacheinfo.c
> +++ b/arch/arm64/kernel/cacheinfo.c
> @@ -43,6 +43,13 @@ static inline enum cache_type get_cache_type(int level)
> return CLIDR_CTYPE(clidr, level);
> }
>
> +int icache_get_numsets(void)
Could this be static ? I could not see it used anywhere else outside this file.
Suzuki
More information about the linux-arm-kernel
mailing list