All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
@ 2017-01-30 16:25 ` Sudeep Holla
  0 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:25 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Marc Zyngier, Catalin Marinas, Will Deacon, Sudeep Holla

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@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@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));
+}
 #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)
+{
+	if (cpu_supports_ccsidr_64b_format())
+		return CACHE_NUMSETS_V2(cache_get_ccsidr(1L));
+	return CACHE_NUMSETS_V1(cache_get_ccsidr(1L));
+}
+
 /*
  * Cache Size Selection Register(CSSELR) selects which Cache Size ID
  * Register(CCSIDR) is accessible by specifying the required cache
@@ -71,15 +78,20 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
 	this_leaf->level = level;
 	this_leaf->type = type;
 	this_leaf->coherency_line_size = CACHE_LINESIZE(tmp);
-	this_leaf->number_of_sets = CACHE_NUMSETS(tmp);
-	this_leaf->ways_of_associativity = CACHE_ASSOCIATIVITY(tmp);
+	if (cpu_supports_ccsidr_64b_format()) {
+		this_leaf->number_of_sets = CACHE_NUMSETS_V2(tmp);
+		this_leaf->ways_of_associativity = CACHE_ASSOCIATIVITY_V2(tmp);
+	} else {
+		this_leaf->number_of_sets = CACHE_NUMSETS_V1(tmp);
+		this_leaf->ways_of_associativity = CACHE_ASSOCIATIVITY_V1(tmp);
+		this_leaf->attributes =
+		 ((tmp & CCSIDR_EL1_WRITE_THROUGH) ? CACHE_WRITE_THROUGH : 0) |
+		 ((tmp & CCSIDR_EL1_WRITE_BACK) ? CACHE_WRITE_BACK : 0) |
+		 ((tmp & CCSIDR_EL1_READ_ALLOCATE) ? CACHE_READ_ALLOCATE : 0) |
+		 ((tmp & CCSIDR_EL1_WRITE_ALLOCATE) ? CACHE_WRITE_ALLOCATE : 0);
+	}
 	this_leaf->size = this_leaf->number_of_sets *
 	    this_leaf->coherency_line_size * this_leaf->ways_of_associativity;
-	this_leaf->attributes =
-		((tmp & CCSIDR_EL1_WRITE_THROUGH) ? CACHE_WRITE_THROUGH : 0) |
-		((tmp & CCSIDR_EL1_WRITE_BACK) ? CACHE_WRITE_BACK : 0) |
-		((tmp & CCSIDR_EL1_READ_ALLOCATE) ? CACHE_READ_ALLOCATE : 0) |
-		((tmp & CCSIDR_EL1_WRITE_ALLOCATE) ? CACHE_WRITE_ALLOCATE : 0);
 }

 static int __init_cache_level(unsigned int cpu)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index fdf8f045929f..1a942950d611 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -137,6 +137,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
 };

 static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_CCIDX_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
--
2.7.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
@ 2017-01-30 16:25 ` Sudeep Holla
  0 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:25 UTC (permalink / raw)
  To: linux-arm-kernel

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@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@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));
+}
 #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)
+{
+	if (cpu_supports_ccsidr_64b_format())
+		return CACHE_NUMSETS_V2(cache_get_ccsidr(1L));
+	return CACHE_NUMSETS_V1(cache_get_ccsidr(1L));
+}
+
 /*
  * Cache Size Selection Register(CSSELR) selects which Cache Size ID
  * Register(CCSIDR) is accessible by specifying the required cache
@@ -71,15 +78,20 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
 	this_leaf->level = level;
 	this_leaf->type = type;
 	this_leaf->coherency_line_size = CACHE_LINESIZE(tmp);
-	this_leaf->number_of_sets = CACHE_NUMSETS(tmp);
-	this_leaf->ways_of_associativity = CACHE_ASSOCIATIVITY(tmp);
+	if (cpu_supports_ccsidr_64b_format()) {
+		this_leaf->number_of_sets = CACHE_NUMSETS_V2(tmp);
+		this_leaf->ways_of_associativity = CACHE_ASSOCIATIVITY_V2(tmp);
+	} else {
+		this_leaf->number_of_sets = CACHE_NUMSETS_V1(tmp);
+		this_leaf->ways_of_associativity = CACHE_ASSOCIATIVITY_V1(tmp);
+		this_leaf->attributes =
+		 ((tmp & CCSIDR_EL1_WRITE_THROUGH) ? CACHE_WRITE_THROUGH : 0) |
+		 ((tmp & CCSIDR_EL1_WRITE_BACK) ? CACHE_WRITE_BACK : 0) |
+		 ((tmp & CCSIDR_EL1_READ_ALLOCATE) ? CACHE_READ_ALLOCATE : 0) |
+		 ((tmp & CCSIDR_EL1_WRITE_ALLOCATE) ? CACHE_WRITE_ALLOCATE : 0);
+	}
 	this_leaf->size = this_leaf->number_of_sets *
 	    this_leaf->coherency_line_size * this_leaf->ways_of_associativity;
-	this_leaf->attributes =
-		((tmp & CCSIDR_EL1_WRITE_THROUGH) ? CACHE_WRITE_THROUGH : 0) |
-		((tmp & CCSIDR_EL1_WRITE_BACK) ? CACHE_WRITE_BACK : 0) |
-		((tmp & CCSIDR_EL1_READ_ALLOCATE) ? CACHE_READ_ALLOCATE : 0) |
-		((tmp & CCSIDR_EL1_WRITE_ALLOCATE) ? CACHE_WRITE_ALLOCATE : 0);
 }

 static int __init_cache_level(unsigned int cpu)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index fdf8f045929f..1a942950d611 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -137,6 +137,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
 };

 static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_CCIDX_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
--
2.7.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros
  2017-01-30 16:25 ` Sudeep Holla
@ 2017-01-30 16:25   ` Sudeep Holla
  -1 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:25 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Marc Zyngier, Catalin Marinas, Will Deacon, Sudeep Holla

We already have various macros related to cache type and bitfields in
CLIDR system register. We can replace some of the hardcoded values
here using those existing macros.

This patch reuses those existing cache type/info related macros and
replaces the hardcorded values. It also removes some of the comments
that become trivial with the macro names.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 arch/arm64/include/asm/cachetype.h |  7 +++++++
 arch/arm64/kernel/cacheinfo.c      |  7 -------
 arch/arm64/kvm/sys_regs.c          | 33 ++++++++++++++++-----------------
 3 files changed, 23 insertions(+), 24 deletions(-)

v1->v2:
	- Fixed issue pointed by Christoffer(left shift operator)
	- Replace couple of more hardcored values with macros

diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
index 180b3288aa3f..6cefbd39a40f 100644
--- a/arch/arm64/include/asm/cachetype.h
+++ b/arch/arm64/include/asm/cachetype.h
@@ -39,6 +39,13 @@

 extern unsigned long __icache_flags;

+#define MAX_CACHE_LEVEL			7	/* Max 7 level supported */
+/* 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))
+
 /*
  * +---------------+---------+---------+------------------------------+
  * | Property      |   v1    |    v2   | Calculation                  |
diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c
index 888b38f1709f..fdb384f18906 100644
--- a/arch/arm64/kernel/cacheinfo.c
+++ b/arch/arm64/kernel/cacheinfo.c
@@ -26,13 +26,6 @@
 #include <asm/cachetype.h>
 #include <asm/processor.h>

-#define MAX_CACHE_LEVEL			7	/* Max 7 level supported */
-/* 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))
-
 static inline enum cache_type get_cache_type(int level)
 {
 	u64 clidr;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 87e7e6608cd8..72656743b4cc 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -21,11 +21,13 @@
  */

 #include <linux/bsearch.h>
