aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2014-07-16 11:32:45 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2014-07-18 10:24:10 -0400
commit59ccc0d41b7a60c82c636cd056021f522c30557e (patch)
tree6a9a1c3aa4f346b8061cc841b738dcf7670c15c3
parentdf857416a13734ed9356f6e4f0152d55e4fb748a (diff)
arm64: cachetype: report weakest cache policy
In big.LITTLE systems, the I-cache policy may differ across CPUs, and thus we must always meet the most stringent maintenance requirements of any I-cache in the system when performing maintenance to ensure correctness. Unfortunately this requirement is not met as we always look at the current CPU's cache type register to determine the maintenance requirements. This patch causes the I-cache policy of all CPUs to be taken into account for icache_is_aliasing and icache_is_aivivt. If any I-cache in the system is aliasing or AIVIVT, the respective function will return true. At boot each CPU may set flags to identify that at least one I-cache in the system is aliasing and/or AIVIVT. The now unused and potentially misleading icache_policy function is removed. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/include/asm/cachetype.h16
-rw-r--r--arch/arm64/kernel/cpuinfo.c26
2 files changed, 36 insertions, 6 deletions
diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
index 4b23e758d5e0..7a2e0762cb40 100644
--- a/arch/arm64/include/asm/cachetype.h
+++ b/arch/arm64/include/asm/cachetype.h
@@ -30,10 +30,14 @@
30 30
31#ifndef __ASSEMBLY__ 31#ifndef __ASSEMBLY__
32 32
33static inline u32 icache_policy(void) 33#include <linux/bitops.h>
34{ 34
35 return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK; 35#define CTR_L1IP(ctr) (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
36} 36
37#define ICACHEF_ALIASING BIT(0)
38#define ICACHEF_AIVIVT BIT(1)
39
40extern unsigned long __icache_flags;
37 41
38/* 42/*
39 * Whilst the D-side always behaves as PIPT on AArch64, aliasing is 43 * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
@@ -41,12 +45,12 @@ static inline u32 icache_policy(void)
41 */ 45 */
42static inline int icache_is_aliasing(void) 46static inline int icache_is_aliasing(void)
43{ 47{
44 return icache_policy() != ICACHE_POLICY_PIPT; 48 return test_bit(ICACHEF_ALIASING, &__icache_flags);
45} 49}
46 50
47static inline int icache_is_aivivt(void) 51static inline int icache_is_aivivt(void)
48{ 52{
49 return icache_policy() == ICACHE_POLICY_AIVIVT; 53 return test_bit(ICACHEF_AIVIVT, &__icache_flags);
50} 54}
51 55
52static inline u32 cache_type_cwg(void) 56static inline u32 cache_type_cwg(void)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 1f350fe5b318..3ce99fc1fde1 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -19,7 +19,9 @@
19#include <asm/cpu.h> 19#include <asm/cpu.h>
20#include <asm/cputype.h> 20#include <asm/cputype.h>
21 21
22#include <linux/bitops.h>
22#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/printk.h>
23#include <linux/smp.h> 25#include <linux/smp.h>
24 26
25/* 27/*
@@ -30,6 +32,28 @@
30DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); 32DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
31static struct cpuinfo_arm64 boot_cpu_data; 33static struct cpuinfo_arm64 boot_cpu_data;
32 34
35static char *icache_policy_str[] = {
36 [ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
37 [ICACHE_POLICY_AIVIVT] = "AIVIVT",
38 [ICACHE_POLICY_VIPT] = "VIPT",
39 [ICACHE_POLICY_PIPT] = "PIPT",
40};
41
42unsigned long __icache_flags;
43
44static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
45{
46 unsigned int cpu = smp_processor_id();
47 u32 l1ip = CTR_L1IP(info->reg_ctr);
48
49 if (l1ip != ICACHE_POLICY_PIPT)
50 set_bit(ICACHEF_ALIASING, &__icache_flags);
51 if (l1ip == ICACHE_POLICY_AIVIVT);
52 set_bit(ICACHEF_AIVIVT, &__icache_flags);
53
54 pr_info("Detected %s I-cache on CPU%d", icache_policy_str[l1ip], cpu);
55}
56
33static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) 57static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
34{ 58{
35 info->reg_cntfrq = arch_timer_get_cntfrq(); 59 info->reg_cntfrq = arch_timer_get_cntfrq();
@@ -56,6 +80,8 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
56 info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1); 80 info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
57 info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1); 81 info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
58 info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1); 82 info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
83
84 cpuinfo_detect_icache_policy(info);
59} 85}
60 86
61void cpuinfo_store_cpu(void) 87void cpuinfo_store_cpu(void)