* [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes
@ 2014-08-06 15:46 Ard Biesheuvel
2014-08-06 15:46 ` [PATCH v3 2/2] arm64: don't flag non-aliasing VIPT I-caches as aliasing Ard Biesheuvel
2014-08-07 17:27 ` [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes Will Deacon
0 siblings, 2 replies; 4+ messages in thread
From: Ard Biesheuvel @ 2014-08-06 15:46 UTC (permalink / raw)
To: linux-arm-kernel
This adds helper functions and #defines to <asm/cachetype.h> to read the
line size and the number of sets from the level 1 instruction cache.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
v3: add WARN_ON(preemptible()), move icache_get_ccsidr() to cpuinfo.c to
prevent #include header recursion hell
v2: put () around macro args, use 64-bit types for asm() mrs/msr calls
arch/arm64/include/asm/cachetype.h | 20 ++++++++++++++++++++
arch/arm64/kernel/cpuinfo.c | 14 ++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
index 7a2e0762cb40..4c631a0a3609 100644
--- a/arch/arm64/include/asm/cachetype.h
+++ b/arch/arm64/include/asm/cachetype.h
@@ -39,6 +39,26 @@
extern unsigned long __icache_flags;
+#define CCSIDR_EL1_LINESIZE_MASK 0x7
+#define CCSIDR_EL1_LINESIZE(x) ((x) & CCSIDR_EL1_LINESIZE_MASK)
+
+#define CCSIDR_EL1_NUMSETS_SHIFT 13
+#define CCSIDR_EL1_NUMSETS_MASK (0x7fff << CCSIDR_EL1_NUMSETS_SHIFT)
+#define CCSIDR_EL1_NUMSETS(x) \
+ (((x) & CCSIDR_EL1_NUMSETS_MASK) >> CCSIDR_EL1_NUMSETS_SHIFT)
+
+extern u64 __attribute_const__ icache_get_ccsidr(void);
+
+static inline int icache_get_linesize(void)
+{
+ return 16 << CCSIDR_EL1_LINESIZE(icache_get_ccsidr());
+}
+
+static inline int icache_get_numsets(void)
+{
+ return 1 + CCSIDR_EL1_NUMSETS(icache_get_ccsidr());
+}
+
/*
* Whilst the D-side always behaves as PIPT on AArch64, aliasing is
* permitted in the I-cache.
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index f798f66634af..319255ff536d 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -20,8 +20,10 @@
#include <asm/cputype.h>
#include <linux/bitops.h>
+#include <linux/bug.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/preempt.h>
#include <linux/printk.h>
#include <linux/smp.h>
@@ -190,3 +192,15 @@ void __init cpuinfo_store_boot_cpu(void)
boot_cpu_data = *info;
}
+
+u64 __attribute_const__ icache_get_ccsidr(void)
+{
+ u64 ccsidr;
+
+ WARN_ON(preemptible());
+
+ /* Select L1 I-cache and read its size ID register */
+ asm("msr csselr_el1, %1; isb; mrs %0, ccsidr_el1"
+ : "=r"(ccsidr) : "r"(1L));
+ return ccsidr;
+}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] arm64: don't flag non-aliasing VIPT I-caches as aliasing
2014-08-06 15:46 [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes Ard Biesheuvel
@ 2014-08-06 15:46 ` Ard Biesheuvel
2014-08-07 17:28 ` Will Deacon
2014-08-07 17:27 ` [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes Will Deacon
1 sibling, 1 reply; 4+ messages in thread
From: Ard Biesheuvel @ 2014-08-06 15:46 UTC (permalink / raw)
To: linux-arm-kernel
VIPT caches are non-aliasing if the index is derived from address bits that
are always equal between VA and PA. Classifying these as aliasing results in
unnecessary flushing which may hurt performance.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
v2, v3: no changes
arch/arm64/kernel/cpuinfo.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 319255ff536d..a5b6dce48094 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -49,7 +49,13 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
unsigned int cpu = smp_processor_id();
u32 l1ip = CTR_L1IP(info->reg_ctr);
- if (l1ip != ICACHE_POLICY_PIPT)
+ /*
+ * VIPT caches are non-aliasing if the VA always equals the PA in all
+ * bit positions that are covered by the index, i.e., if num_sets_shift
+ * is less than or equal to PAGE_SHIFT minus line_size_shift.
+ */
+ if (l1ip != ICACHE_POLICY_PIPT && !(l1ip == ICACHE_POLICY_VIPT &&
+ icache_get_linesize() * icache_get_numsets() <= PAGE_SIZE))
set_bit(ICACHEF_ALIASING, &__icache_flags);
if (l1ip == ICACHE_POLICY_AIVIVT);
set_bit(ICACHEF_AIVIVT, &__icache_flags);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes
2014-08-06 15:46 [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes Ard Biesheuvel
2014-08-06 15:46 ` [PATCH v3 2/2] arm64: don't flag non-aliasing VIPT I-caches as aliasing Ard Biesheuvel
@ 2014-08-07 17:27 ` Will Deacon
1 sibling, 0 replies; 4+ messages in thread
From: Will Deacon @ 2014-08-07 17:27 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Aug 06, 2014 at 04:46:05PM +0100, Ard Biesheuvel wrote:
> This adds helper functions and #defines to <asm/cachetype.h> to read the
> line size and the number of sets from the level 1 instruction cache.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> v3: add WARN_ON(preemptible()), move icache_get_ccsidr() to cpuinfo.c to
> prevent #include header recursion hell
> v2: put () around macro args, use 64-bit types for asm() mrs/msr calls
>
> arch/arm64/include/asm/cachetype.h | 20 ++++++++++++++++++++
> arch/arm64/kernel/cpuinfo.c | 14 ++++++++++++++
> 2 files changed, 34 insertions(+)
Acked-by: Will Deacon <will.deacon@arm.com>
Will
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] arm64: don't flag non-aliasing VIPT I-caches as aliasing
2014-08-06 15:46 ` [PATCH v3 2/2] arm64: don't flag non-aliasing VIPT I-caches as aliasing Ard Biesheuvel
@ 2014-08-07 17:28 ` Will Deacon
0 siblings, 0 replies; 4+ messages in thread
From: Will Deacon @ 2014-08-07 17:28 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Aug 06, 2014 at 04:46:06PM +0100, Ard Biesheuvel wrote:
> VIPT caches are non-aliasing if the index is derived from address bits that
> are always equal between VA and PA. Classifying these as aliasing results in
> unnecessary flushing which may hurt performance.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> v2, v3: no changes
>
> arch/arm64/kernel/cpuinfo.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 319255ff536d..a5b6dce48094 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -49,7 +49,13 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
> unsigned int cpu = smp_processor_id();
> u32 l1ip = CTR_L1IP(info->reg_ctr);
>
> - if (l1ip != ICACHE_POLICY_PIPT)
> + /*
> + * VIPT caches are non-aliasing if the VA always equals the PA in all
> + * bit positions that are covered by the index, i.e., if num_sets_shift
> + * is less than or equal to PAGE_SHIFT minus line_size_shift.
> + */
> + if (l1ip != ICACHE_POLICY_PIPT && !(l1ip == ICACHE_POLICY_VIPT &&
> + icache_get_linesize() * icache_get_numsets() <= PAGE_SIZE))
Might just be me, but I'd find this a lot easier to understand if you had a
local `way_size' variable and set it to linesize * num_sets.
Either way:
Acked-by: Will Deacon <will.deacon@arm.com>
Will
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-08-07 17:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-06 15:46 [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes Ard Biesheuvel
2014-08-06 15:46 ` [PATCH v3 2/2] arm64: don't flag non-aliasing VIPT I-caches as aliasing Ard Biesheuvel
2014-08-07 17:28 ` Will Deacon
2014-08-07 17:27 ` [PATCH v3 1/2] arm64: add helper functions to read I-cache attributes Will Deacon
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.