+#include <linux/cacheinfo.h>
 #include <linux/kvm_host.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>

 #include <asm/cacheflush.h>
+#include <asm/cachetype.h>
 #include <asm/cputype.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
@@ -59,7 +61,7 @@
 static u32 cache_levels;

 /* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
-#define CSSELR_MAX 12
+#define CSSELR_MAX 	((MAX_CACHE_LEVEL - 1) << 1)

 /* Which cache CCSIDR represents depends on CSSELR value. */
 static u32 get_ccsidr(u32 csselr)
@@ -68,9 +70,7 @@ static u32 get_ccsidr(u32 csselr)

 	/* Make sure noone else changes CSSELR during this! */
 	local_irq_disable();
-	write_sysreg(csselr, csselr_el1);
-	isb();
-	ccsidr = read_sysreg(ccsidr_el1);
+	ccsidr = cache_get_ccsidr(csselr);
 	local_irq_enable();

 	return ccsidr;
@@ -1960,19 +1960,18 @@ static bool is_valid_cache(u32 val)
 		return false;

 	/* Bottom bit is Instruction or Data bit.  Next 3 bits are level. */
-	level = (val >> 1);
-	ctype = (cache_levels >> (level * 3)) & 7;
+	level = (val >> 1) + 1;
+	ctype = CLIDR_CTYPE(cache_levels, level);

 	switch (ctype) {
-	case 0: /* No cache */
-		return false;
-	case 1: /* Instruction cache only */
-		return (val & 1);
-	case 2: /* Data cache only */
-	case 4: /* Unified cache */
-		return !(val & 1);
-	case 3: /* Separate instruction and data caches */
+	case CACHE_TYPE_INST:
+		return (val & CACHE_TYPE_INST);
+	case CACHE_TYPE_DATA:
+	case CACHE_TYPE_UNIFIED:
+		return !(val & CACHE_TYPE_INST);
+	case CACHE_TYPE_SEPARATE:
 		return true;
+	case CACHE_TYPE_NOCACHE:
 	default: /* Reserved: we can't know instruction or data. */
 		return false;
 	}
@@ -2239,11 +2238,11 @@ void kvm_sys_reg_table_init(void)
 	 */
 	get_clidr_el1(NULL, &clidr); /* Ugly... */
 	cache_levels = clidr.val;
-	for (i = 0; i < 7; i++)
-		if (((cache_levels >> (i*3)) & 7) == 0)
+	for (i = 1; i <= MAX_CACHE_LEVEL; i++)
+		if (CLIDR_CTYPE(cache_levels, i) == CACHE_TYPE_NOCACHE)
 			break;
 	/* Clear all higher bits. */
-	cache_levels &= (1 << (i*3))-1;
+	cache_levels &= (1 << CLIDR_CTYPE_SHIFT(i)) - 1;
 }

 /**
--
2.7.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros
@ 2017-01-30 16:25   ` Sudeep Holla
  0 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:25 UTC (permalink / raw)
  To: linux-arm-kernel

We already have various macros related to cache type and bitfields in
CLIDR system register. We can replace some of the hardcoded values
here using those existing macros.

This patch reuses those existing cache type/info related macros and
replaces the hardcorded values. It also removes some of the comments
that become trivial with the macro names.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 arch/arm64/include/asm/cachetype.h |  7 +++++++
 arch/arm64/kernel/cacheinfo.c      |  7 -------
 arch/arm64/kvm/sys_regs.c          | 33 ++++++++++++++++-----------------
 3 files changed, 23 insertions(+), 24 deletions(-)

v1->v2:
	- Fixed issue pointed by Christoffer(left shift operator)
	- Replace couple of more hardcored values with macros

diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
index 180b3288aa3f..6cefbd39a40f 100644
--- a/arch/arm64/include/asm/cachetype.h
+++ b/arch/arm64/include/asm/cachetype.h
@@ -39,6 +39,13 @@

 extern unsigned long __icache_flags;

+#define MAX_CACHE_LEVEL			7	/* Max 7 level supported */
+/* 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))
+
 /*
  * +---------------+---------+---------+------------------------------+
  * | Property      |   v1    |    v2   | Calculation                  |
diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c
index 888b38f1709f..fdb384f18906 100644
--- a/arch/arm64/kernel/cacheinfo.c
+++ b/arch/arm64/kernel/cacheinfo.c
@@ -26,13 +26,6 @@
 #include <asm/cachetype.h>
 #include <asm/processor.h>

-#define MAX_CACHE_LEVEL			7	/* Max 7 level supported */
-/* 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))
-
 static inline enum cache_type get_cache_type(int level)
 {
 	u64 clidr;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 87e7e6608cd8..72656743b4cc 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -21,11 +21,13 @@
  */

 #include <linux/bsearch.h>
+#include <linux/cacheinfo.h>
 #include <linux/kvm_host.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>

 #include <asm/cacheflush.h>
+#include <asm/cachetype.h>
 #include <asm/cputype.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
@@ -59,7 +61,7 @@
 static u32 cache_levels;

 /* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
-#define CSSELR_MAX 12
+#define CSSELR_MAX 	((MAX_CACHE_LEVEL - 1) << 1)

 /* Which cache CCSIDR represents depends on CSSELR value. */
 static u32 get_ccsidr(u32 csselr)
@@ -68,9 +70,7 @@ static u32 get_ccsidr(u32 csselr)

 	/* Make sure noone else changes CSSELR during this! */
 	local_irq_disable();
-	write_sysreg(csselr, csselr_el1);
-	isb();
-	ccsidr = read_sysreg(ccsidr_el1);
+	ccsidr = cache_get_ccsidr(csselr);
 	local_irq_enable();

 	return ccsidr;
@@ -1960,19 +1960,18 @@ static bool is_valid_cache(u32 val)
 		return false;

 	/* Bottom bit is Instruction or Data bit.  Next 3 bits are level. */
-	level = (val >> 1);
-	ctype = (cache_levels >> (level * 3)) & 7;
+	level = (val >> 1) + 1;
+	ctype = CLIDR_CTYPE(cache_levels, level);

 	switch (ctype) {
-	case 0: /* No cache */
-		return false;
-	case 1: /* Instruction cache only */
-		return (val & 1);
-	case 2: /* Data cache only */
-	case 4: /* Unified cache */
-		return !(val & 1);
-	case 3: /* Separate instruction and data caches */
+	case CACHE_TYPE_INST:
+		return (val & CACHE_TYPE_INST);
+	case CACHE_TYPE_DATA:
+	case CACHE_TYPE_UNIFIED:
+		return !(val & CACHE_TYPE_INST);
+	case CACHE_TYPE_SEPARATE:
 		return true;
+	case CACHE_TYPE_NOCACHE:
 	default: /* Reserved: we can't know instruction or data. */
 		return false;
 	}
@@ -2239,11 +2238,11 @@ void kvm_sys_reg_table_init(void)
 	 */
 	get_clidr_el1(NULL, &clidr); /* Ugly... */
 	cache_levels = clidr.val;
-	for (i = 0; i < 7; i++)
-		if (((cache_levels >> (i*3)) & 7) == 0)
+	for (i = 1; i <= MAX_CACHE_LEVEL; i++)
+		if (CLIDR_CTYPE(cache_levels, i) == CACHE_TYPE_NOCACHE)
 			break;
 	/* Clear all higher bits. */
-	cache_levels &= (1 << (i*3))-1;
+	cache_levels &= (1 << CLIDR_CTYPE_SHIFT(i)) - 1;
 }

 /**
--
2.7.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr
  2017-01-30 16:25 ` Sudeep Holla
@ 2017-01-30 16:25   ` Sudeep Holla
  -1 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:25 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel; +Cc: Marc Zyngier, Sudeep Holla

csselr and ccsidr are treated as 64-bit values already elsewhere in the
kernel. It also aligns well with the architecture extensions that allow
64-bit format for ccsidr.

This patch upgrades the existing accesses to csselr and ccsidr from
32-bit to 64-bit in preparation to add support to those extensions.
It also add dedicated KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register
to handle 64-bit ccsidr in KVM.

Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 arch/arm64/include/uapi/asm/kvm.h |   1 +
 arch/arm64/kvm/sys_regs.c         | 104 ++++++++++++++++++++++++++++----------
 2 files changed, 77 insertions(+), 28 deletions(-)

v1->v2:
	- Added dependency on cpu_supports_ccsidr_64b_format(PATCH 1/3)
	- Added a new KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register id
	  to support new 64bit CCSIDR

diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 3051f86a9b5f..8aa18e65e6a5 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -161,6 +161,7 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_DEMUX_ID_MASK	0x000000000000FF00
 #define KVM_REG_ARM_DEMUX_ID_SHIFT	8
 #define KVM_REG_ARM_DEMUX_ID_CCSIDR	(0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
+#define KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR	(0x01 << KVM_REG_ARM_DEMUX_ID_SHIFT)
 #define KVM_REG_ARM_DEMUX_VAL_MASK	0x00000000000000FF
 #define KVM_REG_ARM_DEMUX_VAL_SHIFT	0

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 72656743b4cc..f9822ac6d9ab 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -58,15 +58,15 @@
  */

 /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
-static u32 cache_levels;
+static u64 cache_levels;

-/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
+/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_{EXT_,}CCSIDR */
 #define CSSELR_MAX 	((MAX_CACHE_LEVEL - 1) << 1)

 /* Which cache CCSIDR represents depends on CSSELR value. */
-static u32 get_ccsidr(u32 csselr)
+static u64 get_ccsidr(u64 csselr)
 {
-	u32 ccsidr;
+	u64 ccsidr;

 	/* Make sure noone else changes CSSELR during this! */
 	local_irq_disable();
@@ -1952,9 +1952,9 @@ static int set_invariant_sys_reg(u64 id, void __user *uaddr)
 	return 0;
 }

-static bool is_valid_cache(u32 val)
+static bool is_valid_cache(u64 val)
 {
-	u32 level, ctype;
+	u64 level, ctype;

 	if (val >= CSSELR_MAX)
 		return false;
@@ -1977,10 +1977,28 @@ static bool is_valid_cache(u32 val)
 	}
 }

+static int demux_ccsidr_validate_get(u64 id, int size, u64 *val)
+{
+	u64 cidx;
+
+	if (KVM_REG_SIZE(id) != size)
+		return -ENOENT;
+
+	cidx = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
+			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
+	if (!is_valid_cache(cidx))
+		return -ENOENT;
+
+	*val = get_ccsidr(cidx);
+	return 0;
+}
+
 static int demux_c15_get(u64 id, void __user *uaddr)
 {
-	u32 val;
-	u32 __user *uval = uaddr;
+	int ret;
+	u64 val;
+	u32 __user *uval;
+	u64 __user *uval64;

 	/* Fail if we have unknown bits set. */
 	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
@@ -1989,14 +2007,17 @@ static int demux_c15_get(u64 id, void __user *uaddr)

 	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
 	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
-		if (KVM_REG_SIZE(id) != 4)
-			return -ENOENT;
-		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
-			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
-		if (!is_valid_cache(val))
-			return -ENOENT;
-
-		return put_user(get_ccsidr(val), uval);
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
+		if (ret)
+			return ret;
+		uval = uaddr;
+		return put_user(val, uval);
+	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval64), &val);
+		if (ret)
+			return ret;
+		uval64 = uaddr;
+		return put_user(val, uval64);
 	default:
 		return -ENOENT;
 	}
@@ -2004,8 +2025,10 @@ static int demux_c15_get(u64 id, void __user *uaddr)

 static int demux_c15_set(u64 id, void __user *uaddr)
 {
-	u32 val, newval;
-	u32 __user *uval = uaddr;
+	int ret;
+	u64 val, newval;
+	u32 __user *uval;
+	u64 __user *uval64;

 	/* Fail if we have unknown bits set. */
 	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
@@ -2014,18 +2037,29 @@ static int demux_c15_set(u64 id, void __user *uaddr)

 	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
 	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
-		if (KVM_REG_SIZE(id) != 4)
-			return -ENOENT;
-		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
-			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
-		if (!is_valid_cache(val))
-			return -ENOENT;
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
+		if (ret)
+			return ret;

+		uval = uaddr;
 		if (get_user(newval, uval))
 			return -EFAULT;

 		/* This is also invariant: you can't change it. */
-		if (newval != get_ccsidr(val))
+		if (newval != val)
+			return -EINVAL;
+		return 0;
+	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
+		if (ret)
+			return ret;
+
+		uval64 = uaddr;
+		if (get_user(newval, uval64))
+			return -EFAULT;
+
+		/* This is also invariant: you can't change it. */
+		if (newval != val)
 			return -EINVAL;
 		return 0;
 	default:
@@ -2086,12 +2120,10 @@ static unsigned int num_demux_regs(void)
 	return count;
 }

-static int write_demux_regids(u64 __user *uindices)
+static int write_demux_ccsidr(u64 val, u64 __user *uindices)
 {
-	u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
 	unsigned int i;

-	val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
 	for (i = 0; i < CSSELR_MAX; i++) {
 		if (!is_valid_cache(i))
 			continue;
@@ -2099,9 +2131,25 @@ static int write_demux_regids(u64 __user *uindices)
 			return -EFAULT;
 		uindices++;
 	}
+
 	return 0;
 }

+static int write_demux_regids(u64 __user *uindices)
+{
+	int ret;
+	u64 val = KVM_REG_ARM64 | KVM_REG_ARM_DEMUX;
+
+	if (cpu_supports_ccsidr_64b_format())
+		/* 64 bit extended CCSIDR */
+		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR |
+					 KVM_REG_SIZE_U64, uindices);
+	else
+		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_CCSIDR |
+					 KVM_REG_SIZE_U32, uindices);
+	return ret;
+}
+
 static u64 sys_reg_to_index(const struct sys_reg_desc *reg)
 {
 	return (KVM_REG_ARM64 | KVM_REG_SIZE_U64 |
--
2.7.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr
@ 2017-01-30 16:25   ` Sudeep Holla
  0 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:25 UTC (permalink / raw)
  To: linux-arm-kernel

csselr and ccsidr are treated as 64-bit values already elsewhere in the
kernel. It also aligns well with the architecture extensions that allow
64-bit format for ccsidr.

This patch upgrades the existing accesses to csselr and ccsidr from
32-bit to 64-bit in preparation to add support to those extensions.
It also add dedicated KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register
to handle 64-bit ccsidr in KVM.

Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 arch/arm64/include/uapi/asm/kvm.h |   1 +
 arch/arm64/kvm/sys_regs.c         | 104 ++++++++++++++++++++++++++++----------
 2 files changed, 77 insertions(+), 28 deletions(-)

v1->v2:
	- Added dependency on cpu_supports_ccsidr_64b_format(PATCH 1/3)
	- Added a new KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register id
	  to support new 64bit CCSIDR

diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 3051f86a9b5f..8aa18e65e6a5 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -161,6 +161,7 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_DEMUX_ID_MASK	0x000000000000FF00
 #define KVM_REG_ARM_DEMUX_ID_SHIFT	8
 #define KVM_REG_ARM_DEMUX_ID_CCSIDR	(0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
+#define KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR	(0x01 << KVM_REG_ARM_DEMUX_ID_SHIFT)
 #define KVM_REG_ARM_DEMUX_VAL_MASK	0x00000000000000FF
 #define KVM_REG_ARM_DEMUX_VAL_SHIFT	0

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 72656743b4cc..f9822ac6d9ab 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -58,15 +58,15 @@
  */

 /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
-static u32 cache_levels;
+static u64 cache_levels;

-/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
+/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_{EXT_,}CCSIDR */
 #define CSSELR_MAX 	((MAX_CACHE_LEVEL - 1) << 1)

 /* Which cache CCSIDR represents depends on CSSELR value. */
-static u32 get_ccsidr(u32 csselr)
+static u64 get_ccsidr(u64 csselr)
 {
-	u32 ccsidr;
+	u64 ccsidr;

 	/* Make sure noone else changes CSSELR during this! */
 	local_irq_disable();
@@ -1952,9 +1952,9 @@ static int set_invariant_sys_reg(u64 id, void __user *uaddr)
 	return 0;
 }

-static bool is_valid_cache(u32 val)
+static bool is_valid_cache(u64 val)
 {
-	u32 level, ctype;
+	u64 level, ctype;

 	if (val >= CSSELR_MAX)
 		return false;
@@ -1977,10 +1977,28 @@ static bool is_valid_cache(u32 val)
 	}
 }

+static int demux_ccsidr_validate_get(u64 id, int size, u64 *val)
+{
+	u64 cidx;
+
+	if (KVM_REG_SIZE(id) != size)
+		return -ENOENT;
+
+	cidx = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
+			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
+	if (!is_valid_cache(cidx))
+		return -ENOENT;
+
+	*val = get_ccsidr(cidx);
+	return 0;
+}
+
 static int demux_c15_get(u64 id, void __user *uaddr)
 {
-	u32 val;
-	u32 __user *uval = uaddr;
+	int ret;
+	u64 val;
+	u32 __user *uval;
+	u64 __user *uval64;

 	/* Fail if we have unknown bits set. */
 	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
@@ -1989,14 +2007,17 @@ static int demux_c15_get(u64 id, void __user *uaddr)

 	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
 	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
-		if (KVM_REG_SIZE(id) != 4)
-			return -ENOENT;
-		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
-			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
-		if (!is_valid_cache(val))
-			return -ENOENT;
-
-		return put_user(get_ccsidr(val), uval);
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
+		if (ret)
+			return ret;
+		uval = uaddr;
+		return put_user(val, uval);
+	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval64), &val);
+		if (ret)
+			return ret;
+		uval64 = uaddr;
+		return put_user(val, uval64);
 	default:
 		return -ENOENT;
 	}
@@ -2004,8 +2025,10 @@ static int demux_c15_get(u64 id, void __user *uaddr)

 static int demux_c15_set(u64 id, void __user *uaddr)
 {
-	u32 val, newval;
-	u32 __user *uval = uaddr;
+	int ret;
+	u64 val, newval;
+	u32 __user *uval;
+	u64 __user *uval64;

 	/* Fail if we have unknown bits set. */
 	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
@@ -2014,18 +2037,29 @@ static int demux_c15_set(u64 id, void __user *uaddr)

 	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
 	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
-		if (KVM_REG_SIZE(id) != 4)
-			return -ENOENT;
-		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
-			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
-		if (!is_valid_cache(val))
-			return -ENOENT;
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
+		if (ret)
+			return ret;

+		uval = uaddr;
 		if (get_user(newval, uval))
 			return -EFAULT;

 		/* This is also invariant: you can't change it. */
-		if (newval != get_ccsidr(val))
+		if (newval != val)
+			return -EINVAL;
+		return 0;
+	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
+		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
+		if (ret)
+			return ret;
+
+		uval64 = uaddr;
+		if (get_user(newval, uval64))
+			return -EFAULT;
+
+		/* This is also invariant: you can't change it. */
+		if (newval != val)
 			return -EINVAL;
 		return 0;
 	default:
@@ -2086,12 +2120,10 @@ static unsigned int num_demux_regs(void)
 	return count;
 }

-static int write_demux_regids(u64 __user *uindices)
+static int write_demux_ccsidr(u64 val, u64 __user *uindices)
 {
-	u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
 	unsigned int i;

-	val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
 	for (i = 0; i < CSSELR_MAX; i++) {
 		if (!is_valid_cache(i))
 			continue;
@@ -2099,9 +2131,25 @@ static int write_demux_regids(u64 __user *uindices)
 			return -EFAULT;
 		uindices++;
 	}
+
 	return 0;
 }

+static int write_demux_regids(u64 __user *uindices)
+{
+	int ret;
+	u64 val = KVM_REG_ARM64 | KVM_REG_ARM_DEMUX;
+
+	if (cpu_supports_ccsidr_64b_format())
+		/* 64 bit extended CCSIDR */
+		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR |
+					 KVM_REG_SIZE_U64, uindices);
+	else
+		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_CCSIDR |
+					 KVM_REG_SIZE_U32, uindices);
+	return ret;
+}
+
 static u64 sys_reg_to_index(const struct sys_reg_desc *reg)
 {
 	return (KVM_REG_ARM64 | KVM_REG_SIZE_U64 |
--
2.7.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
  2017-01-30 16:25 ` Sudeep Holla
@ 2017-01-30 16:47   ` Suzuki K Poulose
  -1 siblings, 0 replies; 20+ messages in thread
From: Suzuki K Poulose @ 2017-01-30 16:47 UTC (permalink / raw)
  To: Sudeep Holla, kvmarm, linux-arm-kernel
  Cc: Marc Zyngier, Catalin Marinas, Will Deacon

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@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
@ 2017-01-30 16:47   ` Suzuki K Poulose
  0 siblings, 0 replies; 20+ messages in thread
From: Suzuki K Poulose @ 2017-01-30 16:47 UTC (permalink / raw)
  To: linux-arm-kernel

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@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
  2017-01-30 16:47   ` Suzuki K Poulose
@ 2017-01-30 16:57     ` Sudeep Holla
  -1 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:57 UTC (permalink / raw)
  To: Suzuki K Poulose, kvmarm, linux-arm-kernel
  Cc: Marc Zyngier, Catalin Marinas, Will Deacon, Sudeep Holla



On 30/01/17 16:47, Suzuki K Poulose wrote:
> 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.

[...]

>>  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.
> 

Thanks, fixed locally, will post as part of next version.

>> +}
>>  #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.

Used in arch/arm64/kernel/cpuinfo.c

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
@ 2017-01-30 16:57     ` Sudeep Holla
  0 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-01-30 16:57 UTC (permalink / raw)
  To: linux-arm-kernel



On 30/01/17 16:47, Suzuki K Poulose wrote:
> 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.

[...]

>>  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.
> 

Thanks, fixed locally, will post as part of next version.

>> +}
>>  #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.

Used in arch/arm64/kernel/cpuinfo.c

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
  2017-01-30 16:57     ` Sudeep Holla
@ 2017-01-30 17:19       ` Suzuki K Poulose
  -1 siblings, 0 replies; 20+ messages in thread
From: Suzuki K Poulose @ 2017-01-30 17:19 UTC (permalink / raw)
  To: Sudeep Holla, kvmarm, linux-arm-kernel
  Cc: Marc Zyngier, Catalin Marinas, Will Deacon

On 30/01/17 16:57, Sudeep Holla wrote:
>> Could this be static ? I could not see it used anywhere else outside
>> this file.
>
> Used in arch/arm64/kernel/cpuinfo.c

Ah, you're right.

Suzuki

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1
@ 2017-01-30 17:19       ` Suzuki K Poulose
  0 siblings, 0 replies; 20+ messages in thread
From: Suzuki K Poulose @ 2017-01-30 17:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/17 16:57, Sudeep Holla wrote:
>> Could this be static ? I could not see it used anywhere else outside
>> this file.
>
> Used in arch/arm64/kernel/cpuinfo.c

Ah, you're right.

Suzuki

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros
  2017-01-30 16:25   ` Sudeep Holla
@ 2017-02-01 15:44     ` Marc Zyngier
  -1 siblings, 0 replies; 20+ messages in thread
From: Marc Zyngier @ 2017-02-01 15:44 UTC (permalink / raw)
  To: Sudeep Holla, kvmarm, linux-arm-kernel; +Cc: Catalin Marinas, Will Deacon

On 30/01/17 16:25, Sudeep Holla wrote:
> We already have various macros related to cache type and bitfields in
> CLIDR system register. We can replace some of the hardcoded values
> here using those existing macros.
> 
> This patch reuses those existing cache type/info related macros and
> replaces the hardcorded values. It also removes some of the comments
> that become trivial with the macro names.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Christoffer Dall <christoffer.dall@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros
@ 2017-02-01 15:44     ` Marc Zyngier
  0 siblings, 0 replies; 20+ messages in thread
From: Marc Zyngier @ 2017-02-01 15:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/17 16:25, Sudeep Holla wrote:
> We already have various macros related to cache type and bitfields in
> CLIDR system register. We can replace some of the hardcoded values
> here using those existing macros.
> 
> This patch reuses those existing cache type/info related macros and
> replaces the hardcorded values. It also removes some of the comments
> that become trivial with the macro names.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Christoffer Dall <christoffer.dall@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr
  2017-01-30 16:25   ` Sudeep Holla
@ 2017-02-01 16:02     ` Marc Zyngier
  -1 siblings, 0 replies; 20+ messages in thread
From: Marc Zyngier @ 2017-02-01 16:02 UTC (permalink / raw)
  To: Sudeep Holla, kvmarm, linux-arm-kernel, Christoffer Dall

On 30/01/17 16:25, Sudeep Holla wrote:
> csselr and ccsidr are treated as 64-bit values already elsewhere in the
> kernel. It also aligns well with the architecture extensions that allow
> 64-bit format for ccsidr.
> 
> This patch upgrades the existing accesses to csselr and ccsidr from
> 32-bit to 64-bit in preparation to add support to those extensions.
> It also add dedicated KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register
> to handle 64-bit ccsidr in KVM.
> 
> Cc: Christoffer Dall <christoffer.dall@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  arch/arm64/include/uapi/asm/kvm.h |   1 +
>  arch/arm64/kvm/sys_regs.c         | 104 ++++++++++++++++++++++++++++----------
>  2 files changed, 77 insertions(+), 28 deletions(-)
> 
> v1->v2:
> 	- Added dependency on cpu_supports_ccsidr_64b_format(PATCH 1/3)
> 	- Added a new KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register id
> 	  to support new 64bit CCSIDR
> 
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 3051f86a9b5f..8aa18e65e6a5 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -161,6 +161,7 @@ struct kvm_arch_memory_slot {
>  #define KVM_REG_ARM_DEMUX_ID_MASK	0x000000000000FF00
>  #define KVM_REG_ARM_DEMUX_ID_SHIFT	8
>  #define KVM_REG_ARM_DEMUX_ID_CCSIDR	(0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
> +#define KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR	(0x01 << KVM_REG_ARM_DEMUX_ID_SHIFT)
>  #define KVM_REG_ARM_DEMUX_VAL_MASK	0x00000000000000FF
>  #define KVM_REG_ARM_DEMUX_VAL_SHIFT	0
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 72656743b4cc..f9822ac6d9ab 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -58,15 +58,15 @@
>   */
> 
>  /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
> -static u32 cache_levels;
> +static u64 cache_levels;
> 
> -/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
> +/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_{EXT_,}CCSIDR */
>  #define CSSELR_MAX 	((MAX_CACHE_LEVEL - 1) << 1)
> 
>  /* Which cache CCSIDR represents depends on CSSELR value. */
> -static u32 get_ccsidr(u32 csselr)
> +static u64 get_ccsidr(u64 csselr)
>  {
> -	u32 ccsidr;
> +	u64 ccsidr;
> 
>  	/* Make sure noone else changes CSSELR during this! */
>  	local_irq_disable();
> @@ -1952,9 +1952,9 @@ static int set_invariant_sys_reg(u64 id, void __user *uaddr)
>  	return 0;
>  }
> 
> -static bool is_valid_cache(u32 val)
> +static bool is_valid_cache(u64 val)
>  {
> -	u32 level, ctype;
> +	u64 level, ctype;
> 
>  	if (val >= CSSELR_MAX)
>  		return false;
> @@ -1977,10 +1977,28 @@ static bool is_valid_cache(u32 val)
>  	}
>  }
> 
> +static int demux_ccsidr_validate_get(u64 id, int size, u64 *val)
> +{
> +	u64 cidx;
> +
> +	if (KVM_REG_SIZE(id) != size)
> +		return -ENOENT;
> +
> +	cidx = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
> +			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
> +	if (!is_valid_cache(cidx))
> +		return -ENOENT;
> +
> +	*val = get_ccsidr(cidx);
> +	return 0;
> +}
> +
>  static int demux_c15_get(u64 id, void __user *uaddr)
>  {
> -	u32 val;
> -	u32 __user *uval = uaddr;
> +	int ret;
> +	u64 val;
> +	u32 __user *uval;
> +	u64 __user *uval64;
> 
>  	/* Fail if we have unknown bits set. */
>  	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
> @@ -1989,14 +2007,17 @@ static int demux_c15_get(u64 id, void __user *uaddr)
> 
>  	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
>  	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
> -		if (KVM_REG_SIZE(id) != 4)
> -			return -ENOENT;
> -		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
> -			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
> -		if (!is_valid_cache(val))
> -			return -ENOENT;
> -
> -		return put_user(get_ccsidr(val), uval);
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
> +		if (ret)
> +			return ret;
> +		uval = uaddr;
> +		return put_user(val, uval);
> +	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval64), &val);
> +		if (ret)
> +			return ret;
> +		uval64 = uaddr;
> +		return put_user(val, uval64);
>  	default:
>  		return -ENOENT;
>  	}
> @@ -2004,8 +2025,10 @@ static int demux_c15_get(u64 id, void __user *uaddr)
> 
>  static int demux_c15_set(u64 id, void __user *uaddr)
>  {
> -	u32 val, newval;
> -	u32 __user *uval = uaddr;
> +	int ret;
> +	u64 val, newval;
> +	u32 __user *uval;
> +	u64 __user *uval64;
> 
>  	/* Fail if we have unknown bits set. */
>  	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
> @@ -2014,18 +2037,29 @@ static int demux_c15_set(u64 id, void __user *uaddr)
> 
>  	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
>  	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
> -		if (KVM_REG_SIZE(id) != 4)
> -			return -ENOENT;
> -		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
> -			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
> -		if (!is_valid_cache(val))
> -			return -ENOENT;
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
> +		if (ret)
> +			return ret;
> 
> +		uval = uaddr;
>  		if (get_user(newval, uval))
>  			return -EFAULT;
> 
>  		/* This is also invariant: you can't change it. */
> -		if (newval != get_ccsidr(val))
> +		if (newval != val)
> +			return -EINVAL;
> +		return 0;
> +	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
> +		if (ret)
> +			return ret;
> +
> +		uval64 = uaddr;
> +		if (get_user(newval, uval64))
> +			return -EFAULT;
> +
> +		/* This is also invariant: you can't change it. */
> +		if (newval != val)
>  			return -EINVAL;
>  		return 0;
>  	default:
> @@ -2086,12 +2120,10 @@ static unsigned int num_demux_regs(void)
>  	return count;
>  }
> 
> -static int write_demux_regids(u64 __user *uindices)
> +static int write_demux_ccsidr(u64 val, u64 __user *uindices)
>  {
> -	u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
>  	unsigned int i;
> 
> -	val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
>  	for (i = 0; i < CSSELR_MAX; i++) {
>  		if (!is_valid_cache(i))
>  			continue;
> @@ -2099,9 +2131,25 @@ static int write_demux_regids(u64 __user *uindices)
>  			return -EFAULT;
>  		uindices++;
>  	}
> +
>  	return 0;
>  }
> 
> +static int write_demux_regids(u64 __user *uindices)
> +{
> +	int ret;
> +	u64 val = KVM_REG_ARM64 | KVM_REG_ARM_DEMUX;
> +
> +	if (cpu_supports_ccsidr_64b_format())
> +		/* 64 bit extended CCSIDR */
> +		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR |
> +					 KVM_REG_SIZE_U64, uindices);
> +	else
> +		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_CCSIDR |
> +					 KVM_REG_SIZE_U32, uindices);
> +	return ret;
> +}
> +
>  static u64 sys_reg_to_index(const struct sys_reg_desc *reg)
>  {
>  	return (KVM_REG_ARM64 | KVM_REG_SIZE_U64 |
> --
> 2.7.4
> 

I'm a bit worried about this patch. If we snapshot a VM on a 32bit
CCSIDR system, and restore it on a 64bit CSSIDR system (or the reverse),
what happens? My hunch is that we cannot restore the VM properly.

Now, I'm questioning the need for having those altogether, as we do a
lot of work to prevent the guest from actually using that geometry (and
on a big-little system, this hardly works).

Christoffer, what do you think?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr
@ 2017-02-01 16:02     ` Marc Zyngier
  0 siblings, 0 replies; 20+ messages in thread
From: Marc Zyngier @ 2017-02-01 16:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/17 16:25, Sudeep Holla wrote:
> csselr and ccsidr are treated as 64-bit values already elsewhere in the
> kernel. It also aligns well with the architecture extensions that allow
> 64-bit format for ccsidr.
> 
> This patch upgrades the existing accesses to csselr and ccsidr from
> 32-bit to 64-bit in preparation to add support to those extensions.
> It also add dedicated KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register
> to handle 64-bit ccsidr in KVM.
> 
> Cc: Christoffer Dall <christoffer.dall@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  arch/arm64/include/uapi/asm/kvm.h |   1 +
>  arch/arm64/kvm/sys_regs.c         | 104 ++++++++++++++++++++++++++++----------
>  2 files changed, 77 insertions(+), 28 deletions(-)
> 
> v1->v2:
> 	- Added dependency on cpu_supports_ccsidr_64b_format(PATCH 1/3)
> 	- Added a new KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR demux register id
> 	  to support new 64bit CCSIDR
> 
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 3051f86a9b5f..8aa18e65e6a5 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -161,6 +161,7 @@ struct kvm_arch_memory_slot {
>  #define KVM_REG_ARM_DEMUX_ID_MASK	0x000000000000FF00
>  #define KVM_REG_ARM_DEMUX_ID_SHIFT	8
>  #define KVM_REG_ARM_DEMUX_ID_CCSIDR	(0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
> +#define KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR	(0x01 << KVM_REG_ARM_DEMUX_ID_SHIFT)
>  #define KVM_REG_ARM_DEMUX_VAL_MASK	0x00000000000000FF
>  #define KVM_REG_ARM_DEMUX_VAL_SHIFT	0
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 72656743b4cc..f9822ac6d9ab 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -58,15 +58,15 @@
>   */
> 
>  /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
> -static u32 cache_levels;
> +static u64 cache_levels;
> 
> -/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
> +/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_{EXT_,}CCSIDR */
>  #define CSSELR_MAX 	((MAX_CACHE_LEVEL - 1) << 1)
> 
>  /* Which cache CCSIDR represents depends on CSSELR value. */
> -static u32 get_ccsidr(u32 csselr)
> +static u64 get_ccsidr(u64 csselr)
>  {
> -	u32 ccsidr;
> +	u64 ccsidr;
> 
>  	/* Make sure noone else changes CSSELR during this! */
>  	local_irq_disable();
> @@ -1952,9 +1952,9 @@ static int set_invariant_sys_reg(u64 id, void __user *uaddr)
>  	return 0;
>  }
> 
> -static bool is_valid_cache(u32 val)
> +static bool is_valid_cache(u64 val)
>  {
> -	u32 level, ctype;
> +	u64 level, ctype;
> 
>  	if (val >= CSSELR_MAX)
>  		return false;
> @@ -1977,10 +1977,28 @@ static bool is_valid_cache(u32 val)
>  	}
>  }
> 
> +static int demux_ccsidr_validate_get(u64 id, int size, u64 *val)
> +{
> +	u64 cidx;
> +
> +	if (KVM_REG_SIZE(id) != size)
> +		return -ENOENT;
> +
> +	cidx = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
> +			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
> +	if (!is_valid_cache(cidx))
> +		return -ENOENT;
> +
> +	*val = get_ccsidr(cidx);
> +	return 0;
> +}
> +
>  static int demux_c15_get(u64 id, void __user *uaddr)
>  {
> -	u32 val;
> -	u32 __user *uval = uaddr;
> +	int ret;
> +	u64 val;
> +	u32 __user *uval;
> +	u64 __user *uval64;
> 
>  	/* Fail if we have unknown bits set. */
>  	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
> @@ -1989,14 +2007,17 @@ static int demux_c15_get(u64 id, void __user *uaddr)
> 
>  	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
>  	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
> -		if (KVM_REG_SIZE(id) != 4)
> -			return -ENOENT;
> -		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
> -			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
> -		if (!is_valid_cache(val))
> -			return -ENOENT;
> -
> -		return put_user(get_ccsidr(val), uval);
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
> +		if (ret)
> +			return ret;
> +		uval = uaddr;
> +		return put_user(val, uval);
> +	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval64), &val);
> +		if (ret)
> +			return ret;
> +		uval64 = uaddr;
> +		return put_user(val, uval64);
>  	default:
>  		return -ENOENT;
>  	}
> @@ -2004,8 +2025,10 @@ static int demux_c15_get(u64 id, void __user *uaddr)
> 
>  static int demux_c15_set(u64 id, void __user *uaddr)
>  {
> -	u32 val, newval;
> -	u32 __user *uval = uaddr;
> +	int ret;
> +	u64 val, newval;
> +	u32 __user *uval;
> +	u64 __user *uval64;
> 
>  	/* Fail if we have unknown bits set. */
>  	if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
> @@ -2014,18 +2037,29 @@ static int demux_c15_set(u64 id, void __user *uaddr)
> 
>  	switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
>  	case KVM_REG_ARM_DEMUX_ID_CCSIDR:
> -		if (KVM_REG_SIZE(id) != 4)
> -			return -ENOENT;
> -		val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
> -			>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
> -		if (!is_valid_cache(val))
> -			return -ENOENT;
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
> +		if (ret)
> +			return ret;
> 
> +		uval = uaddr;
>  		if (get_user(newval, uval))
>  			return -EFAULT;
> 
>  		/* This is also invariant: you can't change it. */
> -		if (newval != get_ccsidr(val))
> +		if (newval != val)
> +			return -EINVAL;
> +		return 0;
> +	case KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR:
> +		ret = demux_ccsidr_validate_get(id, sizeof(*uval), &val);
> +		if (ret)
> +			return ret;
> +
> +		uval64 = uaddr;
> +		if (get_user(newval, uval64))
> +			return -EFAULT;
> +
> +		/* This is also invariant: you can't change it. */
> +		if (newval != val)
>  			return -EINVAL;
>  		return 0;
>  	default:
> @@ -2086,12 +2120,10 @@ static unsigned int num_demux_regs(void)
>  	return count;
>  }
> 
> -static int write_demux_regids(u64 __user *uindices)
> +static int write_demux_ccsidr(u64 val, u64 __user *uindices)
>  {
> -	u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
>  	unsigned int i;
> 
> -	val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
>  	for (i = 0; i < CSSELR_MAX; i++) {
>  		if (!is_valid_cache(i))
>  			continue;
> @@ -2099,9 +2131,25 @@ static int write_demux_regids(u64 __user *uindices)
>  			return -EFAULT;
>  		uindices++;
>  	}
> +
>  	return 0;
>  }
> 
> +static int write_demux_regids(u64 __user *uindices)
> +{
> +	int ret;
> +	u64 val = KVM_REG_ARM64 | KVM_REG_ARM_DEMUX;
> +
> +	if (cpu_supports_ccsidr_64b_format())
> +		/* 64 bit extended CCSIDR */
> +		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_EXT_CCSIDR |
> +					 KVM_REG_SIZE_U64, uindices);
> +	else
> +		ret = write_demux_ccsidr(val | KVM_REG_ARM_DEMUX_ID_CCSIDR |
> +					 KVM_REG_SIZE_U32, uindices);
> +	return ret;
> +}
> +
>  static u64 sys_reg_to_index(const struct sys_reg_desc *reg)
>  {
>  	return (KVM_REG_ARM64 | KVM_REG_SIZE_U64 |
> --
> 2.7.4
> 

I'm a bit worried about this patch. If we snapshot a VM on a 32bit
CCSIDR system, and restore it on a 64bit CSSIDR system (or the reverse),
what happens? My hunch is that we cannot restore the VM properly.

Now, I'm questioning the need for having those altogether, as we do a
lot of work to prevent the guest from actually using that geometry (and
on a big-little system, this hardly works).

Christoffer, what do you think?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr
  2017-02-01 16:02     ` Marc Zyngier
@ 2017-02-03 10:44       ` Sudeep Holla
  -1 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-02-03 10:44 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-arm-kernel, Christoffer Dall; +Cc: Sudeep Holla

Hi Marc,

On 01/02/17 16:02, Marc Zyngier wrote:
[...]

> 
> I'm a bit worried about this patch. If we snapshot a VM on a 32bit
> CCSIDR system, and restore it on a 64bit CSSIDR system (or the reverse),
> what happens? My hunch is that we cannot restore the VM properly.
>

I agree. I had a look at QEMU as you suggested offline. Looks like QEMU
emulate these registers with predefined values for each core type. Also
it looks like it's not using the existing DEMUX_ID_CCSIDR

> Now, I'm questioning the need for having those altogether, as we do a
> lot of work to prevent the guest from actually using that geometry (and
> on a big-little system, this hardly works).
> 

If we can conclude there are no users for DEMUX_ID_CCSIDR, we can remove
it all together instead of introducing new one for 64bit.

Are there any other users of these interface provided by KVM after from
kvmtool and qemu ?

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr
@ 2017-02-03 10:44       ` Sudeep Holla
  0 siblings, 0 replies; 20+ messages in thread
From: Sudeep Holla @ 2017-02-03 10:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 01/02/17 16:02, Marc Zyngier wrote:
[...]

> 
> I'm a bit worried about this patch. If we snapshot a VM on a 32bit
> CCSIDR system, and restore it on a 64bit CSSIDR system (or the reverse),
> what happens? My hunch is that we cannot restore the VM properly.
>

I agree. I had a look at QEMU as you suggested offline. Looks like QEMU
emulate these registers with predefined values for each core type. Also
it looks like it's not using the existing DEMUX_ID_CCSIDR

> Now, I'm questioning the need for having those altogether, as we do a
> lot of work to prevent the guest from actually using that geometry (and
> on a big-little system, this hardly works).
> 

If we can conclude there are no users for DEMUX_ID_CCSIDR, we can remove
it all together instead of introducing new one for 64bit.

Are there any other users of these interface provided by KVM after from
kvmtool and qemu ?

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros
  2017-01-30 16:25   ` Sudeep Holla
@ 2017-02-23 15:57     ` Christoffer Dall
  -1 siblings, 0 replies; 20+ messages in thread
From: Christoffer Dall @ 2017-02-23 15:57 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Marc Zyngier, Catalin Marinas, Will Deacon, linux-arm-kernel, kvmarm

On Mon, Jan 30, 2017 at 04:25:26PM +0000, Sudeep Holla wrote:
> We already have various macros related to cache type and bitfields in
> CLIDR system register. We can replace some of the hardcoded values
> here using those existing macros.
> 
> This patch reuses those existing cache type/info related macros and
> replaces the hardcorded values. It also removes some of the comments
> that become trivial with the macro names.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Christoffer Dall <christoffer.dall@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Acked-by: Christoffer Dall <cdall@linaro.org>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros
@ 2017-02-23 15:57     ` Christoffer Dall
  0 siblings, 0 replies; 20+ messages in thread
From: Christoffer Dall @ 2017-02-23 15:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 30, 2017 at 04:25:26PM +0000, Sudeep Holla wrote:
> We already have various macros related to cache type and bitfields in
> CLIDR system register. We can replace some of the hardcoded values
> here using those existing macros.
> 
> This patch reuses those existing cache type/info related macros and
> replaces the hardcorded values. It also removes some of the comments
> that become trivial with the macro names.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Christoffer Dall <christoffer.dall@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Acked-by: Christoffer Dall <cdall@linaro.org>

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2017-02-23 15:57 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-30 16:25 [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1 Sudeep Holla
2017-01-30 16:25 ` Sudeep Holla
2017-01-30 16:25 ` [PATCH v2 2/3] arm64: kvm: reuse existing cache type/info related macros Sudeep Holla
2017-01-30 16:25   ` Sudeep Holla
2017-02-01 15:44   ` Marc Zyngier
2017-02-01 15:44     ` Marc Zyngier
2017-02-23 15:57   ` Christoffer Dall
2017-02-23 15:57     ` Christoffer Dall
2017-01-30 16:25 ` [PATCH v2 3/3] arm64: kvm: add support for the extended 64bit ccsidr Sudeep Holla
2017-01-30 16:25   ` Sudeep Holla
2017-02-01 16:02   ` Marc Zyngier
2017-02-01 16:02     ` Marc Zyngier
2017-02-03 10:44     ` Sudeep Holla
2017-02-03 10:44       ` Sudeep Holla
2017-01-30 16:47 ` [PATCH v2 1/3] arm64: cacheinfo: add support for alternative format of CCSIDR_EL1 Suzuki K Poulose
2017-01-30 16:47   ` Suzuki K Poulose
2017-01-30 16:57   ` Sudeep Holla
2017-01-30 16:57     ` Sudeep Holla
2017-01-30 17:19     ` Suzuki K Poulose
2017-01-30 17:19       ` Suzuki K Poulose

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.