All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] arm64: Rework cpu capabilities handling
@ 2018-01-23 12:27 ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

This series reworks the arm64 CPU capabilities handling (which
manages the system features and errata). The current infrastructure
doesn't allow fine control for handling different features or errata.
There is one rule for features and another rule for errata.

* Features are checked only once, after all the boot time CPUs are
  activated. Any new CPU that is brought up is prevented from booting
  if it misses a feature already established. If the new CPU has a
  feature not enabled already, it is allowed to boot.

* Errata checks are performed on all the CPUs and any new CPU is
  OK to miss the capability. However if a late CPU requires a work around,
  then we fail the CPU.

  This doesn't always apply to some features. e.g, KPTI is a security
  feature which should be applied when at least one CPU needs it. So,
  the tests should be performed on all the booting CPUs individually.
  Also, if a CPU that needs this security feature is brought up later,
  when the system has not enabled it, the CPU can boot making the system
  insecure. Another exception is the hardware DBM for page tables. The
  kernel can safely run with a mix of CPUs that have the feature turned
  on and off. This again causes problem when a new CPU is brought up
  which may not have the feature, which is killed.

  Also there are other features like, GICV3 system register access,
  which now need to be enabled very early based on the boot CPU to
  allow the use of Priority handling to implement NMI.

This calls for finer level of control per capability and the series
implements the same by defining how to deal with a conflict of a
given capability on a CPU with that of the system level state. It
also consolidates the handling of features and errata into generic
helpers. The table of features and errata are left as they are to
allow easier look up for a given type.
We also cleans up the MIDR range handling and cleans up some of the
errata checks where the entries were duplicated for checking different
CPU models. Finally it also implements a work around for Arm Cortex-A55
erratum 1024718 based on the new infrastructure.

Applies on aarch64 for-next/core tree + [0]. The tree is also available
at :
	git://linux-arm.org/linux-skp.git cpu-caps-rework/v1

[0] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/554754.html

Dave Martin (1):
  arm64: capabilities: Update prototype for enable call back

Suzuki K Poulose (15):
  arm64: Move errata work around check on boot CPU
  arm64: Move errata capability processing code
  arm64: capabilities: Prepare for fine grained capabilities
  arm64: Add flags to check the safety of a capability for late CPU
  arm64: capabilities: Unify the verification
  arm64: capabilities: Filter the entries based on a given type
  arm64: capabilities: Group handling of features and errata
  arm64: capabilities: Introduce strict features based on local CPU
  arm64: Make KPTI strict CPU local feature
  arm64: errata: Clean up midr range helpers
  arm64: Add helpers for checking CPU MIDR against a range
  arm64: Add support for checking errata based on a list of MIDRS
  arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
  arm64: Delay enabling hardware DBM feature
  arm64: Add work around for Arm Cortex-A55 Erratum 1024718

 Documentation/arm64/silicon-errata.txt |   1 +
 arch/arm64/Kconfig                     |  14 ++
 arch/arm64/include/asm/cpucaps.h       |   3 +-
 arch/arm64/include/asm/cpufeature.h    |  89 ++++++++---
 arch/arm64/include/asm/cputype.h       |  42 ++++++
 arch/arm64/include/asm/fpsimd.h        |   4 +-
 arch/arm64/include/asm/processor.h     |   7 +-
 arch/arm64/kernel/cpu_errata.c         | 173 +++++++++------------
 arch/arm64/kernel/cpufeature.c         | 267 +++++++++++++++++++++++++--------
 arch/arm64/kernel/fpsimd.c             |   3 +-
 arch/arm64/kernel/smp.c                |   6 -
 arch/arm64/kernel/traps.c              |   3 +-
 arch/arm64/mm/fault.c                  |   2 +-
 arch/arm64/mm/proc.S                   |   5 +-
 14 files changed, 422 insertions(+), 197 deletions(-)

-- 
2.13.6

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

* [PATCH 00/16] arm64: Rework cpu capabilities handling
@ 2018-01-23 12:27 ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

This series reworks the arm64 CPU capabilities handling (which
manages the system features and errata). The current infrastructure
doesn't allow fine control for handling different features or errata.
There is one rule for features and another rule for errata.

* Features are checked only once, after all the boot time CPUs are
  activated. Any new CPU that is brought up is prevented from booting
  if it misses a feature already established. If the new CPU has a
  feature not enabled already, it is allowed to boot.

* Errata checks are performed on all the CPUs and any new CPU is
  OK to miss the capability. However if a late CPU requires a work around,
  then we fail the CPU.

  This doesn't always apply to some features. e.g, KPTI is a security
  feature which should be applied when at least one CPU needs it. So,
  the tests should be performed on all the booting CPUs individually.
  Also, if a CPU that needs this security feature is brought up later,
  when the system has not enabled it, the CPU can boot making the system
  insecure. Another exception is the hardware DBM for page tables. The
  kernel can safely run with a mix of CPUs that have the feature turned
  on and off. This again causes problem when a new CPU is brought up
  which may not have the feature, which is killed.

  Also there are other features like, GICV3 system register access,
  which now need to be enabled very early based on the boot CPU to
  allow the use of Priority handling to implement NMI.

This calls for finer level of control per capability and the series
implements the same by defining how to deal with a conflict of a
given capability on a CPU with that of the system level state. It
also consolidates the handling of features and errata into generic
helpers. The table of features and errata are left as they are to
allow easier look up for a given type.
We also cleans up the MIDR range handling and cleans up some of the
errata checks where the entries were duplicated for checking different
CPU models. Finally it also implements a work around for Arm Cortex-A55
erratum 1024718 based on the new infrastructure.

Applies on aarch64 for-next/core tree + [0]. The tree is also available
at :
	git://linux-arm.org/linux-skp.git cpu-caps-rework/v1

[0] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/554754.html

Dave Martin (1):
  arm64: capabilities: Update prototype for enable call back

Suzuki K Poulose (15):
  arm64: Move errata work around check on boot CPU
  arm64: Move errata capability processing code
  arm64: capabilities: Prepare for fine grained capabilities
  arm64: Add flags to check the safety of a capability for late CPU
  arm64: capabilities: Unify the verification
  arm64: capabilities: Filter the entries based on a given type
  arm64: capabilities: Group handling of features and errata
  arm64: capabilities: Introduce strict features based on local CPU
  arm64: Make KPTI strict CPU local feature
  arm64: errata: Clean up midr range helpers
  arm64: Add helpers for checking CPU MIDR against a range
  arm64: Add support for checking errata based on a list of MIDRS
  arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
  arm64: Delay enabling hardware DBM feature
  arm64: Add work around for Arm Cortex-A55 Erratum 1024718

 Documentation/arm64/silicon-errata.txt |   1 +
 arch/arm64/Kconfig                     |  14 ++
 arch/arm64/include/asm/cpucaps.h       |   3 +-
 arch/arm64/include/asm/cpufeature.h    |  89 ++++++++---
 arch/arm64/include/asm/cputype.h       |  42 ++++++
 arch/arm64/include/asm/fpsimd.h        |   4 +-
 arch/arm64/include/asm/processor.h     |   7 +-
 arch/arm64/kernel/cpu_errata.c         | 173 +++++++++------------
 arch/arm64/kernel/cpufeature.c         | 267 +++++++++++++++++++++++++--------
 arch/arm64/kernel/fpsimd.c             |   3 +-
 arch/arm64/kernel/smp.c                |   6 -
 arch/arm64/kernel/traps.c              |   3 +-
 arch/arm64/mm/fault.c                  |   2 +-
 arch/arm64/mm/proc.S                   |   5 +-
 14 files changed, 422 insertions(+), 197 deletions(-)

-- 
2.13.6

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Dave Martin,
	Robin Murphy, Andre Przywara, James Morse, Suzuki K Poulose

From: Dave Martin <dave.martin@arm.com>

We issue the enable() call back for all CPU hwcaps capabilities
available on the system, on all the CPUs. So far we have ignored
the argument passed to the call back, which had a prototype to
accept a "void *" for use with on_each_cpu() and later with
stop_machine(). However, with commit 0a0d111d40fd1
("arm64: cpufeature: Pass capability structure to ->enable callback"),
there are some users of the argument who wants the matching capability
struct pointer where there are multiple matching criteria for a single
capability. Update the prototype for enable to accept a const pointer.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Andre Przywara <andre.przywara@arm.com>
Cc: James Morse <james.morse@arm.com>
Reviewed-by: Julien Thierry <julien.thierry@arm.com>
Signed-off-by: Dave Martin <dave.martin@arm.com>
[ Rebased to for-next/core converting more users ]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  3 ++-
 arch/arm64/include/asm/fpsimd.h     |  4 +++-
 arch/arm64/include/asm/processor.h  |  7 ++++---
 arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
 arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
 arch/arm64/kernel/fpsimd.c          |  3 ++-
 arch/arm64/kernel/traps.c           |  3 ++-
 arch/arm64/mm/fault.c               |  2 +-
 8 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index ac67cfc2585a..cefbd685292c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
 	u16 capability;
 	int def_scope;			/* default scope */
 	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
-	int (*enable)(void *);		/* Called on all active CPUs */
+	/* Called on all active CPUs for all  "available" capabilities */
+	int (*enable)(const struct arm64_cpu_capabilities *caps);
 	union {
 		struct {	/* To be used for erratum handling only */
 			u32 midr_model;
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 8857a0f0d0f7..2a4b5fc681a3 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -83,7 +83,9 @@ extern void sve_save_state(void *state, u32 *pfpsr);
 extern void sve_load_state(void const *state, u32 const *pfpsr,
 			   unsigned long vq_minus_1);
 extern unsigned int sve_get_vl(void);
-extern int sve_kernel_enable(void *);
+
+struct arm64_cpu_capabilities;
+extern int sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
 
 extern int __ro_after_init sve_max_vl;
 
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index cee4ae25a5d1..ff4c753a75fe 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -34,6 +34,7 @@
 #include <linux/string.h>
 
 #include <asm/alternative.h>
+#include <asm/cpufeature.h>
 #include <asm/fpsimd.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/lse.h>
@@ -214,9 +215,9 @@ static inline void spin_lock_prefetch(const void *ptr)
 
 #endif
 
-int cpu_enable_pan(void *__unused);
-int cpu_enable_cache_maint_trap(void *__unused);
-int cpu_clear_disr(void *__unused);
+int cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
+int cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
+int cpu_clear_disr(const struct arm64_cpu_capabilities *__unused);
 
 /* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */
 #define SVE_SET_VL(arg)	sve_set_current_vl(arg)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 54e41dfe41f6..9ae0d7e395cf 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -53,7 +53,8 @@ has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry,
 		(arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask);
 }
 
-static int cpu_enable_trap_ctr_access(void *__unused)
+static int cpu_enable_trap_ctr_access(
+	const struct arm64_cpu_capabilities *__unused)
 {
 	/* Clear SCTLR_EL1.UCT */
 	config_sctlr_el1(SCTLR_EL1_UCT, 0);
@@ -144,10 +145,8 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
 
 #include <linux/psci.h>
 
-static int enable_psci_bp_hardening(void *data)
+static int enable_psci_bp_hardening(const struct arm64_cpu_capabilities *entry)
 {
-	const struct arm64_cpu_capabilities *entry = data;
-
 	if (psci_ops.get_version)
 		install_bp_hardening_cb(entry,
 				       (bp_hardening_cb_t)psci_ops.get_version,
@@ -169,10 +168,9 @@ static void qcom_link_stack_sanitization(void)
 		     : "=&r" (tmp));
 }
 
-static int qcom_enable_link_stack_sanitization(void *data)
+static int qcom_enable_link_stack_sanitization(
+			const struct arm64_cpu_capabilities *entry)
 {
-	const struct arm64_cpu_capabilities *entry = data;
-
 	install_bp_hardening_cb(entry, qcom_link_stack_sanitization,
 				__qcom_hyp_sanitize_link_stack_start,
 				__qcom_hyp_sanitize_link_stack_end);
@@ -376,7 +374,7 @@ void verify_local_cpu_errata_workarounds(void)
 	for (; caps->matches; caps++) {
 		if (cpus_have_cap(caps->capability)) {
 			if (caps->enable)
-				caps->enable((void *)caps);
+				caps->enable(caps);
 		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
 			pr_crit("CPU%d: Requires work around for %s, not detected"
 					" at boot time\n",
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 5612d6f46331..6a8dfdc532b1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -887,7 +887,7 @@ static int __init parse_kpti(char *str)
 __setup("kpti=", parse_kpti);
 #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
-static int cpu_copy_el2regs(void *__unused)
+static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * Copy register values that aren't redirected by hardware.
@@ -1183,6 +1183,14 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+
+static int __enable_cpu_capability(void *arg)
+{
+	const struct arm64_cpu_capabilities *cap = arg;
+
+	return cap->enable(cap);
+}
+
 /*
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
@@ -1205,7 +1213,7 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 			 * uses an IPI, giving us a PSTATE that disappears when
 			 * we return.
 			 */
-			stop_machine(caps->enable, (void *)caps, cpu_online_mask);
+			stop_machine(__enable_cpu_capability, (void *)caps, cpu_online_mask);
 		}
 	}
 }
@@ -1249,7 +1257,7 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
 			cpu_die_early();
 		}
 		if (caps->enable)
-			caps->enable((void *)caps);
+			caps->enable(caps);
 	}
 }
 
@@ -1472,7 +1480,7 @@ static int __init enable_mrs_emulation(void)
 
 core_initcall(enable_mrs_emulation);
 
-int cpu_clear_disr(void *__unused)
+int cpu_clear_disr(const struct arm64_cpu_capabilities *__unused)
 {
 	/* Firmware may have left a deferred SError in this register. */
 	write_sysreg_s(0, SYS_DISR_EL1);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 55fb544072f6..4d7eff33c643 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -40,6 +40,7 @@
 #include <linux/sysctl.h>
 
 #include <asm/fpsimd.h>
+#include <asm/cpufeature.h>
 #include <asm/cputype.h>
 #include <asm/simd.h>
 #include <asm/sigcontext.h>
@@ -757,7 +758,7 @@ static void __init sve_efi_setup(void)
  * Enable SVE for EL1.
  * Intended for use by the cpufeatures code during CPU boot.
  */
-int sve_kernel_enable(void *__always_unused p)
+int sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
 {
 	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
 	isb();
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index bbb0fde2780e..296fab8e5c67 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -38,6 +38,7 @@
 
 #include <asm/atomic.h>
 #include <asm/bug.h>
+#include <asm/cpufeature.h>
 #include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
@@ -374,7 +375,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
 }
 
-int cpu_enable_cache_maint_trap(void *__unused)
+int cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
 {
 	config_sctlr_el1(SCTLR_EL1_UCI, 0);
 	return 0;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0e671ddf4855..937f89d2c353 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -813,7 +813,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
 NOKPROBE_SYMBOL(do_debug_exception);
 
 #ifdef CONFIG_ARM64_PAN
-int cpu_enable_pan(void *__unused)
+int cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * We modify PSTATE. This won't work from irq context as the PSTATE
-- 
2.13.6

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
@ 2018-01-23 12:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Dave Martin <dave.martin@arm.com>

We issue the enable() call back for all CPU hwcaps capabilities
available on the system, on all the CPUs. So far we have ignored
the argument passed to the call back, which had a prototype to
accept a "void *" for use with on_each_cpu() and later with
stop_machine(). However, with commit 0a0d111d40fd1
("arm64: cpufeature: Pass capability structure to ->enable callback"),
there are some users of the argument who wants the matching capability
struct pointer where there are multiple matching criteria for a single
capability. Update the prototype for enable to accept a const pointer.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Andre Przywara <andre.przywara@arm.com>
Cc: James Morse <james.morse@arm.com>
Reviewed-by: Julien Thierry <julien.thierry@arm.com>
Signed-off-by: Dave Martin <dave.martin@arm.com>
[ Rebased to for-next/core converting more users ]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  3 ++-
 arch/arm64/include/asm/fpsimd.h     |  4 +++-
 arch/arm64/include/asm/processor.h  |  7 ++++---
 arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
 arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
 arch/arm64/kernel/fpsimd.c          |  3 ++-
 arch/arm64/kernel/traps.c           |  3 ++-
 arch/arm64/mm/fault.c               |  2 +-
 8 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index ac67cfc2585a..cefbd685292c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
 	u16 capability;
 	int def_scope;			/* default scope */
 	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
-	int (*enable)(void *);		/* Called on all active CPUs */
+	/* Called on all active CPUs for all  "available" capabilities */
+	int (*enable)(const struct arm64_cpu_capabilities *caps);
 	union {
 		struct {	/* To be used for erratum handling only */
 			u32 midr_model;
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 8857a0f0d0f7..2a4b5fc681a3 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -83,7 +83,9 @@ extern void sve_save_state(void *state, u32 *pfpsr);
 extern void sve_load_state(void const *state, u32 const *pfpsr,
 			   unsigned long vq_minus_1);
 extern unsigned int sve_get_vl(void);
-extern int sve_kernel_enable(void *);
+
+struct arm64_cpu_capabilities;
+extern int sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
 
 extern int __ro_after_init sve_max_vl;
 
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index cee4ae25a5d1..ff4c753a75fe 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -34,6 +34,7 @@
 #include <linux/string.h>
 
 #include <asm/alternative.h>
+#include <asm/cpufeature.h>
 #include <asm/fpsimd.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/lse.h>
@@ -214,9 +215,9 @@ static inline void spin_lock_prefetch(const void *ptr)
 
 #endif
 
-int cpu_enable_pan(void *__unused);
-int cpu_enable_cache_maint_trap(void *__unused);
-int cpu_clear_disr(void *__unused);
+int cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
+int cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
+int cpu_clear_disr(const struct arm64_cpu_capabilities *__unused);
 
 /* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */
 #define SVE_SET_VL(arg)	sve_set_current_vl(arg)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 54e41dfe41f6..9ae0d7e395cf 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -53,7 +53,8 @@ has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry,
 		(arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask);
 }
 
-static int cpu_enable_trap_ctr_access(void *__unused)
+static int cpu_enable_trap_ctr_access(
+	const struct arm64_cpu_capabilities *__unused)
 {
 	/* Clear SCTLR_EL1.UCT */
 	config_sctlr_el1(SCTLR_EL1_UCT, 0);
@@ -144,10 +145,8 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
 
 #include <linux/psci.h>
 
-static int enable_psci_bp_hardening(void *data)
+static int enable_psci_bp_hardening(const struct arm64_cpu_capabilities *entry)
 {
-	const struct arm64_cpu_capabilities *entry = data;
-
 	if (psci_ops.get_version)
 		install_bp_hardening_cb(entry,
 				       (bp_hardening_cb_t)psci_ops.get_version,
@@ -169,10 +168,9 @@ static void qcom_link_stack_sanitization(void)
 		     : "=&r" (tmp));
 }
 
-static int qcom_enable_link_stack_sanitization(void *data)
+static int qcom_enable_link_stack_sanitization(
+			const struct arm64_cpu_capabilities *entry)
 {
-	const struct arm64_cpu_capabilities *entry = data;
-
 	install_bp_hardening_cb(entry, qcom_link_stack_sanitization,
 				__qcom_hyp_sanitize_link_stack_start,
 				__qcom_hyp_sanitize_link_stack_end);
@@ -376,7 +374,7 @@ void verify_local_cpu_errata_workarounds(void)
 	for (; caps->matches; caps++) {
 		if (cpus_have_cap(caps->capability)) {
 			if (caps->enable)
-				caps->enable((void *)caps);
+				caps->enable(caps);
 		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
 			pr_crit("CPU%d: Requires work around for %s, not detected"
 					" at boot time\n",
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 5612d6f46331..6a8dfdc532b1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -887,7 +887,7 @@ static int __init parse_kpti(char *str)
 __setup("kpti=", parse_kpti);
 #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
-static int cpu_copy_el2regs(void *__unused)
+static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * Copy register values that aren't redirected by hardware.
@@ -1183,6 +1183,14 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+
+static int __enable_cpu_capability(void *arg)
+{
+	const struct arm64_cpu_capabilities *cap = arg;
+
+	return cap->enable(cap);
+}
+
 /*
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
@@ -1205,7 +1213,7 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 			 * uses an IPI, giving us a PSTATE that disappears when
 			 * we return.
 			 */
-			stop_machine(caps->enable, (void *)caps, cpu_online_mask);
+			stop_machine(__enable_cpu_capability, (void *)caps, cpu_online_mask);
 		}
 	}
 }
@@ -1249,7 +1257,7 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
 			cpu_die_early();
 		}
 		if (caps->enable)
-			caps->enable((void *)caps);
+			caps->enable(caps);
 	}
 }
 
@@ -1472,7 +1480,7 @@ static int __init enable_mrs_emulation(void)
 
 core_initcall(enable_mrs_emulation);
 
-int cpu_clear_disr(void *__unused)
+int cpu_clear_disr(const struct arm64_cpu_capabilities *__unused)
 {
 	/* Firmware may have left a deferred SError in this register. */
 	write_sysreg_s(0, SYS_DISR_EL1);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 55fb544072f6..4d7eff33c643 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -40,6 +40,7 @@
 #include <linux/sysctl.h>
 
 #include <asm/fpsimd.h>
+#include <asm/cpufeature.h>
 #include <asm/cputype.h>
 #include <asm/simd.h>
 #include <asm/sigcontext.h>
@@ -757,7 +758,7 @@ static void __init sve_efi_setup(void)
  * Enable SVE for EL1.
  * Intended for use by the cpufeatures code during CPU boot.
  */
-int sve_kernel_enable(void *__always_unused p)
+int sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
 {
 	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
 	isb();
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index bbb0fde2780e..296fab8e5c67 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -38,6 +38,7 @@
 
 #include <asm/atomic.h>
 #include <asm/bug.h>
+#include <asm/cpufeature.h>
 #include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
@@ -374,7 +375,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
 }
 
-int cpu_enable_cache_maint_trap(void *__unused)
+int cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
 {
 	config_sctlr_el1(SCTLR_EL1_UCI, 0);
 	return 0;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0e671ddf4855..937f89d2c353 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -813,7 +813,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
 NOKPROBE_SYMBOL(do_debug_exception);
 
 #ifdef CONFIG_ARM64_PAN
-int cpu_enable_pan(void *__unused)
+int cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * We modify PSTATE. This won't work from irq context as the PSTATE
-- 
2.13.6

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

* [PATCH 02/16] arm64: Move errata work around check on boot CPU
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

We trigger CPU errata work around check on the boot CPU from
smp_prepare_boot_cpu() to make sure that we run the checks only
after the CPU feature infrastructure is initialised.

We can do this from init_cpu_features() which is called only
on the boot CPU and does the initilisation of the infrastructure.
As we are consolidating the cpu capability handling, let us
move this to where it should belong. No functional changes.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 6 ++++++
 arch/arm64/kernel/smp.c        | 6 ------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6a8dfdc532b1..ebb467340b9c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -545,6 +545,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
 		sve_init_vq_map();
 	}
+
+	/*
+	 * Run the errata work around checks on the boot CPU, once we have
+	 * initialised the cpu feature infrastructure.
+	 */
+	update_cpu_errata_workarounds();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 3b8ad7be9c33..5cef11450183 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -448,12 +448,6 @@ void __init smp_prepare_boot_cpu(void)
 	jump_label_init();
 	cpuinfo_store_boot_cpu();
 	save_boot_cpu_run_el();
-	/*
-	 * Run the errata work around checks on the boot CPU, once we have
-	 * initialised the cpu feature infrastructure from
-	 * cpuinfo_store_boot_cpu() above.
-	 */
-	update_cpu_errata_workarounds();
 }
 
 static u64 __init of_get_cpu_mpidr(struct device_node *dn)
-- 
2.13.6

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

* [PATCH 02/16] arm64: Move errata work around check on boot CPU
@ 2018-01-23 12:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

We trigger CPU errata work around check on the boot CPU from
smp_prepare_boot_cpu() to make sure that we run the checks only
after the CPU feature infrastructure is initialised.

We can do this from init_cpu_features() which is called only
on the boot CPU and does the initilisation of the infrastructure.
As we are consolidating the cpu capability handling, let us
move this to where it should belong. No functional changes.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 6 ++++++
 arch/arm64/kernel/smp.c        | 6 ------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6a8dfdc532b1..ebb467340b9c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -545,6 +545,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
 		sve_init_vq_map();
 	}
+
+	/*
+	 * Run the errata work around checks on the boot CPU, once we have
+	 * initialised the cpu feature infrastructure.
+	 */
+	update_cpu_errata_workarounds();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 3b8ad7be9c33..5cef11450183 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -448,12 +448,6 @@ void __init smp_prepare_boot_cpu(void)
 	jump_label_init();
 	cpuinfo_store_boot_cpu();
 	save_boot_cpu_run_el();
-	/*
-	 * Run the errata work around checks on the boot CPU, once we have
-	 * initialised the cpu feature infrastructure from
-	 * cpuinfo_store_boot_cpu() above.
-	 */
-	update_cpu_errata_workarounds();
 }
 
 static u64 __init of_get_cpu_mpidr(struct device_node *dn)
-- 
2.13.6

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

* [PATCH 03/16] arm64: Move errata capability processing code
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

We have errata work around processing code in cpu_errata.c,
which calls back into helpers defined in cpufeature.c. Now
that we are going to make the handling of capabilities
generic by adding the information to each capability
move the errata work around specific processing, which
will be unified with generic routines.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 -------
 arch/arm64/kernel/cpu_errata.c      | 33 ------------------------------
 arch/arm64/kernel/cpufeature.c      | 40 +++++++++++++++++++++++++++++++++++--
 3 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index cefbd685292c..a23c0d4f27e9 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -234,15 +234,8 @@ static inline bool id_aa64pfr0_sve(u64 pfr0)
 }
 
 void __init setup_cpu_features(void);
-
-void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
-			    const char *info);
-void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps);
 void check_local_cpu_capabilities(void);
 
-void update_cpu_errata_workarounds(void);
-void __init enable_errata_workarounds(void);
-void verify_local_cpu_errata_workarounds(void);
 
 u64 read_sanitised_ftr_reg(u32 id);
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 9ae0d7e395cf..40c432d7d5c6 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -361,36 +361,3 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 	}
 };
-
-/*
- * The CPU Errata work arounds are detected and applied at boot time
- * and the related information is freed soon after. If the new CPU requires
- * an errata not detected at boot, fail this CPU.
- */
-void verify_local_cpu_errata_workarounds(void)
-{
-	const struct arm64_cpu_capabilities *caps = arm64_errata;
-
-	for (; caps->matches; caps++) {
-		if (cpus_have_cap(caps->capability)) {
-			if (caps->enable)
-				caps->enable(caps);
-		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
-			pr_crit("CPU%d: Requires work around for %s, not detected"
-					" at boot time\n",
-				smp_processor_id(),
-				caps->desc ? : "an erratum");
-			cpu_die_early();
-		}
-	}
-}
-
-void update_cpu_errata_workarounds(void)
-{
-	update_cpu_capabilities(arm64_errata, "enabling workaround for");
-}
-
-void __init enable_errata_workarounds(void)
-{
-	enable_cpu_capabilities(arm64_errata);
-}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index ebb467340b9c..0bdc58454d7a 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -503,6 +503,9 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
 	reg->user_mask = user_mask;
 }
 
+extern const struct arm64_cpu_capabilities arm64_errata[];
+static void update_cpu_errata_workarounds(void);
+
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
 	/* Before we start using the tables, make sure it is sorted */
@@ -1176,7 +1179,7 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 	return false;
 }
 
-void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info)
 {
 	for (; caps->matches; caps++) {
@@ -1201,7 +1204,7 @@ static int __enable_cpu_capability(void *arg)
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
  */
-void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
+static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
@@ -1285,6 +1288,39 @@ static void verify_sve_features(void)
 }
 
 /*
+ * The CPU Errata work arounds are detected and applied at boot time
+ * and the related information is freed soon after. If the new CPU requires
+ * an errata not detected at boot, fail this CPU.
+ */
+static void verify_local_cpu_errata_workarounds(void)
+{
+	const struct arm64_cpu_capabilities *caps = arm64_errata;
+
+	for (; caps->matches; caps++) {
+		if (cpus_have_cap(caps->capability)) {
+			if (caps->enable)
+				caps->enable(caps);
+		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
+			pr_crit("CPU%d: Requires work around for %s, not detected"
+					" at boot time\n",
+				smp_processor_id(),
+				caps->desc ? : "an erratum");
+			cpu_die_early();
+		}
+	}
+}
+
+static void update_cpu_errata_workarounds(void)
+{
+	update_cpu_capabilities(arm64_errata, "enabling workaround for");
+}
+
+static void __init enable_errata_workarounds(void)
+{
+	enable_cpu_capabilities(arm64_errata);
+}
+
+/*
  * Run through the enabled system capabilities and enable() it on this CPU.
  * The capabilities were decided based on the available CPUs at the boot time.
  * Any new CPU should match the system wide status of the capability. If the
-- 
2.13.6

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

* [PATCH 03/16] arm64: Move errata capability processing code
@ 2018-01-23 12:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

We have errata work around processing code in cpu_errata.c,
which calls back into helpers defined in cpufeature.c. Now
that we are going to make the handling of capabilities
generic by adding the information to each capability
move the errata work around specific processing, which
will be unified with generic routines.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 -------
 arch/arm64/kernel/cpu_errata.c      | 33 ------------------------------
 arch/arm64/kernel/cpufeature.c      | 40 +++++++++++++++++++++++++++++++++++--
 3 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index cefbd685292c..a23c0d4f27e9 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -234,15 +234,8 @@ static inline bool id_aa64pfr0_sve(u64 pfr0)
 }
 
 void __init setup_cpu_features(void);
-
-void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
-			    const char *info);
-void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps);
 void check_local_cpu_capabilities(void);
 
-void update_cpu_errata_workarounds(void);
-void __init enable_errata_workarounds(void);
-void verify_local_cpu_errata_workarounds(void);
 
 u64 read_sanitised_ftr_reg(u32 id);
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 9ae0d7e395cf..40c432d7d5c6 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -361,36 +361,3 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 	}
 };
-
-/*
- * The CPU Errata work arounds are detected and applied at boot time
- * and the related information is freed soon after. If the new CPU requires
- * an errata not detected at boot, fail this CPU.
- */
-void verify_local_cpu_errata_workarounds(void)
-{
-	const struct arm64_cpu_capabilities *caps = arm64_errata;
-
-	for (; caps->matches; caps++) {
-		if (cpus_have_cap(caps->capability)) {
-			if (caps->enable)
-				caps->enable(caps);
-		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
-			pr_crit("CPU%d: Requires work around for %s, not detected"
-					" at boot time\n",
-				smp_processor_id(),
-				caps->desc ? : "an erratum");
-			cpu_die_early();
-		}
-	}
-}
-
-void update_cpu_errata_workarounds(void)
-{
-	update_cpu_capabilities(arm64_errata, "enabling workaround for");
-}
-
-void __init enable_errata_workarounds(void)
-{
-	enable_cpu_capabilities(arm64_errata);
-}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index ebb467340b9c..0bdc58454d7a 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -503,6 +503,9 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
 	reg->user_mask = user_mask;
 }
 
+extern const struct arm64_cpu_capabilities arm64_errata[];
+static void update_cpu_errata_workarounds(void);
+
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
 	/* Before we start using the tables, make sure it is sorted */
@@ -1176,7 +1179,7 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 	return false;
 }
 
-void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info)
 {
 	for (; caps->matches; caps++) {
@@ -1201,7 +1204,7 @@ static int __enable_cpu_capability(void *arg)
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
  */
-void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
+static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
@@ -1285,6 +1288,39 @@ static void verify_sve_features(void)
 }
 
 /*
+ * The CPU Errata work arounds are detected and applied at boot time
+ * and the related information is freed soon after. If the new CPU requires
+ * an errata not detected at boot, fail this CPU.
+ */
+static void verify_local_cpu_errata_workarounds(void)
+{
+	const struct arm64_cpu_capabilities *caps = arm64_errata;
+
+	for (; caps->matches; caps++) {
+		if (cpus_have_cap(caps->capability)) {
+			if (caps->enable)
+				caps->enable(caps);
+		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
+			pr_crit("CPU%d: Requires work around for %s, not detected"
+					" at boot time\n",
+				smp_processor_id(),
+				caps->desc ? : "an erratum");
+			cpu_die_early();
+		}
+	}
+}
+
+static void update_cpu_errata_workarounds(void)
+{
+	update_cpu_capabilities(arm64_errata, "enabling workaround for");
+}
+
+static void __init enable_errata_workarounds(void)
+{
+	enable_cpu_capabilities(arm64_errata);
+}
+
+/*
  * Run through the enabled system capabilities and enable() it on this CPU.
  * The capabilities were decided based on the available CPUs at the boot time.
  * Any new CPU should match the system wide status of the capability. If the
-- 
2.13.6

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
to the userspace and the CPU hwcaps used by the kernel, which
include cpu features and CPU errata work arounds.

At the moment we have the following restricions:

 a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
   - Detected mostly on system wide CPU feature register. But
     there are some which really uses a local CPU's value to
     decide the availability (e.g, availability of hardware
     prefetch). So, we run the check only once, after all the
     boot-time active CPUs are turned on.
   - Any late CPU which doesn't posses all the established features
     is killed.
   - Any late CPU which possess a feature *not* already available
     is allowed to boot.

 b) CPU Errata work arounds (arm64_errata)
   - Detected mostly based on a local CPU's feature register.
     The checks are run on each boot time activated CPUs.
   - Any late CPU which doesn't have any of the established errata
     work around capabilities is ignored and is allowed to boot.
   - Any late CPU which has an errata work around not already available
     is killed.

However there are some exceptions to the cases above.

1) KPTI is a feature that we need to enable when at least one CPU needs it.
   And any late CPU that has this "feature" should be killed.
2) Hardware DBM feature is a non-conflicting capability which could be
   enabled on CPUs which has it without any issues, even if the CPU is
   brought up late.

So this calls for a lot more fine grained behavior for each capability.
And if we define all the attributes to control their behavior properly,
we may be able to use a single table for the CPU hwcaps (not the
ELF HWCAPs, which cover errata and features). This is a prepartory step
to get there. We define type for a capability, which for now encodes the
scope of the check. i.e, whether it should be checked system wide or on
each local CPU. We define two types :

  1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
  1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.

As such there is no change in how the capabilities are treated.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
 arch/arm64/kernel/cpu_errata.c      |  8 ++++----
 arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
 3 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a23c0d4f27e9..4fd5de8ef33e 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -86,16 +86,23 @@ struct arm64_ftr_reg {
 
 extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 
-/* scope of capability check */
-enum {
-	SCOPE_SYSTEM,
-	SCOPE_LOCAL_CPU,
-};
+
+/* Decide how the capability is detected. On a local CPU vs System wide */
+#define ARM64_CPUCAP_SCOPE_MASK			0x3
+#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
+#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
+#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
+#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
+
+/* CPU errata detected at boot time based on feature of one or more CPUs */
+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
+/* CPU feature detected at boot time based on system-wide value of a feature */
+#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
-	int def_scope;			/* default scope */
+	u16 type;
 	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
 	/* Called on all active CPUs for all  "available" capabilities */
 	int (*enable)(const struct arm64_cpu_capabilities *caps);
@@ -116,6 +123,11 @@ struct arm64_cpu_capabilities {
 	};
 };
 
+static inline int cpucap_default_scope(const struct arm64_cpu_capabilities *cap)
+{
+	return cap->type & ARM64_CPUCAP_SCOPE_MASK;
+}
+
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 extern struct static_key_false arm64_const_caps_ready;
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 40c432d7d5c6..550ac8a0854b 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -180,14 +180,14 @@ static int qcom_enable_link_stack_sanitization(
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
-	.def_scope = SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = min, \
 	.midr_range_max = max
 
 #define MIDR_ALL_VERSIONS(model) \
-	.def_scope = SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = 0, \
@@ -291,7 +291,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "Mismatched cache line size",
 		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
 		.matches = has_mismatched_cache_line_size,
-		.def_scope = SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM,
 		.enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -305,7 +305,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
-		.def_scope = SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM,
 		.midr_model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 0bdc58454d7a..43c7e992d784 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -916,7 +916,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
 		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -927,7 +927,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -940,7 +940,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "LSE atomic instructions",
 		.capability = ARM64_HAS_LSE_ATOMICS,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -951,14 +951,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -972,21 +972,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_PAN
 	{
 		.capability = ARM64_ALT_PAN_NOT_UAO,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = cpufeature_pan_not_uao,
 	},
 #endif /* CONFIG_ARM64_PAN */
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = runs_at_el2,
 		.enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
 		.capability = ARM64_HAS_32BIT_EL0,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -996,21 +996,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Reduced HYP mapping offset",
 		.capability = ARM64_HYP_OFFSET_LOW,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = hyp_offset_low,
 	},
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1018,7 +1018,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Data cache clean to Point of Persistence",
 		.capability = ARM64_HAS_DCPOP,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR1_EL1,
 		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
@@ -1028,8 +1028,8 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_SVE
 	{
 		.desc = "Scalable Vector Extension",
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.capability = ARM64_SVE,
-		.def_scope = SCOPE_SYSTEM,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
 		.field_pos = ID_AA64PFR0_SVE_SHIFT,
@@ -1042,7 +1042,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "RAS Extension Support",
 		.capability = ARM64_HAS_RAS_EXTN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1054,16 +1054,16 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{},
 };
 
-#define HWCAP_CAP(reg, field, s, min_value, type, cap)	\
+#define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
 	{							\
 		.desc = #cap,					\
-		.def_scope = SCOPE_SYSTEM,			\
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,	\
 		.matches = has_cpuid_feature,			\
 		.sys_reg = reg,					\
 		.field_pos = field,				\
 		.sign = s,					\
 		.min_field_value = min_value,			\
-		.hwcap_type = type,				\
+		.hwcap_type = cap_type,				\
 		.hwcap = cap,					\
 	}
 
@@ -1156,7 +1156,7 @@ static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps)
 	/* We support emulation of accesses to CPU ID feature registers */
 	elf_hwcap |= HWCAP_CPUID;
 	for (; hwcaps->matches; hwcaps++)
-		if (hwcaps->matches(hwcaps, hwcaps->def_scope))
+		if (hwcaps->matches(hwcaps, cpucap_default_scope(hwcaps)))
 			cap_set_elf_hwcap(hwcaps);
 }
 
@@ -1183,7 +1183,7 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info)
 {
 	for (; caps->matches; caps++) {
-		if (!caps->matches(caps, caps->def_scope))
+		if (!caps->matches(caps, cpucap_default_scope(caps)))
 			continue;
 
 		if (!cpus_have_cap(caps->capability) && caps->desc)
-- 
2.13.6

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-23 12:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
to the userspace and the CPU hwcaps used by the kernel, which
include cpu features and CPU errata work arounds.

At the moment we have the following restricions:

 a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
   - Detected mostly on system wide CPU feature register. But
     there are some which really uses a local CPU's value to
     decide the availability (e.g, availability of hardware
     prefetch). So, we run the check only once, after all the
     boot-time active CPUs are turned on.
   - Any late CPU which doesn't posses all the established features
     is killed.
   - Any late CPU which possess a feature *not* already available
     is allowed to boot.

 b) CPU Errata work arounds (arm64_errata)
   - Detected mostly based on a local CPU's feature register.
     The checks are run on each boot time activated CPUs.
   - Any late CPU which doesn't have any of the established errata
     work around capabilities is ignored and is allowed to boot.
   - Any late CPU which has an errata work around not already available
     is killed.

However there are some exceptions to the cases above.

1) KPTI is a feature that we need to enable when at least one CPU needs it.
   And any late CPU that has this "feature" should be killed.
2) Hardware DBM feature is a non-conflicting capability which could be
   enabled on CPUs which has it without any issues, even if the CPU is
   brought up late.

So this calls for a lot more fine grained behavior for each capability.
And if we define all the attributes to control their behavior properly,
we may be able to use a single table for the CPU hwcaps (not the
ELF HWCAPs, which cover errata and features). This is a prepartory step
to get there. We define type for a capability, which for now encodes the
scope of the check. i.e, whether it should be checked system wide or on
each local CPU. We define two types :

  1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
  1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.

As such there is no change in how the capabilities are treated.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
 arch/arm64/kernel/cpu_errata.c      |  8 ++++----
 arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
 3 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a23c0d4f27e9..4fd5de8ef33e 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -86,16 +86,23 @@ struct arm64_ftr_reg {
 
 extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 
-/* scope of capability check */
-enum {
-	SCOPE_SYSTEM,
-	SCOPE_LOCAL_CPU,
-};
+
+/* Decide how the capability is detected. On a local CPU vs System wide */
+#define ARM64_CPUCAP_SCOPE_MASK			0x3
+#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
+#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
+#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
+#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
+
+/* CPU errata detected at boot time based on feature of one or more CPUs */
+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
+/* CPU feature detected at boot time based on system-wide value of a feature */
+#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
-	int def_scope;			/* default scope */
+	u16 type;
 	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
 	/* Called on all active CPUs for all  "available" capabilities */
 	int (*enable)(const struct arm64_cpu_capabilities *caps);
@@ -116,6 +123,11 @@ struct arm64_cpu_capabilities {
 	};
 };
 
+static inline int cpucap_default_scope(const struct arm64_cpu_capabilities *cap)
+{
+	return cap->type & ARM64_CPUCAP_SCOPE_MASK;
+}
+
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 extern struct static_key_false arm64_const_caps_ready;
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 40c432d7d5c6..550ac8a0854b 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -180,14 +180,14 @@ static int qcom_enable_link_stack_sanitization(
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
-	.def_scope = SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = min, \
 	.midr_range_max = max
 
 #define MIDR_ALL_VERSIONS(model) \
-	.def_scope = SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = 0, \
@@ -291,7 +291,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "Mismatched cache line size",
 		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
 		.matches = has_mismatched_cache_line_size,
-		.def_scope = SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM,
 		.enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -305,7 +305,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
-		.def_scope = SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM,
 		.midr_model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 0bdc58454d7a..43c7e992d784 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -916,7 +916,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
 		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -927,7 +927,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -940,7 +940,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "LSE atomic instructions",
 		.capability = ARM64_HAS_LSE_ATOMICS,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -951,14 +951,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -972,21 +972,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_PAN
 	{
 		.capability = ARM64_ALT_PAN_NOT_UAO,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = cpufeature_pan_not_uao,
 	},
 #endif /* CONFIG_ARM64_PAN */
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = runs_at_el2,
 		.enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
 		.capability = ARM64_HAS_32BIT_EL0,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -996,21 +996,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Reduced HYP mapping offset",
 		.capability = ARM64_HYP_OFFSET_LOW,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = hyp_offset_low,
 	},
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1018,7 +1018,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Data cache clean to Point of Persistence",
 		.capability = ARM64_HAS_DCPOP,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR1_EL1,
 		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
@@ -1028,8 +1028,8 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_SVE
 	{
 		.desc = "Scalable Vector Extension",
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.capability = ARM64_SVE,
-		.def_scope = SCOPE_SYSTEM,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
 		.field_pos = ID_AA64PFR0_SVE_SHIFT,
@@ -1042,7 +1042,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "RAS Extension Support",
 		.capability = ARM64_HAS_RAS_EXTN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1054,16 +1054,16 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{},
 };
 
-#define HWCAP_CAP(reg, field, s, min_value, type, cap)	\
+#define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
 	{							\
 		.desc = #cap,					\
-		.def_scope = SCOPE_SYSTEM,			\
+		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,	\
 		.matches = has_cpuid_feature,			\
 		.sys_reg = reg,					\
 		.field_pos = field,				\
 		.sign = s,					\
 		.min_field_value = min_value,			\
-		.hwcap_type = type,				\
+		.hwcap_type = cap_type,				\
 		.hwcap = cap,					\
 	}
 
@@ -1156,7 +1156,7 @@ static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps)
 	/* We support emulation of accesses to CPU ID feature registers */
 	elf_hwcap |= HWCAP_CPUID;
 	for (; hwcaps->matches; hwcaps++)
-		if (hwcaps->matches(hwcaps, hwcaps->def_scope))
+		if (hwcaps->matches(hwcaps, cpucap_default_scope(hwcaps)))
 			cap_set_elf_hwcap(hwcaps);
 }
 
@@ -1183,7 +1183,7 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info)
 {
 	for (; caps->matches; caps++) {
-		if (!caps->matches(caps, caps->def_scope))
+		if (!caps->matches(caps, cpucap_default_scope(caps)))
 			continue;
 
 		if (!cpus_have_cap(caps->capability) && caps->desc)
-- 
2.13.6

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

* [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Add two different flags to indicate if the conflict of a capability
on a late CPU with the current system state

 1) Can a CPU have a capability when the system doesn't have it ?

    Most arm64 features could have this set. While erratum work arounds
    cannot have this, as we may miss work arounds.

 2) Can a CPU miss a capability when the system has it ?
    This could be set for arm64 erratum work arounds as we don't
    care if a CPU doesn't need the work around. However it should
    be clear for features.

These flags could be added to certain entries based on their nature.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 4fd5de8ef33e..27d037bb0451 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
 #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
 
-/* CPU errata detected at boot time based on feature of one or more CPUs */
-#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
-/* CPU feature detected at boot time based on system-wide value of a feature */
-#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
+/* Is it safe for a late CPU to have this capability when system doesn't already have */
+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
+/* Is it safe for a late CPU to miss this capability when system has it */
+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
+
+/*
+ * CPU errata detected at boot time based on feature of one or more CPUs.
+ * It is not safe for a late CPU to have this feature when the system doesn't
+ * have it. But it is safe to miss the feature if the system has it.
+ */
+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
+/*
+ * CPU feature detected at boot time based on system-wide value of a feature.
+ * It is safe for a late CPU to have this feature even though the system doesn't
+ * have it already. But the CPU must have this feature if the system does.
+ */
+#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
@@ -128,6 +143,18 @@ static inline int cpucap_default_scope(const struct arm64_cpu_capabilities *cap)
 	return cap->type & ARM64_CPUCAP_SCOPE_MASK;
 }
 
+static inline bool
+cpucap_late_cpu_missing_cap_safe(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS);
+}
+
+static inline bool
+cpucap_late_cpu_have_cap_safe(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE);
+}
+
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 extern struct static_key_false arm64_const_caps_ready;
-- 
2.13.6

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

* [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
@ 2018-01-23 12:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

Add two different flags to indicate if the conflict of a capability
on a late CPU with the current system state

 1) Can a CPU have a capability when the system doesn't have it ?

    Most arm64 features could have this set. While erratum work arounds
    cannot have this, as we may miss work arounds.

 2) Can a CPU miss a capability when the system has it ?
    This could be set for arm64 erratum work arounds as we don't
    care if a CPU doesn't need the work around. However it should
    be clear for features.

These flags could be added to certain entries based on their nature.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 4fd5de8ef33e..27d037bb0451 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
 #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
 
-/* CPU errata detected at boot time based on feature of one or more CPUs */
-#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
-/* CPU feature detected at boot time based on system-wide value of a feature */
-#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
+/* Is it safe for a late CPU to have this capability when system doesn't already have */
+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
+/* Is it safe for a late CPU to miss this capability when system has it */
+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
+
+/*
+ * CPU errata detected at boot time based on feature of one or more CPUs.
+ * It is not safe for a late CPU to have this feature when the system doesn't
+ * have it. But it is safe to miss the feature if the system has it.
+ */
+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
+/*
+ * CPU feature detected at boot time based on system-wide value of a feature.
+ * It is safe for a late CPU to have this feature even though the system doesn't
+ * have it already. But the CPU must have this feature if the system does.
+ */
+#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
@@ -128,6 +143,18 @@ static inline int cpucap_default_scope(const struct arm64_cpu_capabilities *cap)
 	return cap->type & ARM64_CPUCAP_SCOPE_MASK;
 }
 
+static inline bool
+cpucap_late_cpu_missing_cap_safe(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS);
+}
+
+static inline bool
+cpucap_late_cpu_have_cap_safe(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE);
+}
+
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 extern struct static_key_false arm64_const_caps_ready;
-- 
2.13.6

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

* [PATCH 06/16] arm64: capabilities: Unify the verification
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Now that each capability describes how to treat the conflicts
of CPU cap state vs System wide cap state, we can unify the
verification logic to a single place.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 43c7e992d784..79737034a628 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
 }
 
 /*
+ * Run through the list of capabilities to check for conflicts.
+ * Returns "false" on conflicts.
+ */
+static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
+{
+	bool cpu_has_cap, system_has_cap;
+	const struct arm64_cpu_capabilities *caps = caps_list;
+
+	for (; caps->matches; caps++) {
+		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
+		system_has_cap =  cpus_have_cap(caps->capability);
+
+		if (system_has_cap) {
+			/*
+			 * Check if the new CPU misses an advertised feature, which is not
+			 * safe to miss.
+			 */
+			if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(caps))
+				break;
+			/*
+			 * We have to issue enable() irrespective of whether the CPU
+			 * has it or not, as it is enabeld system wide. It is upto
+			 * the call back to take appropriate action on this CPU.
+			 */
+			if (caps->enable)
+				caps->enable(caps);
+		} else {
+			/*
+			 * Check if the CPU has this capability if it isn't safe to
+			 * have when the system doesn't.
+			 */
+			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
+				break;
+		}
+	}
+
+	if (caps->matches) {
+		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
+			smp_processor_id(), caps->capability,
+			caps->desc ? : "no description",
+			system_has_cap, cpu_has_cap);
+		return false;
+	}
+
+	return true;
+}
+
+/*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
  */
@@ -1249,25 +1297,10 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
 		}
 }
 
-static void
-verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
+static void verify_local_cpu_features(void)
 {
-	const struct arm64_cpu_capabilities *caps = caps_list;
-	for (; caps->matches; caps++) {
-		if (!cpus_have_cap(caps->capability))
-			continue;
-		/*
-		 * If the new CPU misses an advertised feature, we cannot proceed
-		 * further, park the cpu.
-		 */
-		if (!__this_cpu_has_cap(caps_list, caps->capability)) {
-			pr_crit("CPU%d: missing feature: %s\n",
-					smp_processor_id(), caps->desc);
-			cpu_die_early();
-		}
-		if (caps->enable)
-			caps->enable(caps);
-	}
+	if (!__verify_local_cpu_caps(arm64_features))
+		cpu_die_early();
 }
 
 static void verify_sve_features(void)
@@ -1294,20 +1327,8 @@ static void verify_sve_features(void)
  */
 static void verify_local_cpu_errata_workarounds(void)
 {
-	const struct arm64_cpu_capabilities *caps = arm64_errata;
-
-	for (; caps->matches; caps++) {
-		if (cpus_have_cap(caps->capability)) {
-			if (caps->enable)
-				caps->enable(caps);
-		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
-			pr_crit("CPU%d: Requires work around for %s, not detected"
-					" at boot time\n",
-				smp_processor_id(),
-				caps->desc ? : "an erratum");
-			cpu_die_early();
-		}
-	}
+	if (__verify_local_cpu_caps(arm64_errata))
+		cpu_die_early();
 }
 
 static void update_cpu_errata_workarounds(void)
@@ -1331,7 +1352,7 @@ static void __init enable_errata_workarounds(void)
 static void verify_local_cpu_capabilities(void)
 {
 	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features(arm64_features);
+	verify_local_cpu_features();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
-- 
2.13.6

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

* [PATCH 06/16] arm64: capabilities: Unify the verification
@ 2018-01-23 12:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

Now that each capability describes how to treat the conflicts
of CPU cap state vs System wide cap state, we can unify the
verification logic to a single place.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 43c7e992d784..79737034a628 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
 }
 
 /*
+ * Run through the list of capabilities to check for conflicts.
+ * Returns "false" on conflicts.
+ */
+static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
+{
+	bool cpu_has_cap, system_has_cap;
+	const struct arm64_cpu_capabilities *caps = caps_list;
+
+	for (; caps->matches; caps++) {
+		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
+		system_has_cap =  cpus_have_cap(caps->capability);
+
+		if (system_has_cap) {
+			/*
+			 * Check if the new CPU misses an advertised feature, which is not
+			 * safe to miss.
+			 */
+			if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(caps))
+				break;
+			/*
+			 * We have to issue enable() irrespective of whether the CPU
+			 * has it or not, as it is enabeld system wide. It is upto
+			 * the call back to take appropriate action on this CPU.
+			 */
+			if (caps->enable)
+				caps->enable(caps);
+		} else {
+			/*
+			 * Check if the CPU has this capability if it isn't safe to
+			 * have when the system doesn't.
+			 */
+			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
+				break;
+		}
+	}
+
+	if (caps->matches) {
+		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
+			smp_processor_id(), caps->capability,
+			caps->desc ? : "no description",
+			system_has_cap, cpu_has_cap);
+		return false;
+	}
+
+	return true;
+}
+
+/*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
  */
@@ -1249,25 +1297,10 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
 		}
 }
 
-static void
-verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
+static void verify_local_cpu_features(void)
 {
-	const struct arm64_cpu_capabilities *caps = caps_list;
-	for (; caps->matches; caps++) {
-		if (!cpus_have_cap(caps->capability))
-			continue;
-		/*
-		 * If the new CPU misses an advertised feature, we cannot proceed
-		 * further, park the cpu.
-		 */
-		if (!__this_cpu_has_cap(caps_list, caps->capability)) {
-			pr_crit("CPU%d: missing feature: %s\n",
-					smp_processor_id(), caps->desc);
-			cpu_die_early();
-		}
-		if (caps->enable)
-			caps->enable(caps);
-	}
+	if (!__verify_local_cpu_caps(arm64_features))
+		cpu_die_early();
 }
 
 static void verify_sve_features(void)
@@ -1294,20 +1327,8 @@ static void verify_sve_features(void)
  */
 static void verify_local_cpu_errata_workarounds(void)
 {
-	const struct arm64_cpu_capabilities *caps = arm64_errata;
-
-	for (; caps->matches; caps++) {
-		if (cpus_have_cap(caps->capability)) {
-			if (caps->enable)
-				caps->enable(caps);
-		} else if (caps->matches(caps, SCOPE_LOCAL_CPU)) {
-			pr_crit("CPU%d: Requires work around for %s, not detected"
-					" at boot time\n",
-				smp_processor_id(),
-				caps->desc ? : "an erratum");
-			cpu_die_early();
-		}
-	}
+	if (__verify_local_cpu_caps(arm64_errata))
+		cpu_die_early();
 }
 
 static void update_cpu_errata_workarounds(void)
@@ -1331,7 +1352,7 @@ static void __init enable_errata_workarounds(void)
 static void verify_local_cpu_capabilities(void)
 {
 	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features(arm64_features);
+	verify_local_cpu_features();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
-- 
2.13.6

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

* [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

While processing the list of capabilities, it is useful to
filter out some of the entries based on the given type to
allow better control. This can be used later for handling
LOCAL vs SYSTEM wide capabilities and more.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  5 +++++
 arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 27d037bb0451..a621d2184227 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 /* Is it safe for a late CPU to miss this capability when system has it */
 #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
 
+#define ARM64_CPUCAP_TYPE_ALL			 \
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
+	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
 /*
  * CPU errata detected at boot time based on feature of one or more CPUs.
  * It is not safe for a late CPU to have this feature when the system doesn't
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 79737034a628..198c5daddd65 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1180,9 +1180,11 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 }
 
 static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
-			    const char *info)
+				    u16 cap_type, const char *info)
 {
 	for (; caps->matches; caps++) {
+		if (!(caps->type & cap_type))
+			continue;
 		if (!caps->matches(caps, cpucap_default_scope(caps)))
 			continue;
 
@@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
  */
-static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
+static void __init
+enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
 {
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
 
-		if (!cpus_have_cap(num))
+		if (!(caps->type & caps_type) || !cpus_have_cap(num))
 			continue;
 
 		/* Ensure cpus_have_const_cap(num) works */
@@ -1231,12 +1234,16 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
  * Run through the list of capabilities to check for conflicts.
  * Returns "false" on conflicts.
  */
-static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
+static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
+				    u16 caps_type)
 {
 	bool cpu_has_cap, system_has_cap;
 	const struct arm64_cpu_capabilities *caps = caps_list;
 
 	for (; caps->matches; caps++) {
+		if (!(caps->type & caps_type))
+			continue;
+
 		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
 		system_has_cap =  cpus_have_cap(caps->capability);
 
@@ -1299,7 +1306,7 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
 
 static void verify_local_cpu_features(void)
 {
-	if (!__verify_local_cpu_caps(arm64_features))
+	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
 		cpu_die_early();
 }
 
@@ -1327,18 +1334,20 @@ static void verify_sve_features(void)
  */
 static void verify_local_cpu_errata_workarounds(void)
 {
-	if (__verify_local_cpu_caps(arm64_errata))
+	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
 		cpu_die_early();
 }
 
 static void update_cpu_errata_workarounds(void)
 {
-	update_cpu_capabilities(arm64_errata, "enabling workaround for");
+	update_cpu_capabilities(arm64_errata,
+				ARM64_CPUCAP_TYPE_ALL,
+				"enabling workaround for");
 }
 
 static void __init enable_errata_workarounds(void)
 {
-	enable_cpu_capabilities(arm64_errata);
+	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_TYPE_ALL);
 }
 
 /*
@@ -1387,8 +1396,9 @@ void check_local_cpu_capabilities(void)
 
 static void __init setup_feature_capabilities(void)
 {
-	update_cpu_capabilities(arm64_features, "detected feature:");
-	enable_cpu_capabilities(arm64_features);
+	update_cpu_capabilities(arm64_features,
+				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
+	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
-- 
2.13.6

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

* [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

While processing the list of capabilities, it is useful to
filter out some of the entries based on the given type to
allow better control. This can be used later for handling
LOCAL vs SYSTEM wide capabilities and more.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  5 +++++
 arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 27d037bb0451..a621d2184227 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 /* Is it safe for a late CPU to miss this capability when system has it */
 #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
 
+#define ARM64_CPUCAP_TYPE_ALL			 \
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
+	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
 /*
  * CPU errata detected at boot time based on feature of one or more CPUs.
  * It is not safe for a late CPU to have this feature when the system doesn't
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 79737034a628..198c5daddd65 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1180,9 +1180,11 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 }
 
 static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
-			    const char *info)
+				    u16 cap_type, const char *info)
 {
 	for (; caps->matches; caps++) {
+		if (!(caps->type & cap_type))
+			continue;
 		if (!caps->matches(caps, cpucap_default_scope(caps)))
 			continue;
 
@@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
  */
-static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
+static void __init
+enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
 {
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
 
-		if (!cpus_have_cap(num))
+		if (!(caps->type & caps_type) || !cpus_have_cap(num))
 			continue;
 
 		/* Ensure cpus_have_const_cap(num) works */
@@ -1231,12 +1234,16 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
  * Run through the list of capabilities to check for conflicts.
  * Returns "false" on conflicts.
  */
-static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
+static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
+				    u16 caps_type)
 {
 	bool cpu_has_cap, system_has_cap;
 	const struct arm64_cpu_capabilities *caps = caps_list;
 
 	for (; caps->matches; caps++) {
+		if (!(caps->type & caps_type))
+			continue;
+
 		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
 		system_has_cap =  cpus_have_cap(caps->capability);
 
@@ -1299,7 +1306,7 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
 
 static void verify_local_cpu_features(void)
 {
-	if (!__verify_local_cpu_caps(arm64_features))
+	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
 		cpu_die_early();
 }
 
@@ -1327,18 +1334,20 @@ static void verify_sve_features(void)
  */
 static void verify_local_cpu_errata_workarounds(void)
 {
-	if (__verify_local_cpu_caps(arm64_errata))
+	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
 		cpu_die_early();
 }
 
 static void update_cpu_errata_workarounds(void)
 {
-	update_cpu_capabilities(arm64_errata, "enabling workaround for");
+	update_cpu_capabilities(arm64_errata,
+				ARM64_CPUCAP_TYPE_ALL,
+				"enabling workaround for");
 }
 
 static void __init enable_errata_workarounds(void)
 {
-	enable_cpu_capabilities(arm64_errata);
+	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_TYPE_ALL);
 }
 
 /*
@@ -1387,8 +1396,9 @@ void check_local_cpu_capabilities(void)
 
 static void __init setup_feature_capabilities(void)
 {
-	update_cpu_capabilities(arm64_features, "detected feature:");
-	enable_cpu_capabilities(arm64_features);
+	update_cpu_capabilities(arm64_features,
+				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
+	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
-- 
2.13.6

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

So far we have had separate routes for triggering errata and feature
capabilities. Also, we never allowed "features" based on local CPU
and "errata" based on System wide safe registers. This patch
groups the handling of errata and features and also allows them
to have all the possible scopes.

So, we now run through the arm64_features and arm64_errata:

 1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
    via update_cpu_local_capabilities().
 2) with SCOPE_SYSTEM filter only once after all boot time enabled
    CPUs are active.

We could ideally merge the two tables into one. But leave it as
it is for easy access to the list of particular type.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 77 ++++++++++++++++++++++++------------------
 1 file changed, 44 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 198c5daddd65..7ae5cf9092d0 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,7 +504,7 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
 }
 
 extern const struct arm64_cpu_capabilities arm64_errata[];
-static void update_cpu_errata_workarounds(void);
+static void update_cpu_local_capabilities(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -553,7 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 	 * Run the errata work around checks on the boot CPU, once we have
 	 * initialised the cpu feature infrastructure.
 	 */
-	update_cpu_errata_workarounds();
+	update_cpu_local_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1179,8 +1179,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 	return false;
 }
 
-static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
-				    u16 cap_type, const char *info)
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+				      u16 cap_type, const char *info)
 {
 	for (; caps->matches; caps++) {
 		if (!(caps->type & cap_type))
@@ -1194,6 +1194,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+static void update_cpu_capabilities(u16 type)
+{
+	__update_cpu_capabilities(arm64_features, type,
+				"detected feature:");
+	__update_cpu_capabilities(arm64_errata, type,
+				"enabling work around for");
+}
 
 static int __enable_cpu_capability(void *arg)
 {
@@ -1207,7 +1214,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
 {
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
@@ -1282,6 +1289,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+static bool verify_local_cpu_caps(u16 type)
+{
+	return __verify_local_cpu_caps(arm64_features, type) &&
+	       __verify_local_cpu_caps(arm64_errata, type);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1304,12 +1317,6 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
 		}
 }
 
-static void verify_local_cpu_features(void)
-{
-	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1328,26 +1335,28 @@ static void verify_sve_features(void)
 }
 
 /*
- * The CPU Errata work arounds are detected and applied at boot time
- * and the related information is freed soon after. If the new CPU requires
- * an errata not detected at boot, fail this CPU.
+ * Check for all capablities within the scope of local CPU.
+ * This is run on all boot time activated CPUs.
  */
-static void verify_local_cpu_errata_workarounds(void)
+static void update_cpu_local_capabilities(void)
 {
-	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
-		cpu_die_early();
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_LOCAL_CPU);
 }
 
-static void update_cpu_errata_workarounds(void)
+/*
+ * Check for all capablities with a system wide scope.
+ * This is run only once after all the boot CPUs are
+ * brought online.
+ */
+static void update_system_capabilities(void)
 {
-	update_cpu_capabilities(arm64_errata,
-				ARM64_CPUCAP_TYPE_ALL,
-				"enabling workaround for");
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
 }
 
-static void __init enable_errata_workarounds(void)
+static void enable_cpu_capabilities(u16 type)
 {
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_TYPE_ALL);
+	__enable_cpu_capabilities(arm64_errata, type);
+	__enable_cpu_capabilities(arm64_features, type);
 }
 
 /*
@@ -1360,8 +1369,8 @@ static void __init enable_errata_workarounds(void)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features();
+	if (!verify_local_cpu_caps(ARM64_CPUCAP_TYPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1389,16 +1398,20 @@ void check_local_cpu_capabilities(void)
 	 * advertised capabilities.
 	 */
 	if (!sys_caps_initialised)
-		update_cpu_errata_workarounds();
+		update_cpu_local_capabilities();
 	else
 		verify_local_cpu_capabilities();
 }
 
-static void __init setup_feature_capabilities(void)
+static void __init setup_system_capabilities(void)
 {
-	update_cpu_capabilities(arm64_features,
-				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
+	/*
+	 * We have finalised the system wide safe feature registers,
+	 * finalise the capabilities that depend on it.
+	 */
+	update_system_capabilities();
+	/* Enable all the available capabilities */
+	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
 	u32 cwg;
 	int cls;
 
-	/* Set the CPU feature capabilies */
-	setup_feature_capabilities();
-	enable_errata_workarounds();
+	setup_system_capabilities();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.13.6

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

So far we have had separate routes for triggering errata and feature
capabilities. Also, we never allowed "features" based on local CPU
and "errata" based on System wide safe registers. This patch
groups the handling of errata and features and also allows them
to have all the possible scopes.

So, we now run through the arm64_features and arm64_errata:

 1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
    via update_cpu_local_capabilities().
 2) with SCOPE_SYSTEM filter only once after all boot time enabled
    CPUs are active.

We could ideally merge the two tables into one. But leave it as
it is for easy access to the list of particular type.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 77 ++++++++++++++++++++++++------------------
 1 file changed, 44 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 198c5daddd65..7ae5cf9092d0 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,7 +504,7 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
 }
 
 extern const struct arm64_cpu_capabilities arm64_errata[];
-static void update_cpu_errata_workarounds(void);
+static void update_cpu_local_capabilities(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -553,7 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 	 * Run the errata work around checks on the boot CPU, once we have
 	 * initialised the cpu feature infrastructure.
 	 */
-	update_cpu_errata_workarounds();
+	update_cpu_local_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1179,8 +1179,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 	return false;
 }
 
-static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
-				    u16 cap_type, const char *info)
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+				      u16 cap_type, const char *info)
 {
 	for (; caps->matches; caps++) {
 		if (!(caps->type & cap_type))
@@ -1194,6 +1194,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+static void update_cpu_capabilities(u16 type)
+{
+	__update_cpu_capabilities(arm64_features, type,
+				"detected feature:");
+	__update_cpu_capabilities(arm64_errata, type,
+				"enabling work around for");
+}
 
 static int __enable_cpu_capability(void *arg)
 {
@@ -1207,7 +1214,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
 {
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
@@ -1282,6 +1289,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+static bool verify_local_cpu_caps(u16 type)
+{
+	return __verify_local_cpu_caps(arm64_features, type) &&
+	       __verify_local_cpu_caps(arm64_errata, type);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1304,12 +1317,6 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
 		}
 }
 
-static void verify_local_cpu_features(void)
-{
-	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1328,26 +1335,28 @@ static void verify_sve_features(void)
 }
 
 /*
- * The CPU Errata work arounds are detected and applied at boot time
- * and the related information is freed soon after. If the new CPU requires
- * an errata not detected at boot, fail this CPU.
+ * Check for all capablities within the scope of local CPU.
+ * This is run on all boot time activated CPUs.
  */
-static void verify_local_cpu_errata_workarounds(void)
+static void update_cpu_local_capabilities(void)
 {
-	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
-		cpu_die_early();
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_LOCAL_CPU);
 }
 
-static void update_cpu_errata_workarounds(void)
+/*
+ * Check for all capablities with a system wide scope.
+ * This is run only once after all the boot CPUs are
+ * brought online.
+ */
+static void update_system_capabilities(void)
 {
-	update_cpu_capabilities(arm64_errata,
-				ARM64_CPUCAP_TYPE_ALL,
-				"enabling workaround for");
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
 }
 
-static void __init enable_errata_workarounds(void)
+static void enable_cpu_capabilities(u16 type)
 {
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_TYPE_ALL);
+	__enable_cpu_capabilities(arm64_errata, type);
+	__enable_cpu_capabilities(arm64_features, type);
 }
 
 /*
@@ -1360,8 +1369,8 @@ static void __init enable_errata_workarounds(void)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features();
+	if (!verify_local_cpu_caps(ARM64_CPUCAP_TYPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1389,16 +1398,20 @@ void check_local_cpu_capabilities(void)
 	 * advertised capabilities.
 	 */
 	if (!sys_caps_initialised)
-		update_cpu_errata_workarounds();
+		update_cpu_local_capabilities();
 	else
 		verify_local_cpu_capabilities();
 }
 
-static void __init setup_feature_capabilities(void)
+static void __init setup_system_capabilities(void)
 {
-	update_cpu_capabilities(arm64_features,
-				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
+	/*
+	 * We have finalised the system wide safe feature registers,
+	 * finalise the capabilities that depend on it.
+	 */
+	update_system_capabilities();
+	/* Enable all the available capabilities */
+	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
 	u32 cwg;
 	int cls;
 
-	/* Set the CPU feature capabilies */
-	setup_feature_capabilities();
-	enable_errata_workarounds();
+	setup_system_capabilities();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.13.6

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

* [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Add type for features that are detected on individual CPUs,
rather than on a system wide safe features. This behavior
is similar to that of a strict cpu erratum, where a later
CPU is not allowed to boot if the system doesn't posses it.

Use this for software prefetching capability.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 7 +++++++
 arch/arm64/kernel/cpufeature.c      | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a621d2184227..4c3d6987acfc 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -118,6 +118,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 #define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
 	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
+/*
+ * CPU feature detected at boot time based on feature of one or more CPUs.
+ * It is not safe for a late CPU to have this feature, when the system doesn't
+ * have it. But it is safe to miss the feature if the system has it.
+ */
+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 7ae5cf9092d0..111f6c4b4cd7 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -951,7 +951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
-- 
2.13.6

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

* [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

Add type for features that are detected on individual CPUs,
rather than on a system wide safe features. This behavior
is similar to that of a strict cpu erratum, where a later
CPU is not allowed to boot if the system doesn't posses it.

Use this for software prefetching capability.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 7 +++++++
 arch/arm64/kernel/cpufeature.c      | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a621d2184227..4c3d6987acfc 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -118,6 +118,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 #define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
 	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
+/*
+ * CPU feature detected at boot time based on feature of one or more CPUs.
+ * It is not safe for a late CPU to have this feature, when the system doesn't
+ * have it. But it is safe to miss the feature if the system has it.
+ */
+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 7ae5cf9092d0..111f6c4b4cd7 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -951,7 +951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
-- 
2.13.6

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

* [PATCH 10/16] arm64: Make KPTI strict CPU local feature
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

KPTI capability is a security feature which should be enabled
when at least one CPU on the system needs it. Any late CPU
which needs the kernel support, should be prevented from
booting (and thus making the system unsecure) if the feature
was not already enabled.

Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 111f6c4b4cd7..2627a836e99d 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -862,9 +862,8 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
 static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
 
 static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
-				int __unused)
+				int scope)
 {
-	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
 
 	/* Forced on command line? */
 	if (__kpti_forced) {
@@ -878,8 +877,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 		return true;
 
 	/* Defer to CPU feature registers */
-	return !cpuid_feature_extract_unsigned_field(pfr0,
-						     ID_AA64PFR0_CSV3_SHIFT);
+	return !has_cpuid_feature(entry, scope);
 }
 
 static int __init parse_kpti(char *str)
@@ -1003,7 +1001,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
+		.sys_reg = SYS_ID_AA64PFR0_EL1,
+		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
+		.min_field_value = 1,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
-- 
2.13.6

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

* [PATCH 10/16] arm64: Make KPTI strict CPU local feature
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

KPTI capability is a security feature which should be enabled
when at least one CPU on the system needs it. Any late CPU
which needs the kernel support, should be prevented from
booting (and thus making the system unsecure) if the feature
was not already enabled.

Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 111f6c4b4cd7..2627a836e99d 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -862,9 +862,8 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
 static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
 
 static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
-				int __unused)
+				int scope)
 {
-	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
 
 	/* Forced on command line? */
 	if (__kpti_forced) {
@@ -878,8 +877,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 		return true;
 
 	/* Defer to CPU feature registers */
-	return !cpuid_feature_extract_unsigned_field(pfr0,
-						     ID_AA64PFR0_CSV3_SHIFT);
+	return !has_cpuid_feature(entry, scope);
 }
 
 static int __init parse_kpti(char *str)
@@ -1003,7 +1001,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
+		.sys_reg = SYS_ID_AA64PFR0_EL1,
+		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
+		.min_field_value = 1,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
-- 
2.13.6

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

* [PATCH 11/16] arm64: errata: Clean up midr range helpers
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

We are about to introduce generic MIDR range helpers. Clean
up the existing helpers in errat handling, preparing them
to use generic version.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpu_errata.c | 76 +++++++++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 35 deletions(-)

diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 550ac8a0854b..054b17009f41 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -179,14 +179,23 @@ static int qcom_enable_link_stack_sanitization(
 }
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
-#define MIDR_RANGE(model, min, max) \
+#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
-	.midr_range_min = min, \
-	.midr_range_max = max
+	.midr_range_min = MIDR_CPU_VAR_REV(v_min, r_min), \
+	.midr_range_max = MIDR_CPU_VAR_REV(v_max, r_max)
 
-#define MIDR_ALL_VERSIONS(model) \
+/* Errata affecting a range of revisions of  given model variant */
+#define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
+	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
+
+/* Errata affecting a single variant/revision of a model */
+#define ERRATA_MIDR(model, var, rev)	\
+	ERRATA_MIDR_RANGE(model, var, rev, var, rev)
+
+/* Errata affecting all variants/revisions of a given a model */
+#define ERRATA_MIDR_ALL_VERSIONS(model) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
@@ -201,7 +210,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A53 r0p[012] */
 		.desc = "ARM errata 826319, 827319, 824069",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
-		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
+		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0x0, 0x0, 0x2),
 		.enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -210,7 +219,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A53 r0p[01] */
 		.desc = "ARM errata 819472",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
-		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
+		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0x0, 0x0, 0x01),
 		.enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -219,9 +228,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A57 r0p0 - r1p2 */
 		.desc = "ARM erratum 832075",
 		.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
-		MIDR_RANGE(MIDR_CORTEX_A57,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(1, 2)),
+		ERRATA_MIDR_RANGE(MIDR_CORTEX_A57,
+				  0, 0,
+				  1, 2),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_834220
@@ -229,9 +238,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A57 r0p0 - r1p2 */
 		.desc = "ARM erratum 834220",
 		.capability = ARM64_WORKAROUND_834220,
-		MIDR_RANGE(MIDR_CORTEX_A57,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(1, 2)),
+		ERRATA_MIDR_RANGE(MIDR_CORTEX_A57,
+				  0, 0,
+				  1, 2),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -239,7 +248,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A53 r0p[01234] */
 		.desc = "ARM erratum 845719",
 		.capability = ARM64_WORKAROUND_845719,
-		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
+		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0x0, 0x0, 0x4),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_23154
@@ -247,7 +256,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, pass 1.x */
 		.desc = "Cavium erratum 23154",
 		.capability = ARM64_WORKAROUND_CAVIUM_23154,
-		MIDR_RANGE(MIDR_THUNDERX, 0x00, 0x01),
+		ERRATA_MIDR_REV_RANGE(MIDR_THUNDERX, 0x0, 0x0, 0x01),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_27456
@@ -255,15 +264,15 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, T88 pass 1.x - 2.1 */
 		.desc = "Cavium erratum 27456",
 		.capability = ARM64_WORKAROUND_CAVIUM_27456,
-		MIDR_RANGE(MIDR_THUNDERX,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(1, 1)),
+		ERRATA_MIDR_RANGE(MIDR_THUNDERX,
+				  0, 0,
+				  1, 1),
 	},
 	{
 	/* Cavium ThunderX, T81 pass 1.0 */
 		.desc = "Cavium erratum 27456",
 		.capability = ARM64_WORKAROUND_CAVIUM_27456,
-		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
+		ERRATA_MIDR(MIDR_THUNDERX_81XX, 0x0, 0x0),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_30115
@@ -271,20 +280,21 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, T88 pass 1.x - 2.2 */
 		.desc = "Cavium erratum 30115",
 		.capability = ARM64_WORKAROUND_CAVIUM_30115,
-		MIDR_RANGE(MIDR_THUNDERX, 0x00,
-			   (1 << MIDR_VARIANT_SHIFT) | 2),
+		ERRATA_MIDR_RANGE(MIDR_THUNDERX,
+				      0x0, 0x0,
+				      0x1, 0x2),
 	},
 	{
 	/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
 		.desc = "Cavium erratum 30115",
 		.capability = ARM64_WORKAROUND_CAVIUM_30115,
-		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
+		ERRATA_MIDR_REV_RANGE(MIDR_THUNDERX_81XX, 0x0, 0x0, 0x02),
 	},
 	{
 	/* Cavium ThunderX, T83 pass 1.0 */
 		.desc = "Cavium erratum 30115",
 		.capability = ARM64_WORKAROUND_CAVIUM_30115,
-		MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
+		ERRATA_MIDR(MIDR_THUNDERX_83XX, 0x0, 0x0),
 	},
 #endif
 	{
@@ -298,9 +308,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Falkor erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
-		MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(0, 0)),
+		ERRATA_MIDR(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
@@ -314,9 +322,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Falkor erratum 1009",
 		.capability = ARM64_WORKAROUND_REPEAT_TLBI,
-		MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(0, 0)),
+		ERRATA_MIDR(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
@@ -324,38 +330,38 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A73 all versions */
 		.desc = "ARM erratum 858921",
 		.capability = ARM64_WORKAROUND_858921,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
 	},
 #endif
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 		.enable = qcom_enable_link_stack_sanitization,
 	},
 	{
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
-		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 	},
 #endif
 	{
-- 
2.13.6

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

* [PATCH 11/16] arm64: errata: Clean up midr range helpers
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

We are about to introduce generic MIDR range helpers. Clean
up the existing helpers in errat handling, preparing them
to use generic version.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpu_errata.c | 76 +++++++++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 35 deletions(-)

diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 550ac8a0854b..054b17009f41 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -179,14 +179,23 @@ static int qcom_enable_link_stack_sanitization(
 }
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
-#define MIDR_RANGE(model, min, max) \
+#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
-	.midr_range_min = min, \
-	.midr_range_max = max
+	.midr_range_min = MIDR_CPU_VAR_REV(v_min, r_min), \
+	.midr_range_max = MIDR_CPU_VAR_REV(v_max, r_max)
 
-#define MIDR_ALL_VERSIONS(model) \
+/* Errata affecting a range of revisions of  given model variant */
+#define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
+	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
+
+/* Errata affecting a single variant/revision of a model */
+#define ERRATA_MIDR(model, var, rev)	\
+	ERRATA_MIDR_RANGE(model, var, rev, var, rev)
+
+/* Errata affecting all variants/revisions of a given a model */
+#define ERRATA_MIDR_ALL_VERSIONS(model) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
@@ -201,7 +210,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A53 r0p[012] */
 		.desc = "ARM errata 826319, 827319, 824069",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
-		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
+		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0x0, 0x0, 0x2),
 		.enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -210,7 +219,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A53 r0p[01] */
 		.desc = "ARM errata 819472",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
-		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
+		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0x0, 0x0, 0x01),
 		.enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -219,9 +228,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A57 r0p0 - r1p2 */
 		.desc = "ARM erratum 832075",
 		.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
-		MIDR_RANGE(MIDR_CORTEX_A57,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(1, 2)),
+		ERRATA_MIDR_RANGE(MIDR_CORTEX_A57,
+				  0, 0,
+				  1, 2),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_834220
@@ -229,9 +238,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A57 r0p0 - r1p2 */
 		.desc = "ARM erratum 834220",
 		.capability = ARM64_WORKAROUND_834220,
-		MIDR_RANGE(MIDR_CORTEX_A57,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(1, 2)),
+		ERRATA_MIDR_RANGE(MIDR_CORTEX_A57,
+				  0, 0,
+				  1, 2),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -239,7 +248,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A53 r0p[01234] */
 		.desc = "ARM erratum 845719",
 		.capability = ARM64_WORKAROUND_845719,
-		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
+		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0x0, 0x0, 0x4),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_23154
@@ -247,7 +256,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, pass 1.x */
 		.desc = "Cavium erratum 23154",
 		.capability = ARM64_WORKAROUND_CAVIUM_23154,
-		MIDR_RANGE(MIDR_THUNDERX, 0x00, 0x01),
+		ERRATA_MIDR_REV_RANGE(MIDR_THUNDERX, 0x0, 0x0, 0x01),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_27456
@@ -255,15 +264,15 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, T88 pass 1.x - 2.1 */
 		.desc = "Cavium erratum 27456",
 		.capability = ARM64_WORKAROUND_CAVIUM_27456,
-		MIDR_RANGE(MIDR_THUNDERX,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(1, 1)),
+		ERRATA_MIDR_RANGE(MIDR_THUNDERX,
+				  0, 0,
+				  1, 1),
 	},
 	{
 	/* Cavium ThunderX, T81 pass 1.0 */
 		.desc = "Cavium erratum 27456",
 		.capability = ARM64_WORKAROUND_CAVIUM_27456,
-		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
+		ERRATA_MIDR(MIDR_THUNDERX_81XX, 0x0, 0x0),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_30115
@@ -271,20 +280,21 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, T88 pass 1.x - 2.2 */
 		.desc = "Cavium erratum 30115",
 		.capability = ARM64_WORKAROUND_CAVIUM_30115,
-		MIDR_RANGE(MIDR_THUNDERX, 0x00,
-			   (1 << MIDR_VARIANT_SHIFT) | 2),
+		ERRATA_MIDR_RANGE(MIDR_THUNDERX,
+				      0x0, 0x0,
+				      0x1, 0x2),
 	},
 	{
 	/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
 		.desc = "Cavium erratum 30115",
 		.capability = ARM64_WORKAROUND_CAVIUM_30115,
-		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
+		ERRATA_MIDR_REV_RANGE(MIDR_THUNDERX_81XX, 0x0, 0x0, 0x02),
 	},
 	{
 	/* Cavium ThunderX, T83 pass 1.0 */
 		.desc = "Cavium erratum 30115",
 		.capability = ARM64_WORKAROUND_CAVIUM_30115,
-		MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
+		ERRATA_MIDR(MIDR_THUNDERX_83XX, 0x0, 0x0),
 	},
 #endif
 	{
@@ -298,9 +308,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Falkor erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
-		MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(0, 0)),
+		ERRATA_MIDR(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
@@ -314,9 +322,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Falkor erratum 1009",
 		.capability = ARM64_WORKAROUND_REPEAT_TLBI,
-		MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
-			   MIDR_CPU_VAR_REV(0, 0),
-			   MIDR_CPU_VAR_REV(0, 0)),
+		ERRATA_MIDR(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
@@ -324,38 +330,38 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A73 all versions */
 		.desc = "ARM erratum 858921",
 		.capability = ARM64_WORKAROUND_858921,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
 	},
 #endif
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 		.enable = qcom_enable_link_stack_sanitization,
 	},
 	{
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
-		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 	},
 #endif
 	{
-- 
2.13.6

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

* [PATCH 12/16] arm64: Add helpers for checking CPU MIDR against a range
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Add helpers for checking if the given CPU midr falls in a range
of variants/revisions for a given model.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 ++-----
 arch/arm64/include/asm/cputype.h    | 38 +++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/cpu_errata.c      | 16 +++++-----------
 3 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 4c3d6987acfc..a3d54c2c411f 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -10,6 +10,7 @@
 #define __ASM_CPUFEATURE_H
 
 #include <asm/cpucaps.h>
+#include <asm/cputype.h>
 #include <asm/fpsimd.h>
 #include <asm/hwcap.h>
 #include <asm/sigcontext.h>
@@ -134,11 +135,7 @@ struct arm64_cpu_capabilities {
 	/* Called on all active CPUs for all  "available" capabilities */
 	int (*enable)(const struct arm64_cpu_capabilities *caps);
 	union {
-		struct {	/* To be used for erratum handling only */
-			u32 midr_model;
-			u32 midr_range_min, midr_range_max;
-		};
-
+		struct midr_range midr_range;	/* To be used for erratum handling only */
 		struct {	/* Feature register checking */
 			u32 sys_reg;
 			u8 field_pos;
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 2f8d39ed9c2e..26bc5b302060 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -116,6 +116,44 @@
 #define read_cpuid(reg)			read_sysreg_s(SYS_ ## reg)
 
 /*
+ * Represent a range of MIDR values for a given CPU model and a
+ * range of variant/revision values.
+ *
+ * @model	- CPU model as defined by MIDR_CPU_MODEL
+ * @rv_min	- Minimum value for the revision/variant as defined by
+ *		  MIDR_CPU_VAR_REV
+ * @rv_max	- Maximum value for the variant/revision for the range.
+ */
+struct midr_range {
+	u32 model;
+	u32 rv_min;
+	u32 rv_max;
+};
+
+#define MIDR_RANGE(m, v_min, r_min, v_max, r_max)		\
+	{							\
+		.model = m,					\
+		.rv_min = MIDR_CPU_VAR_REV(v_min, r_min),	\
+		.rv_max = MIDR_CPU_VAR_REV(v_max, r_max),	\
+	}
+
+#define MIDR_ALL_VERSIONS(m) MIDR_RANGE(m, 0, 0, 0xf, 0xf)
+
+static inline bool is_midr_in_range(u32 midr, struct midr_range const *range)
+{
+	return MIDR_IS_CPU_MODEL_RANGE(midr, range->model,
+				 range->rv_min, range->rv_max);
+}
+
+static inline bool is_midr_in_range_list(u32 midr, struct midr_range const *ranges)
+{
+	while (ranges->model)
+		if (is_midr_in_range(midr, ranges++))
+			return true;
+	return false;
+}
+
+/*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
  * rather than directly reading processor_id or read_cpuid() directly.
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 054b17009f41..10eb7fa0d0d7 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -25,9 +25,7 @@ static bool __maybe_unused
 is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 {
 	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
-	return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model,
-				       entry->midr_range_min,
-				       entry->midr_range_max);
+	return is_midr_in_range(read_cpuid_id(), &entry->midr_range);
 }
 
 static bool __maybe_unused
@@ -41,7 +39,7 @@ is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
 	model &= MIDR_IMPLEMENTOR_MASK | (0xf00 << MIDR_PARTNUM_SHIFT) |
 		 MIDR_ARCHITECTURE_MASK;
 
-	return model == entry->midr_model;
+	return model == entry->midr_range.model;
 }
 
 static bool
@@ -182,9 +180,7 @@ static int qcom_enable_link_stack_sanitization(
 #define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = MIDR_CPU_VAR_REV(v_min, r_min), \
-	.midr_range_max = MIDR_CPU_VAR_REV(v_max, r_max)
+	.midr_range =  MIDR_RANGE(model, v_min, r_min, v_max, r_max)
 
 /* Errata affecting a range of revisions of  given model variant */
 #define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
@@ -198,9 +194,7 @@ static int qcom_enable_link_stack_sanitization(
 #define ERRATA_MIDR_ALL_VERSIONS(model) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = 0, \
-	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
+	.midr_range = MIDR_ALL_VERSIONS(model)
 
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
@@ -314,7 +308,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
 		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM,
-		.midr_model = MIDR_QCOM_KRYO,
+		.midr_range.model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
 #endif
-- 
2.13.6

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

* [PATCH 12/16] arm64: Add helpers for checking CPU MIDR against a range
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

Add helpers for checking if the given CPU midr falls in a range
of variants/revisions for a given model.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 ++-----
 arch/arm64/include/asm/cputype.h    | 38 +++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/cpu_errata.c      | 16 +++++-----------
 3 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 4c3d6987acfc..a3d54c2c411f 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -10,6 +10,7 @@
 #define __ASM_CPUFEATURE_H
 
 #include <asm/cpucaps.h>
+#include <asm/cputype.h>
 #include <asm/fpsimd.h>
 #include <asm/hwcap.h>
 #include <asm/sigcontext.h>
@@ -134,11 +135,7 @@ struct arm64_cpu_capabilities {
 	/* Called on all active CPUs for all  "available" capabilities */
 	int (*enable)(const struct arm64_cpu_capabilities *caps);
 	union {
-		struct {	/* To be used for erratum handling only */
-			u32 midr_model;
-			u32 midr_range_min, midr_range_max;
-		};
-
+		struct midr_range midr_range;	/* To be used for erratum handling only */
 		struct {	/* Feature register checking */
 			u32 sys_reg;
 			u8 field_pos;
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 2f8d39ed9c2e..26bc5b302060 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -116,6 +116,44 @@
 #define read_cpuid(reg)			read_sysreg_s(SYS_ ## reg)
 
 /*
+ * Represent a range of MIDR values for a given CPU model and a
+ * range of variant/revision values.
+ *
+ * @model	- CPU model as defined by MIDR_CPU_MODEL
+ * @rv_min	- Minimum value for the revision/variant as defined by
+ *		  MIDR_CPU_VAR_REV
+ * @rv_max	- Maximum value for the variant/revision for the range.
+ */
+struct midr_range {
+	u32 model;
+	u32 rv_min;
+	u32 rv_max;
+};
+
+#define MIDR_RANGE(m, v_min, r_min, v_max, r_max)		\
+	{							\
+		.model = m,					\
+		.rv_min = MIDR_CPU_VAR_REV(v_min, r_min),	\
+		.rv_max = MIDR_CPU_VAR_REV(v_max, r_max),	\
+	}
+
+#define MIDR_ALL_VERSIONS(m) MIDR_RANGE(m, 0, 0, 0xf, 0xf)
+
+static inline bool is_midr_in_range(u32 midr, struct midr_range const *range)
+{
+	return MIDR_IS_CPU_MODEL_RANGE(midr, range->model,
+				 range->rv_min, range->rv_max);
+}
+
+static inline bool is_midr_in_range_list(u32 midr, struct midr_range const *ranges)
+{
+	while (ranges->model)
+		if (is_midr_in_range(midr, ranges++))
+			return true;
+	return false;
+}
+
+/*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
  * rather than directly reading processor_id or read_cpuid() directly.
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 054b17009f41..10eb7fa0d0d7 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -25,9 +25,7 @@ static bool __maybe_unused
 is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 {
 	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
-	return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model,
-				       entry->midr_range_min,
-				       entry->midr_range_max);
+	return is_midr_in_range(read_cpuid_id(), &entry->midr_range);
 }
 
 static bool __maybe_unused
@@ -41,7 +39,7 @@ is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
 	model &= MIDR_IMPLEMENTOR_MASK | (0xf00 << MIDR_PARTNUM_SHIFT) |
 		 MIDR_ARCHITECTURE_MASK;
 
-	return model == entry->midr_model;
+	return model == entry->midr_range.model;
 }
 
 static bool
@@ -182,9 +180,7 @@ static int qcom_enable_link_stack_sanitization(
 #define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = MIDR_CPU_VAR_REV(v_min, r_min), \
-	.midr_range_max = MIDR_CPU_VAR_REV(v_max, r_max)
+	.midr_range =  MIDR_RANGE(model, v_min, r_min, v_max, r_max)
 
 /* Errata affecting a range of revisions of  given model variant */
 #define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
@@ -198,9 +194,7 @@ static int qcom_enable_link_stack_sanitization(
 #define ERRATA_MIDR_ALL_VERSIONS(model) \
 	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
 	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = 0, \
-	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
+	.midr_range = MIDR_ALL_VERSIONS(model)
 
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
@@ -314,7 +308,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
 		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM,
-		.midr_model = MIDR_QCOM_KRYO,
+		.midr_range.model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
 #endif
-- 
2.13.6

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Add helpers for detecting an errata on list of midr ranges
of affected CPUs.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
 2 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a3d54c2c411f..70712de687c7 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -136,6 +136,7 @@ struct arm64_cpu_capabilities {
 	int (*enable)(const struct arm64_cpu_capabilities *caps);
 	union {
 		struct midr_range midr_range;	/* To be used for erratum handling only */
+		const struct midr_range *midr_range_list;
 		struct {	/* Feature register checking */
 			u32 sys_reg;
 			u8 field_pos;
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 10eb7fa0d0d7..8472d156c225 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -29,6 +29,13 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 }
 
 static bool __maybe_unused
+is_affected_midr_range_list(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+	return is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list);
+}
+
+static bool __maybe_unused
 is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
 {
 	u32 model;
@@ -196,6 +203,22 @@ static int qcom_enable_link_stack_sanitization(
 	.matches = is_affected_midr_range, \
 	.midr_range = MIDR_ALL_VERSIONS(model)
 
+/* Errata affecting a list of midr ranges, with same work around */
+#define ERRATA_MIDR_RANGE_LIST(midr_list) \
+	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
+	.matches = is_affected_midr_range_list, \
+	.midr_range_list = midr_list
+
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+static const struct midr_range cortex_bp_harden_cpus[] = {
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+	{},
+};
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
 	defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
-		.enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-		.enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-		.enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
-- 
2.13.6

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

Add helpers for detecting an errata on list of midr ranges
of affected CPUs.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
 2 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a3d54c2c411f..70712de687c7 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -136,6 +136,7 @@ struct arm64_cpu_capabilities {
 	int (*enable)(const struct arm64_cpu_capabilities *caps);
 	union {
 		struct midr_range midr_range;	/* To be used for erratum handling only */
+		const struct midr_range *midr_range_list;
 		struct {	/* Feature register checking */
 			u32 sys_reg;
 			u8 field_pos;
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 10eb7fa0d0d7..8472d156c225 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -29,6 +29,13 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 }
 
 static bool __maybe_unused
+is_affected_midr_range_list(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+	return is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list);
+}
+
+static bool __maybe_unused
 is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
 {
 	u32 model;
@@ -196,6 +203,22 @@ static int qcom_enable_link_stack_sanitization(
 	.matches = is_affected_midr_range, \
 	.midr_range = MIDR_ALL_VERSIONS(model)
 
+/* Errata affecting a list of midr ranges, with same work around */
+#define ERRATA_MIDR_RANGE_LIST(midr_list) \
+	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
+	.matches = is_affected_midr_range_list, \
+	.midr_range_list = midr_list
+
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+static const struct midr_range cortex_bp_harden_cpus[] = {
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+	{},
+};
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
 	defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
-		.enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-		.enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-		.enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
 		.enable = enable_psci_bp_hardening,
 	},
 	{
-- 
2.13.6

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

* [PATCH 14/16] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Update the MIDR encodings for the Cortex-A55 and Cortex-A35

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cputype.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 26bc5b302060..308507e99430 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -83,6 +83,8 @@
 #define ARM_CPU_PART_CORTEX_A53		0xD03
 #define ARM_CPU_PART_CORTEX_A73		0xD09
 #define ARM_CPU_PART_CORTEX_A75		0xD0A
+#define ARM_CPU_PART_CORTEX_A35		0xD04
+#define ARM_CPU_PART_CORTEX_A55		0xD05
 
 #define APM_CPU_PART_POTENZA		0x000
 
@@ -101,6 +103,8 @@
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
 #define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75)
+#define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35)
+#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
-- 
2.13.6

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

* [PATCH 14/16] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

Update the MIDR encodings for the Cortex-A55 and Cortex-A35

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cputype.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 26bc5b302060..308507e99430 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -83,6 +83,8 @@
 #define ARM_CPU_PART_CORTEX_A53		0xD03
 #define ARM_CPU_PART_CORTEX_A73		0xD09
 #define ARM_CPU_PART_CORTEX_A75		0xD0A
+#define ARM_CPU_PART_CORTEX_A35		0xD04
+#define ARM_CPU_PART_CORTEX_A55		0xD05
 
 #define APM_CPU_PART_POTENZA		0x000
 
@@ -101,6 +103,8 @@
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
 #define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75)
+#define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35)
+#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
-- 
2.13.6

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

* [PATCH 15/16] arm64: Delay enabling hardware DBM feature
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

We enable hardware DBM bit in a capable CPU, very early in the
boot via __cpu_setup. This doesn't give us a flexibility of
optionally disable the feature, as the clearing the bit
is a bit costly as the TLB can cache the settings. Instead,
we delay enabling the feature until the CPU is brought up
into the kernel. We use the feature capability mechanism
to handle it.

The hardware DBM is a non-conflicting feature. i.e, the kernel
can safely run with a mix of CPUs with some using the feature
and the others don't. So, it is safe for a late CPU to have
this capability and enable it, even if the active CPUs don't.

To get this handled properly by the infrastructure, we
unconditionally set the capability and only enable it
on CPUs which really have the feature. Adds a new type
of feature to the capability infrastructure which
ignores the conflict in a late CPU.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpucaps.h    |  3 ++-
 arch/arm64/include/asm/cpufeature.h |  8 +++++++
 arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/proc.S                |  5 +----
 4 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index bb263820de13..8df80cc828ac 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -45,7 +45,8 @@
 #define ARM64_HARDEN_BRANCH_PREDICTOR		24
 #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
 #define ARM64_HAS_RAS_EXTN			26
+#define ARM64_HW_DBM				27
 
-#define ARM64_NCAPS				27
+#define ARM64_NCAPS				28
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 70712de687c7..243ec7c77c79 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
+/*
+ * CPU feature detected on each local CPU. It is safe for a late CPU to
+ * either have it or not.
+ */
+#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 2627a836e99d..8af755b8219d 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
 __setup("kpti=", parse_kpti);
 #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
+#ifdef CONFIG_ARM64_HW_AFDBM
+static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	/*
+	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
+	 * a mix of CPUs with and without the feature. So, we unconditionally
+	 * enable the capability to allow any late CPU to use the feature.
+	 * We only enable the control bits on the CPU, if it actually supports.
+	 */
+	return true;
+}
+
+static inline void __cpu_enable_hw_dbm(void)
+{
+	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
+
+	write_sysreg(tcr, tcr_el1);
+	isb();
+}
+
+static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
+{
+	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
+		__cpu_enable_hw_dbm();
+
+	return 0;
+}
+#endif
+
 static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
@@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.enable = cpu_clear_disr,
 	},
 #endif /* CONFIG_ARM64_RAS_EXTN */
+#ifdef CONFIG_ARM64_HW_AFDBM
+	{
+		.desc = "Hardware pagetable Dirty Bit Management",
+		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
+		.capability = ARM64_HW_DBM,
+		.sys_reg = SYS_ID_AA64MMFR1_EL1,
+		.sign = FTR_UNSIGNED,
+		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
+		.min_field_value = 2,
+		.matches = has_hw_dbm,
+		.enable = cpu_enable_hw_dbm,
+	},
+#endif
 	{},
 };
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index c6a12073ef46..73897dd2e555 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -254,10 +254,7 @@ ENTRY(__cpu_setup)
 	mrs	x9, ID_AA64MMFR1_EL1
 	and	x9, x9, #0xf
 	cbz	x9, 2f
-	cmp	x9, #2
-	b.lt	1f
-	orr	x10, x10, #TCR_HD		// hardware Dirty flag update
-1:	orr	x10, x10, #TCR_HA		// hardware Access flag update
+	orr	x10, x10, #TCR_HA		// hardware Access flag update
 2:
 #endif	/* CONFIG_ARM64_HW_AFDBM */
 	msr	tcr_el1, x10
-- 
2.13.6

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

* [PATCH 15/16] arm64: Delay enabling hardware DBM feature
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

We enable hardware DBM bit in a capable CPU, very early in the
boot via __cpu_setup. This doesn't give us a flexibility of
optionally disable the feature, as the clearing the bit
is a bit costly as the TLB can cache the settings. Instead,
we delay enabling the feature until the CPU is brought up
into the kernel. We use the feature capability mechanism
to handle it.

The hardware DBM is a non-conflicting feature. i.e, the kernel
can safely run with a mix of CPUs with some using the feature
and the others don't. So, it is safe for a late CPU to have
this capability and enable it, even if the active CPUs don't.

To get this handled properly by the infrastructure, we
unconditionally set the capability and only enable it
on CPUs which really have the feature. Adds a new type
of feature to the capability infrastructure which
ignores the conflict in a late CPU.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpucaps.h    |  3 ++-
 arch/arm64/include/asm/cpufeature.h |  8 +++++++
 arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/proc.S                |  5 +----
 4 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index bb263820de13..8df80cc828ac 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -45,7 +45,8 @@
 #define ARM64_HARDEN_BRANCH_PREDICTOR		24
 #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
 #define ARM64_HAS_RAS_EXTN			26
+#define ARM64_HW_DBM				27
 
-#define ARM64_NCAPS				27
+#define ARM64_NCAPS				28
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 70712de687c7..243ec7c77c79 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
+/*
+ * CPU feature detected on each local CPU. It is safe for a late CPU to
+ * either have it or not.
+ */
+#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 2627a836e99d..8af755b8219d 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
 __setup("kpti=", parse_kpti);
 #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
+#ifdef CONFIG_ARM64_HW_AFDBM
+static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	/*
+	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
+	 * a mix of CPUs with and without the feature. So, we unconditionally
+	 * enable the capability to allow any late CPU to use the feature.
+	 * We only enable the control bits on the CPU, if it actually supports.
+	 */
+	return true;
+}
+
+static inline void __cpu_enable_hw_dbm(void)
+{
+	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
+
+	write_sysreg(tcr, tcr_el1);
+	isb();
+}
+
+static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
+{
+	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
+		__cpu_enable_hw_dbm();
+
+	return 0;
+}
+#endif
+
 static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
@@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.enable = cpu_clear_disr,
 	},
 #endif /* CONFIG_ARM64_RAS_EXTN */
+#ifdef CONFIG_ARM64_HW_AFDBM
+	{
+		.desc = "Hardware pagetable Dirty Bit Management",
+		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
+		.capability = ARM64_HW_DBM,
+		.sys_reg = SYS_ID_AA64MMFR1_EL1,
+		.sign = FTR_UNSIGNED,
+		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
+		.min_field_value = 2,
+		.matches = has_hw_dbm,
+		.enable = cpu_enable_hw_dbm,
+	},
+#endif
 	{},
 };
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index c6a12073ef46..73897dd2e555 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -254,10 +254,7 @@ ENTRY(__cpu_setup)
 	mrs	x9, ID_AA64MMFR1_EL1
 	and	x9, x9, #0xf
 	cbz	x9, 2f
-	cmp	x9, #2
-	b.lt	1f
-	orr	x10, x10, #TCR_HD		// hardware Dirty flag update
-1:	orr	x10, x10, #TCR_HA		// hardware Access flag update
+	orr	x10, x10, #TCR_HA		// hardware Access flag update
 2:
 #endif	/* CONFIG_ARM64_HW_AFDBM */
 	msr	tcr_el1, x10
-- 
2.13.6

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

* [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
  2018-01-23 12:27 ` Suzuki K Poulose
@ 2018-01-23 12:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, jnair, Suzuki K Poulose

Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
from an erratum 1024718, which causes incorrect updates when DBM/AP
bits in a page table entry is modified without a break-before-make
sequence. The work around is to skip enabling the hardware DBM feature
on the affected cores. The hardware Access Flag management features
is not affected.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 Documentation/arm64/silicon-errata.txt |  1 +
 arch/arm64/Kconfig                     | 14 ++++++++++++++
 arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index b9d93e981a05..5203e71c113d 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -55,6 +55,7 @@ stable kernels.
 | ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220        |
 | ARM            | Cortex-A72      | #853709         | N/A                         |
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
+| ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
 | ARM            | MMU-500         | #841119,#826419 | N/A                         |
 |                |                 |                 |                             |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375        |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1d51c8edf34b..070efe1f7ec3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -461,6 +461,20 @@ config ARM64_ERRATUM_843419
 
 	  If unsure, say Y.
 
+config ARM64_ERRATUM_1024718
+	bool "Cortex-A55: 1024718: Update of DBM/AP bits without break before make might result in incorrect update"
+	default y
+	help
+	  This option adds work around for Arm Cortex-A55 Erratum 1024718.
+
+	  Affected Cortex-A55 cores (r0p0, r0p1, r1p0) could cause incorrect
+	  update of the hardware dirty bit when the DBM/AP bits are updated
+	  without a break-before-make. The work around is to disable the usage
+	  of hardware DBM locally on the affected cores. CPUs not affected by
+	  erratum will continue to use the feature.
+
+	  If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
 	bool "Cavium erratum 22375, 24313"
 	default y
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 8af755b8219d..64f1e911c6af 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
 	isb();
 }
 
+static bool cpu_has_erratum_1024718(void)
+{
+	static const struct midr_range __maybe_unused cpus[] = {
+		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
+		{},
+	};
+
+	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
+	       is_midr_in_range_list(read_cpuid_id(), cpus);
+}
+
 static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
 {
-	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
+	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU) &&
+	    !cpu_has_erratum_1024718())
 		__cpu_enable_hw_dbm();
 
 	return 0;
-- 
2.13.6

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

* [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
@ 2018-01-23 12:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
from an erratum 1024718, which causes incorrect updates when DBM/AP
bits in a page table entry is modified without a break-before-make
sequence. The work around is to skip enabling the hardware DBM feature
on the affected cores. The hardware Access Flag management features
is not affected.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 Documentation/arm64/silicon-errata.txt |  1 +
 arch/arm64/Kconfig                     | 14 ++++++++++++++
 arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index b9d93e981a05..5203e71c113d 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -55,6 +55,7 @@ stable kernels.
 | ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220        |
 | ARM            | Cortex-A72      | #853709         | N/A                         |
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
+| ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
 | ARM            | MMU-500         | #841119,#826419 | N/A                         |
 |                |                 |                 |                             |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375        |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1d51c8edf34b..070efe1f7ec3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -461,6 +461,20 @@ config ARM64_ERRATUM_843419
 
 	  If unsure, say Y.
 
+config ARM64_ERRATUM_1024718
+	bool "Cortex-A55: 1024718: Update of DBM/AP bits without break before make might result in incorrect update"
+	default y
+	help
+	  This option adds work around for Arm Cortex-A55 Erratum 1024718.
+
+	  Affected Cortex-A55 cores (r0p0, r0p1, r1p0) could cause incorrect
+	  update of the hardware dirty bit when the DBM/AP bits are updated
+	  without a break-before-make. The work around is to disable the usage
+	  of hardware DBM locally on the affected cores. CPUs not affected by
+	  erratum will continue to use the feature.
+
+	  If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
 	bool "Cavium erratum 22375, 24313"
 	default y
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 8af755b8219d..64f1e911c6af 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
 	isb();
 }
 
+static bool cpu_has_erratum_1024718(void)
+{
+	static const struct midr_range __maybe_unused cpus[] = {
+		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
+		{},
+	};
+
+	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
+	       is_midr_in_range_list(read_cpuid_id(), cpus);
+}
+
 static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
 {
-	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
+	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU) &&
+	    !cpu_has_erratum_1024718())
 		__cpu_enable_hw_dbm();
 
 	return 0;
-- 
2.13.6

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

* Re: [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
  2018-01-23 12:27   ` Suzuki K Poulose
@ 2018-01-23 14:52     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 14:52 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel,
	James Morse, jnair, Andre Przywara, Robin Murphy

On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
> From: Dave Martin <dave.martin@arm.com>
> 
> We issue the enable() call back for all CPU hwcaps capabilities
> available on the system, on all the CPUs. So far we have ignored
> the argument passed to the call back, which had a prototype to
> accept a "void *" for use with on_each_cpu() and later with
> stop_machine(). However, with commit 0a0d111d40fd1
> ("arm64: cpufeature: Pass capability structure to ->enable callback"),
> there are some users of the argument who wants the matching capability
> struct pointer where there are multiple matching criteria for a single
> capability. Update the prototype for enable to accept a const pointer.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Andre Przywara <andre.przywara@arm.com>
> Cc: James Morse <james.morse@arm.com>
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>
> Signed-off-by: Dave Martin <dave.martin@arm.com>
> [ Rebased to for-next/core converting more users ]
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  3 ++-
>  arch/arm64/include/asm/fpsimd.h     |  4 +++-
>  arch/arm64/include/asm/processor.h  |  7 ++++---
>  arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
>  arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
>  arch/arm64/kernel/fpsimd.c          |  3 ++-
>  arch/arm64/kernel/traps.c           |  3 ++-
>  arch/arm64/mm/fault.c               |  2 +-
>  8 files changed, 32 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc2585a..cefbd685292c 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
>  	u16 capability;
>  	int def_scope;			/* default scope */
>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
> -	int (*enable)(void *);		/* Called on all active CPUs */
> +	/* Called on all active CPUs for all  "available" capabilities */

Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
workarounds.

Maybe applicable would be a better word?

> +	int (*enable)(const struct arm64_cpu_capabilities *caps);

Alternatively, if the comment is liable to be ambiguous, maybe it would
be better to delete it.  The explicit argument type already makes this
more self-documenting than previously.

I don't feel that strongly either way though; probably not worth a
respin unless you have other things to change.

Also please note that I didn't test the original patch here (in case
I didn't point that out already...)

[...]

Cheers
---Dave

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
@ 2018-01-23 14:52     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 14:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
> From: Dave Martin <dave.martin@arm.com>
> 
> We issue the enable() call back for all CPU hwcaps capabilities
> available on the system, on all the CPUs. So far we have ignored
> the argument passed to the call back, which had a prototype to
> accept a "void *" for use with on_each_cpu() and later with
> stop_machine(). However, with commit 0a0d111d40fd1
> ("arm64: cpufeature: Pass capability structure to ->enable callback"),
> there are some users of the argument who wants the matching capability
> struct pointer where there are multiple matching criteria for a single
> capability. Update the prototype for enable to accept a const pointer.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Andre Przywara <andre.przywara@arm.com>
> Cc: James Morse <james.morse@arm.com>
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>
> Signed-off-by: Dave Martin <dave.martin@arm.com>
> [ Rebased to for-next/core converting more users ]
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  3 ++-
>  arch/arm64/include/asm/fpsimd.h     |  4 +++-
>  arch/arm64/include/asm/processor.h  |  7 ++++---
>  arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
>  arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
>  arch/arm64/kernel/fpsimd.c          |  3 ++-
>  arch/arm64/kernel/traps.c           |  3 ++-
>  arch/arm64/mm/fault.c               |  2 +-
>  8 files changed, 32 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc2585a..cefbd685292c 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
>  	u16 capability;
>  	int def_scope;			/* default scope */
>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
> -	int (*enable)(void *);		/* Called on all active CPUs */
> +	/* Called on all active CPUs for all  "available" capabilities */

Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
workarounds.

Maybe applicable would be a better word?

> +	int (*enable)(const struct arm64_cpu_capabilities *caps);

Alternatively, if the comment is liable to be ambiguous, maybe it would
be better to delete it.  The explicit argument type already makes this
more self-documenting than previously.

I don't feel that strongly either way though; probably not worth a
respin unless you have other things to change.

Also please note that I didn't test the original patch here (in case
I didn't point that out already...)

[...]

Cheers
---Dave

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

* Re: [PATCH 02/16] arm64: Move errata work around check on boot CPU
  2018-01-23 12:27   ` Suzuki K Poulose
@ 2018-01-23 14:59     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 14:59 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:27:55PM +0000, Suzuki K Poulose wrote:
> We trigger CPU errata work around check on the boot CPU from
> smp_prepare_boot_cpu() to make sure that we run the checks only
> after the CPU feature infrastructure is initialised.

On the surface of it, this sounds like a bug fix.

Should there be a Fixes tag if so?

If this reordering doesn't matter for upstream, it would be good to have
a quick explanation here as to why not.

Cheers
---Dave

> 
> We can do this from init_cpu_features() which is called only
> on the boot CPU and does the initilisation of the infrastructure.
> As we are consolidating the cpu capability handling, let us
> move this to where it should belong. No functional changes.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 6 ++++++
>  arch/arm64/kernel/smp.c        | 6 ------
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 6a8dfdc532b1..ebb467340b9c 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -545,6 +545,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
>  		sve_init_vq_map();
>  	}
> +
> +	/*
> +	 * Run the errata work around checks on the boot CPU, once we have
> +	 * initialised the cpu feature infrastructure.
> +	 */
> +	update_cpu_errata_workarounds();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 3b8ad7be9c33..5cef11450183 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -448,12 +448,6 @@ void __init smp_prepare_boot_cpu(void)
>  	jump_label_init();
>  	cpuinfo_store_boot_cpu();
>  	save_boot_cpu_run_el();
> -	/*
> -	 * Run the errata work around checks on the boot CPU, once we have
> -	 * initialised the cpu feature infrastructure from
> -	 * cpuinfo_store_boot_cpu() above.
> -	 */
> -	update_cpu_errata_workarounds();
>  }
>  
>  static u64 __init of_get_cpu_mpidr(struct device_node *dn)
> -- 
> 2.13.6
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 02/16] arm64: Move errata work around check on boot CPU
@ 2018-01-23 14:59     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:27:55PM +0000, Suzuki K Poulose wrote:
> We trigger CPU errata work around check on the boot CPU from
> smp_prepare_boot_cpu() to make sure that we run the checks only
> after the CPU feature infrastructure is initialised.

On the surface of it, this sounds like a bug fix.

Should there be a Fixes tag if so?

If this reordering doesn't matter for upstream, it would be good to have
a quick explanation here as to why not.

Cheers
---Dave

> 
> We can do this from init_cpu_features() which is called only
> on the boot CPU and does the initilisation of the infrastructure.
> As we are consolidating the cpu capability handling, let us
> move this to where it should belong. No functional changes.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 6 ++++++
>  arch/arm64/kernel/smp.c        | 6 ------
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 6a8dfdc532b1..ebb467340b9c 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -545,6 +545,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
>  		sve_init_vq_map();
>  	}
> +
> +	/*
> +	 * Run the errata work around checks on the boot CPU, once we have
> +	 * initialised the cpu feature infrastructure.
> +	 */
> +	update_cpu_errata_workarounds();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 3b8ad7be9c33..5cef11450183 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -448,12 +448,6 @@ void __init smp_prepare_boot_cpu(void)
>  	jump_label_init();
>  	cpuinfo_store_boot_cpu();
>  	save_boot_cpu_run_el();
> -	/*
> -	 * Run the errata work around checks on the boot CPU, once we have
> -	 * initialised the cpu feature infrastructure from
> -	 * cpuinfo_store_boot_cpu() above.
> -	 */
> -	update_cpu_errata_workarounds();
>  }
>  
>  static u64 __init of_get_cpu_mpidr(struct device_node *dn)
> -- 
> 2.13.6
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 02/16] arm64: Move errata work around check on boot CPU
  2018-01-23 14:59     ` Dave Martin
@ 2018-01-23 15:07       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 15:07 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 23/01/18 14:59, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:55PM +0000, Suzuki K Poulose wrote:
>> We trigger CPU errata work around check on the boot CPU from
>> smp_prepare_boot_cpu() to make sure that we run the checks only
>> after the CPU feature infrastructure is initialised.
> 
> On the surface of it, this sounds like a bug fix.

No, this is not. It is just moving the code to cpufeature.c

Earlier it was :

smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features()

and then we did update_cpu_errata_workarounds() after we have done
cpuinfo_store_boot_cpu(). With this change we do :

smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features() -> update_cpu_errata_workarounds()


> 
> Should there be a Fixes tag if so?
> 
> If this reordering doesn't matter for upstream, it would be good to have
> a quick explanation here as to why not.

Sure, will make it clearer.

Cheers
Suzuki

> 
> Cheers
> ---Dave
> 
>>
>> We can do this from init_cpu_features() which is called only
>> on the boot CPU and does the initilisation of the infrastructure.
>> As we are consolidating the cpu capability handling, let us
>> move this to where it should belong. No functional changes.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/kernel/cpufeature.c | 6 ++++++
>>   arch/arm64/kernel/smp.c        | 6 ------
>>   2 files changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 6a8dfdc532b1..ebb467340b9c 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -545,6 +545,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>>   		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
>>   		sve_init_vq_map();
>>   	}
>> +
>> +	/*
>> +	 * Run the errata work around checks on the boot CPU, once we have
>> +	 * initialised the cpu feature infrastructure.
>> +	 */
>> +	update_cpu_errata_workarounds();
>>   }
>>   
>>   static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
>> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
>> index 3b8ad7be9c33..5cef11450183 100644
>> --- a/arch/arm64/kernel/smp.c
>> +++ b/arch/arm64/kernel/smp.c
>> @@ -448,12 +448,6 @@ void __init smp_prepare_boot_cpu(void)
>>   	jump_label_init();
>>   	cpuinfo_store_boot_cpu();
>>   	save_boot_cpu_run_el();
>> -	/*
>> -	 * Run the errata work around checks on the boot CPU, once we have
>> -	 * initialised the cpu feature infrastructure from
>> -	 * cpuinfo_store_boot_cpu() above.
>> -	 */
>> -	update_cpu_errata_workarounds();
>>   }
>>   
>>   static u64 __init of_get_cpu_mpidr(struct device_node *dn)
>> -- 
>> 2.13.6
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 02/16] arm64: Move errata work around check on boot CPU
@ 2018-01-23 15:07       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 15:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 23/01/18 14:59, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:55PM +0000, Suzuki K Poulose wrote:
>> We trigger CPU errata work around check on the boot CPU from
>> smp_prepare_boot_cpu() to make sure that we run the checks only
>> after the CPU feature infrastructure is initialised.
> 
> On the surface of it, this sounds like a bug fix.

No, this is not. It is just moving the code to cpufeature.c

Earlier it was :

smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features()

and then we did update_cpu_errata_workarounds() after we have done
cpuinfo_store_boot_cpu(). With this change we do :

smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features() -> update_cpu_errata_workarounds()


> 
> Should there be a Fixes tag if so?
> 
> If this reordering doesn't matter for upstream, it would be good to have
> a quick explanation here as to why not.

Sure, will make it clearer.

Cheers
Suzuki

> 
> Cheers
> ---Dave
> 
>>
>> We can do this from init_cpu_features() which is called only
>> on the boot CPU and does the initilisation of the infrastructure.
>> As we are consolidating the cpu capability handling, let us
>> move this to where it should belong. No functional changes.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/kernel/cpufeature.c | 6 ++++++
>>   arch/arm64/kernel/smp.c        | 6 ------
>>   2 files changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 6a8dfdc532b1..ebb467340b9c 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -545,6 +545,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>>   		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
>>   		sve_init_vq_map();
>>   	}
>> +
>> +	/*
>> +	 * Run the errata work around checks on the boot CPU, once we have
>> +	 * initialised the cpu feature infrastructure.
>> +	 */
>> +	update_cpu_errata_workarounds();
>>   }
>>   
>>   static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
>> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
>> index 3b8ad7be9c33..5cef11450183 100644
>> --- a/arch/arm64/kernel/smp.c
>> +++ b/arch/arm64/kernel/smp.c
>> @@ -448,12 +448,6 @@ void __init smp_prepare_boot_cpu(void)
>>   	jump_label_init();
>>   	cpuinfo_store_boot_cpu();
>>   	save_boot_cpu_run_el();
>> -	/*
>> -	 * Run the errata work around checks on the boot CPU, once we have
>> -	 * initialised the cpu feature infrastructure from
>> -	 * cpuinfo_store_boot_cpu() above.
>> -	 */
>> -	update_cpu_errata_workarounds();
>>   }
>>   
>>   static u64 __init of_get_cpu_mpidr(struct device_node *dn)
>> -- 
>> 2.13.6
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 02/16] arm64: Move errata work around check on boot CPU
  2018-01-23 15:07       ` Suzuki K Poulose
@ 2018-01-23 15:11         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 15:11 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Tue, Jan 23, 2018 at 03:07:18PM +0000, Suzuki K Poulose wrote:
> On 23/01/18 14:59, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:55PM +0000, Suzuki K Poulose wrote:
> >>We trigger CPU errata work around check on the boot CPU from
> >>smp_prepare_boot_cpu() to make sure that we run the checks only
> >>after the CPU feature infrastructure is initialised.
> >
> >On the surface of it, this sounds like a bug fix.
> 
> No, this is not. It is just moving the code to cpufeature.c
> 
> Earlier it was :
> 
> smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features()
> 
> and then we did update_cpu_errata_workarounds() after we have done
> cpuinfo_store_boot_cpu(). With this change we do :
> 
> smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features() -> update_cpu_errata_workarounds()
> 
> 
> >
> >Should there be a Fixes tag if so?
> >
> >If this reordering doesn't matter for upstream, it would be good to have
> >a quick explanation here as to why not.
> 
> Sure, will make it clearer.

Fair enough -- thanks.

I was a bit sketchy on the exact code flow here.

[...]

Cheers
---Dave

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

* [PATCH 02/16] arm64: Move errata work around check on boot CPU
@ 2018-01-23 15:11         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 15:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 03:07:18PM +0000, Suzuki K Poulose wrote:
> On 23/01/18 14:59, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:55PM +0000, Suzuki K Poulose wrote:
> >>We trigger CPU errata work around check on the boot CPU from
> >>smp_prepare_boot_cpu() to make sure that we run the checks only
> >>after the CPU feature infrastructure is initialised.
> >
> >On the surface of it, this sounds like a bug fix.
> 
> No, this is not. It is just moving the code to cpufeature.c
> 
> Earlier it was :
> 
> smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features()
> 
> and then we did update_cpu_errata_workarounds() after we have done
> cpuinfo_store_boot_cpu(). With this change we do :
> 
> smp_prepare_boot_cpu()  -> cpuinfo_store_boot_cpu() -> init_cpu_features() -> update_cpu_errata_workarounds()
> 
> 
> >
> >Should there be a Fixes tag if so?
> >
> >If this reordering doesn't matter for upstream, it would be good to have
> >a quick explanation here as to why not.
> 
> Sure, will make it clearer.

Fair enough -- thanks.

I was a bit sketchy on the exact code flow here.

[...]

Cheers
---Dave

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

* Re: [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
  2018-01-23 14:52     ` Dave Martin
@ 2018-01-23 15:38       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 15:38 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel,
	James Morse, jnair, Andre Przywara, Robin Murphy

On 23/01/18 14:52, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
>> From: Dave Martin <dave.martin@arm.com>
>>
>> We issue the enable() call back for all CPU hwcaps capabilities
>> available on the system, on all the CPUs. So far we have ignored
>> the argument passed to the call back, which had a prototype to
>> accept a "void *" for use with on_each_cpu() and later with
>> stop_machine(). However, with commit 0a0d111d40fd1
>> ("arm64: cpufeature: Pass capability structure to ->enable callback"),
>> there are some users of the argument who wants the matching capability
>> struct pointer where there are multiple matching criteria for a single
>> capability. Update the prototype for enable to accept a const pointer.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Andre Przywara <andre.przywara@arm.com>
>> Cc: James Morse <james.morse@arm.com>
>> Reviewed-by: Julien Thierry <julien.thierry@arm.com>
>> Signed-off-by: Dave Martin <dave.martin@arm.com>
>> [ Rebased to for-next/core converting more users ]
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  3 ++-
>>   arch/arm64/include/asm/fpsimd.h     |  4 +++-
>>   arch/arm64/include/asm/processor.h  |  7 ++++---
>>   arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
>>   arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
>>   arch/arm64/kernel/fpsimd.c          |  3 ++-
>>   arch/arm64/kernel/traps.c           |  3 ++-
>>   arch/arm64/mm/fault.c               |  2 +-
>>   8 files changed, 32 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index ac67cfc2585a..cefbd685292c 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
>>   	u16 capability;
>>   	int def_scope;			/* default scope */
>>   	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>> -	int (*enable)(void *);		/* Called on all active CPUs */
>> +	/* Called on all active CPUs for all  "available" capabilities */
> 
> Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
> workarounds.
> 

Thanks for spotting, will fix it.

> Maybe applicable would be a better word?
> 

There is a subtle difference. If there are two entries for a capability,
with only one of them matches, we end up calling the enable() for both
the entries. "Applicable" could potentially be misunderstood, leading
to assumption that the enable() is called only if that "entry" matches,
which is not true. I accept that "available" doesn't sound any better either.


>> +	int (*enable)(const struct arm64_cpu_capabilities *caps);
> 
> Alternatively, if the comment is liable to be ambiguous, maybe it would
> be better to delete it.  The explicit argument type already makes this
> more self-documenting than previously.

I think we still need to make it clear that the enable is called on
all active CPUs. It is not about the argument anymore.

How about :

/*
  * Called on all active CPUs if the capability associated with
  * this entry is set.
  */


> 
> I don't feel that strongly either way though; probably not worth a
> respin unless you have other things to change.
> 
> Also please note that I didn't test the original patch here (in case
> I didn't point that out already...)

I think I did test it using the HW DBM feature (see the patch at the end).
However, will do some more testing with it. Thanks for mentioning.

Suzuki

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
@ 2018-01-23 15:38       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-23 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 23/01/18 14:52, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
>> From: Dave Martin <dave.martin@arm.com>
>>
>> We issue the enable() call back for all CPU hwcaps capabilities
>> available on the system, on all the CPUs. So far we have ignored
>> the argument passed to the call back, which had a prototype to
>> accept a "void *" for use with on_each_cpu() and later with
>> stop_machine(). However, with commit 0a0d111d40fd1
>> ("arm64: cpufeature: Pass capability structure to ->enable callback"),
>> there are some users of the argument who wants the matching capability
>> struct pointer where there are multiple matching criteria for a single
>> capability. Update the prototype for enable to accept a const pointer.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Andre Przywara <andre.przywara@arm.com>
>> Cc: James Morse <james.morse@arm.com>
>> Reviewed-by: Julien Thierry <julien.thierry@arm.com>
>> Signed-off-by: Dave Martin <dave.martin@arm.com>
>> [ Rebased to for-next/core converting more users ]
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  3 ++-
>>   arch/arm64/include/asm/fpsimd.h     |  4 +++-
>>   arch/arm64/include/asm/processor.h  |  7 ++++---
>>   arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
>>   arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
>>   arch/arm64/kernel/fpsimd.c          |  3 ++-
>>   arch/arm64/kernel/traps.c           |  3 ++-
>>   arch/arm64/mm/fault.c               |  2 +-
>>   8 files changed, 32 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index ac67cfc2585a..cefbd685292c 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
>>   	u16 capability;
>>   	int def_scope;			/* default scope */
>>   	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>> -	int (*enable)(void *);		/* Called on all active CPUs */
>> +	/* Called on all active CPUs for all  "available" capabilities */
> 
> Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
> workarounds.
> 

Thanks for spotting, will fix it.

> Maybe applicable would be a better word?
> 

There is a subtle difference. If there are two entries for a capability,
with only one of them matches, we end up calling the enable() for both
the entries. "Applicable" could potentially be misunderstood, leading
to assumption that the enable() is called only if that "entry" matches,
which is not true. I accept that "available" doesn't sound any better either.


>> +	int (*enable)(const struct arm64_cpu_capabilities *caps);
> 
> Alternatively, if the comment is liable to be ambiguous, maybe it would
> be better to delete it.  The explicit argument type already makes this
> more self-documenting than previously.

I think we still need to make it clear that the enable is called on
all active CPUs. It is not about the argument anymore.

How about :

/*
  * Called on all active CPUs if the capability associated with
  * this entry is set.
  */


> 
> I don't feel that strongly either way though; probably not worth a
> respin unless you have other things to change.
> 
> Also please note that I didn't test the original patch here (in case
> I didn't point that out already...)

I think I did test it using the HW DBM feature (see the patch at the end).
However, will do some more testing with it. Thanks for mentioning.

Suzuki

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-23 12:27   ` Suzuki K Poulose
@ 2018-01-23 17:33     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 17:33 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> to the userspace and the CPU hwcaps used by the kernel, which
> include cpu features and CPU errata work arounds.
> 
> At the moment we have the following restricions:
> 
>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>    - Detected mostly on system wide CPU feature register. But
>      there are some which really uses a local CPU's value to
>      decide the availability (e.g, availability of hardware
>      prefetch). So, we run the check only once, after all the
>      boot-time active CPUs are turned on.
>    - Any late CPU which doesn't posses all the established features
>      is killed.
>    - Any late CPU which possess a feature *not* already available
>      is allowed to boot.
> 
>  b) CPU Errata work arounds (arm64_errata)
>    - Detected mostly based on a local CPU's feature register.
>      The checks are run on each boot time activated CPUs.
>    - Any late CPU which doesn't have any of the established errata
>      work around capabilities is ignored and is allowed to boot.
>    - Any late CPU which has an errata work around not already available
>      is killed.
> 
> However there are some exceptions to the cases above.
> 
> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>    And any late CPU that has this "feature" should be killed.
> 2) Hardware DBM feature is a non-conflicting capability which could be
>    enabled on CPUs which has it without any issues, even if the CPU is
>    brought up late.
> 
> So this calls for a lot more fine grained behavior for each capability.
> And if we define all the attributes to control their behavior properly,
> we may be able to use a single table for the CPU hwcaps (not the
> ELF HWCAPs, which cover errata and features). This is a prepartory step
> to get there. We define type for a capability, which for now encodes the
> scope of the check. i.e, whether it should be checked system wide or on
> each local CPU. We define two types :
> 
>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.

I'm a bit confused by the naming here.

I'm not keen on the word "strict" because it doesn't really mean
anything unless the rule to be strictly enforced is documented, and
then doesn't really add anything: you could take the view that either
there's an (enforced) rule or there's no rule at all.

In this case, (b) seems the "relaxed" case anyway: we allow these
capabilities to be enabled/disabled differently on different CPUs,
rather than requiring the same configuration on all CPUs (KPTI).

I think there are 2 x 2 orthogonal options:

A FEATURE capability must be disabled on every CPU where the feature is
not present.  A feature capability is considered desirable, and should
be enabled when possible.

An ERRATUM capability must be enabled on every CPU where the erratum is
present.  An erratum capability is considered undesirable, and should
be disabled when possible.

(An erratum is the inverse of a feature with respect to desirability,
enablement and presence.)

and:

A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
(Thus, a decision must be taken during boot, based on desirability/
undesirability of each capability and based on the assumption that
late CPUs won't violate the decision -- unless this assumption is
overridden by a cmdline arg etc.)

A LOCAL capability may freely be enabled on some CPUs while disabled on
other CPUs.

(Thus, LOCAL is precisely the inverse of GLOBAL.)


So:

	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).

("PERCPU" could be substituted for "LOCAL" if we want to be clearer
about the way in which LOCAL is more permissive.)


Anyway, so much for bikeshedding.  Does the above make any sense?

This only affects the naming in any case, not what the code does.

[...]

> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h

[...]

>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> -	int def_scope;			/* default scope */
> +	u16 type;

u16?

There are 2 types in this patch, and (I presume) another 2 later.

Using an enum probably costs at most 2 bytes per capability, which seems
a reasonable price to pay for potentially better compile-time checking.

(Similarly for capability, though it's probably pointless churn to
change that now it's established.)

>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>  	/* Called on all active CPUs for all  "available" capabilities */
>  	int (*enable)(const struct arm64_cpu_capabilities *caps);
> @@ -116,6 +123,11 @@ struct arm64_cpu_capabilities {
>  	};
>  };

[...]

Cheers
---Dave

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-23 17:33     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-23 17:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> to the userspace and the CPU hwcaps used by the kernel, which
> include cpu features and CPU errata work arounds.
> 
> At the moment we have the following restricions:
> 
>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>    - Detected mostly on system wide CPU feature register. But
>      there are some which really uses a local CPU's value to
>      decide the availability (e.g, availability of hardware
>      prefetch). So, we run the check only once, after all the
>      boot-time active CPUs are turned on.
>    - Any late CPU which doesn't posses all the established features
>      is killed.
>    - Any late CPU which possess a feature *not* already available
>      is allowed to boot.
> 
>  b) CPU Errata work arounds (arm64_errata)
>    - Detected mostly based on a local CPU's feature register.
>      The checks are run on each boot time activated CPUs.
>    - Any late CPU which doesn't have any of the established errata
>      work around capabilities is ignored and is allowed to boot.
>    - Any late CPU which has an errata work around not already available
>      is killed.
> 
> However there are some exceptions to the cases above.
> 
> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>    And any late CPU that has this "feature" should be killed.
> 2) Hardware DBM feature is a non-conflicting capability which could be
>    enabled on CPUs which has it without any issues, even if the CPU is
>    brought up late.
> 
> So this calls for a lot more fine grained behavior for each capability.
> And if we define all the attributes to control their behavior properly,
> we may be able to use a single table for the CPU hwcaps (not the
> ELF HWCAPs, which cover errata and features). This is a prepartory step
> to get there. We define type for a capability, which for now encodes the
> scope of the check. i.e, whether it should be checked system wide or on
> each local CPU. We define two types :
> 
>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.

I'm a bit confused by the naming here.

I'm not keen on the word "strict" because it doesn't really mean
anything unless the rule to be strictly enforced is documented, and
then doesn't really add anything: you could take the view that either
there's an (enforced) rule or there's no rule at all.

In this case, (b) seems the "relaxed" case anyway: we allow these
capabilities to be enabled/disabled differently on different CPUs,
rather than requiring the same configuration on all CPUs (KPTI).

I think there are 2 x 2 orthogonal options:

A FEATURE capability must be disabled on every CPU where the feature is
not present.  A feature capability is considered desirable, and should
be enabled when possible.

An ERRATUM capability must be enabled on every CPU where the erratum is
present.  An erratum capability is considered undesirable, and should
be disabled when possible.

(An erratum is the inverse of a feature with respect to desirability,
enablement and presence.)

and:

A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
(Thus, a decision must be taken during boot, based on desirability/
undesirability of each capability and based on the assumption that
late CPUs won't violate the decision -- unless this assumption is
overridden by a cmdline arg etc.)

A LOCAL capability may freely be enabled on some CPUs while disabled on
other CPUs.

(Thus, LOCAL is precisely the inverse of GLOBAL.)


So:

	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).

("PERCPU" could be substituted for "LOCAL" if we want to be clearer
about the way in which LOCAL is more permissive.)


Anyway, so much for bikeshedding.  Does the above make any sense?

This only affects the naming in any case, not what the code does.

[...]

> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h

[...]

>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> -	int def_scope;			/* default scope */
> +	u16 type;

u16?

There are 2 types in this patch, and (I presume) another 2 later.

Using an enum probably costs at most 2 bytes per capability, which seems
a reasonable price to pay for potentially better compile-time checking.

(Similarly for capability, though it's probably pointless churn to
change that now it's established.)

>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>  	/* Called on all active CPUs for all  "available" capabilities */
>  	int (*enable)(const struct arm64_cpu_capabilities *caps);
> @@ -116,6 +123,11 @@ struct arm64_cpu_capabilities {
>  	};
>  };

[...]

Cheers
---Dave

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-23 17:33     ` Dave Martin
@ 2018-01-24 18:45       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-24 18:45 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

Dave,

Thanks a lot for taking the time to review the patch and for
opening up the discussion ! See my comments below.

On 23/01/18 17:33, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>> to the userspace and the CPU hwcaps used by the kernel, which
>> include cpu features and CPU errata work arounds.
>>
>> At the moment we have the following restricions:
>>
>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>     - Detected mostly on system wide CPU feature register. But
>>       there are some which really uses a local CPU's value to
>>       decide the availability (e.g, availability of hardware
>>       prefetch). So, we run the check only once, after all the
>>       boot-time active CPUs are turned on.
>>     - Any late CPU which doesn't posses all the established features
>>       is killed.
>>     - Any late CPU which possess a feature *not* already available
>>       is allowed to boot.
>>
>>   b) CPU Errata work arounds (arm64_errata)
>>     - Detected mostly based on a local CPU's feature register.
>>       The checks are run on each boot time activated CPUs.
>>     - Any late CPU which doesn't have any of the established errata
>>       work around capabilities is ignored and is allowed to boot.
>>     - Any late CPU which has an errata work around not already available
>>       is killed.
>>
>> However there are some exceptions to the cases above.
>>
>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>     And any late CPU that has this "feature" should be killed.
>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>     enabled on CPUs which has it without any issues, even if the CPU is
>>     brought up late.
>>
>> So this calls for a lot more fine grained behavior for each capability.
>> And if we define all the attributes to control their behavior properly,
>> we may be able to use a single table for the CPU hwcaps (not the
>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>> to get there. We define type for a capability, which for now encodes the
>> scope of the check. i.e, whether it should be checked system wide or on
>> each local CPU. We define two types :
>>
>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> 
> I'm a bit confused by the naming here.


I understand they are not well documented.  I will try to explain here and
stick it in somewhere, in the next revision.

There are 3 aspects for any capability.

1) SCOPE: How is the capability detected ?
i.e, whether it should be detected based on at least one CPU's ID register
(e.g, MIDR) (SCOPE_CPU_LOCAL) or System wide value (like ELF HWCAP)(SCOPE_SYSTEM)

This is fairly straight forward and hasn't changed much. The only
change we need is to allow for CPU "Features" that could be detected on
a local CPU. So, "LOCAL" tag has been added to the capabilities which
are CPU local.

2) WHEN: When is the capability "enabled" or in other words, when does the
kernel start using the capability. At the moment there is only
one place. After all the CPUs are brought up during the kernel init, from
setup_cpu_features. (But this will change when we add support for enabling
some capabilities very early during the boot, based on the boot CPU. e.g, VHE
and GIC CPUIF - for NMI).

For now, unless you see "EARLY", in the type, everything is enabled from
setup_cpu_features.

3) WHERE: Where all do we apply the "enable" for a given capability, when it
is to be enabled. Do we run it on all CPUs or only on the CPUs with the capability.
We don't deal with this in the infrastructure and we run the enable callback
on all CPUs irrespective of when the CPU is booted. It is upto the callback
to decide if it needs to take some action on a given CPU.


4) CONFLICT: How should we treat a conflict of a capability on a CPU which
boots after the capability was enabled in the kernel (as per 2, it could
be earlier or after smp CPUs are brought up) ?

Here are the possible combinations, representing a Conflict:

	System		| Late Booting CPU
a)	   y		|   n
b) 	   n		|   y

(a) Is considered safe for features like Erratum and KPTI where some
actions have to be taken to make the system behave in desirable manner.
However (a) is not considered safe for some features we advertise to the
user (e.g, ELF HWCAP)

(b) Is considered safe for most of the features (except KPTI and Software
prefetching), while it is unsafe for Errata, as we couldn't possibly take
any action as the time for applying the actions (enabling as per (2) above)
has passed already.

There are some capabilities where we could ignore both (a) and (b), e.g DBM.


So we have the following cases :
  i)   a_Safe && b_not_Safe
  ii)  a_not_Safe && b_Safe
  iii) a_Safe && b_Safe

I have used "STRICT" tag for category (i) and "WEAK" for (iii). (ii) doesn't
have any tag. I acknowledge that this scheme is not particularly intuitive.
However I have tried to explain the behavior of "each" defined type in a
comment above.

> 
> I'm not keen on the word "strict" because it doesn't really mean
> anything unless the rule to be strictly enforced is documented, and
> then doesn't really add anything: you could take the view that either
> there's an (enforced) rule or there's no rule at all.

As I mentioned above, each type is documented on the rules. But the tags
are not particularly helpful.

> 
> In this case, (b) seems the "relaxed" case anyway: we allow these
> capabilities to be enabled/disabled differently on different CPUs,
> rather than requiring the same configuration on all CPUs (KPTI).
> 
> I think there are 2 x 2 orthogonal options:
> 
> A FEATURE capability must be disabled on every CPU where the feature is
> not present.  A feature capability is considered desirable, and should
> be enabled when possible.
> 
> An ERRATUM capability must be enabled on every CPU where the erratum is
> present.  An erratum capability is considered undesirable, and should
> be disabled when possible.
> 
> (An erratum is the inverse of a feature with respect to desirability,
> enablement and presence.)

I would really like to avoid tagging the capabilities FEATURE/ERRATUM
to indicate their behavior, because :

1) We could be naming a "feature" ERRATUM, where it is really not one.
e.g, KPTI is a security feature and not an erratum.

2) We could be "marking" all "CPU Errata" unsafe when detected late.
e.g, Cortex-A55 errata 1024718, can be safely handled by disabling the
DBM feature and the conflict can be "ignored" (even though it is not
handled via capability).

So using the FEATURE/ERRATA will cause further confusion on the real
type of the capability. Hence, it would be better if we came up with
something other to make it clear.

> 
> and:
> 
> A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
> (Thus, a decision must be taken during boot, based on desirability/
> undesirability of each capability and based on the assumption that
> late CPUs won't violate the decision -- unless this assumption is
> overridden by a cmdline arg etc.)
> 
> A LOCAL capability may freely be enabled on some CPUs while disabled on
> other CPUs.

As discussed in (3) above, I would like to leave it to the "enable()" method
to decide where actions are need, to avoid adding more combinations of tags
to the type names. We continue to invoke enable() on all CPUs.

> 
> (Thus, LOCAL is precisely the inverse of GLOBAL.)
> 
> 
> So:
> 
> 	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
> 	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
> 	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
> 	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).
> 
> ("PERCPU" could be substituted for "LOCAL" if we want to be clearer
> about the way in which LOCAL is more permissive.)

In general, I understand the names could get some improved scheme.
I think if we come up with some nice tag for types i, ii & ii in section (4)
we should be good to go.

> 
> 
> Anyway, so much for bikeshedding.  Does the above make any sense?
> 
> This only affects the naming in any case, not what the code does.
> 
> [...]
> 
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> 
> [...]
> 
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>>   	u16 capability;
>> -	int def_scope;			/* default scope */
>> +	u16 type;
> 
> u16?
> 
> There are 2 types in this patch, and (I presume) another 2 later.
> 
> Using an enum probably costs at most 2 bytes per capability, which seems
> a reasonable price to pay for potentially better compile-time checking.

Actually, I chose u16 to align the structure a bit, following the "capability" field.
We use it more like bit mask to check how to deal with the cap, rather than a single number
which represents something. I agree that we get more type safety with the enum,
but felt suited for more like an abstract quantity.

> 
> (Similarly for capability, though it's probably pointless churn to
> change that now it's established.)
> 
>>   	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>>   	/* Called on all active CPUs for all  "available" capabilities */
>>   	int (*enable)(const struct arm64_cpu_capabilities *caps);
>> @@ -116,6 +123,11 @@ struct arm64_cpu_capabilities {
>>   	};
>>   };
> 

Suzuki

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-24 18:45       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-24 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

Dave,

Thanks a lot for taking the time to review the patch and for
opening up the discussion ! See my comments below.

On 23/01/18 17:33, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>> to the userspace and the CPU hwcaps used by the kernel, which
>> include cpu features and CPU errata work arounds.
>>
>> At the moment we have the following restricions:
>>
>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>     - Detected mostly on system wide CPU feature register. But
>>       there are some which really uses a local CPU's value to
>>       decide the availability (e.g, availability of hardware
>>       prefetch). So, we run the check only once, after all the
>>       boot-time active CPUs are turned on.
>>     - Any late CPU which doesn't posses all the established features
>>       is killed.
>>     - Any late CPU which possess a feature *not* already available
>>       is allowed to boot.
>>
>>   b) CPU Errata work arounds (arm64_errata)
>>     - Detected mostly based on a local CPU's feature register.
>>       The checks are run on each boot time activated CPUs.
>>     - Any late CPU which doesn't have any of the established errata
>>       work around capabilities is ignored and is allowed to boot.
>>     - Any late CPU which has an errata work around not already available
>>       is killed.
>>
>> However there are some exceptions to the cases above.
>>
>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>     And any late CPU that has this "feature" should be killed.
>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>     enabled on CPUs which has it without any issues, even if the CPU is
>>     brought up late.
>>
>> So this calls for a lot more fine grained behavior for each capability.
>> And if we define all the attributes to control their behavior properly,
>> we may be able to use a single table for the CPU hwcaps (not the
>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>> to get there. We define type for a capability, which for now encodes the
>> scope of the check. i.e, whether it should be checked system wide or on
>> each local CPU. We define two types :
>>
>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> 
> I'm a bit confused by the naming here.


I understand they are not well documented.  I will try to explain here and
stick it in somewhere, in the next revision.

There are 3 aspects for any capability.

1) SCOPE: How is the capability detected ?
i.e, whether it should be detected based on at least one CPU's ID register
(e.g, MIDR) (SCOPE_CPU_LOCAL) or System wide value (like ELF HWCAP)(SCOPE_SYSTEM)

This is fairly straight forward and hasn't changed much. The only
change we need is to allow for CPU "Features" that could be detected on
a local CPU. So, "LOCAL" tag has been added to the capabilities which
are CPU local.

2) WHEN: When is the capability "enabled" or in other words, when does the
kernel start using the capability. At the moment there is only
one place. After all the CPUs are brought up during the kernel init, from
setup_cpu_features. (But this will change when we add support for enabling
some capabilities very early during the boot, based on the boot CPU. e.g, VHE
and GIC CPUIF - for NMI).

For now, unless you see "EARLY", in the type, everything is enabled from
setup_cpu_features.

3) WHERE: Where all do we apply the "enable" for a given capability, when it
is to be enabled. Do we run it on all CPUs or only on the CPUs with the capability.
We don't deal with this in the infrastructure and we run the enable callback
on all CPUs irrespective of when the CPU is booted. It is upto the callback
to decide if it needs to take some action on a given CPU.


4) CONFLICT: How should we treat a conflict of a capability on a CPU which
boots after the capability was enabled in the kernel (as per 2, it could
be earlier or after smp CPUs are brought up) ?

Here are the possible combinations, representing a Conflict:

	System		| Late Booting CPU
a)	   y		|   n
b) 	   n		|   y

(a) Is considered safe for features like Erratum and KPTI where some
actions have to be taken to make the system behave in desirable manner.
However (a) is not considered safe for some features we advertise to the
user (e.g, ELF HWCAP)

(b) Is considered safe for most of the features (except KPTI and Software
prefetching), while it is unsafe for Errata, as we couldn't possibly take
any action as the time for applying the actions (enabling as per (2) above)
has passed already.

There are some capabilities where we could ignore both (a) and (b), e.g DBM.


So we have the following cases :
  i)   a_Safe && b_not_Safe
  ii)  a_not_Safe && b_Safe
  iii) a_Safe && b_Safe

I have used "STRICT" tag for category (i) and "WEAK" for (iii). (ii) doesn't
have any tag. I acknowledge that this scheme is not particularly intuitive.
However I have tried to explain the behavior of "each" defined type in a
comment above.

> 
> I'm not keen on the word "strict" because it doesn't really mean
> anything unless the rule to be strictly enforced is documented, and
> then doesn't really add anything: you could take the view that either
> there's an (enforced) rule or there's no rule at all.

As I mentioned above, each type is documented on the rules. But the tags
are not particularly helpful.

> 
> In this case, (b) seems the "relaxed" case anyway: we allow these
> capabilities to be enabled/disabled differently on different CPUs,
> rather than requiring the same configuration on all CPUs (KPTI).
> 
> I think there are 2 x 2 orthogonal options:
> 
> A FEATURE capability must be disabled on every CPU where the feature is
> not present.  A feature capability is considered desirable, and should
> be enabled when possible.
> 
> An ERRATUM capability must be enabled on every CPU where the erratum is
> present.  An erratum capability is considered undesirable, and should
> be disabled when possible.
> 
> (An erratum is the inverse of a feature with respect to desirability,
> enablement and presence.)

I would really like to avoid tagging the capabilities FEATURE/ERRATUM
to indicate their behavior, because :

1) We could be naming a "feature" ERRATUM, where it is really not one.
e.g, KPTI is a security feature and not an erratum.

2) We could be "marking" all "CPU Errata" unsafe when detected late.
e.g, Cortex-A55 errata 1024718, can be safely handled by disabling the
DBM feature and the conflict can be "ignored" (even though it is not
handled via capability).

So using the FEATURE/ERRATA will cause further confusion on the real
type of the capability. Hence, it would be better if we came up with
something other to make it clear.

> 
> and:
> 
> A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
> (Thus, a decision must be taken during boot, based on desirability/
> undesirability of each capability and based on the assumption that
> late CPUs won't violate the decision -- unless this assumption is
> overridden by a cmdline arg etc.)
> 
> A LOCAL capability may freely be enabled on some CPUs while disabled on
> other CPUs.

As discussed in (3) above, I would like to leave it to the "enable()" method
to decide where actions are need, to avoid adding more combinations of tags
to the type names. We continue to invoke enable() on all CPUs.

> 
> (Thus, LOCAL is precisely the inverse of GLOBAL.)
> 
> 
> So:
> 
> 	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
> 	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
> 	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
> 	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).
> 
> ("PERCPU" could be substituted for "LOCAL" if we want to be clearer
> about the way in which LOCAL is more permissive.)

In general, I understand the names could get some improved scheme.
I think if we come up with some nice tag for types i, ii & ii in section (4)
we should be good to go.

> 
> 
> Anyway, so much for bikeshedding.  Does the above make any sense?
> 
> This only affects the naming in any case, not what the code does.
> 
> [...]
> 
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> 
> [...]
> 
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>>   	u16 capability;
>> -	int def_scope;			/* default scope */
>> +	u16 type;
> 
> u16?
> 
> There are 2 types in this patch, and (I presume) another 2 later.
> 
> Using an enum probably costs at most 2 bytes per capability, which seems
> a reasonable price to pay for potentially better compile-time checking.

Actually, I chose u16 to align the structure a bit, following the "capability" field.
We use it more like bit mask to check how to deal with the cap, rather than a single number
which represents something. I agree that we get more type safety with the enum,
but felt suited for more like an abstract quantity.

> 
> (Similarly for capability, though it's probably pointless churn to
> change that now it's established.)
> 
>>   	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>>   	/* Called on all active CPUs for all  "available" capabilities */
>>   	int (*enable)(const struct arm64_cpu_capabilities *caps);
>> @@ -116,6 +123,11 @@ struct arm64_cpu_capabilities {
>>   	};
>>   };
> 

Suzuki

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-24 18:45       ` Suzuki K Poulose
@ 2018-01-25 13:43         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 13:43 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Wed, Jan 24, 2018 at 06:45:01PM +0000, Suzuki K Poulose wrote:
> Dave,
> 
> Thanks a lot for taking the time to review the patch and for
> opening up the discussion ! See my comments below.
> 
> On 23/01/18 17:33, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> >>We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> >>to the userspace and the CPU hwcaps used by the kernel, which
> >>include cpu features and CPU errata work arounds.
> >>
> >>At the moment we have the following restricions:
> >>
> >>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
> >>    - Detected mostly on system wide CPU feature register. But
> >>      there are some which really uses a local CPU's value to
> >>      decide the availability (e.g, availability of hardware
> >>      prefetch). So, we run the check only once, after all the
> >>      boot-time active CPUs are turned on.
> >>    - Any late CPU which doesn't posses all the established features
> >>      is killed.
> >>    - Any late CPU which possess a feature *not* already available
> >>      is allowed to boot.
> >>
> >>  b) CPU Errata work arounds (arm64_errata)
> >>    - Detected mostly based on a local CPU's feature register.
> >>      The checks are run on each boot time activated CPUs.
> >>    - Any late CPU which doesn't have any of the established errata
> >>      work around capabilities is ignored and is allowed to boot.
> >>    - Any late CPU which has an errata work around not already available
> >>      is killed.
> >>
> >>However there are some exceptions to the cases above.
> >>
> >>1) KPTI is a feature that we need to enable when at least one CPU needs it.
> >>    And any late CPU that has this "feature" should be killed.
> >>2) Hardware DBM feature is a non-conflicting capability which could be
> >>    enabled on CPUs which has it without any issues, even if the CPU is
> >>    brought up late.
> >>
> >>So this calls for a lot more fine grained behavior for each capability.
> >>And if we define all the attributes to control their behavior properly,
> >>we may be able to use a single table for the CPU hwcaps (not the
> >>ELF HWCAPs, which cover errata and features). This is a prepartory step
> >>to get there. We define type for a capability, which for now encodes the
> >>scope of the check. i.e, whether it should be checked system wide or on
> >>each local CPU. We define two types :
> >>
> >>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
> >>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> >
> >I'm a bit confused by the naming here.
> 
> 
> I understand they are not well documented.  I will try to explain here and
> stick it in somewhere, in the next revision.
> 
> There are 3 aspects for any capability.
> 
> 1) SCOPE: How is the capability detected ?
> i.e, whether it should be detected based on at least one CPU's ID register
> (e.g, MIDR) (SCOPE_CPU_LOCAL) or System wide value (like ELF HWCAP)(SCOPE_SYSTEM)
> 
> This is fairly straight forward and hasn't changed much. The only
> change we need is to allow for CPU "Features" that could be detected on
> a local CPU. So, "LOCAL" tag has been added to the capabilities which
> are CPU local.

I think my confusion here is mostly semantic, so I won't worry too
much about it for now as I review the patches.

<aside>

It is confusing code to dive into though: there is too much overlap
and ambiguity between the intuitive meanings of "feature", "capability",
"erratum" etc.  I think this is just the way the code evolved:
"capability" is an intuitive word to describe that the system can do
something, but it's a strange word to use for the presence of an
erratum that must be worked around.

The immutable properties of CPUs, and the desicion taken by Linux about
what to do with them, are two quite different things.  I find it easy to
confuse myself about which is being referred to when we talk about
"capabilities", partly because the intuitive meaning of this word often
seems to point to the wrong answer.

Choosing different words might help, but precise definitions and
consistent would also help.

Here, "detecting" sounds like discovery of an immutable characteristic
of something, but really in the System-wide case you're talking about
making a policy decision (i.e., what tradeoff to make between working
with the boot and/or early CPUs, and working with late CPUs that we
haven't seen yet).  It would be equally valid to make a different
decision and reject some _early_ CPUs in the hopes that this will
result in a better performing system (perhaps because we can now
enable a desirable feature globally, or perhaps to minimise likelihood
of rejecting late CPUs).

</aside>

Anyway, this isn't a high priority.  It's just something that takes a
little time to get my head around...

> 2) WHEN: When is the capability "enabled" or in other words, when does the
> kernel start using the capability. At the moment there is only
> one place. After all the CPUs are brought up during the kernel init, from
> setup_cpu_features. (But this will change when we add support for enabling
> some capabilities very early during the boot, based on the boot CPU. e.g, VHE
> and GIC CPUIF - for NMI).
> 
> For now, unless you see "EARLY", in the type, everything is enabled from
> setup_cpu_features.

Agreed -- I'd forgotten about this.  To what extent is this orthogonal
to 1/3/4?

> 3) WHERE: Where all do we apply the "enable" for a given capability, when it
> is to be enabled. Do we run it on all CPUs or only on the CPUs with the capability.
> We don't deal with this in the infrastructure and we run the enable callback
> on all CPUs irrespective of when the CPU is booted. It is upto the callback
> to decide if it needs to take some action on a given CPU.
> 
> 
> 4) CONFLICT: How should we treat a conflict of a capability on a CPU which
> boots after the capability was enabled in the kernel (as per 2, it could
> be earlier or after smp CPUs are brought up) ?
> 
> Here are the possible combinations, representing a Conflict:
> 
> 	System		| Late Booting CPU
> a)	   y		|   n
> b) 	   n		|   y
> 
> (a) Is considered safe for features like Erratum and KPTI where some
> actions have to be taken to make the system behave in desirable manner.
> However (a) is not considered safe for some features we advertise to the
> user (e.g, ELF HWCAP)
> 
> (b) Is considered safe for most of the features (except KPTI and Software
> prefetching), while it is unsafe for Errata, as we couldn't possibly take
> any action as the time for applying the actions (enabling as per (2) above)
> has passed already.
> 
> 
> So we have the following cases :
>  i)   a_Safe && b_not_Safe
>  ii)  a_not_Safe && b_Safe
>  iii) a_Safe && b_Safe

Is this the same as saying that the CONFLICT type (iii) is not
applicable to capabilites that are not decided globally?

> I have used "STRICT" tag for category (i) and "WEAK" for (iii). (ii) doesn't
> have any tag. I acknowledge that this scheme is not particularly intuitive.
> However I have tried to explain the behavior of "each" defined type in a
> comment above.
> 
> >
> >I'm not keen on the word "strict" because it doesn't really mean
> >anything unless the rule to be strictly enforced is documented, and
> >then doesn't really add anything: you could take the view that either
> >there's an (enforced) rule or there's no rule at all.
> 
> As I mentioned above, each type is documented on the rules. But the tags
> are not particularly helpful.
> 
> >
> >In this case, (b) seems the "relaxed" case anyway: we allow these
> >capabilities to be enabled/disabled differently on different CPUs,
> >rather than requiring the same configuration on all CPUs (KPTI).
> >
> >I think there are 2 x 2 orthogonal options:
> >
> >A FEATURE capability must be disabled on every CPU where the feature is
> >not present.  A feature capability is considered desirable, and should
> >be enabled when possible.
> >
> >An ERRATUM capability must be enabled on every CPU where the erratum is
> >present.  An erratum capability is considered undesirable, and should
> >be disabled when possible.
> >
> >(An erratum is the inverse of a feature with respect to desirability,
> >enablement and presence.)
> 
> I would really like to avoid tagging the capabilities FEATURE/ERRATUM
> to indicate their behavior, because :
> 
> 1) We could be naming a "feature" ERRATUM, where it is really not one.
> e.g, KPTI is a security feature and not an erratum.
> 
> 2) We could be "marking" all "CPU Errata" unsafe when detected late.
> e.g, Cortex-A55 errata 1024718, can be safely handled by disabling the
> DBM feature and the conflict can be "ignored" (even though it is not
> handled via capability).

That's a fair point.  "Erratum" is describing a set of constraints
between the CPUs and kernel that is typical of errata handing, but could
also apply to other features.  So I guess it's not the best choice of
word.

> So using the FEATURE/ERRATA will cause further confusion on the real
> type of the capability. Hence, it would be better if we came up with
> something other to make it clear.

I guess it may not be quite as clear-cut as I'm hoping...

> >and:
> >
> >A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
> >(Thus, a decision must be taken during boot, based on desirability/
> >undesirability of each capability and based on the assumption that
> >late CPUs won't violate the decision -- unless this assumption is
> >overridden by a cmdline arg etc.)
> >
> >A LOCAL capability may freely be enabled on some CPUs while disabled on
> >other CPUs.
> 
> As discussed in (3) above, I would like to leave it to the "enable()" method
> to decide where actions are need, to avoid adding more combinations of tags
> to the type names. We continue to invoke enable() on all CPUs.

Sure -- if the decisions are made enable() methods rather than blanket
rules, then we don't need a distinct capability type for every possible
case.  For the very common cases like the ELF HWCAPs it may be worth it,
but not for fiddly one-off things.

> >(Thus, LOCAL is precisely the inverse of GLOBAL.)
> >
> >
> >So:
> >
> >	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
> >	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
> >	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
> >	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).
> >
> >("PERCPU" could be substituted for "LOCAL" if we want to be clearer
> >about the way in which LOCAL is more permissive.)
> 
> In general, I understand the names could get some improved scheme.
> I think if we come up with some nice tag for types i, ii & ii in section (4)
> we should be good to go.

This is always something that could be reexamined later.

I think I understand the basic ideas here a bit better now -- thanks.

[...]

> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >
> >[...]
> >
> >>  struct arm64_cpu_capabilities {
> >>  	const char *desc;
> >>  	u16 capability;
> >>-	int def_scope;			/* default scope */
> >>+	u16 type;
> >
> >u16?
> >
> >There are 2 types in this patch, and (I presume) another 2 later.
> >
> >Using an enum probably costs at most 2 bytes per capability, which seems
> >a reasonable price to pay for potentially better compile-time checking.
> 
> Actually, I chose u16 to align the structure a bit, following the "capability" field.
> We use it more like bit mask to check how to deal with the cap, rather than a single number
> which represents something. I agree that we get more type safety with the enum,
> but felt suited for more like an abstract quantity.

If it's a bitmask then u16 seems a bit more natural.

Cheers
---Dave

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-25 13:43         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 24, 2018 at 06:45:01PM +0000, Suzuki K Poulose wrote:
> Dave,
> 
> Thanks a lot for taking the time to review the patch and for
> opening up the discussion ! See my comments below.
> 
> On 23/01/18 17:33, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> >>We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> >>to the userspace and the CPU hwcaps used by the kernel, which
> >>include cpu features and CPU errata work arounds.
> >>
> >>At the moment we have the following restricions:
> >>
> >>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
> >>    - Detected mostly on system wide CPU feature register. But
> >>      there are some which really uses a local CPU's value to
> >>      decide the availability (e.g, availability of hardware
> >>      prefetch). So, we run the check only once, after all the
> >>      boot-time active CPUs are turned on.
> >>    - Any late CPU which doesn't posses all the established features
> >>      is killed.
> >>    - Any late CPU which possess a feature *not* already available
> >>      is allowed to boot.
> >>
> >>  b) CPU Errata work arounds (arm64_errata)
> >>    - Detected mostly based on a local CPU's feature register.
> >>      The checks are run on each boot time activated CPUs.
> >>    - Any late CPU which doesn't have any of the established errata
> >>      work around capabilities is ignored and is allowed to boot.
> >>    - Any late CPU which has an errata work around not already available
> >>      is killed.
> >>
> >>However there are some exceptions to the cases above.
> >>
> >>1) KPTI is a feature that we need to enable when at least one CPU needs it.
> >>    And any late CPU that has this "feature" should be killed.
> >>2) Hardware DBM feature is a non-conflicting capability which could be
> >>    enabled on CPUs which has it without any issues, even if the CPU is
> >>    brought up late.
> >>
> >>So this calls for a lot more fine grained behavior for each capability.
> >>And if we define all the attributes to control their behavior properly,
> >>we may be able to use a single table for the CPU hwcaps (not the
> >>ELF HWCAPs, which cover errata and features). This is a prepartory step
> >>to get there. We define type for a capability, which for now encodes the
> >>scope of the check. i.e, whether it should be checked system wide or on
> >>each local CPU. We define two types :
> >>
> >>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
> >>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> >
> >I'm a bit confused by the naming here.
> 
> 
> I understand they are not well documented.  I will try to explain here and
> stick it in somewhere, in the next revision.
> 
> There are 3 aspects for any capability.
> 
> 1) SCOPE: How is the capability detected ?
> i.e, whether it should be detected based on at least one CPU's ID register
> (e.g, MIDR) (SCOPE_CPU_LOCAL) or System wide value (like ELF HWCAP)(SCOPE_SYSTEM)
> 
> This is fairly straight forward and hasn't changed much. The only
> change we need is to allow for CPU "Features" that could be detected on
> a local CPU. So, "LOCAL" tag has been added to the capabilities which
> are CPU local.

I think my confusion here is mostly semantic, so I won't worry too
much about it for now as I review the patches.

<aside>

It is confusing code to dive into though: there is too much overlap
and ambiguity between the intuitive meanings of "feature", "capability",
"erratum" etc.  I think this is just the way the code evolved:
"capability" is an intuitive word to describe that the system can do
something, but it's a strange word to use for the presence of an
erratum that must be worked around.

The immutable properties of CPUs, and the desicion taken by Linux about
what to do with them, are two quite different things.  I find it easy to
confuse myself about which is being referred to when we talk about
"capabilities", partly because the intuitive meaning of this word often
seems to point to the wrong answer.

Choosing different words might help, but precise definitions and
consistent would also help.

Here, "detecting" sounds like discovery of an immutable characteristic
of something, but really in the System-wide case you're talking about
making a policy decision (i.e., what tradeoff to make between working
with the boot and/or early CPUs, and working with late CPUs that we
haven't seen yet).  It would be equally valid to make a different
decision and reject some _early_ CPUs in the hopes that this will
result in a better performing system (perhaps because we can now
enable a desirable feature globally, or perhaps to minimise likelihood
of rejecting late CPUs).

</aside>

Anyway, this isn't a high priority.  It's just something that takes a
little time to get my head around...

> 2) WHEN: When is the capability "enabled" or in other words, when does the
> kernel start using the capability. At the moment there is only
> one place. After all the CPUs are brought up during the kernel init, from
> setup_cpu_features. (But this will change when we add support for enabling
> some capabilities very early during the boot, based on the boot CPU. e.g, VHE
> and GIC CPUIF - for NMI).
> 
> For now, unless you see "EARLY", in the type, everything is enabled from
> setup_cpu_features.

Agreed -- I'd forgotten about this.  To what extent is this orthogonal
to 1/3/4?

> 3) WHERE: Where all do we apply the "enable" for a given capability, when it
> is to be enabled. Do we run it on all CPUs or only on the CPUs with the capability.
> We don't deal with this in the infrastructure and we run the enable callback
> on all CPUs irrespective of when the CPU is booted. It is upto the callback
> to decide if it needs to take some action on a given CPU.
> 
> 
> 4) CONFLICT: How should we treat a conflict of a capability on a CPU which
> boots after the capability was enabled in the kernel (as per 2, it could
> be earlier or after smp CPUs are brought up) ?
> 
> Here are the possible combinations, representing a Conflict:
> 
> 	System		| Late Booting CPU
> a)	   y		|   n
> b) 	   n		|   y
> 
> (a) Is considered safe for features like Erratum and KPTI where some
> actions have to be taken to make the system behave in desirable manner.
> However (a) is not considered safe for some features we advertise to the
> user (e.g, ELF HWCAP)
> 
> (b) Is considered safe for most of the features (except KPTI and Software
> prefetching), while it is unsafe for Errata, as we couldn't possibly take
> any action as the time for applying the actions (enabling as per (2) above)
> has passed already.
> 
> 
> So we have the following cases :
>  i)   a_Safe && b_not_Safe
>  ii)  a_not_Safe && b_Safe
>  iii) a_Safe && b_Safe

Is this the same as saying that the CONFLICT type (iii) is not
applicable to capabilites that are not decided globally?

> I have used "STRICT" tag for category (i) and "WEAK" for (iii). (ii) doesn't
> have any tag. I acknowledge that this scheme is not particularly intuitive.
> However I have tried to explain the behavior of "each" defined type in a
> comment above.
> 
> >
> >I'm not keen on the word "strict" because it doesn't really mean
> >anything unless the rule to be strictly enforced is documented, and
> >then doesn't really add anything: you could take the view that either
> >there's an (enforced) rule or there's no rule at all.
> 
> As I mentioned above, each type is documented on the rules. But the tags
> are not particularly helpful.
> 
> >
> >In this case, (b) seems the "relaxed" case anyway: we allow these
> >capabilities to be enabled/disabled differently on different CPUs,
> >rather than requiring the same configuration on all CPUs (KPTI).
> >
> >I think there are 2 x 2 orthogonal options:
> >
> >A FEATURE capability must be disabled on every CPU where the feature is
> >not present.  A feature capability is considered desirable, and should
> >be enabled when possible.
> >
> >An ERRATUM capability must be enabled on every CPU where the erratum is
> >present.  An erratum capability is considered undesirable, and should
> >be disabled when possible.
> >
> >(An erratum is the inverse of a feature with respect to desirability,
> >enablement and presence.)
> 
> I would really like to avoid tagging the capabilities FEATURE/ERRATUM
> to indicate their behavior, because :
> 
> 1) We could be naming a "feature" ERRATUM, where it is really not one.
> e.g, KPTI is a security feature and not an erratum.
> 
> 2) We could be "marking" all "CPU Errata" unsafe when detected late.
> e.g, Cortex-A55 errata 1024718, can be safely handled by disabling the
> DBM feature and the conflict can be "ignored" (even though it is not
> handled via capability).

That's a fair point.  "Erratum" is describing a set of constraints
between the CPUs and kernel that is typical of errata handing, but could
also apply to other features.  So I guess it's not the best choice of
word.

> So using the FEATURE/ERRATA will cause further confusion on the real
> type of the capability. Hence, it would be better if we came up with
> something other to make it clear.

I guess it may not be quite as clear-cut as I'm hoping...

> >and:
> >
> >A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
> >(Thus, a decision must be taken during boot, based on desirability/
> >undesirability of each capability and based on the assumption that
> >late CPUs won't violate the decision -- unless this assumption is
> >overridden by a cmdline arg etc.)
> >
> >A LOCAL capability may freely be enabled on some CPUs while disabled on
> >other CPUs.
> 
> As discussed in (3) above, I would like to leave it to the "enable()" method
> to decide where actions are need, to avoid adding more combinations of tags
> to the type names. We continue to invoke enable() on all CPUs.

Sure -- if the decisions are made enable() methods rather than blanket
rules, then we don't need a distinct capability type for every possible
case.  For the very common cases like the ELF HWCAPs it may be worth it,
but not for fiddly one-off things.

> >(Thus, LOCAL is precisely the inverse of GLOBAL.)
> >
> >
> >So:
> >
> >	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
> >	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
> >	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
> >	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).
> >
> >("PERCPU" could be substituted for "LOCAL" if we want to be clearer
> >about the way in which LOCAL is more permissive.)
> 
> In general, I understand the names could get some improved scheme.
> I think if we come up with some nice tag for types i, ii & ii in section (4)
> we should be good to go.

This is always something that could be reexamined later.

I think I understand the basic ideas here a bit better now -- thanks.

[...]

> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >
> >[...]
> >
> >>  struct arm64_cpu_capabilities {
> >>  	const char *desc;
> >>  	u16 capability;
> >>-	int def_scope;			/* default scope */
> >>+	u16 type;
> >
> >u16?
> >
> >There are 2 types in this patch, and (I presume) another 2 later.
> >
> >Using an enum probably costs at most 2 bytes per capability, which seems
> >a reasonable price to pay for potentially better compile-time checking.
> 
> Actually, I chose u16 to align the structure a bit, following the "capability" field.
> We use it more like bit mask to check how to deal with the cap, rather than a single number
> which represents something. I agree that we get more type safety with the enum,
> but felt suited for more like an abstract quantity.

If it's a bitmask then u16 seems a bit more natural.

Cheers
---Dave

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

* Re: [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
  2018-01-23 15:38       ` Suzuki K Poulose
@ 2018-01-25 15:36         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 15:36 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, James Morse, jnair,
	Andre Przywara, Robin Murphy, linux-arm-kernel

On Tue, Jan 23, 2018 at 03:38:37PM +0000, Suzuki K Poulose wrote:
> On 23/01/18 14:52, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
> >>From: Dave Martin <dave.martin@arm.com>
> >>
> >>We issue the enable() call back for all CPU hwcaps capabilities
> >>available on the system, on all the CPUs. So far we have ignored
> >>the argument passed to the call back, which had a prototype to
> >>accept a "void *" for use with on_each_cpu() and later with
> >>stop_machine(). However, with commit 0a0d111d40fd1
> >>("arm64: cpufeature: Pass capability structure to ->enable callback"),
> >>there are some users of the argument who wants the matching capability
> >>struct pointer where there are multiple matching criteria for a single
> >>capability. Update the prototype for enable to accept a const pointer.
> >>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Robin Murphy <robin.murphy@arm.com>
> >>Cc: Catalin Marinas <catalin.marinas@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>Cc: Andre Przywara <andre.przywara@arm.com>
> >>Cc: James Morse <james.morse@arm.com>
> >>Reviewed-by: Julien Thierry <julien.thierry@arm.com>
> >>Signed-off-by: Dave Martin <dave.martin@arm.com>
> >>[ Rebased to for-next/core converting more users ]
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  3 ++-
> >>  arch/arm64/include/asm/fpsimd.h     |  4 +++-
> >>  arch/arm64/include/asm/processor.h  |  7 ++++---
> >>  arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
> >>  arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
> >>  arch/arm64/kernel/fpsimd.c          |  3 ++-
> >>  arch/arm64/kernel/traps.c           |  3 ++-
> >>  arch/arm64/mm/fault.c               |  2 +-
> >>  8 files changed, 32 insertions(+), 20 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index ac67cfc2585a..cefbd685292c 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
> >>  	u16 capability;
> >>  	int def_scope;			/* default scope */
> >>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
> >>-	int (*enable)(void *);		/* Called on all active CPUs */
> >>+	/* Called on all active CPUs for all  "available" capabilities */
> >
> >Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
> >workarounds.
> >
> 
> Thanks for spotting, will fix it.
> 
> >Maybe applicable would be a better word?
> >
> 
> There is a subtle difference. If there are two entries for a capability,
> with only one of them matches, we end up calling the enable() for both
> the entries. "Applicable" could potentially be misunderstood, leading
> to assumption that the enable() is called only if that "entry" matches,
> which is not true. I accept that "available" doesn't sound any better either.
> 
> 
> >>+	int (*enable)(const struct arm64_cpu_capabilities *caps);

This probably shouldn't be "caps" here: this argument refers a single
capability, not an array.  Also, this shouldn't be any random capability,
but the one corresponding to the enable method:

	cap->enable(cap) 

(i.e., cap1->enable(cap2) is invalid, and the cpufeature framework won't
do that).

> >Alternatively, if the comment is liable to be ambiguous, maybe it would
> >be better to delete it.  The explicit argument type already makes this
> >more self-documenting than previously.
> 
> I think we still need to make it clear that the enable is called on
> all active CPUs. It is not about the argument anymore.
> 
> How about :
> 
> /*
>  * Called on all active CPUs if the capability associated with
>  * this entry is set.
>  */

Maybe, but now we have the new concept of "setting" a capability.

Really, this is enabling the capability for a CPU, not globally, so
maybe it could be renamed to "cpu_enable".

Could we describe the method in terms of what it is required to do,
as well as the circumstances of the call, e.g.:

/*
 * Take the appropriate actions to enable this capability for this cpu.
 * Every time a cpu is booted, this method is called under stop_machine()
 * for each globally enabled capability.
 */

(I'm hoping that "globally enabled" is meaningful wording, though
perhaps not.)

Also, what does the return value of this method mean?

Previously, the return value was ignored, but other patches in this
series might change that.

[...]

Cheers
---Dave

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
@ 2018-01-25 15:36         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 15:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 03:38:37PM +0000, Suzuki K Poulose wrote:
> On 23/01/18 14:52, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
> >>From: Dave Martin <dave.martin@arm.com>
> >>
> >>We issue the enable() call back for all CPU hwcaps capabilities
> >>available on the system, on all the CPUs. So far we have ignored
> >>the argument passed to the call back, which had a prototype to
> >>accept a "void *" for use with on_each_cpu() and later with
> >>stop_machine(). However, with commit 0a0d111d40fd1
> >>("arm64: cpufeature: Pass capability structure to ->enable callback"),
> >>there are some users of the argument who wants the matching capability
> >>struct pointer where there are multiple matching criteria for a single
> >>capability. Update the prototype for enable to accept a const pointer.
> >>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Robin Murphy <robin.murphy@arm.com>
> >>Cc: Catalin Marinas <catalin.marinas@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>Cc: Andre Przywara <andre.przywara@arm.com>
> >>Cc: James Morse <james.morse@arm.com>
> >>Reviewed-by: Julien Thierry <julien.thierry@arm.com>
> >>Signed-off-by: Dave Martin <dave.martin@arm.com>
> >>[ Rebased to for-next/core converting more users ]
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  3 ++-
> >>  arch/arm64/include/asm/fpsimd.h     |  4 +++-
> >>  arch/arm64/include/asm/processor.h  |  7 ++++---
> >>  arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
> >>  arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
> >>  arch/arm64/kernel/fpsimd.c          |  3 ++-
> >>  arch/arm64/kernel/traps.c           |  3 ++-
> >>  arch/arm64/mm/fault.c               |  2 +-
> >>  8 files changed, 32 insertions(+), 20 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index ac67cfc2585a..cefbd685292c 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
> >>  	u16 capability;
> >>  	int def_scope;			/* default scope */
> >>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
> >>-	int (*enable)(void *);		/* Called on all active CPUs */
> >>+	/* Called on all active CPUs for all  "available" capabilities */
> >
> >Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
> >workarounds.
> >
> 
> Thanks for spotting, will fix it.
> 
> >Maybe applicable would be a better word?
> >
> 
> There is a subtle difference. If there are two entries for a capability,
> with only one of them matches, we end up calling the enable() for both
> the entries. "Applicable" could potentially be misunderstood, leading
> to assumption that the enable() is called only if that "entry" matches,
> which is not true. I accept that "available" doesn't sound any better either.
> 
> 
> >>+	int (*enable)(const struct arm64_cpu_capabilities *caps);

This probably shouldn't be "caps" here: this argument refers a single
capability, not an array.  Also, this shouldn't be any random capability,
but the one corresponding to the enable method:

	cap->enable(cap) 

(i.e., cap1->enable(cap2) is invalid, and the cpufeature framework won't
do that).

> >Alternatively, if the comment is liable to be ambiguous, maybe it would
> >be better to delete it.  The explicit argument type already makes this
> >more self-documenting than previously.
> 
> I think we still need to make it clear that the enable is called on
> all active CPUs. It is not about the argument anymore.
> 
> How about :
> 
> /*
>  * Called on all active CPUs if the capability associated with
>  * this entry is set.
>  */

Maybe, but now we have the new concept of "setting" a capability.

Really, this is enabling the capability for a CPU, not globally, so
maybe it could be renamed to "cpu_enable".

Could we describe the method in terms of what it is required to do,
as well as the circumstances of the call, e.g.:

/*
 * Take the appropriate actions to enable this capability for this cpu.
 * Every time a cpu is booted, this method is called under stop_machine()
 * for each globally enabled capability.
 */

(I'm hoping that "globally enabled" is meaningful wording, though
perhaps not.)

Also, what does the return value of this method mean?

Previously, the return value was ignored, but other patches in this
series might change that.

[...]

Cheers
---Dave

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

* Re: [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
  2018-01-25 15:36         ` Dave Martin
@ 2018-01-25 16:57           ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-25 16:57 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, James Morse, jnair,
	Andre Przywara, Robin Murphy, linux-arm-kernel

On 25/01/18 15:36, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 03:38:37PM +0000, Suzuki K Poulose wrote:
>> On 23/01/18 14:52, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
>>>> From: Dave Martin <dave.martin@arm.com>
>>>>
>>>> We issue the enable() call back for all CPU hwcaps capabilities
>>>> available on the system, on all the CPUs. So far we have ignored
>>>> the argument passed to the call back, which had a prototype to
>>>> accept a "void *" for use with on_each_cpu() and later with
>>>> stop_machine(). However, with commit 0a0d111d40fd1
>>>> ("arm64: cpufeature: Pass capability structure to ->enable callback"),
>>>> there are some users of the argument who wants the matching capability
>>>> struct pointer where there are multiple matching criteria for a single
>>>> capability. Update the prototype for enable to accept a const pointer.
>>>>
>>>> Cc: Will Deacon <will.deacon@arm.com>
>>>> Cc: Robin Murphy <robin.murphy@arm.com>
>>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Cc: Andre Przywara <andre.przywara@arm.com>
>>>> Cc: James Morse <james.morse@arm.com>
>>>> Reviewed-by: Julien Thierry <julien.thierry@arm.com>
>>>> Signed-off-by: Dave Martin <dave.martin@arm.com>
>>>> [ Rebased to for-next/core converting more users ]
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h |  3 ++-
>>>>   arch/arm64/include/asm/fpsimd.h     |  4 +++-
>>>>   arch/arm64/include/asm/processor.h  |  7 ++++---
>>>>   arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
>>>>   arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
>>>>   arch/arm64/kernel/fpsimd.c          |  3 ++-
>>>>   arch/arm64/kernel/traps.c           |  3 ++-
>>>>   arch/arm64/mm/fault.c               |  2 +-
>>>>   8 files changed, 32 insertions(+), 20 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index ac67cfc2585a..cefbd685292c 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
>>>>   	u16 capability;
>>>>   	int def_scope;			/* default scope */
>>>>   	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>>>> -	int (*enable)(void *);		/* Called on all active CPUs */
>>>> +	/* Called on all active CPUs for all  "available" capabilities */
>>>
>>> Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
>>> workarounds.
>>>
>>
>> Thanks for spotting, will fix it.
>>
>>> Maybe applicable would be a better word?
>>>
>>
>> There is a subtle difference. If there are two entries for a capability,
>> with only one of them matches, we end up calling the enable() for both
>> the entries. "Applicable" could potentially be misunderstood, leading
>> to assumption that the enable() is called only if that "entry" matches,
>> which is not true. I accept that "available" doesn't sound any better either.
>>
>>
>>>> +	int (*enable)(const struct arm64_cpu_capabilities *caps);
> 
> This probably shouldn't be "caps" here: this argument refers a single
> capability, not an array.  Also, this shouldn't be any random capability,
> but the one corresponding to the enable method:
> 
> 	cap->enable(cap)
> 
> (i.e., cap1->enable(cap2) is invalid, and the cpufeature framework won't
> do that).
> 

Yes, thats correct. I will change it.

>>> Alternatively, if the comment is liable to be ambiguous, maybe it would
>>> be better to delete it.  The explicit argument type already makes this
>>> more self-documenting than previously.
>>
>> I think we still need to make it clear that the enable is called on
>> all active CPUs. It is not about the argument anymore.
>>
>> How about :
>>
>> /*
>>   * Called on all active CPUs if the capability associated with
>>   * this entry is set.
>>   */
> 
> Maybe, but now we have the new concept of "setting" a capability.
> 
> Really, this is enabling the capability for a CPU, not globally, so
> maybe it could be renamed to "cpu_enable".
> 
> Could we describe the method in terms of what it is required to do,
> as well as the circumstances of the call, e.g.:
> 
> /*
>   * Take the appropriate actions to enable this capability for this cpu.
>   * Every time a cpu is booted, this method is called under stop_machine()
>   * for each globally enabled capability.
>   */

Make sense, except for the "stop_machine" part. It is called under stop_machine
for all CPUs brought up by kernel, for capabilities which are enabled from
setup_cpu_features(), i.e, after all the CPUs are booted. But, it is called
directly on the CPU, if the CPU is booted after it has been enabled on CPUs
in the system. (e.g, a CPU brought up by the user - via __verify_local_cpu_caps -,
or a capability that is enabled early by boot CPU - will post the changes in the next
revision).

> 
> (I'm hoping that "globally enabled" is meaningful wording, though
> perhaps not.)

Hmm.. "globally enabled" kind of sounds recursive for describing "enable" :-).
How about "globally accepted" or "globally detected" ?

> 
> Also, what does the return value of this method mean?

Thats a good point. We ignore it. I believe it is best to leave it to the method
to decide, what to do about it if there is a failure. It was there just to make
sure we comply with what stop_machine expected. Now that we don't pass it to
stop_machine directly, we could change it to void.
  
> Previously, the return value was ignored, but other patches in this
> series might change that.
> 

Cheers
Suzuki

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
@ 2018-01-25 16:57           ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-25 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 25/01/18 15:36, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 03:38:37PM +0000, Suzuki K Poulose wrote:
>> On 23/01/18 14:52, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
>>>> From: Dave Martin <dave.martin@arm.com>
>>>>
>>>> We issue the enable() call back for all CPU hwcaps capabilities
>>>> available on the system, on all the CPUs. So far we have ignored
>>>> the argument passed to the call back, which had a prototype to
>>>> accept a "void *" for use with on_each_cpu() and later with
>>>> stop_machine(). However, with commit 0a0d111d40fd1
>>>> ("arm64: cpufeature: Pass capability structure to ->enable callback"),
>>>> there are some users of the argument who wants the matching capability
>>>> struct pointer where there are multiple matching criteria for a single
>>>> capability. Update the prototype for enable to accept a const pointer.
>>>>
>>>> Cc: Will Deacon <will.deacon@arm.com>
>>>> Cc: Robin Murphy <robin.murphy@arm.com>
>>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Cc: Andre Przywara <andre.przywara@arm.com>
>>>> Cc: James Morse <james.morse@arm.com>
>>>> Reviewed-by: Julien Thierry <julien.thierry@arm.com>
>>>> Signed-off-by: Dave Martin <dave.martin@arm.com>
>>>> [ Rebased to for-next/core converting more users ]
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h |  3 ++-
>>>>   arch/arm64/include/asm/fpsimd.h     |  4 +++-
>>>>   arch/arm64/include/asm/processor.h  |  7 ++++---
>>>>   arch/arm64/kernel/cpu_errata.c      | 14 ++++++--------
>>>>   arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++----
>>>>   arch/arm64/kernel/fpsimd.c          |  3 ++-
>>>>   arch/arm64/kernel/traps.c           |  3 ++-
>>>>   arch/arm64/mm/fault.c               |  2 +-
>>>>   8 files changed, 32 insertions(+), 20 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index ac67cfc2585a..cefbd685292c 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
>>>>   	u16 capability;
>>>>   	int def_scope;			/* default scope */
>>>>   	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>>>> -	int (*enable)(void *);		/* Called on all active CPUs */
>>>> +	/* Called on all active CPUs for all  "available" capabilities */
>>>
>>> Nit: Odd spacing?  Also, "available" doesn't really make sense for errata
>>> workarounds.
>>>
>>
>> Thanks for spotting, will fix it.
>>
>>> Maybe applicable would be a better word?
>>>
>>
>> There is a subtle difference. If there are two entries for a capability,
>> with only one of them matches, we end up calling the enable() for both
>> the entries. "Applicable" could potentially be misunderstood, leading
>> to assumption that the enable() is called only if that "entry" matches,
>> which is not true. I accept that "available" doesn't sound any better either.
>>
>>
>>>> +	int (*enable)(const struct arm64_cpu_capabilities *caps);
> 
> This probably shouldn't be "caps" here: this argument refers a single
> capability, not an array.  Also, this shouldn't be any random capability,
> but the one corresponding to the enable method:
> 
> 	cap->enable(cap)
> 
> (i.e., cap1->enable(cap2) is invalid, and the cpufeature framework won't
> do that).
> 

Yes, thats correct. I will change it.

>>> Alternatively, if the comment is liable to be ambiguous, maybe it would
>>> be better to delete it.  The explicit argument type already makes this
>>> more self-documenting than previously.
>>
>> I think we still need to make it clear that the enable is called on
>> all active CPUs. It is not about the argument anymore.
>>
>> How about :
>>
>> /*
>>   * Called on all active CPUs if the capability associated with
>>   * this entry is set.
>>   */
> 
> Maybe, but now we have the new concept of "setting" a capability.
> 
> Really, this is enabling the capability for a CPU, not globally, so
> maybe it could be renamed to "cpu_enable".
> 
> Could we describe the method in terms of what it is required to do,
> as well as the circumstances of the call, e.g.:
> 
> /*
>   * Take the appropriate actions to enable this capability for this cpu.
>   * Every time a cpu is booted, this method is called under stop_machine()
>   * for each globally enabled capability.
>   */

Make sense, except for the "stop_machine" part. It is called under stop_machine
for all CPUs brought up by kernel, for capabilities which are enabled from
setup_cpu_features(), i.e, after all the CPUs are booted. But, it is called
directly on the CPU, if the CPU is booted after it has been enabled on CPUs
in the system. (e.g, a CPU brought up by the user - via __verify_local_cpu_caps -,
or a capability that is enabled early by boot CPU - will post the changes in the next
revision).

> 
> (I'm hoping that "globally enabled" is meaningful wording, though
> perhaps not.)

Hmm.. "globally enabled" kind of sounds recursive for describing "enable" :-).
How about "globally accepted" or "globally detected" ?

> 
> Also, what does the return value of this method mean?

Thats a good point. We ignore it. I believe it is best to leave it to the method
to decide, what to do about it if there is a failure. It was there just to make
sure we comply with what stop_machine expected. Now that we don't pass it to
stop_machine directly, we could change it to void.
  
> Previously, the return value was ignored, but other patches in this
> series might change that.
> 

Cheers
Suzuki

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-25 13:43         ` Dave Martin
@ 2018-01-25 17:08           ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-25 17:08 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 25/01/18 13:43, Dave Martin wrote:
> On Wed, Jan 24, 2018 at 06:45:01PM +0000, Suzuki K Poulose wrote:
>> Dave,
>>
>> Thanks a lot for taking the time to review the patch and for
>> opening up the discussion ! See my comments below.
>>
>> On 23/01/18 17:33, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>>>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>>>> to the userspace and the CPU hwcaps used by the kernel, which
>>>> include cpu features and CPU errata work arounds.
>>>>
>>>> At the moment we have the following restricions:
>>>>
>>>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>>>     - Detected mostly on system wide CPU feature register. But
>>>>       there are some which really uses a local CPU's value to
>>>>       decide the availability (e.g, availability of hardware
>>>>       prefetch). So, we run the check only once, after all the
>>>>       boot-time active CPUs are turned on.
>>>>     - Any late CPU which doesn't posses all the established features
>>>>       is killed.
>>>>     - Any late CPU which possess a feature *not* already available
>>>>       is allowed to boot.
>>>>
>>>>   b) CPU Errata work arounds (arm64_errata)
>>>>     - Detected mostly based on a local CPU's feature register.
>>>>       The checks are run on each boot time activated CPUs.
>>>>     - Any late CPU which doesn't have any of the established errata
>>>>       work around capabilities is ignored and is allowed to boot.
>>>>     - Any late CPU which has an errata work around not already available
>>>>       is killed.
>>>>
>>>> However there are some exceptions to the cases above.
>>>>
>>>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>>>     And any late CPU that has this "feature" should be killed.
>>>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>>>     enabled on CPUs which has it without any issues, even if the CPU is
>>>>     brought up late.
>>>>
>>>> So this calls for a lot more fine grained behavior for each capability.
>>>> And if we define all the attributes to control their behavior properly,
>>>> we may be able to use a single table for the CPU hwcaps (not the
>>>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>>>> to get there. We define type for a capability, which for now encodes the
>>>> scope of the check. i.e, whether it should be checked system wide or on
>>>> each local CPU. We define two types :
>>>>
>>>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
>>>
>>> I'm a bit confused by the naming here.
>>
>>
>> I understand they are not well documented.  I will try to explain here and
>> stick it in somewhere, in the next revision.
>>
>> There are 3 aspects for any capability.
>>
>> 1) SCOPE: How is the capability detected ?
>> i.e, whether it should be detected based on at least one CPU's ID register
>> (e.g, MIDR) (SCOPE_CPU_LOCAL) or System wide value (like ELF HWCAP)(SCOPE_SYSTEM)
>>
>> This is fairly straight forward and hasn't changed much. The only
>> change we need is to allow for CPU "Features" that could be detected on
>> a local CPU. So, "LOCAL" tag has been added to the capabilities which
>> are CPU local.
> 
> I think my confusion here is mostly semantic, so I won't worry too
> much about it for now as I review the patches.
> 
> <aside>
> 
> It is confusing code to dive into though: there is too much overlap
> and ambiguity between the intuitive meanings of "feature", "capability",
> "erratum" etc.  I think this is just the way the code evolved:
> "capability" is an intuitive word to describe that the system can do
> something, but it's a strange word to use for the presence of an
> erratum that must be worked around.
> 
> The immutable properties of CPUs, and the desicion taken by Linux about
> what to do with them, are two quite different things.  I find it easy to
> confuse myself about which is being referred to when we talk about
> "capabilities", partly because the intuitive meaning of this word often
> seems to point to the wrong answer.
> 
> Choosing different words might help, but precise definitions and
> consistent would also help.
> 
> Here, "detecting" sounds like discovery of an immutable characteristic
> of something, but really in the System-wide case you're talking about
> making a policy decision (i.e., what tradeoff to make between working
> with the boot and/or early CPUs, and working with late CPUs that we
> haven't seen yet).  It would be equally valid to make a different
> decision and reject some _early_ CPUs in the hopes that this will
> result in a better performing system (perhaps because we can now
> enable a desirable feature globally, or perhaps to minimise likelihood
> of rejecting late CPUs).
> 
> </aside>
> 
> Anyway, this isn't a high priority.  It's just something that takes a
> little time to get my head around...
> 
>> 2) WHEN: When is the capability "enabled" or in other words, when does the
>> kernel start using the capability. At the moment there is only
>> one place. After all the CPUs are brought up during the kernel init, from
>> setup_cpu_features. (But this will change when we add support for enabling
>> some capabilities very early during the boot, based on the boot CPU. e.g, VHE
>> and GIC CPUIF - for NMI).
>>
>> For now, unless you see "EARLY", in the type, everything is enabled from
>> setup_cpu_features.
> 
> Agreed -- I'd forgotten about this.  To what extent is this orthogonal
> to 1/3/4?

Apologies for not posting the work here, it was delayed due to some
issues with how we handle VHE. I will include it in the next version.

The Early capabilities are based on Boot CPU, and is "detected" only on boot
CPU. So, scope implies SCOPE_CPU_LOCAL. As for (2), the capability is enabled
on the boot CPU right after it is detected, to allow early usage of the feature.
For any other CPU (including the boot time activated ones) we make sure that
they are verified against "early" capabilities.

To make the rule a bit generic, any CPU is verified against the already
"enabled" capabilities. There are two stages during the boot when the capabilities
are enabled.
  1) Early caps: Detected and Enabled on the boot CPU, before any other CPU is
     brought up.
  2) All the other caps: Could be detected on CPU / System wide. But enabled
     only after all the boot time active CPUs are up.

So, in any context, "LATE" tag now implies "after the particular capability"
is enabled by the kernel.

---------------------------------------------------------------
Verification:  | Boot CPU | SMP CPUs by kernel | CPUs by user |
---------------------------------------------------------------
Early cap      |   n      |      y             |       y      |
---------------------------------------------------------------
All other cap  |   n      |      n             |       y      |
---------------------------------------------------------------

The above table kind of  shows how the capabilities are checked for conflicts.
Any early capability is treated as critical and a conflict will result in a
Panic, unless the non-compatible CPU is parked safely. (e.g, for VHE we park
the late CPU with MMU off).

>> 3) WHERE: Where all do we apply the "enable" for a given capability, when it
>> is to be enabled. Do we run it on all CPUs or only on the CPUs with the capability.
>> We don't deal with this in the infrastructure and we run the enable callback
>> on all CPUs irrespective of when the CPU is booted. It is upto the callback
>> to decide if it needs to take some action on a given CPU.
>>
>>
>> 4) CONFLICT: How should we treat a conflict of a capability on a CPU which
>> boots after the capability was enabled in the kernel (as per 2, it could
>> be earlier or after smp CPUs are brought up) ?
>>
>> Here are the possible combinations, representing a Conflict:
>>
>> 	System		| Late Booting CPU
>> a)	   y		|   n
>> b) 	   n		|   y
>>
>> (a) Is considered safe for features like Erratum and KPTI where some
>> actions have to be taken to make the system behave in desirable manner.
>> However (a) is not considered safe for some features we advertise to the
>> user (e.g, ELF HWCAP)
>>
>> (b) Is considered safe for most of the features (except KPTI and Software
>> prefetching), while it is unsafe for Errata, as we couldn't possibly take
>> any action as the time for applying the actions (enabling as per (2) above)
>> has passed already.
>>
>>
>> So we have the following cases :
>>   i)   a_Safe && b_not_Safe
>>   ii)  a_not_Safe && b_Safe
>>   iii) a_Safe && b_Safe
> 
> Is this the same as saying that the CONFLICT type (iii) is not
> applicable to capabilites that are not decided globally?

Practically, yes. But we don't want to label it as such, as we don't know
what future features could come with.

> 
>> I have used "STRICT" tag for category (i) and "WEAK" for (iii). (ii) doesn't
>> have any tag. I acknowledge that this scheme is not particularly intuitive.
>> However I have tried to explain the behavior of "each" defined type in a
>> comment above.
>>
>>>
>>> I'm not keen on the word "strict" because it doesn't really mean
>>> anything unless the rule to be strictly enforced is documented, and
>>> then doesn't really add anything: you could take the view that either
>>> there's an (enforced) rule or there's no rule at all.
>>
>> As I mentioned above, each type is documented on the rules. But the tags
>> are not particularly helpful.
>>
>>>
>>> In this case, (b) seems the "relaxed" case anyway: we allow these
>>> capabilities to be enabled/disabled differently on different CPUs,
>>> rather than requiring the same configuration on all CPUs (KPTI).
>>>
>>> I think there are 2 x 2 orthogonal options:
>>>
>>> A FEATURE capability must be disabled on every CPU where the feature is
>>> not present.  A feature capability is considered desirable, and should
>>> be enabled when possible.
>>>
>>> An ERRATUM capability must be enabled on every CPU where the erratum is
>>> present.  An erratum capability is considered undesirable, and should
>>> be disabled when possible.
>>>
>>> (An erratum is the inverse of a feature with respect to desirability,
>>> enablement and presence.)
>>
>> I would really like to avoid tagging the capabilities FEATURE/ERRATUM
>> to indicate their behavior, because :
>>
>> 1) We could be naming a "feature" ERRATUM, where it is really not one.
>> e.g, KPTI is a security feature and not an erratum.
>>
>> 2) We could be "marking" all "CPU Errata" unsafe when detected late.
>> e.g, Cortex-A55 errata 1024718, can be safely handled by disabling the
>> DBM feature and the conflict can be "ignored" (even though it is not
>> handled via capability).
> 
> That's a fair point.  "Erratum" is describing a set of constraints
> between the CPUs and kernel that is typical of errata handing, but could
> also apply to other features.  So I guess it's not the best choice of
> word.
> 
>> So using the FEATURE/ERRATA will cause further confusion on the real
>> type of the capability. Hence, it would be better if we came up with
>> something other to make it clear.
> 
> I guess it may not be quite as clear-cut as I'm hoping...
> 
>>> and:
>>>
>>> A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
>>> (Thus, a decision must be taken during boot, based on desirability/
>>> undesirability of each capability and based on the assumption that
>>> late CPUs won't violate the decision -- unless this assumption is
>>> overridden by a cmdline arg etc.)
>>>
>>> A LOCAL capability may freely be enabled on some CPUs while disabled on
>>> other CPUs.
>>
>> As discussed in (3) above, I would like to leave it to the "enable()" method
>> to decide where actions are need, to avoid adding more combinations of tags
>> to the type names. We continue to invoke enable() on all CPUs.
> 
> Sure -- if the decisions are made enable() methods rather than blanket
> rules, then we don't need a distinct capability type for every possible
> case.  For the very common cases like the ELF HWCAPs it may be worth it,
> but not for fiddly one-off things.

The types are just a name for collective flags and sometimes there may be
same bits in different names. This is for making it easier to add new
entries to the table with the right bits set.

> 
>>> (Thus, LOCAL is precisely the inverse of GLOBAL.)
>>>
>>>
>>> So:
>>>
>>> 	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
>>> 	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
>>> 	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
>>> 	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).
>>>
>>> ("PERCPU" could be substituted for "LOCAL" if we want to be clearer
>>> about the way in which LOCAL is more permissive.)
>>
>> In general, I understand the names could get some improved scheme.
>> I think if we come up with some nice tag for types i, ii & ii in section (4)
>> we should be good to go.
> 
> This is always something that could be reexamined later.
> 
> I think I understand the basic ideas here a bit better now -- thanks.
> 
> [...]
> 

Thanks
Suzuki

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-25 17:08           ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-25 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

On 25/01/18 13:43, Dave Martin wrote:
> On Wed, Jan 24, 2018 at 06:45:01PM +0000, Suzuki K Poulose wrote:
>> Dave,
>>
>> Thanks a lot for taking the time to review the patch and for
>> opening up the discussion ! See my comments below.
>>
>> On 23/01/18 17:33, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>>>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>>>> to the userspace and the CPU hwcaps used by the kernel, which
>>>> include cpu features and CPU errata work arounds.
>>>>
>>>> At the moment we have the following restricions:
>>>>
>>>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>>>     - Detected mostly on system wide CPU feature register. But
>>>>       there are some which really uses a local CPU's value to
>>>>       decide the availability (e.g, availability of hardware
>>>>       prefetch). So, we run the check only once, after all the
>>>>       boot-time active CPUs are turned on.
>>>>     - Any late CPU which doesn't posses all the established features
>>>>       is killed.
>>>>     - Any late CPU which possess a feature *not* already available
>>>>       is allowed to boot.
>>>>
>>>>   b) CPU Errata work arounds (arm64_errata)
>>>>     - Detected mostly based on a local CPU's feature register.
>>>>       The checks are run on each boot time activated CPUs.
>>>>     - Any late CPU which doesn't have any of the established errata
>>>>       work around capabilities is ignored and is allowed to boot.
>>>>     - Any late CPU which has an errata work around not already available
>>>>       is killed.
>>>>
>>>> However there are some exceptions to the cases above.
>>>>
>>>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>>>     And any late CPU that has this "feature" should be killed.
>>>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>>>     enabled on CPUs which has it without any issues, even if the CPU is
>>>>     brought up late.
>>>>
>>>> So this calls for a lot more fine grained behavior for each capability.
>>>> And if we define all the attributes to control their behavior properly,
>>>> we may be able to use a single table for the CPU hwcaps (not the
>>>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>>>> to get there. We define type for a capability, which for now encodes the
>>>> scope of the check. i.e, whether it should be checked system wide or on
>>>> each local CPU. We define two types :
>>>>
>>>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
>>>
>>> I'm a bit confused by the naming here.
>>
>>
>> I understand they are not well documented.  I will try to explain here and
>> stick it in somewhere, in the next revision.
>>
>> There are 3 aspects for any capability.
>>
>> 1) SCOPE: How is the capability detected ?
>> i.e, whether it should be detected based on at least one CPU's ID register
>> (e.g, MIDR) (SCOPE_CPU_LOCAL) or System wide value (like ELF HWCAP)(SCOPE_SYSTEM)
>>
>> This is fairly straight forward and hasn't changed much. The only
>> change we need is to allow for CPU "Features" that could be detected on
>> a local CPU. So, "LOCAL" tag has been added to the capabilities which
>> are CPU local.
> 
> I think my confusion here is mostly semantic, so I won't worry too
> much about it for now as I review the patches.
> 
> <aside>
> 
> It is confusing code to dive into though: there is too much overlap
> and ambiguity between the intuitive meanings of "feature", "capability",
> "erratum" etc.  I think this is just the way the code evolved:
> "capability" is an intuitive word to describe that the system can do
> something, but it's a strange word to use for the presence of an
> erratum that must be worked around.
> 
> The immutable properties of CPUs, and the desicion taken by Linux about
> what to do with them, are two quite different things.  I find it easy to
> confuse myself about which is being referred to when we talk about
> "capabilities", partly because the intuitive meaning of this word often
> seems to point to the wrong answer.
> 
> Choosing different words might help, but precise definitions and
> consistent would also help.
> 
> Here, "detecting" sounds like discovery of an immutable characteristic
> of something, but really in the System-wide case you're talking about
> making a policy decision (i.e., what tradeoff to make between working
> with the boot and/or early CPUs, and working with late CPUs that we
> haven't seen yet).  It would be equally valid to make a different
> decision and reject some _early_ CPUs in the hopes that this will
> result in a better performing system (perhaps because we can now
> enable a desirable feature globally, or perhaps to minimise likelihood
> of rejecting late CPUs).
> 
> </aside>
> 
> Anyway, this isn't a high priority.  It's just something that takes a
> little time to get my head around...
> 
>> 2) WHEN: When is the capability "enabled" or in other words, when does the
>> kernel start using the capability. At the moment there is only
>> one place. After all the CPUs are brought up during the kernel init, from
>> setup_cpu_features. (But this will change when we add support for enabling
>> some capabilities very early during the boot, based on the boot CPU. e.g, VHE
>> and GIC CPUIF - for NMI).
>>
>> For now, unless you see "EARLY", in the type, everything is enabled from
>> setup_cpu_features.
> 
> Agreed -- I'd forgotten about this.  To what extent is this orthogonal
> to 1/3/4?

Apologies for not posting the work here, it was delayed due to some
issues with how we handle VHE. I will include it in the next version.

The Early capabilities are based on Boot CPU, and is "detected" only on boot
CPU. So, scope implies SCOPE_CPU_LOCAL. As for (2), the capability is enabled
on the boot CPU right after it is detected, to allow early usage of the feature.
For any other CPU (including the boot time activated ones) we make sure that
they are verified against "early" capabilities.

To make the rule a bit generic, any CPU is verified against the already
"enabled" capabilities. There are two stages during the boot when the capabilities
are enabled.
  1) Early caps: Detected and Enabled on the boot CPU, before any other CPU is
     brought up.
  2) All the other caps: Could be detected on CPU / System wide. But enabled
     only after all the boot time active CPUs are up.

So, in any context, "LATE" tag now implies "after the particular capability"
is enabled by the kernel.

---------------------------------------------------------------
Verification:  | Boot CPU | SMP CPUs by kernel | CPUs by user |
---------------------------------------------------------------
Early cap      |   n      |      y             |       y      |
---------------------------------------------------------------
All other cap  |   n      |      n             |       y      |
---------------------------------------------------------------

The above table kind of  shows how the capabilities are checked for conflicts.
Any early capability is treated as critical and a conflict will result in a
Panic, unless the non-compatible CPU is parked safely. (e.g, for VHE we park
the late CPU with MMU off).

>> 3) WHERE: Where all do we apply the "enable" for a given capability, when it
>> is to be enabled. Do we run it on all CPUs or only on the CPUs with the capability.
>> We don't deal with this in the infrastructure and we run the enable callback
>> on all CPUs irrespective of when the CPU is booted. It is upto the callback
>> to decide if it needs to take some action on a given CPU.
>>
>>
>> 4) CONFLICT: How should we treat a conflict of a capability on a CPU which
>> boots after the capability was enabled in the kernel (as per 2, it could
>> be earlier or after smp CPUs are brought up) ?
>>
>> Here are the possible combinations, representing a Conflict:
>>
>> 	System		| Late Booting CPU
>> a)	   y		|   n
>> b) 	   n		|   y
>>
>> (a) Is considered safe for features like Erratum and KPTI where some
>> actions have to be taken to make the system behave in desirable manner.
>> However (a) is not considered safe for some features we advertise to the
>> user (e.g, ELF HWCAP)
>>
>> (b) Is considered safe for most of the features (except KPTI and Software
>> prefetching), while it is unsafe for Errata, as we couldn't possibly take
>> any action as the time for applying the actions (enabling as per (2) above)
>> has passed already.
>>
>>
>> So we have the following cases :
>>   i)   a_Safe && b_not_Safe
>>   ii)  a_not_Safe && b_Safe
>>   iii) a_Safe && b_Safe
> 
> Is this the same as saying that the CONFLICT type (iii) is not
> applicable to capabilites that are not decided globally?

Practically, yes. But we don't want to label it as such, as we don't know
what future features could come with.

> 
>> I have used "STRICT" tag for category (i) and "WEAK" for (iii). (ii) doesn't
>> have any tag. I acknowledge that this scheme is not particularly intuitive.
>> However I have tried to explain the behavior of "each" defined type in a
>> comment above.
>>
>>>
>>> I'm not keen on the word "strict" because it doesn't really mean
>>> anything unless the rule to be strictly enforced is documented, and
>>> then doesn't really add anything: you could take the view that either
>>> there's an (enforced) rule or there's no rule at all.
>>
>> As I mentioned above, each type is documented on the rules. But the tags
>> are not particularly helpful.
>>
>>>
>>> In this case, (b) seems the "relaxed" case anyway: we allow these
>>> capabilities to be enabled/disabled differently on different CPUs,
>>> rather than requiring the same configuration on all CPUs (KPTI).
>>>
>>> I think there are 2 x 2 orthogonal options:
>>>
>>> A FEATURE capability must be disabled on every CPU where the feature is
>>> not present.  A feature capability is considered desirable, and should
>>> be enabled when possible.
>>>
>>> An ERRATUM capability must be enabled on every CPU where the erratum is
>>> present.  An erratum capability is considered undesirable, and should
>>> be disabled when possible.
>>>
>>> (An erratum is the inverse of a feature with respect to desirability,
>>> enablement and presence.)
>>
>> I would really like to avoid tagging the capabilities FEATURE/ERRATUM
>> to indicate their behavior, because :
>>
>> 1) We could be naming a "feature" ERRATUM, where it is really not one.
>> e.g, KPTI is a security feature and not an erratum.
>>
>> 2) We could be "marking" all "CPU Errata" unsafe when detected late.
>> e.g, Cortex-A55 errata 1024718, can be safely handled by disabling the
>> DBM feature and the conflict can be "ignored" (even though it is not
>> handled via capability).
> 
> That's a fair point.  "Erratum" is describing a set of constraints
> between the CPUs and kernel that is typical of errata handing, but could
> also apply to other features.  So I guess it's not the best choice of
> word.
> 
>> So using the FEATURE/ERRATA will cause further confusion on the real
>> type of the capability. Hence, it would be better if we came up with
>> something other to make it clear.
> 
> I guess it may not be quite as clear-cut as I'm hoping...
> 
>>> and:
>>>
>>> A GLOBAL capability must be enabled on all CPUs or disabled on all CPUs.
>>> (Thus, a decision must be taken during boot, based on desirability/
>>> undesirability of each capability and based on the assumption that
>>> late CPUs won't violate the decision -- unless this assumption is
>>> overridden by a cmdline arg etc.)
>>>
>>> A LOCAL capability may freely be enabled on some CPUs while disabled on
>>> other CPUs.
>>
>> As discussed in (3) above, I would like to leave it to the "enable()" method
>> to decide where actions are need, to avoid adding more combinations of tags
>> to the type names. We continue to invoke enable() on all CPUs.
> 
> Sure -- if the decisions are made enable() methods rather than blanket
> rules, then we don't need a distinct capability type for every possible
> case.  For the very common cases like the ELF HWCAPs it may be worth it,
> but not for fiddly one-off things.

The types are just a name for collective flags and sometimes there may be
same bits in different names. This is for making it easier to add new
entries to the table with the right bits set.

> 
>>> (Thus, LOCAL is precisely the inverse of GLOBAL.)
>>>
>>>
>>> So:
>>>
>>> 	ARM64_CPUCAP_GLOBAL_FEATURE	(hwcap case)
>>> 	ARM64_CPUCAP_LOCAL_FEATURE	(DBM case)
>>> 	ARM64_CPUCAP_GLOBAL_ERRATUM	(KPTI case)
>>> 	ARM64_CPUCAP_LOCAL_ERRATUM	(regular CPU erratum case).
>>>
>>> ("PERCPU" could be substituted for "LOCAL" if we want to be clearer
>>> about the way in which LOCAL is more permissive.)
>>
>> In general, I understand the names could get some improved scheme.
>> I think if we come up with some nice tag for types i, ii & ii in section (4)
>> we should be good to go.
> 
> This is always something that could be reexamined later.
> 
> I think I understand the basic ideas here a bit better now -- thanks.
> 
> [...]
> 

Thanks
Suzuki

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-23 12:27   ` Suzuki K Poulose
@ 2018-01-25 17:33     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 17:33 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> to the userspace and the CPU hwcaps used by the kernel, which
> include cpu features and CPU errata work arounds.
> 
> At the moment we have the following restricions:
> 
>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>    - Detected mostly on system wide CPU feature register. But
>      there are some which really uses a local CPU's value to
>      decide the availability (e.g, availability of hardware
>      prefetch). So, we run the check only once, after all the
>      boot-time active CPUs are turned on.

[ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
presumably because the only systems to which it applies are homogeneous,
and anyway it's only an optimisation IIUC.

This could be a separate category, but as a one-off that may be a bit
pointless.

.def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
unused in that case.]

>    - Any late CPU which doesn't posses all the established features
>      is killed.

Does "established feature" above ...

>    - Any late CPU which possess a feature *not* already available
>      is allowed to boot.

mean the same as "feature already available" here?

> 
>  b) CPU Errata work arounds (arm64_errata)
>    - Detected mostly based on a local CPU's feature register.
>      The checks are run on each boot time activated CPUs.
>    - Any late CPU which doesn't have any of the established errata
>      work around capabilities is ignored and is allowed to boot.
>    - Any late CPU which has an errata work around not already available
>      is killed.
> 
> However there are some exceptions to the cases above.
> 
> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>    And any late CPU that has this "feature" should be killed.

Should that be "If KPTI is not enabled during system boot, then any late
CPU that has this "feature" should be killed."

> 2) Hardware DBM feature is a non-conflicting capability which could be
>    enabled on CPUs which has it without any issues, even if the CPU is

have

>    brought up late.
> 
> So this calls for a lot more fine grained behavior for each capability.
> And if we define all the attributes to control their behavior properly,
> we may be able to use a single table for the CPU hwcaps (not the
> ELF HWCAPs, which cover errata and features). This is a prepartory step
> to get there. We define type for a capability, which for now encodes the
> scope of the check. i.e, whether it should be checked system wide or on
> each local CPU. We define two types :
> 
>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.

2)

> As such there is no change in how the capabilities are treated.

OK, I think I finally have my head around this, more or less.

Mechanism (operations on architectural feature regs) and policy (kernel
runtime configuration) seem to be rather mixed together.  This works
fairly naturally for things like deriving the sanitised feature regs
seen by userspace and determining the ELF hwcaps; but not so naturally
for errata workarounds and other anomalous things like
ARM64_HAS_NO_HW_PREFETCH.

I'm not sure that there is a better approach though -- anyway, that
would be out of scope for this series.

> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
>  arch/arm64/kernel/cpu_errata.c      |  8 ++++----
>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
>  3 files changed, 41 insertions(+), 29 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a23c0d4f27e9..4fd5de8ef33e 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -86,16 +86,23 @@ struct arm64_ftr_reg {
>  
>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  
> -/* scope of capability check */
> -enum {
> -	SCOPE_SYSTEM,
> -	SCOPE_LOCAL_CPU,
> -};
> +
> +/* Decide how the capability is detected. On a local CPU vs System wide */
> +#define ARM64_CPUCAP_SCOPE_MASK			0x3
> +#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
> +#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU

Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?

Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).

> +
> +/* CPU errata detected at boot time based on feature of one or more CPUs */
> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)

> +/* CPU feature detected at boot time based on system-wide value of a feature */

I'm still not overly keen on these names, but I do at least see where
they come from now.

Nit: redundant () in these two #defines btw.

[...]

Cheers
---Dave

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-25 17:33     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 17:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> to the userspace and the CPU hwcaps used by the kernel, which
> include cpu features and CPU errata work arounds.
> 
> At the moment we have the following restricions:
> 
>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>    - Detected mostly on system wide CPU feature register. But
>      there are some which really uses a local CPU's value to
>      decide the availability (e.g, availability of hardware
>      prefetch). So, we run the check only once, after all the
>      boot-time active CPUs are turned on.

[ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
presumably because the only systems to which it applies are homogeneous,
and anyway it's only an optimisation IIUC.

This could be a separate category, but as a one-off that may be a bit
pointless.

.def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
unused in that case.]

>    - Any late CPU which doesn't posses all the established features
>      is killed.

Does "established feature" above ...

>    - Any late CPU which possess a feature *not* already available
>      is allowed to boot.

mean the same as "feature already available" here?

> 
>  b) CPU Errata work arounds (arm64_errata)
>    - Detected mostly based on a local CPU's feature register.
>      The checks are run on each boot time activated CPUs.
>    - Any late CPU which doesn't have any of the established errata
>      work around capabilities is ignored and is allowed to boot.
>    - Any late CPU which has an errata work around not already available
>      is killed.
> 
> However there are some exceptions to the cases above.
> 
> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>    And any late CPU that has this "feature" should be killed.

Should that be "If KPTI is not enabled during system boot, then any late
CPU that has this "feature" should be killed."

> 2) Hardware DBM feature is a non-conflicting capability which could be
>    enabled on CPUs which has it without any issues, even if the CPU is

have

>    brought up late.
> 
> So this calls for a lot more fine grained behavior for each capability.
> And if we define all the attributes to control their behavior properly,
> we may be able to use a single table for the CPU hwcaps (not the
> ELF HWCAPs, which cover errata and features). This is a prepartory step
> to get there. We define type for a capability, which for now encodes the
> scope of the check. i.e, whether it should be checked system wide or on
> each local CPU. We define two types :
> 
>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.

2)

> As such there is no change in how the capabilities are treated.

OK, I think I finally have my head around this, more or less.

Mechanism (operations on architectural feature regs) and policy (kernel
runtime configuration) seem to be rather mixed together.  This works
fairly naturally for things like deriving the sanitised feature regs
seen by userspace and determining the ELF hwcaps; but not so naturally
for errata workarounds and other anomalous things like
ARM64_HAS_NO_HW_PREFETCH.

I'm not sure that there is a better approach though -- anyway, that
would be out of scope for this series.

> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
>  arch/arm64/kernel/cpu_errata.c      |  8 ++++----
>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
>  3 files changed, 41 insertions(+), 29 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a23c0d4f27e9..4fd5de8ef33e 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -86,16 +86,23 @@ struct arm64_ftr_reg {
>  
>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  
> -/* scope of capability check */
> -enum {
> -	SCOPE_SYSTEM,
> -	SCOPE_LOCAL_CPU,
> -};
> +
> +/* Decide how the capability is detected. On a local CPU vs System wide */
> +#define ARM64_CPUCAP_SCOPE_MASK			0x3
> +#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
> +#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU

Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?

Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).

> +
> +/* CPU errata detected at boot time based on feature of one or more CPUs */
> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)

> +/* CPU feature detected at boot time based on system-wide value of a feature */

I'm still not overly keen on these names, but I do at least see where
they come from now.

Nit: redundant () in these two #defines btw.

[...]

Cheers
---Dave

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-25 17:08           ` Suzuki K Poulose
@ 2018-01-25 17:38             ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 17:38 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Thu, Jan 25, 2018 at 05:08:58PM +0000, Suzuki K Poulose wrote:
> On 25/01/18 13:43, Dave Martin wrote:

[...]

> >>2) WHEN: When is the capability "enabled" or in other words, when does the
> >>kernel start using the capability. At the moment there is only
> >>one place. After all the CPUs are brought up during the kernel init, from
> >>setup_cpu_features. (But this will change when we add support for enabling
> >>some capabilities very early during the boot, based on the boot CPU. e.g, VHE
> >>and GIC CPUIF - for NMI).
> >>
> >>For now, unless you see "EARLY", in the type, everything is enabled from
> >>setup_cpu_features.
> >
> >Agreed -- I'd forgotten about this.  To what extent is this orthogonal
> >to 1/3/4?
> 
> Apologies for not posting the work here, it was delayed due to some
> issues with how we handle VHE. I will include it in the next version.
> 
> The Early capabilities are based on Boot CPU, and is "detected" only on boot
> CPU. So, scope implies SCOPE_CPU_LOCAL. As for (2), the capability is enabled
> on the boot CPU right after it is detected, to allow early usage of the feature.
> For any other CPU (including the boot time activated ones) we make sure that
> they are verified against "early" capabilities.
> 
> To make the rule a bit generic, any CPU is verified against the already
> "enabled" capabilities. There are two stages during the boot when the capabilities
> are enabled.
>  1) Early caps: Detected and Enabled on the boot CPU, before any other CPU is
>     brought up.
>  2) All the other caps: Could be detected on CPU / System wide. But enabled
>     only after all the boot time active CPUs are up.
> 
> So, in any context, "LATE" tag now implies "after the particular capability"
> is enabled by the kernel.
> 
> ---------------------------------------------------------------
> Verification:  | Boot CPU | SMP CPUs by kernel | CPUs by user |
> ---------------------------------------------------------------
> Early cap      |   n      |      y             |       y      |
> ---------------------------------------------------------------
> All other cap  |   n      |      n             |       y      |
> ---------------------------------------------------------------
> 
> The above table kind of  shows how the capabilities are checked for conflicts.
> Any early capability is treated as critical and a conflict will result in a
> Panic, unless the non-compatible CPU is parked safely. (e.g, for VHE we park
> the late CPU with MMU off).

OK, this makes sense to me now -- thanks.

[...]

> >>4) CONFLICT: How should we treat a conflict of a capability on a CPU which
> >>boots after the capability was enabled in the kernel (as per 2, it could
> >>be earlier or after smp CPUs are brought up) ?
> >>
> >>Here are the possible combinations, representing a Conflict:
> >>
> >>	System		| Late Booting CPU
> >>a)	   y		|   n
> >>b) 	   n		|   y
> >>
> >>(a) Is considered safe for features like Erratum and KPTI where some
> >>actions have to be taken to make the system behave in desirable manner.
> >>However (a) is not considered safe for some features we advertise to the
> >>user (e.g, ELF HWCAP)
> >>
> >>(b) Is considered safe for most of the features (except KPTI and Software
> >>prefetching), while it is unsafe for Errata, as we couldn't possibly take
> >>any action as the time for applying the actions (enabling as per (2) above)
> >>has passed already.
> >>
> >>
> >>So we have the following cases :
> >>  i)   a_Safe && b_not_Safe
> >>  ii)  a_not_Safe && b_Safe
> >>  iii) a_Safe && b_Safe
> >
> >Is this the same as saying that the CONFLICT type (iii) is not
> >applicable to capabilites that are not decided globally?
> 
> Practically, yes. But we don't want to label it as such, as we don't know
> what future features could come with.

[...]

> The types are just a name for collective flags and sometimes there may be
> same bits in different names. This is for making it easier to add new
> entries to the table with the right bits set.

Fair enough.

[...]

Cheers
---Dave

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-25 17:38             ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-25 17:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 25, 2018 at 05:08:58PM +0000, Suzuki K Poulose wrote:
> On 25/01/18 13:43, Dave Martin wrote:

[...]

> >>2) WHEN: When is the capability "enabled" or in other words, when does the
> >>kernel start using the capability. At the moment there is only
> >>one place. After all the CPUs are brought up during the kernel init, from
> >>setup_cpu_features. (But this will change when we add support for enabling
> >>some capabilities very early during the boot, based on the boot CPU. e.g, VHE
> >>and GIC CPUIF - for NMI).
> >>
> >>For now, unless you see "EARLY", in the type, everything is enabled from
> >>setup_cpu_features.
> >
> >Agreed -- I'd forgotten about this.  To what extent is this orthogonal
> >to 1/3/4?
> 
> Apologies for not posting the work here, it was delayed due to some
> issues with how we handle VHE. I will include it in the next version.
> 
> The Early capabilities are based on Boot CPU, and is "detected" only on boot
> CPU. So, scope implies SCOPE_CPU_LOCAL. As for (2), the capability is enabled
> on the boot CPU right after it is detected, to allow early usage of the feature.
> For any other CPU (including the boot time activated ones) we make sure that
> they are verified against "early" capabilities.
> 
> To make the rule a bit generic, any CPU is verified against the already
> "enabled" capabilities. There are two stages during the boot when the capabilities
> are enabled.
>  1) Early caps: Detected and Enabled on the boot CPU, before any other CPU is
>     brought up.
>  2) All the other caps: Could be detected on CPU / System wide. But enabled
>     only after all the boot time active CPUs are up.
> 
> So, in any context, "LATE" tag now implies "after the particular capability"
> is enabled by the kernel.
> 
> ---------------------------------------------------------------
> Verification:  | Boot CPU | SMP CPUs by kernel | CPUs by user |
> ---------------------------------------------------------------
> Early cap      |   n      |      y             |       y      |
> ---------------------------------------------------------------
> All other cap  |   n      |      n             |       y      |
> ---------------------------------------------------------------
> 
> The above table kind of  shows how the capabilities are checked for conflicts.
> Any early capability is treated as critical and a conflict will result in a
> Panic, unless the non-compatible CPU is parked safely. (e.g, for VHE we park
> the late CPU with MMU off).

OK, this makes sense to me now -- thanks.

[...]

> >>4) CONFLICT: How should we treat a conflict of a capability on a CPU which
> >>boots after the capability was enabled in the kernel (as per 2, it could
> >>be earlier or after smp CPUs are brought up) ?
> >>
> >>Here are the possible combinations, representing a Conflict:
> >>
> >>	System		| Late Booting CPU
> >>a)	   y		|   n
> >>b) 	   n		|   y
> >>
> >>(a) Is considered safe for features like Erratum and KPTI where some
> >>actions have to be taken to make the system behave in desirable manner.
> >>However (a) is not considered safe for some features we advertise to the
> >>user (e.g, ELF HWCAP)
> >>
> >>(b) Is considered safe for most of the features (except KPTI and Software
> >>prefetching), while it is unsafe for Errata, as we couldn't possibly take
> >>any action as the time for applying the actions (enabling as per (2) above)
> >>has passed already.
> >>
> >>
> >>So we have the following cases :
> >>  i)   a_Safe && b_not_Safe
> >>  ii)  a_not_Safe && b_Safe
> >>  iii) a_Safe && b_Safe
> >
> >Is this the same as saying that the CONFLICT type (iii) is not
> >applicable to capabilites that are not decided globally?
> 
> Practically, yes. But we don't want to label it as such, as we don't know
> what future features could come with.

[...]

> The types are just a name for collective flags and sometimes there may be
> same bits in different names. This is for making it easier to add new
> entries to the table with the right bits set.

Fair enough.

[...]

Cheers
---Dave

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-25 17:33     ` Dave Martin
@ 2018-01-25 17:56       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-25 17:56 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 25/01/18 17:33, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>> to the userspace and the CPU hwcaps used by the kernel, which
>> include cpu features and CPU errata work arounds.
>>
>> At the moment we have the following restricions:
>>
>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>     - Detected mostly on system wide CPU feature register. But
>>       there are some which really uses a local CPU's value to
>>       decide the availability (e.g, availability of hardware
>>       prefetch). So, we run the check only once, after all the
>>       boot-time active CPUs are turned on.
> 
> [ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
> presumably because the only systems to which it applies are homogeneous,
> and anyway it's only an optimisation IIUC.
> 
> This could be a separate category, but as a one-off that may be a bit
> pointless.
I understand and was planning to fix this back when it was introduced.
But then it was pointless at that time, given that it was always
guaranteed to be a homogeneous system. We do something about it in
Patch 9.

> 
> .def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
> unused in that case.]
> 
>>     - Any late CPU which doesn't posses all the established features
>>       is killed.
> 
> Does "established feature" above ...
> 
>>     - Any late CPU which possess a feature *not* already available
>>       is allowed to boot.
> 
> mean the same as "feature already available" here?

Yes, its the same. I should have been more consistent.

> 
>>
>>   b) CPU Errata work arounds (arm64_errata)
>>     - Detected mostly based on a local CPU's feature register.
>>       The checks are run on each boot time activated CPUs.
>>     - Any late CPU which doesn't have any of the established errata
>>       work around capabilities is ignored and is allowed to boot.
>>     - Any late CPU which has an errata work around not already available
>>       is killed.
>>
>> However there are some exceptions to the cases above.
>>
>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>     And any late CPU that has this "feature" should be killed.
> 
> Should that be "If KPTI is not enabled during system boot, then any late
> CPU that has this "feature" should be killed."

Yes.

> 
>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>     enabled on CPUs which has it without any issues, even if the CPU is
> 
> have
> 

>>     brought up late.
>>
>> So this calls for a lot more fine grained behavior for each capability.
>> And if we define all the attributes to control their behavior properly,
>> we may be able to use a single table for the CPU hwcaps (not the
>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>> to get there. We define type for a capability, which for now encodes the
>> scope of the check. i.e, whether it should be checked system wide or on
>> each local CPU. We define two types :
>>
>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> 
> 2)
> 
>> As such there is no change in how the capabilities are treated.
> 
> OK, I think I finally have my head around this, more or less.
> 
> Mechanism (operations on architectural feature regs) and policy (kernel
> runtime configuration) seem to be rather mixed together.  This works
> fairly naturally for things like deriving the sanitised feature regs
> seen by userspace and determining the ELF hwcaps; but not so naturally
> for errata workarounds and other anomalous things like
> ARM64_HAS_NO_HW_PREFETCH.

Right. We are stuck with "cpu_hwcaps" for both erratum and features,
based on which we make some decisions to change the kernel behavior,
as it is tied to alternative patching.

> 
> I'm not sure that there is a better approach though -- anyway, that
> would be out of scope for this series.
> 
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
>>   arch/arm64/kernel/cpu_errata.c      |  8 ++++----
>>   arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
>>   3 files changed, 41 insertions(+), 29 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index a23c0d4f27e9..4fd5de8ef33e 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -86,16 +86,23 @@ struct arm64_ftr_reg {
>>   
>>   extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   
>> -/* scope of capability check */
>> -enum {
>> -	SCOPE_SYSTEM,
>> -	SCOPE_LOCAL_CPU,
>> -};
>> +
>> +/* Decide how the capability is detected. On a local CPU vs System wide */
>> +#define ARM64_CPUCAP_SCOPE_MASK			0x3
>> +#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
>> +#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
>> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> 
> Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?

It is an unsupported configuration.

> 
> Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).
> 

It is a bit tricky. I chose separate bits to allow filter an entry in a table
of capabilities based on the bits. e.g, we want to

1) Process only the local scope (e.g detecting CPU local capabilities, where
we are not yet ready to run the system wide checks)

2) Process all the entries including local/system. (e.g, verifying all the
capabilities for a late CPU).

Things get further complicated by the addition of "EARLY", where we want to
filter entries based on "EARLY" bit. So, we need to pass on a mask of bits
to the helpers, which are not just the binary scope. See Patch 7 for more
info.

>> +
>> +/* CPU errata detected at boot time based on feature of one or more CPUs */
>> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> 
>> +/* CPU feature detected at boot time based on system-wide value of a feature */
> 
> I'm still not overly keen on these names, but I do at least see where
> they come from now.
> 
> Nit: redundant () in these two #defines btw.

Ok.

Suzuki

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-25 17:56       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-25 17:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 25/01/18 17:33, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>> to the userspace and the CPU hwcaps used by the kernel, which
>> include cpu features and CPU errata work arounds.
>>
>> At the moment we have the following restricions:
>>
>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>     - Detected mostly on system wide CPU feature register. But
>>       there are some which really uses a local CPU's value to
>>       decide the availability (e.g, availability of hardware
>>       prefetch). So, we run the check only once, after all the
>>       boot-time active CPUs are turned on.
> 
> [ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
> presumably because the only systems to which it applies are homogeneous,
> and anyway it's only an optimisation IIUC.
> 
> This could be a separate category, but as a one-off that may be a bit
> pointless.
I understand and was planning to fix this back when it was introduced.
But then it was pointless at that time, given that it was always
guaranteed to be a homogeneous system. We do something about it in
Patch 9.

> 
> .def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
> unused in that case.]
> 
>>     - Any late CPU which doesn't posses all the established features
>>       is killed.
> 
> Does "established feature" above ...
> 
>>     - Any late CPU which possess a feature *not* already available
>>       is allowed to boot.
> 
> mean the same as "feature already available" here?

Yes, its the same. I should have been more consistent.

> 
>>
>>   b) CPU Errata work arounds (arm64_errata)
>>     - Detected mostly based on a local CPU's feature register.
>>       The checks are run on each boot time activated CPUs.
>>     - Any late CPU which doesn't have any of the established errata
>>       work around capabilities is ignored and is allowed to boot.
>>     - Any late CPU which has an errata work around not already available
>>       is killed.
>>
>> However there are some exceptions to the cases above.
>>
>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>     And any late CPU that has this "feature" should be killed.
> 
> Should that be "If KPTI is not enabled during system boot, then any late
> CPU that has this "feature" should be killed."

Yes.

> 
>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>     enabled on CPUs which has it without any issues, even if the CPU is
> 
> have
> 

>>     brought up late.
>>
>> So this calls for a lot more fine grained behavior for each capability.
>> And if we define all the attributes to control their behavior properly,
>> we may be able to use a single table for the CPU hwcaps (not the
>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>> to get there. We define type for a capability, which for now encodes the
>> scope of the check. i.e, whether it should be checked system wide or on
>> each local CPU. We define two types :
>>
>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> 
> 2)
> 
>> As such there is no change in how the capabilities are treated.
> 
> OK, I think I finally have my head around this, more or less.
> 
> Mechanism (operations on architectural feature regs) and policy (kernel
> runtime configuration) seem to be rather mixed together.  This works
> fairly naturally for things like deriving the sanitised feature regs
> seen by userspace and determining the ELF hwcaps; but not so naturally
> for errata workarounds and other anomalous things like
> ARM64_HAS_NO_HW_PREFETCH.

Right. We are stuck with "cpu_hwcaps" for both erratum and features,
based on which we make some decisions to change the kernel behavior,
as it is tied to alternative patching.

> 
> I'm not sure that there is a better approach though -- anyway, that
> would be out of scope for this series.
> 
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
>>   arch/arm64/kernel/cpu_errata.c      |  8 ++++----
>>   arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
>>   3 files changed, 41 insertions(+), 29 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index a23c0d4f27e9..4fd5de8ef33e 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -86,16 +86,23 @@ struct arm64_ftr_reg {
>>   
>>   extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   
>> -/* scope of capability check */
>> -enum {
>> -	SCOPE_SYSTEM,
>> -	SCOPE_LOCAL_CPU,
>> -};
>> +
>> +/* Decide how the capability is detected. On a local CPU vs System wide */
>> +#define ARM64_CPUCAP_SCOPE_MASK			0x3
>> +#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
>> +#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
>> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> 
> Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?

It is an unsupported configuration.

> 
> Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).
> 

It is a bit tricky. I chose separate bits to allow filter an entry in a table
of capabilities based on the bits. e.g, we want to

1) Process only the local scope (e.g detecting CPU local capabilities, where
we are not yet ready to run the system wide checks)

2) Process all the entries including local/system. (e.g, verifying all the
capabilities for a late CPU).

Things get further complicated by the addition of "EARLY", where we want to
filter entries based on "EARLY" bit. So, we need to pass on a mask of bits
to the helpers, which are not just the binary scope. See Patch 7 for more
info.

>> +
>> +/* CPU errata detected at boot time based on feature of one or more CPUs */
>> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> 
>> +/* CPU feature detected at boot time based on system-wide value of a feature */
> 
> I'm still not overly keen on these names, but I do at least see where
> they come from now.
> 
> Nit: redundant () in these two #defines btw.

Ok.

Suzuki

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-25 17:56       ` Suzuki K Poulose
@ 2018-01-26 10:00         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 10:00 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Thu, Jan 25, 2018 at 05:56:02PM +0000, Suzuki K Poulose wrote:
> On 25/01/18 17:33, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> >>We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> >>to the userspace and the CPU hwcaps used by the kernel, which
> >>include cpu features and CPU errata work arounds.
> >>
> >>At the moment we have the following restricions:
> >>
> >>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
> >>    - Detected mostly on system wide CPU feature register. But
> >>      there are some which really uses a local CPU's value to
> >>      decide the availability (e.g, availability of hardware
> >>      prefetch). So, we run the check only once, after all the
> >>      boot-time active CPUs are turned on.
> >
> >[ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
> >presumably because the only systems to which it applies are homogeneous,
> >and anyway it's only an optimisation IIUC.
> >
> >This could be a separate category, but as a one-off that may be a bit
> >pointless.
> I understand and was planning to fix this back when it was introduced.
> But then it was pointless at that time, given that it was always
> guaranteed to be a homogeneous system. We do something about it in
> Patch 9.

This was just on observation than something that needs to be fixed,
but it it's been cleaned up then so much the better :)

I'll take a look.

> >.def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
> >unused in that case.]
> >
> >>    - Any late CPU which doesn't posses all the established features
> >>      is killed.
> >
> >Does "established feature" above ...
> >
> >>    - Any late CPU which possess a feature *not* already available
> >>      is allowed to boot.
> >
> >mean the same as "feature already available" here?
> 
> Yes, its the same. I should have been more consistent.
> 
> >
> >>
> >>  b) CPU Errata work arounds (arm64_errata)
> >>    - Detected mostly based on a local CPU's feature register.
> >>      The checks are run on each boot time activated CPUs.
> >>    - Any late CPU which doesn't have any of the established errata
> >>      work around capabilities is ignored and is allowed to boot.
> >>    - Any late CPU which has an errata work around not already available
> >>      is killed.
> >>
> >>However there are some exceptions to the cases above.
> >>
> >>1) KPTI is a feature that we need to enable when at least one CPU needs it.
> >>    And any late CPU that has this "feature" should be killed.
> >
> >Should that be "If KPTI is not enabled during system boot, then any late
> >CPU that has this "feature" should be killed."
> 
> Yes.
> 
> >
> >>2) Hardware DBM feature is a non-conflicting capability which could be
> >>    enabled on CPUs which has it without any issues, even if the CPU is
> >
> >have
> >
> 
> >>    brought up late.
> >>
> >>So this calls for a lot more fine grained behavior for each capability.
> >>And if we define all the attributes to control their behavior properly,
> >>we may be able to use a single table for the CPU hwcaps (not the
> >>ELF HWCAPs, which cover errata and features). This is a prepartory step
> >>to get there. We define type for a capability, which for now encodes the
> >>scope of the check. i.e, whether it should be checked system wide or on
> >>each local CPU. We define two types :
> >>
> >>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
> >>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> >
> >2)

Meaning you've got 1) twice above (in case you didn't spot it).

> >
> >>As such there is no change in how the capabilities are treated.
> >
> >OK, I think I finally have my head around this, more or less.
> >
> >Mechanism (operations on architectural feature regs) and policy (kernel
> >runtime configuration) seem to be rather mixed together.  This works
> >fairly naturally for things like deriving the sanitised feature regs
> >seen by userspace and determining the ELF hwcaps; but not so naturally
> >for errata workarounds and other anomalous things like
> >ARM64_HAS_NO_HW_PREFETCH.
> 
> Right. We are stuck with "cpu_hwcaps" for both erratum and features,
> based on which we make some decisions to change the kernel behavior,
> as it is tied to alternative patching.
> 
> >
> >I'm not sure that there is a better approach though -- anyway, that
> >would be out of scope for this series.
> >
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
> >>  arch/arm64/kernel/cpu_errata.c      |  8 ++++----
> >>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
> >>  3 files changed, 41 insertions(+), 29 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index a23c0d4f27e9..4fd5de8ef33e 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -86,16 +86,23 @@ struct arm64_ftr_reg {
> >>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>-/* scope of capability check */
> >>-enum {
> >>-	SCOPE_SYSTEM,
> >>-	SCOPE_LOCAL_CPU,
> >>-};
> >>+
> >>+/* Decide how the capability is detected. On a local CPU vs System wide */
> >>+#define ARM64_CPUCAP_SCOPE_MASK			0x3
> >>+#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
> >>+#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
> >>+#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> >>+#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> >
> >Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?
> 
> It is an unsupported configuration.

Surely meaningless, not just unsupported?

> >
> >Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).
> >
> 
> It is a bit tricky. I chose separate bits to allow filter an entry in a table
> of capabilities based on the bits. e.g, we want to
> 
> 1) Process only the local scope (e.g detecting CPU local capabilities, where
> we are not yet ready to run the system wide checks)
> 
> 2) Process all the entries including local/system. (e.g, verifying all the
> capabilities for a late CPU).

OK, so LOCAL_CPU and SYSTEM are mutually exclusive for the cap type, but
by making them separate bits in a bitmask then (LOCAL_CPU | SYSTEM) as a
match value will match on either.

> Things get further complicated by the addition of "EARLY", where we want to
> filter entries based on "EARLY" bit. So, we need to pass on a mask of bits
> to the helpers, which are not just the binary scope. See Patch 7 for more
> info.
> 
> >>+
> >>+/* CPU errata detected at boot time based on feature of one or more CPUs */
> >>+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> >
> >>+/* CPU feature detected at boot time based on system-wide value of a feature */
> >
> >I'm still not overly keen on these names, but I do at least see where
> >they come from now.
> >
> >Nit: redundant () in these two #defines btw.
> 
> Ok.

[...]

Cheers
---Dave

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-26 10:00         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 10:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 25, 2018 at 05:56:02PM +0000, Suzuki K Poulose wrote:
> On 25/01/18 17:33, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
> >>We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
> >>to the userspace and the CPU hwcaps used by the kernel, which
> >>include cpu features and CPU errata work arounds.
> >>
> >>At the moment we have the following restricions:
> >>
> >>  a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
> >>    - Detected mostly on system wide CPU feature register. But
> >>      there are some which really uses a local CPU's value to
> >>      decide the availability (e.g, availability of hardware
> >>      prefetch). So, we run the check only once, after all the
> >>      boot-time active CPUs are turned on.
> >
> >[ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
> >presumably because the only systems to which it applies are homogeneous,
> >and anyway it's only an optimisation IIUC.
> >
> >This could be a separate category, but as a one-off that may be a bit
> >pointless.
> I understand and was planning to fix this back when it was introduced.
> But then it was pointless at that time, given that it was always
> guaranteed to be a homogeneous system. We do something about it in
> Patch 9.

This was just on observation than something that needs to be fixed,
but it it's been cleaned up then so much the better :)

I'll take a look.

> >.def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
> >unused in that case.]
> >
> >>    - Any late CPU which doesn't posses all the established features
> >>      is killed.
> >
> >Does "established feature" above ...
> >
> >>    - Any late CPU which possess a feature *not* already available
> >>      is allowed to boot.
> >
> >mean the same as "feature already available" here?
> 
> Yes, its the same. I should have been more consistent.
> 
> >
> >>
> >>  b) CPU Errata work arounds (arm64_errata)
> >>    - Detected mostly based on a local CPU's feature register.
> >>      The checks are run on each boot time activated CPUs.
> >>    - Any late CPU which doesn't have any of the established errata
> >>      work around capabilities is ignored and is allowed to boot.
> >>    - Any late CPU which has an errata work around not already available
> >>      is killed.
> >>
> >>However there are some exceptions to the cases above.
> >>
> >>1) KPTI is a feature that we need to enable when at least one CPU needs it.
> >>    And any late CPU that has this "feature" should be killed.
> >
> >Should that be "If KPTI is not enabled during system boot, then any late
> >CPU that has this "feature" should be killed."
> 
> Yes.
> 
> >
> >>2) Hardware DBM feature is a non-conflicting capability which could be
> >>    enabled on CPUs which has it without any issues, even if the CPU is
> >
> >have
> >
> 
> >>    brought up late.
> >>
> >>So this calls for a lot more fine grained behavior for each capability.
> >>And if we define all the attributes to control their behavior properly,
> >>we may be able to use a single table for the CPU hwcaps (not the
> >>ELF HWCAPs, which cover errata and features). This is a prepartory step
> >>to get there. We define type for a capability, which for now encodes the
> >>scope of the check. i.e, whether it should be checked system wide or on
> >>each local CPU. We define two types :
> >>
> >>   1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
> >>   1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
> >
> >2)

Meaning you've got 1) twice above (in case you didn't spot it).

> >
> >>As such there is no change in how the capabilities are treated.
> >
> >OK, I think I finally have my head around this, more or less.
> >
> >Mechanism (operations on architectural feature regs) and policy (kernel
> >runtime configuration) seem to be rather mixed together.  This works
> >fairly naturally for things like deriving the sanitised feature regs
> >seen by userspace and determining the ELF hwcaps; but not so naturally
> >for errata workarounds and other anomalous things like
> >ARM64_HAS_NO_HW_PREFETCH.
> 
> Right. We are stuck with "cpu_hwcaps" for both erratum and features,
> based on which we make some decisions to change the kernel behavior,
> as it is tied to alternative patching.
> 
> >
> >I'm not sure that there is a better approach though -- anyway, that
> >would be out of scope for this series.
> >
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
> >>  arch/arm64/kernel/cpu_errata.c      |  8 ++++----
> >>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
> >>  3 files changed, 41 insertions(+), 29 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index a23c0d4f27e9..4fd5de8ef33e 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -86,16 +86,23 @@ struct arm64_ftr_reg {
> >>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>-/* scope of capability check */
> >>-enum {
> >>-	SCOPE_SYSTEM,
> >>-	SCOPE_LOCAL_CPU,
> >>-};
> >>+
> >>+/* Decide how the capability is detected. On a local CPU vs System wide */
> >>+#define ARM64_CPUCAP_SCOPE_MASK			0x3
> >>+#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
> >>+#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
> >>+#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> >>+#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> >
> >Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?
> 
> It is an unsupported configuration.

Surely meaningless, not just unsupported?

> >
> >Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).
> >
> 
> It is a bit tricky. I chose separate bits to allow filter an entry in a table
> of capabilities based on the bits. e.g, we want to
> 
> 1) Process only the local scope (e.g detecting CPU local capabilities, where
> we are not yet ready to run the system wide checks)
> 
> 2) Process all the entries including local/system. (e.g, verifying all the
> capabilities for a late CPU).

OK, so LOCAL_CPU and SYSTEM are mutually exclusive for the cap type, but
by making them separate bits in a bitmask then (LOCAL_CPU | SYSTEM) as a
match value will match on either.

> Things get further complicated by the addition of "EARLY", where we want to
> filter entries based on "EARLY" bit. So, we need to pass on a mask of bits
> to the helpers, which are not just the binary scope. See Patch 7 for more
> info.
> 
> >>+
> >>+/* CPU errata detected at boot time based on feature of one or more CPUs */
> >>+#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> >
> >>+/* CPU feature detected at boot time based on system-wide value of a feature */
> >
> >I'm still not overly keen on these names, but I do at least see where
> >they come from now.
> >
> >Nit: redundant () in these two #defines btw.
> 
> Ok.

[...]

Cheers
---Dave

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

* Re: [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
  2018-01-23 12:27   ` Suzuki K Poulose
@ 2018-01-26 10:10     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 10:10 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
> Add two different flags to indicate if the conflict of a capability
> on a late CPU with the current system state
> 
>  1) Can a CPU have a capability when the system doesn't have it ?
> 
>     Most arm64 features could have this set. While erratum work arounds
>     cannot have this, as we may miss work arounds.
> 
>  2) Can a CPU miss a capability when the system has it ?
>     This could be set for arm64 erratum work arounds as we don't
>     care if a CPU doesn't need the work around. However it should
>     be clear for features.
> 
> These flags could be added to certain entries based on their nature.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
>  1 file changed, 31 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 4fd5de8ef33e..27d037bb0451 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>  #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>  
> -/* CPU errata detected at boot time based on feature of one or more CPUs */
> -#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> -/* CPU feature detected at boot time based on system-wide value of a feature */
> -#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
> +/* Is it safe for a late CPU to have this capability when system doesn't already have */
> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
> +/* Is it safe for a late CPU to miss this capability when system has it */
> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)

Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?

Alternatively,
	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU

might be easier to understand.

[...]

Cheers
---Dave

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

* [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
@ 2018-01-26 10:10     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
> Add two different flags to indicate if the conflict of a capability
> on a late CPU with the current system state
> 
>  1) Can a CPU have a capability when the system doesn't have it ?
> 
>     Most arm64 features could have this set. While erratum work arounds
>     cannot have this, as we may miss work arounds.
> 
>  2) Can a CPU miss a capability when the system has it ?
>     This could be set for arm64 erratum work arounds as we don't
>     care if a CPU doesn't need the work around. However it should
>     be clear for features.
> 
> These flags could be added to certain entries based on their nature.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
>  1 file changed, 31 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 4fd5de8ef33e..27d037bb0451 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>  #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>  
> -/* CPU errata detected at boot time based on feature of one or more CPUs */
> -#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> -/* CPU feature detected at boot time based on system-wide value of a feature */
> -#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
> +/* Is it safe for a late CPU to have this capability when system doesn't already have */
> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
> +/* Is it safe for a late CPU to miss this capability when system has it */
> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)

Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?

Alternatively,
	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU

might be easier to understand.

[...]

Cheers
---Dave

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

* Re: [PATCH 06/16] arm64: capabilities: Unify the verification
  2018-01-23 12:27   ` Suzuki K Poulose
@ 2018-01-26 11:08     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 11:08 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:27:59PM +0000, Suzuki K Poulose wrote:
> Now that each capability describes how to treat the conflicts
> of CPU cap state vs System wide cap state, we can unify the
> verification logic to a single place.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
>  1 file changed, 54 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 43c7e992d784..79737034a628 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>  }

>  
>  /*
> + * Run through the list of capabilities to check for conflicts.
> + * Returns "false" on conflicts.
> + */
> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
> +{
> +	bool cpu_has_cap, system_has_cap;
> +	const struct arm64_cpu_capabilities *caps = caps_list;
> +
> +	for (; caps->matches; caps++) {
> +		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);

What's the point of scanning the whole of caps_list?  Don't we already
have the pointer to the right cap struct?

We already know caps->matches is true.  Can't we just call
caps->matches(caps)?  That seemed pretty intuitive to me in the old
code.

> +		system_has_cap =  cpus_have_cap(caps->capability);
> +
> +		if (system_has_cap) {
> +			/*
> +			 * Check if the new CPU misses an advertised feature, which is not
> +			 * safe to miss.
> +			 */
> +			if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(caps))
> +				break;
> +			/*
> +			 * We have to issue enable() irrespective of whether the CPU
> +			 * has it or not, as it is enabeld system wide. It is upto

enabled

> +			 * the call back to take appropriate action on this CPU.
> +			 */
> +			if (caps->enable)
> +				caps->enable(caps);
> +		} else {
> +			/*
> +			 * Check if the CPU has this capability if it isn't safe to
> +			 * have when the system doesn't.
> +			 */

Possibly most of the commenting here is not needed.  The code is pretty
self-explanatory, so the comments may just be adding clutter.

The role of the ->enable() call is the only real subtlety here.

> +			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
> +				break;
> +		}
> +	}
> +
> +	if (caps->matches) {
> +		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
> +			smp_processor_id(), caps->capability,
> +			caps->desc ? : "no description",

Wouldn't it be a bug for a conflict to occur on a cap with no .desc?

Why can't we just let printk print its default "(null)" for %s
in this case?

Alternatively, is there a reason for any cap not to have a description?

> +			system_has_cap, cpu_has_cap);
> +		return false;
> +	}
> +
> +	return true;
> +}

Perhaps the capability verification procedure could be made a little
clearer by splitting this into two functions:

static bool __verify_local_cpu_cap(const struct arm64_cpu_capabilities *cap)
{
	bool cpu_has_cap = cap->matches(cap, SCOPE_LOCAL_CPU);
	bool system_has_cap =  cpus_have_cap(cap->capability);

	if (system_has_cap) {
		if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(cap))
			goto bad;

		if (cap->enable)
			/* Enable for this cpu if appropriate: */
			cap->enable(cap);
	} else {
		if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(cap))
			goto bad;
	}

	return true;

bad:
	pr_crit([...]);
	return false;
}

static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps)
{
	while (caps->matches) {
		if (!__verify_local_cpu_cap(caps))
			return false;

		++caps;
	}

	return true;
}

[...]

Cheers
---Dave

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

* [PATCH 06/16] arm64: capabilities: Unify the verification
@ 2018-01-26 11:08     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 11:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:27:59PM +0000, Suzuki K Poulose wrote:
> Now that each capability describes how to treat the conflicts
> of CPU cap state vs System wide cap state, we can unify the
> verification logic to a single place.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
>  1 file changed, 54 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 43c7e992d784..79737034a628 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>  }

>  
>  /*
> + * Run through the list of capabilities to check for conflicts.
> + * Returns "false" on conflicts.
> + */
> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
> +{
> +	bool cpu_has_cap, system_has_cap;
> +	const struct arm64_cpu_capabilities *caps = caps_list;
> +
> +	for (; caps->matches; caps++) {
> +		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);

What's the point of scanning the whole of caps_list?  Don't we already
have the pointer to the right cap struct?

We already know caps->matches is true.  Can't we just call
caps->matches(caps)?  That seemed pretty intuitive to me in the old
code.

> +		system_has_cap =  cpus_have_cap(caps->capability);
> +
> +		if (system_has_cap) {
> +			/*
> +			 * Check if the new CPU misses an advertised feature, which is not
> +			 * safe to miss.
> +			 */
> +			if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(caps))
> +				break;
> +			/*
> +			 * We have to issue enable() irrespective of whether the CPU
> +			 * has it or not, as it is enabeld system wide. It is upto

enabled

> +			 * the call back to take appropriate action on this CPU.
> +			 */
> +			if (caps->enable)
> +				caps->enable(caps);
> +		} else {
> +			/*
> +			 * Check if the CPU has this capability if it isn't safe to
> +			 * have when the system doesn't.
> +			 */

Possibly most of the commenting here is not needed.  The code is pretty
self-explanatory, so the comments may just be adding clutter.

The role of the ->enable() call is the only real subtlety here.

> +			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
> +				break;
> +		}
> +	}
> +
> +	if (caps->matches) {
> +		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
> +			smp_processor_id(), caps->capability,
> +			caps->desc ? : "no description",

Wouldn't it be a bug for a conflict to occur on a cap with no .desc?

Why can't we just let printk print its default "(null)" for %s
in this case?

Alternatively, is there a reason for any cap not to have a description?

> +			system_has_cap, cpu_has_cap);
> +		return false;
> +	}
> +
> +	return true;
> +}

Perhaps the capability verification procedure could be made a little
clearer by splitting this into two functions:

static bool __verify_local_cpu_cap(const struct arm64_cpu_capabilities *cap)
{
	bool cpu_has_cap = cap->matches(cap, SCOPE_LOCAL_CPU);
	bool system_has_cap =  cpus_have_cap(cap->capability);

	if (system_has_cap) {
		if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(cap))
			goto bad;

		if (cap->enable)
			/* Enable for this cpu if appropriate: */
			cap->enable(cap);
	} else {
		if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(cap))
			goto bad;
	}

	return true;

bad:
	pr_crit([...]);
	return false;
}

static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps)
{
	while (caps->matches) {
		if (!__verify_local_cpu_cap(caps))
			return false;

		++caps;
	}

	return true;
}

[...]

Cheers
---Dave

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

* Re: [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 11:22     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 11:22 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:00PM +0000, Suzuki K Poulose wrote:
> While processing the list of capabilities, it is useful to
> filter out some of the entries based on the given type to
> allow better control. This can be used later for handling
> LOCAL vs SYSTEM wide capabilities and more.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  5 +++++
>  arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
>  2 files changed, 25 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 27d037bb0451..a621d2184227 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  /* Is it safe for a late CPU to miss this capability when system has it */
>  #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
>  
> +#define ARM64_CPUCAP_TYPE_ALL			 \
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> +	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)

Nit: can we have another tab between | and \?

This will help to make missing |s stand out more if/when more entries
are added to this list in future.

>  /*
>   * CPU errata detected at boot time based on feature of one or more CPUs.
>   * It is not safe for a late CPU to have this feature when the system doesn't
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 79737034a628..198c5daddd65 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1180,9 +1180,11 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>  }
>  
>  static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> -			    const char *info)
> +				    u16 cap_type, const char *info)

Semantically "cap_type" represents a set of accepted types, not a single
type here.

Can we rename it to "cap_types", "cap_type_mask" or similar?

>  {
>  	for (; caps->matches; caps++) {
> +		if (!(caps->type & cap_type))
> +			continue;

Minor nit: insert a blank line here?

To me, lack of a blank line suggests that the code will always fall
through to the next line, which is not the case after
return/continue/break/goto.

Alternatively:

		if (!(caps->type & cap_type) ||
		    !caps->matches(caps, caps->def_scope))
			continue;

still seems fairly intelligible ...[1]

>  		if (!caps->matches(caps, cpucap_default_scope(caps)))
>  			continue;
>  
> @@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
>   * Run through the enabled capabilities and enable() it on all active
>   * CPUs
>   */
> -static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
> +static void __init
> +enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)

The "caps_type" argument should be named consistently with the
corresponding argument to update_cpu_capabilities().

>  {
>  	for (; caps->matches; caps++) {
>  		unsigned int num = caps->capability;
>  
> -		if (!cpus_have_cap(num))
> +		if (!(caps->type & caps_type) || !cpus_have_cap(num))

[1]... and would match the approach taken here.

>  			continue;
>  
>  		/* Ensure cpus_have_const_cap(num) works */
> @@ -1231,12 +1234,16 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>   * Run through the list of capabilities to check for conflicts.
>   * Returns "false" on conflicts.
>   */
> -static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
> +				    u16 caps_type)
>  {
>  	bool cpu_has_cap, system_has_cap;
>  	const struct arm64_cpu_capabilities *caps = caps_list;
>  
>  	for (; caps->matches; caps++) {
> +		if (!(caps->type & caps_type))
> +			continue;
> +
>  		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
>  		system_has_cap =  cpus_have_cap(caps->capability);
>  
> @@ -1299,7 +1306,7 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
>  
>  static void verify_local_cpu_features(void)
>  {
> -	if (!__verify_local_cpu_caps(arm64_features))
> +	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
>  		cpu_die_early();
>  }
>  
> @@ -1327,18 +1334,20 @@ static void verify_sve_features(void)
>   */
>  static void verify_local_cpu_errata_workarounds(void)
>  {
> -	if (__verify_local_cpu_caps(arm64_errata))
> +	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
>  		cpu_die_early();

Did you mean to insert the ! here?

[...]

Cheers
---Dave

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

* [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
@ 2018-01-26 11:22     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 11:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:00PM +0000, Suzuki K Poulose wrote:
> While processing the list of capabilities, it is useful to
> filter out some of the entries based on the given type to
> allow better control. This can be used later for handling
> LOCAL vs SYSTEM wide capabilities and more.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  5 +++++
>  arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
>  2 files changed, 25 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 27d037bb0451..a621d2184227 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  /* Is it safe for a late CPU to miss this capability when system has it */
>  #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
>  
> +#define ARM64_CPUCAP_TYPE_ALL			 \
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> +	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)

Nit: can we have another tab between | and \?

This will help to make missing |s stand out more if/when more entries
are added to this list in future.

>  /*
>   * CPU errata detected at boot time based on feature of one or more CPUs.
>   * It is not safe for a late CPU to have this feature when the system doesn't
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 79737034a628..198c5daddd65 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1180,9 +1180,11 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>  }
>  
>  static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> -			    const char *info)
> +				    u16 cap_type, const char *info)

Semantically "cap_type" represents a set of accepted types, not a single
type here.

Can we rename it to "cap_types", "cap_type_mask" or similar?

>  {
>  	for (; caps->matches; caps++) {
> +		if (!(caps->type & cap_type))
> +			continue;

Minor nit: insert a blank line here?

To me, lack of a blank line suggests that the code will always fall
through to the next line, which is not the case after
return/continue/break/goto.

Alternatively:

		if (!(caps->type & cap_type) ||
		    !caps->matches(caps, caps->def_scope))
			continue;

still seems fairly intelligible ...[1]

>  		if (!caps->matches(caps, cpucap_default_scope(caps)))
>  			continue;
>  
> @@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
>   * Run through the enabled capabilities and enable() it on all active
>   * CPUs
>   */
> -static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
> +static void __init
> +enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)

The "caps_type" argument should be named consistently with the
corresponding argument to update_cpu_capabilities().

>  {
>  	for (; caps->matches; caps++) {
>  		unsigned int num = caps->capability;
>  
> -		if (!cpus_have_cap(num))
> +		if (!(caps->type & caps_type) || !cpus_have_cap(num))

[1]... and would match the approach taken here.

>  			continue;
>  
>  		/* Ensure cpus_have_const_cap(num) works */
> @@ -1231,12 +1234,16 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>   * Run through the list of capabilities to check for conflicts.
>   * Returns "false" on conflicts.
>   */
> -static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
> +				    u16 caps_type)
>  {
>  	bool cpu_has_cap, system_has_cap;
>  	const struct arm64_cpu_capabilities *caps = caps_list;
>  
>  	for (; caps->matches; caps++) {
> +		if (!(caps->type & caps_type))
> +			continue;
> +
>  		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
>  		system_has_cap =  cpus_have_cap(caps->capability);
>  
> @@ -1299,7 +1306,7 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
>  
>  static void verify_local_cpu_features(void)
>  {
> -	if (!__verify_local_cpu_caps(arm64_features))
> +	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
>  		cpu_die_early();
>  }
>  
> @@ -1327,18 +1334,20 @@ static void verify_sve_features(void)
>   */
>  static void verify_local_cpu_errata_workarounds(void)
>  {
> -	if (__verify_local_cpu_caps(arm64_errata))
> +	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
>  		cpu_die_early();

Did you mean to insert the ! here?

[...]

Cheers
---Dave

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

* Re: [PATCH 08/16] arm64: capabilities: Group handling of features and errata
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 11:47     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 11:47 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
> So far we have had separate routes for triggering errata and feature

"triggering errata" ? ;)

Maybe "[...] for determining whether to activate errata workarounds and
whether to enable feature capabilities."

> capabilities. Also, we never allowed "features" based on local CPU
> and "errata" based on System wide safe registers. This patch
> groups the handling of errata and features and also allows them
> to have all the possible scopes.
> 
> So, we now run through the arm64_features and arm64_errata:

when?

What about late cpus?

>  1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
>     via update_cpu_local_capabilities().

"each [...] enabeld CPUs" -> "each [...] enabled CPU".

Also, changing "boot time" -> "boot-time" helps avoid this being misread
as "on each boot", which could be taken to mean "each time a CPU comes
online".  I'm guessing that's not the intended meaning here.

>  2) with SCOPE_SYSTEM filter only once after all boot time enabled
>     CPUs are active.
> 
> We could ideally merge the two tables into one. But leave it as
> it is for easy access to the list of particular type.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 77 ++++++++++++++++++++++++------------------
>  1 file changed, 44 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 198c5daddd65..7ae5cf9092d0 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -504,7 +504,7 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
>  }
>  
>  extern const struct arm64_cpu_capabilities arm64_errata[];
> -static void update_cpu_errata_workarounds(void);
> +static void update_cpu_local_capabilities(void);
>  
>  void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  {
> @@ -553,7 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  	 * Run the errata work around checks on the boot CPU, once we have
>  	 * initialised the cpu feature infrastructure.
>  	 */
> -	update_cpu_errata_workarounds();
> +	update_cpu_local_capabilities();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1179,8 +1179,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>  	return false;
>  }
>  
> -static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> -				    u16 cap_type, const char *info)
> +static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> +				      u16 cap_type, const char *info)
>  {
>  	for (; caps->matches; caps++) {
>  		if (!(caps->type & cap_type))
> @@ -1194,6 +1194,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>  	}
>  }
>  
> +static void update_cpu_capabilities(u16 type)
> +{
> +	__update_cpu_capabilities(arm64_features, type,
> +				"detected feature:");
> +	__update_cpu_capabilities(arm64_errata, type,
> +				"enabling work around for");
> +}
>  
>  static int __enable_cpu_capability(void *arg)
>  {
> @@ -1207,7 +1214,7 @@ static int __enable_cpu_capability(void *arg)
>   * CPUs
>   */
>  static void __init
> -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
> +__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
>  {
>  	for (; caps->matches; caps++) {
>  		unsigned int num = caps->capability;
> @@ -1282,6 +1289,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>  	return true;
>  }
>  
> +static bool verify_local_cpu_caps(u16 type)
> +{
> +	return __verify_local_cpu_caps(arm64_features, type) &&
> +	       __verify_local_cpu_caps(arm64_errata, type);
> +}
> +
>  /*
>   * Check for CPU features that are used in early boot
>   * based on the Boot CPU value.
> @@ -1304,12 +1317,6 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
>  		}
>  }
>  
> -static void verify_local_cpu_features(void)
> -{
> -	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
> -		cpu_die_early();
> -}
> -
>  static void verify_sve_features(void)
>  {
>  	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
> @@ -1328,26 +1335,28 @@ static void verify_sve_features(void)
>  }
>  
>  /*
> - * The CPU Errata work arounds are detected and applied at boot time
> - * and the related information is freed soon after. If the new CPU requires
> - * an errata not detected at boot, fail this CPU.
> + * Check for all capablities within the scope of local CPU.
> + * This is run on all boot time activated CPUs.
>   */
> -static void verify_local_cpu_errata_workarounds(void)
> +static void update_cpu_local_capabilities(void)

[Gaah, stupid git diff making function insertion look like function
modification.  Sometimes --patience does a better job, but there seems
no foolproof solution...  If you do a respin, it might be worth trying
it.]

>  {
> -	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
> -		cpu_die_early();
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_LOCAL_CPU);
>  }
>  
> -static void update_cpu_errata_workarounds(void)
> +/*
> + * Check for all capablities with a system wide scope.
> + * This is run only once after all the boot CPUs are
> + * brought online.
> + */
> +static void update_system_capabilities(void)
>  {
> -	update_cpu_capabilities(arm64_errata,
> -				ARM64_CPUCAP_TYPE_ALL,
> -				"enabling workaround for");
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
>  }
>  
> -static void __init enable_errata_workarounds(void)
> +static void enable_cpu_capabilities(u16 type)
>  {
> -	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_TYPE_ALL);
> +	__enable_cpu_capabilities(arm64_errata, type);
> +	__enable_cpu_capabilities(arm64_features, type);
>  }
>  
>  /*
> @@ -1360,8 +1369,8 @@ static void __init enable_errata_workarounds(void)
>   */
>  static void verify_local_cpu_capabilities(void)
>  {
> -	verify_local_cpu_errata_workarounds();
> -	verify_local_cpu_features();
> +	if (!verify_local_cpu_caps(ARM64_CPUCAP_TYPE_ALL))
> +		cpu_die_early();
>  	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>  
>  	if (system_supports_32bit_el0())
> @@ -1389,16 +1398,20 @@ void check_local_cpu_capabilities(void)
>  	 * advertised capabilities.
>  	 */
>  	if (!sys_caps_initialised)
> -		update_cpu_errata_workarounds();
> +		update_cpu_local_capabilities();
>  	else
>  		verify_local_cpu_capabilities();
>  }
>  
> -static void __init setup_feature_capabilities(void)
> +static void __init setup_system_capabilities(void)
>  {
> -	update_cpu_capabilities(arm64_features,
> -				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
> -	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
> +	/*
> +	 * We have finalised the system wide safe feature registers,
> +	 * finalise the capabilities that depend on it.
> +	 */
> +	update_system_capabilities();
> +	/* Enable all the available capabilities */
> +	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);

So setup_system_capabilities() enables _non_ system-wide capabilities/
errata workarounds too?

Maybe this function should just have a different name, like
"setup_boot_capabilities" or similar?

  }
>  
>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> @@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
>  	u32 cwg;
>  	int cls;
>  
> -	/* Set the CPU feature capabilies */
> -	setup_feature_capabilities();
> -	enable_errata_workarounds();
> +	setup_system_capabilities();
>  	mark_const_caps_ready();
>  	setup_elf_hwcaps(arm64_elf_hwcaps);

I wonder whether we could unify the elf hwcaps handling too.

That's not necessary for this series though.

Cheers
---Dave

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
@ 2018-01-26 11:47     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
> So far we have had separate routes for triggering errata and feature

"triggering errata" ? ;)

Maybe "[...] for determining whether to activate errata workarounds and
whether to enable feature capabilities."

> capabilities. Also, we never allowed "features" based on local CPU
> and "errata" based on System wide safe registers. This patch
> groups the handling of errata and features and also allows them
> to have all the possible scopes.
> 
> So, we now run through the arm64_features and arm64_errata:

when?

What about late cpus?

>  1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
>     via update_cpu_local_capabilities().

"each [...] enabeld CPUs" -> "each [...] enabled CPU".

Also, changing "boot time" -> "boot-time" helps avoid this being misread
as "on each boot", which could be taken to mean "each time a CPU comes
online".  I'm guessing that's not the intended meaning here.

>  2) with SCOPE_SYSTEM filter only once after all boot time enabled
>     CPUs are active.
> 
> We could ideally merge the two tables into one. But leave it as
> it is for easy access to the list of particular type.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 77 ++++++++++++++++++++++++------------------
>  1 file changed, 44 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 198c5daddd65..7ae5cf9092d0 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -504,7 +504,7 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
>  }
>  
>  extern const struct arm64_cpu_capabilities arm64_errata[];
> -static void update_cpu_errata_workarounds(void);
> +static void update_cpu_local_capabilities(void);
>  
>  void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  {
> @@ -553,7 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  	 * Run the errata work around checks on the boot CPU, once we have
>  	 * initialised the cpu feature infrastructure.
>  	 */
> -	update_cpu_errata_workarounds();
> +	update_cpu_local_capabilities();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1179,8 +1179,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>  	return false;
>  }
>  
> -static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> -				    u16 cap_type, const char *info)
> +static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> +				      u16 cap_type, const char *info)
>  {
>  	for (; caps->matches; caps++) {
>  		if (!(caps->type & cap_type))
> @@ -1194,6 +1194,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>  	}
>  }
>  
> +static void update_cpu_capabilities(u16 type)
> +{
> +	__update_cpu_capabilities(arm64_features, type,
> +				"detected feature:");
> +	__update_cpu_capabilities(arm64_errata, type,
> +				"enabling work around for");
> +}
>  
>  static int __enable_cpu_capability(void *arg)
>  {
> @@ -1207,7 +1214,7 @@ static int __enable_cpu_capability(void *arg)
>   * CPUs
>   */
>  static void __init
> -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
> +__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
>  {
>  	for (; caps->matches; caps++) {
>  		unsigned int num = caps->capability;
> @@ -1282,6 +1289,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>  	return true;
>  }
>  
> +static bool verify_local_cpu_caps(u16 type)
> +{
> +	return __verify_local_cpu_caps(arm64_features, type) &&
> +	       __verify_local_cpu_caps(arm64_errata, type);
> +}
> +
>  /*
>   * Check for CPU features that are used in early boot
>   * based on the Boot CPU value.
> @@ -1304,12 +1317,6 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
>  		}
>  }
>  
> -static void verify_local_cpu_features(void)
> -{
> -	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
> -		cpu_die_early();
> -}
> -
>  static void verify_sve_features(void)
>  {
>  	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
> @@ -1328,26 +1335,28 @@ static void verify_sve_features(void)
>  }
>  
>  /*
> - * The CPU Errata work arounds are detected and applied at boot time
> - * and the related information is freed soon after. If the new CPU requires
> - * an errata not detected at boot, fail this CPU.
> + * Check for all capablities within the scope of local CPU.
> + * This is run on all boot time activated CPUs.
>   */
> -static void verify_local_cpu_errata_workarounds(void)
> +static void update_cpu_local_capabilities(void)

[Gaah, stupid git diff making function insertion look like function
modification.  Sometimes --patience does a better job, but there seems
no foolproof solution...  If you do a respin, it might be worth trying
it.]

>  {
> -	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
> -		cpu_die_early();
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_LOCAL_CPU);
>  }
>  
> -static void update_cpu_errata_workarounds(void)
> +/*
> + * Check for all capablities with a system wide scope.
> + * This is run only once after all the boot CPUs are
> + * brought online.
> + */
> +static void update_system_capabilities(void)
>  {
> -	update_cpu_capabilities(arm64_errata,
> -				ARM64_CPUCAP_TYPE_ALL,
> -				"enabling workaround for");
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
>  }
>  
> -static void __init enable_errata_workarounds(void)
> +static void enable_cpu_capabilities(u16 type)
>  {
> -	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_TYPE_ALL);
> +	__enable_cpu_capabilities(arm64_errata, type);
> +	__enable_cpu_capabilities(arm64_features, type);
>  }
>  
>  /*
> @@ -1360,8 +1369,8 @@ static void __init enable_errata_workarounds(void)
>   */
>  static void verify_local_cpu_capabilities(void)
>  {
> -	verify_local_cpu_errata_workarounds();
> -	verify_local_cpu_features();
> +	if (!verify_local_cpu_caps(ARM64_CPUCAP_TYPE_ALL))
> +		cpu_die_early();
>  	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>  
>  	if (system_supports_32bit_el0())
> @@ -1389,16 +1398,20 @@ void check_local_cpu_capabilities(void)
>  	 * advertised capabilities.
>  	 */
>  	if (!sys_caps_initialised)
> -		update_cpu_errata_workarounds();
> +		update_cpu_local_capabilities();
>  	else
>  		verify_local_cpu_capabilities();
>  }
>  
> -static void __init setup_feature_capabilities(void)
> +static void __init setup_system_capabilities(void)
>  {
> -	update_cpu_capabilities(arm64_features,
> -				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
> -	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
> +	/*
> +	 * We have finalised the system wide safe feature registers,
> +	 * finalise the capabilities that depend on it.
> +	 */
> +	update_system_capabilities();
> +	/* Enable all the available capabilities */
> +	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);

So setup_system_capabilities() enables _non_ system-wide capabilities/
errata workarounds too?

Maybe this function should just have a different name, like
"setup_boot_capabilities" or similar?

  }
>  
>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> @@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
>  	u32 cwg;
>  	int cls;
>  
> -	/* Set the CPU feature capabilies */
> -	setup_feature_capabilities();
> -	enable_errata_workarounds();
> +	setup_system_capabilities();
>  	mark_const_caps_ready();
>  	setup_elf_hwcaps(arm64_elf_hwcaps);

I wonder whether we could unify the elf hwcaps handling too.

That's not necessary for this series though.

Cheers
---Dave

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

* Re: [PATCH 06/16] arm64: capabilities: Unify the verification
  2018-01-26 11:08     ` Dave Martin
@ 2018-01-26 12:10       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:10 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 11:08, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:59PM +0000, Suzuki K Poulose wrote:
>> Now that each capability describes how to treat the conflicts
>> of CPU cap state vs System wide cap state, we can unify the
>> verification logic to a single place.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
>>   1 file changed, 54 insertions(+), 33 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 43c7e992d784..79737034a628 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>>   }
> 
>>   
>>   /*
>> + * Run through the list of capabilities to check for conflicts.
>> + * Returns "false" on conflicts.
>> + */
>> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
>> +{
>> +	bool cpu_has_cap, system_has_cap;
>> +	const struct arm64_cpu_capabilities *caps = caps_list;
>> +
>> +	for (; caps->matches; caps++) {
>> +		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
> 
> What's the point of scanning the whole of caps_list?  Don't we already
> have the pointer to the right cap struct?
> 
> We already know caps->matches is true.  Can't we just call
> caps->matches(caps)?  That seemed pretty intuitive to me in the old
> code.
> 

This was supposed to be fixed by [1] in the "old code". Given we have multiple
entries for a "capability", we could be dealing with the one which doesn't
apply to this CPU and could eventually trigger a wrong conflict below. To
avoid this, we need to make sure use the right values.

>> +		system_has_cap =  cpus_have_cap(caps->capability);
>> +
>> +		if (system_has_cap) {
>> +			/*
>> +			 * Check if the new CPU misses an advertised feature, which is not
>> +			 * safe to miss.
>> +			 */
>> +			if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(caps))
>> +				break;
>> +			/*
>> +			 * We have to issue enable() irrespective of whether the CPU
>> +			 * has it or not, as it is enabeld system wide. It is upto
> 
> enabled
> 
>> +			 * the call back to take appropriate action on this CPU.
>> +			 */
>> +			if (caps->enable)
>> +				caps->enable(caps);
>> +		} else {
>> +			/*
>> +			 * Check if the CPU has this capability if it isn't safe to
>> +			 * have when the system doesn't.
>> +			 */
> 
> Possibly most of the commenting here is not needed.  The code is pretty
> self-explanatory, so the comments may just be adding clutter.

Sure.

> 
> The role of the ->enable() call is the only real subtlety here.
> 
>> +			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
>> +				break;
>> +		}
>> +	}
>> +
>> +	if (caps->matches) {
>> +		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
>> +			smp_processor_id(), caps->capability,
>> +			caps->desc ? : "no description",
> 
> Wouldn't it be a bug for a conflict to occur on a cap with no .desc?
> 
> Why can't we just let printk print its default "(null)" for %s
> in this case?

We could.

> 
> Alternatively, is there a reason for any cap not to have a description?

Some of them do. e.g, some of them could be "negative" capabilities. e.g,
ARM64_NO_FPSIMD.

>> +			system_has_cap, cpu_has_cap);
>> +		return false;
>> +	}
>> +
>> +	return true;
>> +}
> 
> Perhaps the capability verification procedure could be made a little
> clearer by splitting this into two functions:
> 

As explained above, the code below is not sufficient.


> static bool __verify_local_cpu_cap(const struct arm64_cpu_capabilities *cap)
> {
> 	bool cpu_has_cap = cap->matches(cap, SCOPE_LOCAL_CPU);
> 	bool system_has_cap =  cpus_have_cap(cap->capability);
> 
> 	if (system_has_cap) {
> 		if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(cap))
> 			goto bad;
> 
> 		if (cap->enable)
> 			/* Enable for this cpu if appropriate: */
> 			cap->enable(cap);
> 	} else {
> 		if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(cap))
> 			goto bad;
> 	}
> 
> 	return true;
> 
> bad:
> 	pr_crit([...]);
> 	return false;
> }
> 
> static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps)
> {
> 	while (caps->matches) {
> 		if (!__verify_local_cpu_cap(caps))
> 			return false;
> 
> 		++caps;
> 	}
> 
> 	return true;
> }


[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/552877.html

Cheers
Suzuki

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

* [PATCH 06/16] arm64: capabilities: Unify the verification
@ 2018-01-26 12:10       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 11:08, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:59PM +0000, Suzuki K Poulose wrote:
>> Now that each capability describes how to treat the conflicts
>> of CPU cap state vs System wide cap state, we can unify the
>> verification logic to a single place.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
>>   1 file changed, 54 insertions(+), 33 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 43c7e992d784..79737034a628 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>>   }
> 
>>   
>>   /*
>> + * Run through the list of capabilities to check for conflicts.
>> + * Returns "false" on conflicts.
>> + */
>> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
>> +{
>> +	bool cpu_has_cap, system_has_cap;
>> +	const struct arm64_cpu_capabilities *caps = caps_list;
>> +
>> +	for (; caps->matches; caps++) {
>> +		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
> 
> What's the point of scanning the whole of caps_list?  Don't we already
> have the pointer to the right cap struct?
> 
> We already know caps->matches is true.  Can't we just call
> caps->matches(caps)?  That seemed pretty intuitive to me in the old
> code.
> 

This was supposed to be fixed by [1] in the "old code". Given we have multiple
entries for a "capability", we could be dealing with the one which doesn't
apply to this CPU and could eventually trigger a wrong conflict below. To
avoid this, we need to make sure use the right values.

>> +		system_has_cap =  cpus_have_cap(caps->capability);
>> +
>> +		if (system_has_cap) {
>> +			/*
>> +			 * Check if the new CPU misses an advertised feature, which is not
>> +			 * safe to miss.
>> +			 */
>> +			if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(caps))
>> +				break;
>> +			/*
>> +			 * We have to issue enable() irrespective of whether the CPU
>> +			 * has it or not, as it is enabeld system wide. It is upto
> 
> enabled
> 
>> +			 * the call back to take appropriate action on this CPU.
>> +			 */
>> +			if (caps->enable)
>> +				caps->enable(caps);
>> +		} else {
>> +			/*
>> +			 * Check if the CPU has this capability if it isn't safe to
>> +			 * have when the system doesn't.
>> +			 */
> 
> Possibly most of the commenting here is not needed.  The code is pretty
> self-explanatory, so the comments may just be adding clutter.

Sure.

> 
> The role of the ->enable() call is the only real subtlety here.
> 
>> +			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
>> +				break;
>> +		}
>> +	}
>> +
>> +	if (caps->matches) {
>> +		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
>> +			smp_processor_id(), caps->capability,
>> +			caps->desc ? : "no description",
> 
> Wouldn't it be a bug for a conflict to occur on a cap with no .desc?
> 
> Why can't we just let printk print its default "(null)" for %s
> in this case?

We could.

> 
> Alternatively, is there a reason for any cap not to have a description?

Some of them do. e.g, some of them could be "negative" capabilities. e.g,
ARM64_NO_FPSIMD.

>> +			system_has_cap, cpu_has_cap);
>> +		return false;
>> +	}
>> +
>> +	return true;
>> +}
> 
> Perhaps the capability verification procedure could be made a little
> clearer by splitting this into two functions:
> 

As explained above, the code below is not sufficient.


> static bool __verify_local_cpu_cap(const struct arm64_cpu_capabilities *cap)
> {
> 	bool cpu_has_cap = cap->matches(cap, SCOPE_LOCAL_CPU);
> 	bool system_has_cap =  cpus_have_cap(cap->capability);
> 
> 	if (system_has_cap) {
> 		if (!cpu_has_cap && !cpucap_late_cpu_missing_cap_safe(cap))
> 			goto bad;
> 
> 		if (cap->enable)
> 			/* Enable for this cpu if appropriate: */
> 			cap->enable(cap);
> 	} else {
> 		if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(cap))
> 			goto bad;
> 	}
> 
> 	return true;
> 
> bad:
> 	pr_crit([...]);
> 	return false;
> }
> 
> static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps)
> {
> 	while (caps->matches) {
> 		if (!__verify_local_cpu_cap(caps))
> 			return false;
> 
> 		++caps;
> 	}
> 
> 	return true;
> }


[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/552877.html

Cheers
Suzuki

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

* Re: [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 12:12     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 12:12 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:02PM +0000, Suzuki K Poulose wrote:
> Add type for features that are detected on individual CPUs,
> rather than on a system wide safe features. This behavior

feature

> is similar to that of a strict cpu erratum, where a later
> CPU is not allowed to boot if the system doesn't posses it.
> 
> Use this for software prefetching capability.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 7 +++++++
>  arch/arm64/kernel/cpufeature.c      | 2 +-
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a621d2184227..4c3d6987acfc 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -118,6 +118,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  #define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
>  	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
> +/*
> + * CPU feature detected at boot time based on feature of one or more CPUs.
> + * It is not safe for a late CPU to have this feature, when the system doesn't
> + * have it. But it is safe to miss the feature if the system has it.
> + */
> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)

"STRICT" seem quite odd here, since we never require all CPUs to have
the feature.  The case we forbid is when the boot-time decision is that
the system doesn't tolerate this feature.  So this feels erratum-like.

>  struct arm64_cpu_capabilities {
>  	const char *desc;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 7ae5cf9092d0..111f6c4b4cd7 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -951,7 +951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Software prefetching using PRFM",
>  		.capability = ARM64_HAS_NO_HW_PREFETCH,
> -		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
>  		.matches = has_no_hw_prefetch,

For ARM64_HAS_NO_HW_PREFETCH this is more describing an implementation
option that only affects performance -- in that case it's not obvious
that we should be strict at all.

This suggests ARM64_CPUCAP_SCOPE_LOCAL_CPU |
	ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE |
	ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS.

But IIUC it doesn't make a difference for the only real systems that
this feature is relevant to.

[...]

Cheers
---Dave

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

* [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU
@ 2018-01-26 12:12     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:02PM +0000, Suzuki K Poulose wrote:
> Add type for features that are detected on individual CPUs,
> rather than on a system wide safe features. This behavior

feature

> is similar to that of a strict cpu erratum, where a later
> CPU is not allowed to boot if the system doesn't posses it.
> 
> Use this for software prefetching capability.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 7 +++++++
>  arch/arm64/kernel/cpufeature.c      | 2 +-
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a621d2184227..4c3d6987acfc 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -118,6 +118,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  #define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
>  	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
> +/*
> + * CPU feature detected at boot time based on feature of one or more CPUs.
> + * It is not safe for a late CPU to have this feature, when the system doesn't
> + * have it. But it is safe to miss the feature if the system has it.
> + */
> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)

"STRICT" seem quite odd here, since we never require all CPUs to have
the feature.  The case we forbid is when the boot-time decision is that
the system doesn't tolerate this feature.  So this feels erratum-like.

>  struct arm64_cpu_capabilities {
>  	const char *desc;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 7ae5cf9092d0..111f6c4b4cd7 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -951,7 +951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Software prefetching using PRFM",
>  		.capability = ARM64_HAS_NO_HW_PREFETCH,
> -		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
>  		.matches = has_no_hw_prefetch,

For ARM64_HAS_NO_HW_PREFETCH this is more describing an implementation
option that only affects performance -- in that case it's not obvious
that we should be strict at all.

This suggests ARM64_CPUCAP_SCOPE_LOCAL_CPU |
	ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE |
	ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS.

But IIUC it doesn't make a difference for the only real systems that
this feature is relevant to.

[...]

Cheers
---Dave

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

* Re: [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-26 10:00         ` Dave Martin
@ 2018-01-26 12:13           ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:13 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 26/01/18 10:00, Dave Martin wrote:
> On Thu, Jan 25, 2018 at 05:56:02PM +0000, Suzuki K Poulose wrote:
>> On 25/01/18 17:33, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>>>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>>>> to the userspace and the CPU hwcaps used by the kernel, which
>>>> include cpu features and CPU errata work arounds.
>>>>
>>>> At the moment we have the following restricions:
>>>>
>>>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>>>     - Detected mostly on system wide CPU feature register. But
>>>>       there are some which really uses a local CPU's value to
>>>>       decide the availability (e.g, availability of hardware
>>>>       prefetch). So, we run the check only once, after all the
>>>>       boot-time active CPUs are turned on.
>>>
>>> [ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
>>> presumably because the only systems to which it applies are homogeneous,
>>> and anyway it's only an optimisation IIUC.
>>>
>>> This could be a separate category, but as a one-off that may be a bit
>>> pointless.
>> I understand and was planning to fix this back when it was introduced.
>> But then it was pointless at that time, given that it was always
>> guaranteed to be a homogeneous system. We do something about it in
>> Patch 9.
> 
> This was just on observation than something that needs to be fixed,
> but it it's been cleaned up then so much the better :)
> 
> I'll take a look.
> 
>>> .def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
>>> unused in that case.]
>>>
>>>>     - Any late CPU which doesn't posses all the established features
>>>>       is killed.
>>>
>>> Does "established feature" above ...
>>>
>>>>     - Any late CPU which possess a feature *not* already available
>>>>       is allowed to boot.
>>>
>>> mean the same as "feature already available" here?
>>
>> Yes, its the same. I should have been more consistent.
>>
>>>
>>>>
>>>>   b) CPU Errata work arounds (arm64_errata)
>>>>     - Detected mostly based on a local CPU's feature register.
>>>>       The checks are run on each boot time activated CPUs.
>>>>     - Any late CPU which doesn't have any of the established errata
>>>>       work around capabilities is ignored and is allowed to boot.
>>>>     - Any late CPU which has an errata work around not already available
>>>>       is killed.
>>>>
>>>> However there are some exceptions to the cases above.
>>>>
>>>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>>>     And any late CPU that has this "feature" should be killed.
>>>
>>> Should that be "If KPTI is not enabled during system boot, then any late
>>> CPU that has this "feature" should be killed."
>>
>> Yes.
>>
>>>
>>>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>>>     enabled on CPUs which has it without any issues, even if the CPU is
>>>
>>> have
>>>
>>
>>>>     brought up late.
>>>>
>>>> So this calls for a lot more fine grained behavior for each capability.
>>>> And if we define all the attributes to control their behavior properly,
>>>> we may be able to use a single table for the CPU hwcaps (not the
>>>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>>>> to get there. We define type for a capability, which for now encodes the
>>>> scope of the check. i.e, whether it should be checked system wide or on
>>>> each local CPU. We define two types :
>>>>
>>>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
>>>
>>> 2)
> 
> Meaning you've got 1) twice above (in case you didn't spot it).
> 

Yes, you're right.

>>>
>>>> As such there is no change in how the capabilities are treated.
>>>
>>> OK, I think I finally have my head around this, more or less.
>>>
>>> Mechanism (operations on architectural feature regs) and policy (kernel
>>> runtime configuration) seem to be rather mixed together.  This works
>>> fairly naturally for things like deriving the sanitised feature regs
>>> seen by userspace and determining the ELF hwcaps; but not so naturally
>>> for errata workarounds and other anomalous things like
>>> ARM64_HAS_NO_HW_PREFETCH.
>>
>> Right. We are stuck with "cpu_hwcaps" for both erratum and features,
>> based on which we make some decisions to change the kernel behavior,
>> as it is tied to alternative patching.
>>
>>>
>>> I'm not sure that there is a better approach though -- anyway, that
>>> would be out of scope for this series.
>>>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
>>>>   arch/arm64/kernel/cpu_errata.c      |  8 ++++----
>>>>   arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
>>>>   3 files changed, 41 insertions(+), 29 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index a23c0d4f27e9..4fd5de8ef33e 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -86,16 +86,23 @@ struct arm64_ftr_reg {
>>>>   extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>>> -/* scope of capability check */
>>>> -enum {
>>>> -	SCOPE_SYSTEM,
>>>> -	SCOPE_LOCAL_CPU,
>>>> -};
>>>> +
>>>> +/* Decide how the capability is detected. On a local CPU vs System wide */
>>>> +#define ARM64_CPUCAP_SCOPE_MASK			0x3
>>>> +#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
>>>> +#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
>>>> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>>>> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>>>
>>> Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?
>>
>> It is an unsupported configuration.
> 
> Surely meaningless, not just unsupported?

Yep.

> 
>>>
>>> Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).
>>>
>>
>> It is a bit tricky. I chose separate bits to allow filter an entry in a table
>> of capabilities based on the bits. e.g, we want to
>>
>> 1) Process only the local scope (e.g detecting CPU local capabilities, where
>> we are not yet ready to run the system wide checks)
>>
>> 2) Process all the entries including local/system. (e.g, verifying all the
>> capabilities for a late CPU).
> 
> OK, so LOCAL_CPU and SYSTEM are mutually exclusive for the cap type, but
> by making them separate bits in a bitmask then (LOCAL_CPU | SYSTEM) as a
> match value will match on either.
> 
>> Things get further complicated by the addition of "EARLY", where we want to
>> filter entries based on "EARLY" bit. So, we need to pass on a mask of bits
>> to the helpers, which are not just the binary scope. See Patch 7 for more
>> info.
>>
>>>> +
>>>> +/* CPU errata detected at boot time based on feature of one or more CPUs */
>>>> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
>>>
>>>> +/* CPU feature detected at boot time based on system-wide value of a feature */
>>>
>>> I'm still not overly keen on these names, but I do at least see where
>>> they come from now.

I will try to make this patch a bit more simpler, by not doing a forward reference
of the conflict "behavior" we introduce in the next patch and, keeping it just to
changing the field name.

Thanks a lot for the feedback.

Cheers
Suzuki

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

* [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-26 12:13           ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 10:00, Dave Martin wrote:
> On Thu, Jan 25, 2018 at 05:56:02PM +0000, Suzuki K Poulose wrote:
>> On 25/01/18 17:33, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:57PM +0000, Suzuki K Poulose wrote:
>>>> We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
>>>> to the userspace and the CPU hwcaps used by the kernel, which
>>>> include cpu features and CPU errata work arounds.
>>>>
>>>> At the moment we have the following restricions:
>>>>
>>>>   a) CPU feature hwcaps (arm64_features) and ELF HWCAPs (arm64_elf_hwcap)
>>>>     - Detected mostly on system wide CPU feature register. But
>>>>       there are some which really uses a local CPU's value to
>>>>       decide the availability (e.g, availability of hardware
>>>>       prefetch). So, we run the check only once, after all the
>>>>       boot-time active CPUs are turned on.
>>>
>>> [ARM64_HAS_NO_HW_PREFETCH is kinda broken, but we also get away with it
>>> presumably because the only systems to which it applies are homogeneous,
>>> and anyway it's only an optimisation IIUC.
>>>
>>> This could be a separate category, but as a one-off that may be a bit
>>> pointless.
>> I understand and was planning to fix this back when it was introduced.
>> But then it was pointless at that time, given that it was always
>> guaranteed to be a homogeneous system. We do something about it in
>> Patch 9.
> 
> This was just on observation than something that needs to be fixed,
> but it it's been cleaned up then so much the better :)
> 
> I'll take a look.
> 
>>> .def_scope == SCOPE_SYSTEM appears anomalous there, but it's also
>>> unused in that case.]
>>>
>>>>     - Any late CPU which doesn't posses all the established features
>>>>       is killed.
>>>
>>> Does "established feature" above ...
>>>
>>>>     - Any late CPU which possess a feature *not* already available
>>>>       is allowed to boot.
>>>
>>> mean the same as "feature already available" here?
>>
>> Yes, its the same. I should have been more consistent.
>>
>>>
>>>>
>>>>   b) CPU Errata work arounds (arm64_errata)
>>>>     - Detected mostly based on a local CPU's feature register.
>>>>       The checks are run on each boot time activated CPUs.
>>>>     - Any late CPU which doesn't have any of the established errata
>>>>       work around capabilities is ignored and is allowed to boot.
>>>>     - Any late CPU which has an errata work around not already available
>>>>       is killed.
>>>>
>>>> However there are some exceptions to the cases above.
>>>>
>>>> 1) KPTI is a feature that we need to enable when at least one CPU needs it.
>>>>     And any late CPU that has this "feature" should be killed.
>>>
>>> Should that be "If KPTI is not enabled during system boot, then any late
>>> CPU that has this "feature" should be killed."
>>
>> Yes.
>>
>>>
>>>> 2) Hardware DBM feature is a non-conflicting capability which could be
>>>>     enabled on CPUs which has it without any issues, even if the CPU is
>>>
>>> have
>>>
>>
>>>>     brought up late.
>>>>
>>>> So this calls for a lot more fine grained behavior for each capability.
>>>> And if we define all the attributes to control their behavior properly,
>>>> we may be able to use a single table for the CPU hwcaps (not the
>>>> ELF HWCAPs, which cover errata and features). This is a prepartory step
>>>> to get there. We define type for a capability, which for now encodes the
>>>> scope of the check. i.e, whether it should be checked system wide or on
>>>> each local CPU. We define two types :
>>>>
>>>>    1) ARM64_CPUCAP_BOOT_SYSTEM_FEATURE - Implies (a) as described above.
>>>>    1) ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM - Implies (b) as described above.
>>>
>>> 2)
> 
> Meaning you've got 1) twice above (in case you didn't spot it).
> 

Yes, you're right.

>>>
>>>> As such there is no change in how the capabilities are treated.
>>>
>>> OK, I think I finally have my head around this, more or less.
>>>
>>> Mechanism (operations on architectural feature regs) and policy (kernel
>>> runtime configuration) seem to be rather mixed together.  This works
>>> fairly naturally for things like deriving the sanitised feature regs
>>> seen by userspace and determining the ELF hwcaps; but not so naturally
>>> for errata workarounds and other anomalous things like
>>> ARM64_HAS_NO_HW_PREFETCH.
>>
>> Right. We are stuck with "cpu_hwcaps" for both erratum and features,
>> based on which we make some decisions to change the kernel behavior,
>> as it is tied to alternative patching.
>>
>>>
>>> I'm not sure that there is a better approach though -- anyway, that
>>> would be out of scope for this series.
>>>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h | 24 +++++++++++++++++------
>>>>   arch/arm64/kernel/cpu_errata.c      |  8 ++++----
>>>>   arch/arm64/kernel/cpufeature.c      | 38 ++++++++++++++++++-------------------
>>>>   3 files changed, 41 insertions(+), 29 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index a23c0d4f27e9..4fd5de8ef33e 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -86,16 +86,23 @@ struct arm64_ftr_reg {
>>>>   extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>>> -/* scope of capability check */
>>>> -enum {
>>>> -	SCOPE_SYSTEM,
>>>> -	SCOPE_LOCAL_CPU,
>>>> -};
>>>> +
>>>> +/* Decide how the capability is detected. On a local CPU vs System wide */
>>>> +#define ARM64_CPUCAP_SCOPE_MASK			0x3
>>>> +#define ARM64_CPUCAP_SCOPE_LOCAL_CPU		BIT(0)
>>>> +#define ARM64_CPUCAP_SCOPE_SYSTEM		BIT(1)
>>>> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>>>> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>>>
>>> Are these really orthogonal?  What would be meant by (LOCAL_CPU | SYSTEM)?
>>
>> It is an unsupported configuration.
> 
> Surely meaningless, not just unsupported?

Yep.

> 
>>>
>>> Otherwise, perhaps they should be 0 and 1, not BIT(0), BIT(1).
>>>
>>
>> It is a bit tricky. I chose separate bits to allow filter an entry in a table
>> of capabilities based on the bits. e.g, we want to
>>
>> 1) Process only the local scope (e.g detecting CPU local capabilities, where
>> we are not yet ready to run the system wide checks)
>>
>> 2) Process all the entries including local/system. (e.g, verifying all the
>> capabilities for a late CPU).
> 
> OK, so LOCAL_CPU and SYSTEM are mutually exclusive for the cap type, but
> by making them separate bits in a bitmask then (LOCAL_CPU | SYSTEM) as a
> match value will match on either.
> 
>> Things get further complicated by the addition of "EARLY", where we want to
>> filter entries based on "EARLY" bit. So, we need to pass on a mask of bits
>> to the helpers, which are not just the binary scope. See Patch 7 for more
>> info.
>>
>>>> +
>>>> +/* CPU errata detected at boot time based on feature of one or more CPUs */
>>>> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
>>>
>>>> +/* CPU feature detected at boot time based on system-wide value of a feature */
>>>
>>> I'm still not overly keen on these names, but I do at least see where
>>> they come from now.

I will try to make this patch a bit more simpler, by not doing a forward reference
of the conflict "behavior" we introduce in the next patch and, keeping it just to
changing the field name.

Thanks a lot for the feedback.

Cheers
Suzuki

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

* Re: [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
  2018-01-26 11:22     ` Dave Martin
@ 2018-01-26 12:21       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:21 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 11:22, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:00PM +0000, Suzuki K Poulose wrote:
>> While processing the list of capabilities, it is useful to
>> filter out some of the entries based on the given type to
>> allow better control. This can be used later for handling
>> LOCAL vs SYSTEM wide capabilities and more.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  5 +++++
>>   arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
>>   2 files changed, 25 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 27d037bb0451..a621d2184227 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   /* Is it safe for a late CPU to miss this capability when system has it */
>>   #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
>>   
>> +#define ARM64_CPUCAP_TYPE_ALL			 \
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
>> +	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> 
> Nit: can we have another tab between | and \?
> 
> This will help to make missing |s stand out more if/when more entries
> are added to this list in future.
> 

Sure, will do.

>>   /*
>>    * CPU errata detected at boot time based on feature of one or more CPUs.
>>    * It is not safe for a late CPU to have this feature when the system doesn't
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 79737034a628..198c5daddd65 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1180,9 +1180,11 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>>   }
>>   
>>   static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>> -			    const char *info)
>> +				    u16 cap_type, const char *info)
> 
> Semantically "cap_type" represents a set of accepted types, not a single
> type here.
> 
> Can we rename it to "cap_types", "cap_type_mask" or similar?
> 
>>   {
>>   	for (; caps->matches; caps++) {
>> +		if (!(caps->type & cap_type))
>> +			continue;
> 
> Minor nit: insert a blank line here?
> 
> To me, lack of a blank line suggests that the code will always fall
> through to the next line, which is not the case after
> return/continue/break/goto.
> 
> Alternatively:
> 
> 		if (!(caps->type & cap_type) ||
> 		    !caps->matches(caps, caps->def_scope))
> 			continue;
> 
> still seems fairly intelligible ...[1]
> 
>>   		if (!caps->matches(caps, cpucap_default_scope(caps)))
>>   			continue;
>>   

Yep, will do.

>> @@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
>>    * Run through the enabled capabilities and enable() it on all active
>>    * CPUs
>>    */
>> -static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
>> +static void __init
>> +enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
> 
> The "caps_type" argument should be named consistently with the
> corresponding argument to update_cpu_capabilities().
> 
>>   {
>>   	for (; caps->matches; caps++) {
>>   		unsigned int num = caps->capability;
>>   
>> -		if (!cpus_have_cap(num))
>> +		if (!(caps->type & caps_type) || !cpus_have_cap(num))
> 
> [1]... and would match the approach taken here.
> 
>>   			continue;
>>   
>>   		/* Ensure cpus_have_const_cap(num) works */
>> @@ -1231,12 +1234,16 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>>    * Run through the list of capabilities to check for conflicts.
>>    * Returns "false" on conflicts.
>>    */
>> -static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
>> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
>> +				    u16 caps_type)
>>   {
>>   	bool cpu_has_cap, system_has_cap;
>>   	const struct arm64_cpu_capabilities *caps = caps_list;
>>   
>>   	for (; caps->matches; caps++) {
>> +		if (!(caps->type & caps_type))
>> +			continue;
>> +
>>   		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
>>   		system_has_cap =  cpus_have_cap(caps->capability);
>>   
>> @@ -1299,7 +1306,7 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
>>   
>>   static void verify_local_cpu_features(void)
>>   {
>> -	if (!__verify_local_cpu_caps(arm64_features))
>> +	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
>>   		cpu_die_early();
>>   }
>>   
>> @@ -1327,18 +1334,20 @@ static void verify_sve_features(void)
>>    */
>>   static void verify_local_cpu_errata_workarounds(void)
>>   {
>> -	if (__verify_local_cpu_caps(arm64_errata))
>> +	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
>>   		cpu_die_early();
> 
> Did you mean to insert the ! here?

Thanks for spotting. I think it should have been there in the first place,
as we get "false" when there is a conflict. I will fix the previous patch which
adds the call.

Cheers
Suzuki

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

* [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
@ 2018-01-26 12:21       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 11:22, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:00PM +0000, Suzuki K Poulose wrote:
>> While processing the list of capabilities, it is useful to
>> filter out some of the entries based on the given type to
>> allow better control. This can be used later for handling
>> LOCAL vs SYSTEM wide capabilities and more.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  5 +++++
>>   arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
>>   2 files changed, 25 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 27d037bb0451..a621d2184227 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   /* Is it safe for a late CPU to miss this capability when system has it */
>>   #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
>>   
>> +#define ARM64_CPUCAP_TYPE_ALL			 \
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
>> +	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> 
> Nit: can we have another tab between | and \?
> 
> This will help to make missing |s stand out more if/when more entries
> are added to this list in future.
> 

Sure, will do.

>>   /*
>>    * CPU errata detected at boot time based on feature of one or more CPUs.
>>    * It is not safe for a late CPU to have this feature when the system doesn't
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 79737034a628..198c5daddd65 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1180,9 +1180,11 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>>   }
>>   
>>   static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>> -			    const char *info)
>> +				    u16 cap_type, const char *info)
> 
> Semantically "cap_type" represents a set of accepted types, not a single
> type here.
> 
> Can we rename it to "cap_types", "cap_type_mask" or similar?
> 
>>   {
>>   	for (; caps->matches; caps++) {
>> +		if (!(caps->type & cap_type))
>> +			continue;
> 
> Minor nit: insert a blank line here?
> 
> To me, lack of a blank line suggests that the code will always fall
> through to the next line, which is not the case after
> return/continue/break/goto.
> 
> Alternatively:
> 
> 		if (!(caps->type & cap_type) ||
> 		    !caps->matches(caps, caps->def_scope))
> 			continue;
> 
> still seems fairly intelligible ...[1]
> 
>>   		if (!caps->matches(caps, cpucap_default_scope(caps)))
>>   			continue;
>>   

Yep, will do.

>> @@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
>>    * Run through the enabled capabilities and enable() it on all active
>>    * CPUs
>>    */
>> -static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
>> +static void __init
>> +enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
> 
> The "caps_type" argument should be named consistently with the
> corresponding argument to update_cpu_capabilities().
> 
>>   {
>>   	for (; caps->matches; caps++) {
>>   		unsigned int num = caps->capability;
>>   
>> -		if (!cpus_have_cap(num))
>> +		if (!(caps->type & caps_type) || !cpus_have_cap(num))
> 
> [1]... and would match the approach taken here.
> 
>>   			continue;
>>   
>>   		/* Ensure cpus_have_const_cap(num) works */
>> @@ -1231,12 +1234,16 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>>    * Run through the list of capabilities to check for conflicts.
>>    * Returns "false" on conflicts.
>>    */
>> -static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
>> +static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
>> +				    u16 caps_type)
>>   {
>>   	bool cpu_has_cap, system_has_cap;
>>   	const struct arm64_cpu_capabilities *caps = caps_list;
>>   
>>   	for (; caps->matches; caps++) {
>> +		if (!(caps->type & caps_type))
>> +			continue;
>> +
>>   		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
>>   		system_has_cap =  cpus_have_cap(caps->capability);
>>   
>> @@ -1299,7 +1306,7 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
>>   
>>   static void verify_local_cpu_features(void)
>>   {
>> -	if (!__verify_local_cpu_caps(arm64_features))
>> +	if (!__verify_local_cpu_caps(arm64_features, ARM64_CPUCAP_TYPE_ALL))
>>   		cpu_die_early();
>>   }
>>   
>> @@ -1327,18 +1334,20 @@ static void verify_sve_features(void)
>>    */
>>   static void verify_local_cpu_errata_workarounds(void)
>>   {
>> -	if (__verify_local_cpu_caps(arm64_errata))
>> +	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
>>   		cpu_die_early();
> 
> Did you mean to insert the ! here?

Thanks for spotting. I think it should have been there in the first place,
as we get "false" when there is a conflict. I will fix the previous patch which
adds the call.

Cheers
Suzuki

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

* Re: [PATCH 10/16] arm64: Make KPTI strict CPU local feature
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 12:25     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 12:25 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:03PM +0000, Suzuki K Poulose wrote:
> KPTI capability is a security feature which should be enabled
> when at least one CPU on the system needs it. Any late CPU
> which needs the kernel support, should be prevented from
> booting (and thus making the system unsecure) if the feature
> was not already enabled.

Is there an actual change to behaviour here?

It's not very obvious from the commit message, or the patch when read in
isolation.

> 
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 111f6c4b4cd7..2627a836e99d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -862,9 +862,8 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
>  static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
>  
>  static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,

[Nit: All the other .matches functions have a predicate-style name, so
"should_unmap_kernel_at_el0" or "must_unmap_kernel_at_el0" might be
better names...  However, the name wasn't introduced by this series and
it's not a huge deal.] 

> -				int __unused)
> +				int scope)
>  {
> -	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
>  
>  	/* Forced on command line? */
>  	if (__kpti_forced) {
> @@ -878,8 +877,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>  		return true;
>  
>  	/* Defer to CPU feature registers */
> -	return !cpuid_feature_extract_unsigned_field(pfr0,
> -						     ID_AA64PFR0_CSV3_SHIFT);
> +	return !has_cpuid_feature(entry, scope);
>  }
>  
>  static int __init parse_kpti(char *str)
> @@ -1003,7 +1001,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Kernel page table isolation (KPTI)",
>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> -		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
> +		.sys_reg = SYS_ID_AA64PFR0_EL1,
> +		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
> +		.min_field_value = 1,
>  		.matches = unmap_kernel_at_el0,
>  	},
>  #endif

[...]

Cheers
---Dave

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

* [PATCH 10/16] arm64: Make KPTI strict CPU local feature
@ 2018-01-26 12:25     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 12:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:03PM +0000, Suzuki K Poulose wrote:
> KPTI capability is a security feature which should be enabled
> when at least one CPU on the system needs it. Any late CPU
> which needs the kernel support, should be prevented from
> booting (and thus making the system unsecure) if the feature
> was not already enabled.

Is there an actual change to behaviour here?

It's not very obvious from the commit message, or the patch when read in
isolation.

> 
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 111f6c4b4cd7..2627a836e99d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -862,9 +862,8 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
>  static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
>  
>  static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,

[Nit: All the other .matches functions have a predicate-style name, so
"should_unmap_kernel_at_el0" or "must_unmap_kernel_at_el0" might be
better names...  However, the name wasn't introduced by this series and
it's not a huge deal.] 

> -				int __unused)
> +				int scope)
>  {
> -	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
>  
>  	/* Forced on command line? */
>  	if (__kpti_forced) {
> @@ -878,8 +877,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>  		return true;
>  
>  	/* Defer to CPU feature registers */
> -	return !cpuid_feature_extract_unsigned_field(pfr0,
> -						     ID_AA64PFR0_CSV3_SHIFT);
> +	return !has_cpuid_feature(entry, scope);
>  }
>  
>  static int __init parse_kpti(char *str)
> @@ -1003,7 +1001,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Kernel page table isolation (KPTI)",
>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> -		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
> +		.sys_reg = SYS_ID_AA64PFR0_EL1,
> +		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
> +		.min_field_value = 1,
>  		.matches = unmap_kernel_at_el0,
>  	},
>  #endif

[...]

Cheers
---Dave

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

* Re: [PATCH 08/16] arm64: capabilities: Group handling of features and errata
  2018-01-26 11:47     ` Dave Martin
@ 2018-01-26 12:31       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:31 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 11:47, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
>> So far we have had separate routes for triggering errata and feature
> 
> "triggering errata" ? ;)
> 

:-). Should have been "triggering errata and feature capability *checks*.

> Maybe "[...] for determining whether to activate errata workarounds and
> whether to enable feature capabilities."
> 


>> capabilities. Also, we never allowed "features" based on local CPU
>> and "errata" based on System wide safe registers. This patch
>> groups the handling of errata and features and also allows them
>> to have all the possible scopes.
>>
>> So, we now run through the arm64_features and arm64_errata:
> 
> when?

with this patch.

> What about late cpus?
> 

We don't detect any new capabilities on them. They continue to get
verified against the enabled capabilities.

>>   1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
>>      via update_cpu_local_capabilities().
> 
> "each [...] enabeld CPUs" -> "each [...] enabled CPU"
> 
> Also, changing "boot time" -> "boot-time" helps avoid this being misread
> as "on each boot", which could be taken to mean "each time a CPU comes
> online".  I'm guessing that's not the intended meaning here.

OK


>>   /*
>> - * The CPU Errata work arounds are detected and applied at boot time
>> - * and the related information is freed soon after. If the new CPU requires
>> - * an errata not detected at boot, fail this CPU.
>> + * Check for all capablities within the scope of local CPU.
>> + * This is run on all boot time activated CPUs.
>>    */
>> -static void verify_local_cpu_errata_workarounds(void)
>> +static void update_cpu_local_capabilities(void)
> 
> [Gaah, stupid git diff making function insertion look like function
> modification.  Sometimes --patience does a better job, but there seems
> no foolproof solution...  If you do a respin, it might be worth trying
> it.]

Will try, thanks for the suggestion. I didn't know about that :-)

>> -static void __init setup_feature_capabilities(void)
>> +static void __init setup_system_capabilities(void)
>>   {
>> -	update_cpu_capabilities(arm64_features,
>> -				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
>> -	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
>> +	/*
>> +	 * We have finalised the system wide safe feature registers,
>> +	 * finalise the capabilities that depend on it.
>> +	 */
>> +	update_system_capabilities();
>> +	/* Enable all the available capabilities */
>> +	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);
> 
> So setup_system_capabilities() enables _non_ system-wide capabilities/
> errata workarounds too?

> Maybe this function should just have a different name, like
> "setup_boot_capabilities" or similar?

The problem with setup_boot_capabilities() is that it could conflict with
"coming soon" setup_boot_cpu_capabilities(). May be,

setup_boot_time_system_capabilities().


> 
>    }
>>   
>>   DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
>> @@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
>>   	u32 cwg;
>>   	int cls;
>>   
>> -	/* Set the CPU feature capabilies */
>> -	setup_feature_capabilities();
>> -	enable_errata_workarounds();
>> +	setup_system_capabilities();
>>   	mark_const_caps_ready();
>>   	setup_elf_hwcaps(arm64_elf_hwcaps);
> 
> I wonder whether we could unify the elf hwcaps handling too.

I was thinking about it today. The only catch is how do we know
if we have "the capability", as it is spread across multiple bitmasks.
(HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).

Suzuki

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
@ 2018-01-26 12:31       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 12:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 11:47, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
>> So far we have had separate routes for triggering errata and feature
> 
> "triggering errata" ? ;)
> 

:-). Should have been "triggering errata and feature capability *checks*.

> Maybe "[...] for determining whether to activate errata workarounds and
> whether to enable feature capabilities."
> 


>> capabilities. Also, we never allowed "features" based on local CPU
>> and "errata" based on System wide safe registers. This patch
>> groups the handling of errata and features and also allows them
>> to have all the possible scopes.
>>
>> So, we now run through the arm64_features and arm64_errata:
> 
> when?

with this patch.

> What about late cpus?
> 

We don't detect any new capabilities on them. They continue to get
verified against the enabled capabilities.

>>   1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
>>      via update_cpu_local_capabilities().
> 
> "each [...] enabeld CPUs" -> "each [...] enabled CPU"
> 
> Also, changing "boot time" -> "boot-time" helps avoid this being misread
> as "on each boot", which could be taken to mean "each time a CPU comes
> online".  I'm guessing that's not the intended meaning here.

OK


>>   /*
>> - * The CPU Errata work arounds are detected and applied at boot time
>> - * and the related information is freed soon after. If the new CPU requires
>> - * an errata not detected at boot, fail this CPU.
>> + * Check for all capablities within the scope of local CPU.
>> + * This is run on all boot time activated CPUs.
>>    */
>> -static void verify_local_cpu_errata_workarounds(void)
>> +static void update_cpu_local_capabilities(void)
> 
> [Gaah, stupid git diff making function insertion look like function
> modification.  Sometimes --patience does a better job, but there seems
> no foolproof solution...  If you do a respin, it might be worth trying
> it.]

Will try, thanks for the suggestion. I didn't know about that :-)

>> -static void __init setup_feature_capabilities(void)
>> +static void __init setup_system_capabilities(void)
>>   {
>> -	update_cpu_capabilities(arm64_features,
>> -				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
>> -	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
>> +	/*
>> +	 * We have finalised the system wide safe feature registers,
>> +	 * finalise the capabilities that depend on it.
>> +	 */
>> +	update_system_capabilities();
>> +	/* Enable all the available capabilities */
>> +	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);
> 
> So setup_system_capabilities() enables _non_ system-wide capabilities/
> errata workarounds too?

> Maybe this function should just have a different name, like
> "setup_boot_capabilities" or similar?

The problem with setup_boot_capabilities() is that it could conflict with
"coming soon" setup_boot_cpu_capabilities(). May be,

setup_boot_time_system_capabilities().


> 
>    }
>>   
>>   DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
>> @@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
>>   	u32 cwg;
>>   	int cls;
>>   
>> -	/* Set the CPU feature capabilies */
>> -	setup_feature_capabilities();
>> -	enable_errata_workarounds();
>> +	setup_system_capabilities();
>>   	mark_const_caps_ready();
>>   	setup_elf_hwcaps(arm64_elf_hwcaps);
> 
> I wonder whether we could unify the elf hwcaps handling too.

I was thinking about it today. The only catch is how do we know
if we have "the capability", as it is spread across multiple bitmasks.
(HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).

Suzuki

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

* Re: [PATCH 11/16] arm64: errata: Clean up midr range helpers
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 13:50     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 13:50 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:04PM +0000, Suzuki K Poulose wrote:
> We are about to introduce generic MIDR range helpers. Clean
> up the existing helpers in errat handling, preparing them

errata/erratum

> to use generic version.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpu_errata.c | 76 +++++++++++++++++++++++-------------------
>  1 file changed, 41 insertions(+), 35 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 550ac8a0854b..054b17009f41 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -179,14 +179,23 @@ static int qcom_enable_link_stack_sanitization(
>  }
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> -#define MIDR_RANGE(model, min, max) \
> +#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
>  	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
> -	.midr_range_min = min, \
> -	.midr_range_max = max
> +	.midr_range_min = MIDR_CPU_VAR_REV(v_min, r_min), \
> +	.midr_range_max = MIDR_CPU_VAR_REV(v_max, r_max)
>  
> -#define MIDR_ALL_VERSIONS(model) \
> +/* Errata affecting a range of revisions of  given model variant */
> +#define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
> +	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
> +
> +/* Errata affecting a single variant/revision of a model */
> +#define ERRATA_MIDR(model, var, rev)	\

Maybe call this ERRATA_MIDR_REV() since it's similar to
ERRATA_MIDR_REV_RANGE() but describes a single revision?

[...]

Cheers
---Dave

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

* [PATCH 11/16] arm64: errata: Clean up midr range helpers
@ 2018-01-26 13:50     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 13:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:04PM +0000, Suzuki K Poulose wrote:
> We are about to introduce generic MIDR range helpers. Clean
> up the existing helpers in errat handling, preparing them

errata/erratum

> to use generic version.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpu_errata.c | 76 +++++++++++++++++++++++-------------------
>  1 file changed, 41 insertions(+), 35 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 550ac8a0854b..054b17009f41 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -179,14 +179,23 @@ static int qcom_enable_link_stack_sanitization(
>  }
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> -#define MIDR_RANGE(model, min, max) \
> +#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
>  	.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
> -	.midr_range_min = min, \
> -	.midr_range_max = max
> +	.midr_range_min = MIDR_CPU_VAR_REV(v_min, r_min), \
> +	.midr_range_max = MIDR_CPU_VAR_REV(v_max, r_max)
>  
> -#define MIDR_ALL_VERSIONS(model) \
> +/* Errata affecting a range of revisions of  given model variant */
> +#define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
> +	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
> +
> +/* Errata affecting a single variant/revision of a model */
> +#define ERRATA_MIDR(model, var, rev)	\

Maybe call this ERRATA_MIDR_REV() since it's similar to
ERRATA_MIDR_REV_RANGE() but describes a single revision?

[...]

Cheers
---Dave

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

* Re: [PATCH 12/16] arm64: Add helpers for checking CPU MIDR against a range
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 14:08     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 14:08 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:05PM +0000, Suzuki K Poulose wrote:
> Add helpers for checking if the given CPU midr falls in a range
> of variants/revisions for a given model.

This doesn't describe what the patch does: instead, helpers are being
added for checking whether an MIDR falls in one of multiple affected
model(s) and or revision(s) here.

Doing this makes logical sense, but is it really worth it?

We might save 100-200 bytes in the kernel image for now, but a common
workaround for errata on multiple unrelated cpus is surely a rare case.

Only if there are many such lists, or if the lists become large does
this start to seem a clear win.

[...]

Cheers
---Dave

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

* [PATCH 12/16] arm64: Add helpers for checking CPU MIDR against a range
@ 2018-01-26 14:08     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:05PM +0000, Suzuki K Poulose wrote:
> Add helpers for checking if the given CPU midr falls in a range
> of variants/revisions for a given model.

This doesn't describe what the patch does: instead, helpers are being
added for checking whether an MIDR falls in one of multiple affected
model(s) and or revision(s) here.

Doing this makes logical sense, but is it really worth it?

We might save 100-200 bytes in the kernel image for now, but a common
workaround for errata on multiple unrelated cpus is surely a rare case.

Only if there are many such lists, or if the lists become large does
this start to seem a clear win.

[...]

Cheers
---Dave

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

* Re: [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 14:16     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 14:16 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
> Add helpers for detecting an errata on list of midr ranges
> of affected CPUs.

This doesn't describe what the patch does: instead, helpers are being
added for checking whether an MIDR falls in one of multiple affected
model(s) and or revision(s).

Doing this makes sense, but is it really worth it?

We might save 100-200 bytes in the kernel image for now, but a common
workaround for errata on multiple unrelated cpus is surely a rare case.

Only if there are many such lists, or if the lists become large does
this start to seem a clear win.

> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
>  2 files changed, 25 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a3d54c2c411f..70712de687c7 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h

[...]

> @@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> -		.enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> +		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),

Could we just use a macro to generate multiple structs, instead of
inventing a new type of struct?

Cheers
---Dave

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
@ 2018-01-26 14:16     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 14:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
> Add helpers for detecting an errata on list of midr ranges
> of affected CPUs.

This doesn't describe what the patch does: instead, helpers are being
added for checking whether an MIDR falls in one of multiple affected
model(s) and or revision(s).

Doing this makes sense, but is it really worth it?

We might save 100-200 bytes in the kernel image for now, but a common
workaround for errata on multiple unrelated cpus is surely a rare case.

Only if there are many such lists, or if the lists become large does
this start to seem a clear win.

> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
>  2 files changed, 25 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a3d54c2c411f..70712de687c7 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h

[...]

> @@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> -		.enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> +		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),

Could we just use a macro to generate multiple structs, instead of
inventing a new type of struct?

Cheers
---Dave

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

* Re: [PATCH 15/16] arm64: Delay enabling hardware DBM feature
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 14:41     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 14:41 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:08PM +0000, Suzuki K Poulose wrote:
> We enable hardware DBM bit in a capable CPU, very early in the
> boot via __cpu_setup. This doesn't give us a flexibility of
> optionally disable the feature, as the clearing the bit
> is a bit costly as the TLB can cache the settings. Instead,
> we delay enabling the feature until the CPU is brought up
> into the kernel. We use the feature capability mechanism
> to handle it.
> 
> The hardware DBM is a non-conflicting feature. i.e, the kernel
> can safely run with a mix of CPUs with some using the feature
> and the others don't. So, it is safe for a late CPU to have
> this capability and enable it, even if the active CPUs don't.
> 
> To get this handled properly by the infrastructure, we
> unconditionally set the capability and only enable it
> on CPUs which really have the feature. Adds a new type
> of feature to the capability infrastructure which
> ignores the conflict in a late CPU.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpucaps.h    |  3 ++-
>  arch/arm64/include/asm/cpufeature.h |  8 +++++++
>  arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/proc.S                |  5 +----
>  4 files changed, 53 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index bb263820de13..8df80cc828ac 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -45,7 +45,8 @@
>  #define ARM64_HARDEN_BRANCH_PREDICTOR		24
>  #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
>  #define ARM64_HAS_RAS_EXTN			26
> +#define ARM64_HW_DBM				27
>  
> -#define ARM64_NCAPS				27
> +#define ARM64_NCAPS				28
>  
>  #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 70712de687c7..243ec7c77c79 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
>  	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> +/*
> + * CPU feature detected on each local CPU. It is safe for a late CPU to
> + * either have it or not.
> + */
> +#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)

OK, so this is similar to my suggestion for HAS_NO_HW_PREFETCH (though
that need not have the same answer -- I was speculating there).

Nit: tab between | and \?

>  struct arm64_cpu_capabilities {
>  	const char *desc;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 2627a836e99d..8af755b8219d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
>  __setup("kpti=", parse_kpti);
>  #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
>  
> +#ifdef CONFIG_ARM64_HW_AFDBM
> +static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
> +{
> +	/*
> +	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
> +	 * a mix of CPUs with and without the feature. So, we unconditionally
> +	 * enable the capability to allow any late CPU to use the feature.
> +	 * We only enable the control bits on the CPU, if it actually supports.
> +	 */
> +	return true;
> +}
> +
> +static inline void __cpu_enable_hw_dbm(void)
> +{
> +	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
> +
> +	write_sysreg(tcr, tcr_el1);
> +	isb();

Do we need this isb?  Do we care exactly when setting TCR_HD appears
to take effect?

> +}
> +
> +static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
> +{
> +	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
> +		__cpu_enable_hw_dbm();
> +
> +	return 0;
> +}
> +#endif
> +
>  static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>  {
>  	/*
> @@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.enable = cpu_clear_disr,
>  	},
>  #endif /* CONFIG_ARM64_RAS_EXTN */
> +#ifdef CONFIG_ARM64_HW_AFDBM
> +	{
> +		.desc = "Hardware pagetable Dirty Bit Management",
> +		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
> +		.capability = ARM64_HW_DBM,
> +		.sys_reg = SYS_ID_AA64MMFR1_EL1,
> +		.sign = FTR_UNSIGNED,
> +		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
> +		.min_field_value = 2,
> +		.matches = has_hw_dbm,

Can't we use has_cpuid_feature here?  Why do we need a fake .matches and
then code the check manually in the enable mathod?

I may be missing something here.

[...]

Cheers
---Dave

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

* [PATCH 15/16] arm64: Delay enabling hardware DBM feature
@ 2018-01-26 14:41     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:08PM +0000, Suzuki K Poulose wrote:
> We enable hardware DBM bit in a capable CPU, very early in the
> boot via __cpu_setup. This doesn't give us a flexibility of
> optionally disable the feature, as the clearing the bit
> is a bit costly as the TLB can cache the settings. Instead,
> we delay enabling the feature until the CPU is brought up
> into the kernel. We use the feature capability mechanism
> to handle it.
> 
> The hardware DBM is a non-conflicting feature. i.e, the kernel
> can safely run with a mix of CPUs with some using the feature
> and the others don't. So, it is safe for a late CPU to have
> this capability and enable it, even if the active CPUs don't.
> 
> To get this handled properly by the infrastructure, we
> unconditionally set the capability and only enable it
> on CPUs which really have the feature. Adds a new type
> of feature to the capability infrastructure which
> ignores the conflict in a late CPU.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpucaps.h    |  3 ++-
>  arch/arm64/include/asm/cpufeature.h |  8 +++++++
>  arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/proc.S                |  5 +----
>  4 files changed, 53 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index bb263820de13..8df80cc828ac 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -45,7 +45,8 @@
>  #define ARM64_HARDEN_BRANCH_PREDICTOR		24
>  #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
>  #define ARM64_HAS_RAS_EXTN			26
> +#define ARM64_HW_DBM				27
>  
> -#define ARM64_NCAPS				27
> +#define ARM64_NCAPS				28
>  
>  #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 70712de687c7..243ec7c77c79 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
>  	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> +/*
> + * CPU feature detected on each local CPU. It is safe for a late CPU to
> + * either have it or not.
> + */
> +#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)

OK, so this is similar to my suggestion for HAS_NO_HW_PREFETCH (though
that need not have the same answer -- I was speculating there).

Nit: tab between | and \?

>  struct arm64_cpu_capabilities {
>  	const char *desc;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 2627a836e99d..8af755b8219d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
>  __setup("kpti=", parse_kpti);
>  #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
>  
> +#ifdef CONFIG_ARM64_HW_AFDBM
> +static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
> +{
> +	/*
> +	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
> +	 * a mix of CPUs with and without the feature. So, we unconditionally
> +	 * enable the capability to allow any late CPU to use the feature.
> +	 * We only enable the control bits on the CPU, if it actually supports.
> +	 */
> +	return true;
> +}
> +
> +static inline void __cpu_enable_hw_dbm(void)
> +{
> +	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
> +
> +	write_sysreg(tcr, tcr_el1);
> +	isb();

Do we need this isb?  Do we care exactly when setting TCR_HD appears
to take effect?

> +}
> +
> +static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
> +{
> +	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
> +		__cpu_enable_hw_dbm();
> +
> +	return 0;
> +}
> +#endif
> +
>  static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>  {
>  	/*
> @@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.enable = cpu_clear_disr,
>  	},
>  #endif /* CONFIG_ARM64_RAS_EXTN */
> +#ifdef CONFIG_ARM64_HW_AFDBM
> +	{
> +		.desc = "Hardware pagetable Dirty Bit Management",
> +		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
> +		.capability = ARM64_HW_DBM,
> +		.sys_reg = SYS_ID_AA64MMFR1_EL1,
> +		.sign = FTR_UNSIGNED,
> +		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
> +		.min_field_value = 2,
> +		.matches = has_hw_dbm,

Can't we use has_cpuid_feature here?  Why do we need a fake .matches and
then code the check manually in the enable mathod?

I may be missing something here.

[...]

Cheers
---Dave

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

* Re: [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
  2018-01-23 12:28   ` Suzuki K Poulose
@ 2018-01-26 15:33     ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 15:33 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On Tue, Jan 23, 2018 at 12:28:09PM +0000, Suzuki K Poulose wrote:
> Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
> from an erratum 1024718, which causes incorrect updates when DBM/AP
> bits in a page table entry is modified without a break-before-make
> sequence. The work around is to skip enabling the hardware DBM feature
> on the affected cores. The hardware Access Flag management features
> is not affected.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  Documentation/arm64/silicon-errata.txt |  1 +
>  arch/arm64/Kconfig                     | 14 ++++++++++++++
>  arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
>  3 files changed, 28 insertions(+), 1 deletion(-)

[...]

> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 8af755b8219d..64f1e911c6af 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
>  	isb();
>  }
>  
> +static bool cpu_has_erratum_1024718(void)
> +{
> +	static const struct midr_range __maybe_unused cpus[] = {

Do you need __maybe_unused?  If #ifdef were used here then
__maybe_unused would be needed, but I thought that if code is optimised
out instead of conditionally copiled, this didn't apply.

> +		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
> +		{},
> +	};
> +
> +	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
> +	       is_midr_in_range_list(read_cpuid_id(), cpus);

Why have a list with just one entry?  Do you expect more entries over
time?

[...]

Cheers
---Dave

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

* [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
@ 2018-01-26 15:33     ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-26 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 23, 2018 at 12:28:09PM +0000, Suzuki K Poulose wrote:
> Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
> from an erratum 1024718, which causes incorrect updates when DBM/AP
> bits in a page table entry is modified without a break-before-make
> sequence. The work around is to skip enabling the hardware DBM feature
> on the affected cores. The hardware Access Flag management features
> is not affected.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  Documentation/arm64/silicon-errata.txt |  1 +
>  arch/arm64/Kconfig                     | 14 ++++++++++++++
>  arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
>  3 files changed, 28 insertions(+), 1 deletion(-)

[...]

> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 8af755b8219d..64f1e911c6af 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
>  	isb();
>  }
>  
> +static bool cpu_has_erratum_1024718(void)
> +{
> +	static const struct midr_range __maybe_unused cpus[] = {

Do you need __maybe_unused?  If #ifdef were used here then
__maybe_unused would be needed, but I thought that if code is optimised
out instead of conditionally copiled, this didn't apply.

> +		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
> +		{},
> +	};
> +
> +	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
> +	       is_midr_in_range_list(read_cpuid_id(), cpus);

Why have a list with just one entry?  Do you expect more entries over
time?

[...]

Cheers
---Dave

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

* Re: [PATCH 10/16] arm64: Make KPTI strict CPU local feature
  2018-01-26 12:25     ` Dave Martin
@ 2018-01-26 15:46       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 15:46 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 12:25, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:03PM +0000, Suzuki K Poulose wrote:
>> KPTI capability is a security feature which should be enabled
>> when at least one CPU on the system needs it. Any late CPU
>> which needs the kernel support, should be prevented from
>> booting (and thus making the system unsecure) if the feature
>> was not already enabled.
> 
> Is there an actual change to behaviour here?

Yes, we now prevent any new CPU from booting if it *matches* the capability,
which we didn't do earlier.

> 
> It's not very obvious from the commit message, or the patch when read in
> isolation.
> 

I will fix the commit message to indicate the current behavior. How about :

"KPTI is treated as a system wide feature, where we enable the feature
when all the CPUs on the system suffers from the security vulnerability,
unless it is enabled via kernel command line. Also, we ignore a late CPU
which might need the defense if the KPTI is not enabled, making the system
insecure. This is not sufficient, as
we should enable the defense when at least one CPU needs it. Also, if
it is not enabled at boot-time, we can no longer enable it when a late
CPU turns up. This patch makes sure that the KPTI is checked on all CPUs
and use it when at least one needs it. Also reject any CPU that needs it,
which turns up late if the KPTI is not already enabled."


Cheers
Suzuki

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

* [PATCH 10/16] arm64: Make KPTI strict CPU local feature
@ 2018-01-26 15:46       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 15:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 12:25, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:03PM +0000, Suzuki K Poulose wrote:
>> KPTI capability is a security feature which should be enabled
>> when at least one CPU on the system needs it. Any late CPU
>> which needs the kernel support, should be prevented from
>> booting (and thus making the system unsecure) if the feature
>> was not already enabled.
> 
> Is there an actual change to behaviour here?

Yes, we now prevent any new CPU from booting if it *matches* the capability,
which we didn't do earlier.

> 
> It's not very obvious from the commit message, or the patch when read in
> isolation.
> 

I will fix the commit message to indicate the current behavior. How about :

"KPTI is treated as a system wide feature, where we enable the feature
when all the CPUs on the system suffers from the security vulnerability,
unless it is enabled via kernel command line. Also, we ignore a late CPU
which might need the defense if the KPTI is not enabled, making the system
insecure. This is not sufficient, as
we should enable the defense when at least one CPU needs it. Also, if
it is not enabled at boot-time, we can no longer enable it when a late
CPU turns up. This patch makes sure that the KPTI is checked on all CPUs
and use it when at least one needs it. Also reject any CPU that needs it,
which turns up late if the KPTI is not already enabled."


Cheers
Suzuki

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

* Re: [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
  2018-01-26 14:16     ` Dave Martin
@ 2018-01-26 15:57       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 15:57 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 14:16, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
>> Add helpers for detecting an errata on list of midr ranges
>> of affected CPUs.
> 
> This doesn't describe what the patch does: instead, helpers are being
> added for checking whether an MIDR falls in one of multiple affected
> model(s) and or revision(s).
> 
> Doing this makes sense, but is it really worth it?

Well, we need th MIDR list helpers anyway for other things:
   - White list of CPUs where we know KPTI is not needed
   - Black list of CPUs where DBM shouldn't be enabled.

So all we do is add a new type which could reduce the number of entries.

> 
> We might save 100-200 bytes in the kernel image for now, but a common
> workaround for errata on multiple unrelated cpus is surely a rare case.
> 
> Only if there are many such lists, or if the lists become large does
> this start to seem a clear win.
> 
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>   arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
>>   2 files changed, 25 insertions(+), 16 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index a3d54c2c411f..70712de687c7 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
> 
> [...]
> 
>> @@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>   #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>>   	{
>>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
>> -		.enable = enable_psci_bp_hardening,
>> -	},
>> -	{
>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
>> -		.enable = enable_psci_bp_hardening,
>> -	},
>> -	{
>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
>> -		.enable = enable_psci_bp_hardening,
>> -	},
>> -	{
>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
>> +		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
> 
> Could we just use a macro to generate multiple structs, instead of
> inventing a new type of struct?

We could. Somehow, I don't think we are over engineering much here.

Cheers
Suzuki

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
@ 2018-01-26 15:57       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 15:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 14:16, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
>> Add helpers for detecting an errata on list of midr ranges
>> of affected CPUs.
> 
> This doesn't describe what the patch does: instead, helpers are being
> added for checking whether an MIDR falls in one of multiple affected
> model(s) and or revision(s).
> 
> Doing this makes sense, but is it really worth it?

Well, we need th MIDR list helpers anyway for other things:
   - White list of CPUs where we know KPTI is not needed
   - Black list of CPUs where DBM shouldn't be enabled.

So all we do is add a new type which could reduce the number of entries.

> 
> We might save 100-200 bytes in the kernel image for now, but a common
> workaround for errata on multiple unrelated cpus is surely a rare case.
> 
> Only if there are many such lists, or if the lists become large does
> this start to seem a clear win.
> 
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>   arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
>>   2 files changed, 25 insertions(+), 16 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index a3d54c2c411f..70712de687c7 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
> 
> [...]
> 
>> @@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>   #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>>   	{
>>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
>> -		.enable = enable_psci_bp_hardening,
>> -	},
>> -	{
>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
>> -		.enable = enable_psci_bp_hardening,
>> -	},
>> -	{
>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
>> -		.enable = enable_psci_bp_hardening,
>> -	},
>> -	{
>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
>> +		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
> 
> Could we just use a macro to generate multiple structs, instead of
> inventing a new type of struct?

We could. Somehow, I don't think we are over engineering much here.

Cheers
Suzuki

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

* Re: [PATCH 15/16] arm64: Delay enabling hardware DBM feature
  2018-01-26 14:41     ` Dave Martin
@ 2018-01-26 16:05       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 16:05 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 14:41, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:08PM +0000, Suzuki K Poulose wrote:
>> We enable hardware DBM bit in a capable CPU, very early in the
>> boot via __cpu_setup. This doesn't give us a flexibility of
>> optionally disable the feature, as the clearing the bit
>> is a bit costly as the TLB can cache the settings. Instead,
>> we delay enabling the feature until the CPU is brought up
>> into the kernel. We use the feature capability mechanism
>> to handle it.
>>
>> The hardware DBM is a non-conflicting feature. i.e, the kernel
>> can safely run with a mix of CPUs with some using the feature
>> and the others don't. So, it is safe for a late CPU to have
>> this capability and enable it, even if the active CPUs don't.
>>
>> To get this handled properly by the infrastructure, we
>> unconditionally set the capability and only enable it
>> on CPUs which really have the feature. Adds a new type
>> of feature to the capability infrastructure which
>> ignores the conflict in a late CPU.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpucaps.h    |  3 ++-
>>   arch/arm64/include/asm/cpufeature.h |  8 +++++++
>>   arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
>>   arch/arm64/mm/proc.S                |  5 +----
>>   4 files changed, 53 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
>> index bb263820de13..8df80cc828ac 100644
>> --- a/arch/arm64/include/asm/cpucaps.h
>> +++ b/arch/arm64/include/asm/cpucaps.h
>> @@ -45,7 +45,8 @@
>>   #define ARM64_HARDEN_BRANCH_PREDICTOR		24
>>   #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
>>   #define ARM64_HAS_RAS_EXTN			26
>> +#define ARM64_HW_DBM				27
>>   
>> -#define ARM64_NCAPS				27
>> +#define ARM64_NCAPS				28
>>   
>>   #endif /* __ASM_CPUCAPS_H */
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 70712de687c7..243ec7c77c79 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    */
>>   #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
>>   	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
>> +/*
>> + * CPU feature detected on each local CPU. It is safe for a late CPU to
>> + * either have it or not.
>> + */
>> +#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
> 
> OK, so this is similar to my suggestion for HAS_NO_HW_PREFETCH (though
> that need not have the same answer -- I was speculating there).

Yes, I was under the assumption that HAS_NO_HW_PREFETCH is treated as
a "Late CPU can't have the capability" type, hence the "STRICT_CPU_LOCAL",
as we can't apply work-arounds anymore for this CPU. However, since
we only suffer a performance impact, we could as well convert it to
a WEAK one.

> 
> Nit: tab between | and \?

Sure.

> 
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 2627a836e99d..8af755b8219d 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
>>   __setup("kpti=", parse_kpti);
>>   #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
>>   
>> +#ifdef CONFIG_ARM64_HW_AFDBM
>> +static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
>> +{
>> +	/*
>> +	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
>> +	 * a mix of CPUs with and without the feature. So, we unconditionally
>> +	 * enable the capability to allow any late CPU to use the feature.
>> +	 * We only enable the control bits on the CPU, if it actually supports.
>> +	 */
>> +	return true;
>> +}
>> +
>> +static inline void __cpu_enable_hw_dbm(void)
>> +{
>> +	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
>> +
>> +	write_sysreg(tcr, tcr_el1);
>> +	isb();
> 
> Do we need this isb?  Do we care exactly when setting TCR_HD appears
> to take effect?

Practically no, as it doesn't matter if we use it or not. But, since the
CPU is anyway booting, there is no harm in enforcing it to take effect.

> 
>> +}
>> +
>> +static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
>> +{
>> +	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
>> +		__cpu_enable_hw_dbm();
>> +
>> +	return 0;
>> +}
>> +#endif
>> +
>>   static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>>   {
>>   	/*
>> @@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   		.enable = cpu_clear_disr,
>>   	},
>>   #endif /* CONFIG_ARM64_RAS_EXTN */
>> +#ifdef CONFIG_ARM64_HW_AFDBM
>> +	{
>> +		.desc = "Hardware pagetable Dirty Bit Management",
>> +		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
>> +		.capability = ARM64_HW_DBM,
>> +		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>> +		.sign = FTR_UNSIGNED,
>> +		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
>> +		.min_field_value = 2,
>> +		.matches = has_hw_dbm,
> 
> Can't we use has_cpuid_feature here?  Why do we need a fake .matches and
> then code the check manually in the enable mathod?

We could, but then we need to add another *type*, where capabilities could
be enabled by a late CPU, where something is not already enabled by the boot-time
CPUs. i.e, if we boot a DBM capable CPU late, we won't be able to use the feature
on it, with the current setup. I didn't want to complicate the infrastructure
further just for this.

> I may be missing something here.

Cheers
Suzuki

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

* [PATCH 15/16] arm64: Delay enabling hardware DBM feature
@ 2018-01-26 16:05       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 14:41, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:08PM +0000, Suzuki K Poulose wrote:
>> We enable hardware DBM bit in a capable CPU, very early in the
>> boot via __cpu_setup. This doesn't give us a flexibility of
>> optionally disable the feature, as the clearing the bit
>> is a bit costly as the TLB can cache the settings. Instead,
>> we delay enabling the feature until the CPU is brought up
>> into the kernel. We use the feature capability mechanism
>> to handle it.
>>
>> The hardware DBM is a non-conflicting feature. i.e, the kernel
>> can safely run with a mix of CPUs with some using the feature
>> and the others don't. So, it is safe for a late CPU to have
>> this capability and enable it, even if the active CPUs don't.
>>
>> To get this handled properly by the infrastructure, we
>> unconditionally set the capability and only enable it
>> on CPUs which really have the feature. Adds a new type
>> of feature to the capability infrastructure which
>> ignores the conflict in a late CPU.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpucaps.h    |  3 ++-
>>   arch/arm64/include/asm/cpufeature.h |  8 +++++++
>>   arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
>>   arch/arm64/mm/proc.S                |  5 +----
>>   4 files changed, 53 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
>> index bb263820de13..8df80cc828ac 100644
>> --- a/arch/arm64/include/asm/cpucaps.h
>> +++ b/arch/arm64/include/asm/cpucaps.h
>> @@ -45,7 +45,8 @@
>>   #define ARM64_HARDEN_BRANCH_PREDICTOR		24
>>   #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
>>   #define ARM64_HAS_RAS_EXTN			26
>> +#define ARM64_HW_DBM				27
>>   
>> -#define ARM64_NCAPS				27
>> +#define ARM64_NCAPS				28
>>   
>>   #endif /* __ASM_CPUCAPS_H */
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 70712de687c7..243ec7c77c79 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    */
>>   #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
>>   	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
>> +/*
>> + * CPU feature detected on each local CPU. It is safe for a late CPU to
>> + * either have it or not.
>> + */
>> +#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
>> +	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
> 
> OK, so this is similar to my suggestion for HAS_NO_HW_PREFETCH (though
> that need not have the same answer -- I was speculating there).

Yes, I was under the assumption that HAS_NO_HW_PREFETCH is treated as
a "Late CPU can't have the capability" type, hence the "STRICT_CPU_LOCAL",
as we can't apply work-arounds anymore for this CPU. However, since
we only suffer a performance impact, we could as well convert it to
a WEAK one.

> 
> Nit: tab between | and \?

Sure.

> 
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 2627a836e99d..8af755b8219d 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
>>   __setup("kpti=", parse_kpti);
>>   #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
>>   
>> +#ifdef CONFIG_ARM64_HW_AFDBM
>> +static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
>> +{
>> +	/*
>> +	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
>> +	 * a mix of CPUs with and without the feature. So, we unconditionally
>> +	 * enable the capability to allow any late CPU to use the feature.
>> +	 * We only enable the control bits on the CPU, if it actually supports.
>> +	 */
>> +	return true;
>> +}
>> +
>> +static inline void __cpu_enable_hw_dbm(void)
>> +{
>> +	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
>> +
>> +	write_sysreg(tcr, tcr_el1);
>> +	isb();
> 
> Do we need this isb?  Do we care exactly when setting TCR_HD appears
> to take effect?

Practically no, as it doesn't matter if we use it or not. But, since the
CPU is anyway booting, there is no harm in enforcing it to take effect.

> 
>> +}
>> +
>> +static int cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
>> +{
>> +	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
>> +		__cpu_enable_hw_dbm();
>> +
>> +	return 0;
>> +}
>> +#endif
>> +
>>   static int cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>>   {
>>   	/*
>> @@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   		.enable = cpu_clear_disr,
>>   	},
>>   #endif /* CONFIG_ARM64_RAS_EXTN */
>> +#ifdef CONFIG_ARM64_HW_AFDBM
>> +	{
>> +		.desc = "Hardware pagetable Dirty Bit Management",
>> +		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
>> +		.capability = ARM64_HW_DBM,
>> +		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>> +		.sign = FTR_UNSIGNED,
>> +		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
>> +		.min_field_value = 2,
>> +		.matches = has_hw_dbm,
> 
> Can't we use has_cpuid_feature here?  Why do we need a fake .matches and
> then code the check manually in the enable mathod?

We could, but then we need to add another *type*, where capabilities could
be enabled by a late CPU, where something is not already enabled by the boot-time
CPUs. i.e, if we boot a DBM capable CPU late, we won't be able to use the feature
on it, with the current setup. I didn't want to complicate the infrastructure
further just for this.

> I may be missing something here.

Cheers
Suzuki

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

* Re: [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
  2018-01-26 15:33     ` Dave Martin
@ 2018-01-26 16:29       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 16:29 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 15:33, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:09PM +0000, Suzuki K Poulose wrote:
>> Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
>> from an erratum 1024718, which causes incorrect updates when DBM/AP
>> bits in a page table entry is modified without a break-before-make
>> sequence. The work around is to skip enabling the hardware DBM feature
>> on the affected cores. The hardware Access Flag management features
>> is not affected.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   Documentation/arm64/silicon-errata.txt |  1 +
>>   arch/arm64/Kconfig                     | 14 ++++++++++++++
>>   arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
>>   3 files changed, 28 insertions(+), 1 deletion(-)
> 
> [...]
> 
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 8af755b8219d..64f1e911c6af 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
>>   	isb();
>>   }
>>   
>> +static bool cpu_has_erratum_1024718(void)
>> +{
>> +	static const struct midr_range __maybe_unused cpus[] = {
> 
> Do you need __maybe_unused?  If #ifdef were used here then
> __maybe_unused would be needed, but I thought that if code is optimised
> out instead of conditionally copiled, this didn't apply.

Yep. I don't know if the compiler could optimise the array itself with
the tag as a hint. I will double check.

> 
>> +		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
>> +		{},
>> +	};
>> +
>> +	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
>> +	       is_midr_in_range_list(read_cpuid_id(), cpus);
> 
> Why have a list with just one entry?  Do you expect more entries over
> time?

Yes. I should have mentioned it here. See [1]

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/554516.html


Cheers
Suzuki

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

* [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
@ 2018-01-26 16:29       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-26 16:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 15:33, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:09PM +0000, Suzuki K Poulose wrote:
>> Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
>> from an erratum 1024718, which causes incorrect updates when DBM/AP
>> bits in a page table entry is modified without a break-before-make
>> sequence. The work around is to skip enabling the hardware DBM feature
>> on the affected cores. The hardware Access Flag management features
>> is not affected.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   Documentation/arm64/silicon-errata.txt |  1 +
>>   arch/arm64/Kconfig                     | 14 ++++++++++++++
>>   arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
>>   3 files changed, 28 insertions(+), 1 deletion(-)
> 
> [...]
> 
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 8af755b8219d..64f1e911c6af 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
>>   	isb();
>>   }
>>   
>> +static bool cpu_has_erratum_1024718(void)
>> +{
>> +	static const struct midr_range __maybe_unused cpus[] = {
> 
> Do you need __maybe_unused?  If #ifdef were used here then
> __maybe_unused would be needed, but I thought that if code is optimised
> out instead of conditionally copiled, this didn't apply.

Yep. I don't know if the compiler could optimise the array itself with
the tag as a hint. I will double check.

> 
>> +		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
>> +		{},
>> +	};
>> +
>> +	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
>> +	       is_midr_in_range_list(read_cpuid_id(), cpus);
> 
> Why have a list with just one entry?  Do you expect more entries over
> time?

Yes. I should have mentioned it here. See [1]

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/554516.html


Cheers
Suzuki

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

* Re: [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
  2018-01-25 16:57           ` Suzuki K Poulose
@ 2018-01-29 16:35             ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 16:35 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, James Morse, jnair,
	Andre Przywara, Robin Murphy, linux-arm-kernel

On Thu, Jan 25, 2018 at 04:57:22PM +0000, Suzuki K Poulose wrote:
> On 25/01/18 15:36, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 03:38:37PM +0000, Suzuki K Poulose wrote:
> >>On 23/01/18 14:52, Dave Martin wrote:
> >>>On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
> >>>>From: Dave Martin <dave.martin@arm.com>
> >>>>
> >>>>We issue the enable() call back for all CPU hwcaps capabilities
> >>>>available on the system, on all the CPUs. So far we have ignored
> >>>>the argument passed to the call back, which had a prototype to
> >>>>accept a "void *" for use with on_each_cpu() and later with
> >>>>stop_machine(). However, with commit 0a0d111d40fd1
> >>>>("arm64: cpufeature: Pass capability structure to ->enable callback"),
> >>>>there are some users of the argument who wants the matching capability
> >>>>struct pointer where there are multiple matching criteria for a single
> >>>>capability. Update the prototype for enable to accept a const pointer.

[...]

> >>>>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>>>index ac67cfc2585a..cefbd685292c 100644
> >>>>--- a/arch/arm64/include/asm/cpufeature.h
> >>>>+++ b/arch/arm64/include/asm/cpufeature.h
> >>>>@@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
> >>>>  	u16 capability;
> >>>>  	int def_scope;			/* default scope */
> >>>>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
> >>>>-	int (*enable)(void *);		/* Called on all active CPUs */

[...]

> >>/*
> >>  * Called on all active CPUs if the capability associated with
> >>  * this entry is set.
> >>  */
> >
> >Maybe, but now we have the new concept of "setting" a capability.
> >
> >Really, this is enabling the capability for a CPU, not globally, so
> >maybe it could be renamed to "cpu_enable".
> >
> >Could we describe the method in terms of what it is required to do,
> >as well as the circumstances of the call, e.g.:
> >
> >/*
> >  * Take the appropriate actions to enable this capability for this cpu.
> >  * Every time a cpu is booted, this method is called under stop_machine()
> >  * for each globally enabled capability.
> >  */
> 
> Make sense, except for the "stop_machine" part. It is called under stop_machine
> for all CPUs brought up by kernel, for capabilities which are enabled from
> setup_cpu_features(), i.e, after all the CPUs are booted. But, it is called
> directly on the CPU, if the CPU is booted after it has been enabled on CPUs
> in the system. (e.g, a CPU brought up by the user - via __verify_local_cpu_caps -,
> or a capability that is enabled early by boot CPU - will post the changes in the next
> revision).

Fair enough.  Saying "this cpu" is probably sufficient to hint that
preemption will be disabled etc.

> >(I'm hoping that "globally enabled" is meaningful wording, though
> >perhaps not.)
> 
> Hmm.. "globally enabled" kind of sounds recursive for describing "enable" :-).
> How about "globally accepted" or "globally detected" ?

"Detected" is probably better, since this terminology at least exists
today in the code (if not very much).

Alternatively, the "enable" method could be renamed to something that
doesn't contain the word "enable" at all, like "cpu_setup" or similar.
That might avoid ambiguity about what is meant by "enable".  This has
no functional value though, and it's probably not worth the churn.

> >Also, what does the return value of this method mean?
> 
> Thats a good point. We ignore it. I believe it is best to leave it to the method
> to decide, what to do about it if there is a failure. It was there just to make
> sure we comply with what stop_machine expected. Now that we don't pass it to
> stop_machine directly, we could change it to void.
> >Previously, the return value was ignored, but other patches in this
> >series might change that.

If we don't change it to void, it would be good to have a comment saying
that it is ignored for now, and method implementations should return 0
for now.

Cheers
---Dave

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

* [PATCH 01/16] arm64: capabilities: Update prototype for enable call back
@ 2018-01-29 16:35             ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 16:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 25, 2018 at 04:57:22PM +0000, Suzuki K Poulose wrote:
> On 25/01/18 15:36, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 03:38:37PM +0000, Suzuki K Poulose wrote:
> >>On 23/01/18 14:52, Dave Martin wrote:
> >>>On Tue, Jan 23, 2018 at 12:27:54PM +0000, Suzuki K Poulose wrote:
> >>>>From: Dave Martin <dave.martin@arm.com>
> >>>>
> >>>>We issue the enable() call back for all CPU hwcaps capabilities
> >>>>available on the system, on all the CPUs. So far we have ignored
> >>>>the argument passed to the call back, which had a prototype to
> >>>>accept a "void *" for use with on_each_cpu() and later with
> >>>>stop_machine(). However, with commit 0a0d111d40fd1
> >>>>("arm64: cpufeature: Pass capability structure to ->enable callback"),
> >>>>there are some users of the argument who wants the matching capability
> >>>>struct pointer where there are multiple matching criteria for a single
> >>>>capability. Update the prototype for enable to accept a const pointer.

[...]

> >>>>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>>>index ac67cfc2585a..cefbd685292c 100644
> >>>>--- a/arch/arm64/include/asm/cpufeature.h
> >>>>+++ b/arch/arm64/include/asm/cpufeature.h
> >>>>@@ -97,7 +97,8 @@ struct arm64_cpu_capabilities {
> >>>>  	u16 capability;
> >>>>  	int def_scope;			/* default scope */
> >>>>  	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
> >>>>-	int (*enable)(void *);		/* Called on all active CPUs */

[...]

> >>/*
> >>  * Called on all active CPUs if the capability associated with
> >>  * this entry is set.
> >>  */
> >
> >Maybe, but now we have the new concept of "setting" a capability.
> >
> >Really, this is enabling the capability for a CPU, not globally, so
> >maybe it could be renamed to "cpu_enable".
> >
> >Could we describe the method in terms of what it is required to do,
> >as well as the circumstances of the call, e.g.:
> >
> >/*
> >  * Take the appropriate actions to enable this capability for this cpu.
> >  * Every time a cpu is booted, this method is called under stop_machine()
> >  * for each globally enabled capability.
> >  */
> 
> Make sense, except for the "stop_machine" part. It is called under stop_machine
> for all CPUs brought up by kernel, for capabilities which are enabled from
> setup_cpu_features(), i.e, after all the CPUs are booted. But, it is called
> directly on the CPU, if the CPU is booted after it has been enabled on CPUs
> in the system. (e.g, a CPU brought up by the user - via __verify_local_cpu_caps -,
> or a capability that is enabled early by boot CPU - will post the changes in the next
> revision).

Fair enough.  Saying "this cpu" is probably sufficient to hint that
preemption will be disabled etc.

> >(I'm hoping that "globally enabled" is meaningful wording, though
> >perhaps not.)
> 
> Hmm.. "globally enabled" kind of sounds recursive for describing "enable" :-).
> How about "globally accepted" or "globally detected" ?

"Detected" is probably better, since this terminology at least exists
today in the code (if not very much).

Alternatively, the "enable" method could be renamed to something that
doesn't contain the word "enable" at all, like "cpu_setup" or similar.
That might avoid ambiguity about what is meant by "enable".  This has
no functional value though, and it's probably not worth the churn.

> >Also, what does the return value of this method mean?
> 
> Thats a good point. We ignore it. I believe it is best to leave it to the method
> to decide, what to do about it if there is a failure. It was there just to make
> sure we comply with what stop_machine expected. Now that we don't pass it to
> stop_machine directly, we could change it to void.
> >Previously, the return value was ignored, but other patches in this
> >series might change that.

If we don't change it to void, it would be good to have a comment saying
that it is ignored for now, and method implementations should return 0
for now.

Cheers
---Dave

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

* Re: [PATCH 06/16] arm64: capabilities: Unify the verification
  2018-01-26 12:10       ` Suzuki K Poulose
@ 2018-01-29 16:57         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 16:57 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 12:10:11PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 11:08, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:59PM +0000, Suzuki K Poulose wrote:
> >>Now that each capability describes how to treat the conflicts
> >>of CPU cap state vs System wide cap state, we can unify the
> >>verification logic to a single place.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
> >>  1 file changed, 54 insertions(+), 33 deletions(-)
> >>
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 43c7e992d784..79737034a628 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
> >>  }
> >
> >>  /*
> >>+ * Run through the list of capabilities to check for conflicts.
> >>+ * Returns "false" on conflicts.
> >>+ */
> >>+static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
> >>+{
> >>+	bool cpu_has_cap, system_has_cap;
> >>+	const struct arm64_cpu_capabilities *caps = caps_list;
> >>+
> >>+	for (; caps->matches; caps++) {
> >>+		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
> >
> >What's the point of scanning the whole of caps_list?  Don't we already
> >have the pointer to the right cap struct?
> >
> >We already know caps->matches is true.  Can't we just call
> >caps->matches(caps)?  That seemed pretty intuitive to me in the old
> >code.
> >
> 
> This was supposed to be fixed by [1] in the "old code". Given we have multiple
> entries for a "capability", we could be dealing with the one which doesn't
> apply to this CPU and could eventually trigger a wrong conflict below. To
> avoid this, we need to make sure use the right values.

Ah, I see: do we want to do something like this:

	for (each cap corresponding to a bit in cpu_hwcaps) {
		for (each arm64_cpu_capabilities c corresponding to this cap) {
			if (c->matches(c, ...))
				goto ok;
		}

		goto mismatch;

	ok:
		continue;
	}

	return 0;

mismatch:
	/* barf */
	return -1;

An additional comment explaining the purpose of the code might help
(though I could have read the commit message, I guess).

We can't do the above directly, becasue we don't index the capabilities
by the capability field.  The above looks O((number of
arm64_cpu_capability structs) ^ 2), which could become slightly annoying
as the number of structs grows (?)

Could this be solved by making the match criteria a separate struct
and allowing a list of them to be specified per-capability?

Maybe too much effort for this series though.

> 

[...]

> >The role of the ->enable() call is the only real subtlety here.
> >
> >>+			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
> >>+				break;
> >>+		}
> >>+	}
> >>+
> >>+	if (caps->matches) {
> >>+		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
> >>+			smp_processor_id(), caps->capability,
> >>+			caps->desc ? : "no description",
> >
> >Wouldn't it be a bug for a conflict to occur on a cap with no .desc?
> >
> >Why can't we just let printk print its default "(null)" for %s
> >in this case?
> 
> We could.
> 
> >
> >Alternatively, is there a reason for any cap not to have a description?
> 
> Some of them do. e.g, some of them could be "negative" capabilities. e.g,
> ARM64_NO_FPSIMD.

Is that a reason not to have a description?

> >>+			system_has_cap, cpu_has_cap);
> >>+		return false;
> >>+	}
> >>+
> >>+	return true;
> >>+}
> >
> >Perhaps the capability verification procedure could be made a little
> >clearer by splitting this into two functions:
> >
> 
> As explained above, the code below is not sufficient.

Fair enough: I hadn't understood what the code was trying to achieve.

Given that, it's a bit harder to refactor than I though, and it's
probably not worth it.

[...]

Cheers
---Dave

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

* [PATCH 06/16] arm64: capabilities: Unify the verification
@ 2018-01-29 16:57         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 12:10:11PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 11:08, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:59PM +0000, Suzuki K Poulose wrote:
> >>Now that each capability describes how to treat the conflicts
> >>of CPU cap state vs System wide cap state, we can unify the
> >>verification logic to a single place.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/kernel/cpufeature.c | 87 ++++++++++++++++++++++++++----------------
> >>  1 file changed, 54 insertions(+), 33 deletions(-)
> >>
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 43c7e992d784..79737034a628 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -1228,6 +1228,54 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
> >>  }
> >
> >>  /*
> >>+ * Run through the list of capabilities to check for conflicts.
> >>+ * Returns "false" on conflicts.
> >>+ */
> >>+static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list)
> >>+{
> >>+	bool cpu_has_cap, system_has_cap;
> >>+	const struct arm64_cpu_capabilities *caps = caps_list;
> >>+
> >>+	for (; caps->matches; caps++) {
> >>+		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
> >
> >What's the point of scanning the whole of caps_list?  Don't we already
> >have the pointer to the right cap struct?
> >
> >We already know caps->matches is true.  Can't we just call
> >caps->matches(caps)?  That seemed pretty intuitive to me in the old
> >code.
> >
> 
> This was supposed to be fixed by [1] in the "old code". Given we have multiple
> entries for a "capability", we could be dealing with the one which doesn't
> apply to this CPU and could eventually trigger a wrong conflict below. To
> avoid this, we need to make sure use the right values.

Ah, I see: do we want to do something like this:

	for (each cap corresponding to a bit in cpu_hwcaps) {
		for (each arm64_cpu_capabilities c corresponding to this cap) {
			if (c->matches(c, ...))
				goto ok;
		}

		goto mismatch;

	ok:
		continue;
	}

	return 0;

mismatch:
	/* barf */
	return -1;

An additional comment explaining the purpose of the code might help
(though I could have read the commit message, I guess).

We can't do the above directly, becasue we don't index the capabilities
by the capability field.  The above looks O((number of
arm64_cpu_capability structs) ^ 2), which could become slightly annoying
as the number of structs grows (?)

Could this be solved by making the match criteria a separate struct
and allowing a list of them to be specified per-capability?

Maybe too much effort for this series though.

> 

[...]

> >The role of the ->enable() call is the only real subtlety here.
> >
> >>+			if (cpu_has_cap && !cpucap_late_cpu_have_cap_safe(caps))
> >>+				break;
> >>+		}
> >>+	}
> >>+
> >>+	if (caps->matches) {
> >>+		pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
> >>+			smp_processor_id(), caps->capability,
> >>+			caps->desc ? : "no description",
> >
> >Wouldn't it be a bug for a conflict to occur on a cap with no .desc?
> >
> >Why can't we just let printk print its default "(null)" for %s
> >in this case?
> 
> We could.
> 
> >
> >Alternatively, is there a reason for any cap not to have a description?
> 
> Some of them do. e.g, some of them could be "negative" capabilities. e.g,
> ARM64_NO_FPSIMD.

Is that a reason not to have a description?

> >>+			system_has_cap, cpu_has_cap);
> >>+		return false;
> >>+	}
> >>+
> >>+	return true;
> >>+}
> >
> >Perhaps the capability verification procedure could be made a little
> >clearer by splitting this into two functions:
> >
> 
> As explained above, the code below is not sufficient.

Fair enough: I hadn't understood what the code was trying to achieve.

Given that, it's a bit harder to refactor than I though, and it's
probably not worth it.

[...]

Cheers
---Dave

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

* Re: [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
  2018-01-26 12:21       ` Suzuki K Poulose
@ 2018-01-29 17:06         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 17:06 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 12:21:43PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 11:22, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:00PM +0000, Suzuki K Poulose wrote:
> >>While processing the list of capabilities, it is useful to
> >>filter out some of the entries based on the given type to
> >>allow better control. This can be used later for handling
> >>LOCAL vs SYSTEM wide capabilities and more.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  5 +++++
> >>  arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
> >>  2 files changed, 25 insertions(+), 10 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 27d037bb0451..a621d2184227 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>  /* Is it safe for a late CPU to miss this capability when system has it */
> >>  #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
> >>+#define ARM64_CPUCAP_TYPE_ALL			 \
> >>+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> >>+	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> >
> >Nit: can we have another tab between | and \?
> >
> >This will help to make missing |s stand out more if/when more entries
> >are added to this list in future.
> >
> 
> Sure, will do.
> 
> >>  /*
> >>   * CPU errata detected at boot time based on feature of one or more CPUs.
> >>   * It is not safe for a late CPU to have this feature when the system doesn't
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c

[...]

> >>@@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
> >>   * Run through the enabled capabilities and enable() it on all active
> >>   * CPUs
> >>   */
> >>-static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
> >>+static void __init
> >>+enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
> >
> >The "caps_type" argument should be named consistently with the
> >corresponding argument to update_cpu_capabilities().

[...]

> >>  static void verify_local_cpu_errata_workarounds(void)
> >>  {
> >>-	if (__verify_local_cpu_caps(arm64_errata))
> >>+	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
> >>  		cpu_die_early();
> >
> >Did you mean to insert the ! here?
> 
> Thanks for spotting. I think it should have been there in the first place,
> as we get "false" when there is a conflict. I will fix the previous patch which
> adds the call.

Oh, right.  Yes, I think that probably makes sense.

Cheers
---Dave

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

* [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type
@ 2018-01-29 17:06         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 17:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 12:21:43PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 11:22, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:00PM +0000, Suzuki K Poulose wrote:
> >>While processing the list of capabilities, it is useful to
> >>filter out some of the entries based on the given type to
> >>allow better control. This can be used later for handling
> >>LOCAL vs SYSTEM wide capabilities and more.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  5 +++++
> >>  arch/arm64/kernel/cpufeature.c      | 30 ++++++++++++++++++++----------
> >>  2 files changed, 25 insertions(+), 10 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 27d037bb0451..a621d2184227 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -99,6 +99,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>  /* Is it safe for a late CPU to miss this capability when system has it */
> >>  #define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
> >>+#define ARM64_CPUCAP_TYPE_ALL			 \
> >>+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> >>+	 ARM64_CPUCAP_SCOPE_SYSTEM		|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> >
> >Nit: can we have another tab between | and \?
> >
> >This will help to make missing |s stand out more if/when more entries
> >are added to this list in future.
> >
> 
> Sure, will do.
> 
> >>  /*
> >>   * CPU errata detected at boot time based on feature of one or more CPUs.
> >>   * It is not safe for a late CPU to have this feature when the system doesn't
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c

[...]

> >>@@ -1204,12 +1206,13 @@ static int __enable_cpu_capability(void *arg)
> >>   * Run through the enabled capabilities and enable() it on all active
> >>   * CPUs
> >>   */
> >>-static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
> >>+static void __init
> >>+enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 caps_type)
> >
> >The "caps_type" argument should be named consistently with the
> >corresponding argument to update_cpu_capabilities().

[...]

> >>  static void verify_local_cpu_errata_workarounds(void)
> >>  {
> >>-	if (__verify_local_cpu_caps(arm64_errata))
> >>+	if (!__verify_local_cpu_caps(arm64_errata, ARM64_CPUCAP_TYPE_ALL))
> >>  		cpu_die_early();
> >
> >Did you mean to insert the ! here?
> 
> Thanks for spotting. I think it should have been there in the first place,
> as we get "false" when there is a conflict. I will fix the previous patch which
> adds the call.

Oh, right.  Yes, I think that probably makes sense.

Cheers
---Dave

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

* Re: [PATCH 08/16] arm64: capabilities: Group handling of features and errata
  2018-01-26 12:31       ` Suzuki K Poulose
@ 2018-01-29 17:14         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 17:14 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 12:31:18PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 11:47, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
> >>So far we have had separate routes for triggering errata and feature
> >
> >"triggering errata" ? ;)
> >
> 
> :-). Should have been "triggering errata and feature capability *checks*.
> 
> >Maybe "[...] for determining whether to activate errata workarounds and
> >whether to enable feature capabilities."
> >
> 
> 
> >>capabilities. Also, we never allowed "features" based on local CPU
> >>and "errata" based on System wide safe registers. This patch
> >>groups the handling of errata and features and also allows them
> >>to have all the possible scopes.
> >>
> >>So, we now run through the arm64_features and arm64_errata:
> >
> >when?
> 
> with this patch.

I mean, when at runtime?

> >What about late cpus?
> >
> 
> We don't detect any new capabilities on them. They continue to get
> verified against the enabled capabilities.
> 
> >>  1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
> >>     via update_cpu_local_capabilities().
> >
> >"each [...] enabeld CPUs" -> "each [...] enabled CPU"
> >
> >Also, changing "boot time" -> "boot-time" helps avoid this being misread
> >as "on each boot", which could be taken to mean "each time a CPU comes
> >online".  I'm guessing that's not the intended meaning here.
> 
> OK

[...]

> >[Gaah, stupid git diff making function insertion look like function
> >modification.  Sometimes --patience does a better job, but there seems
> >no foolproof solution...  If you do a respin, it might be worth trying
> >it.]
> 
> Will try, thanks for the suggestion. I didn't know about that :-)

YMMV though.  The output is different, but it's not always better...

> >>-static void __init setup_feature_capabilities(void)
> >>+static void __init setup_system_capabilities(void)
> >>  {
> >>-	update_cpu_capabilities(arm64_features,
> >>-				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
> >>-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
> >>+	/*
> >>+	 * We have finalised the system wide safe feature registers,
> >>+	 * finalise the capabilities that depend on it.
> >>+	 */
> >>+	update_system_capabilities();
> >>+	/* Enable all the available capabilities */
> >>+	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);
> >
> >So setup_system_capabilities() enables _non_ system-wide capabilities/
> >errata workarounds too?
> 
> >Maybe this function should just have a different name, like
> >"setup_boot_capabilities" or similar?
> 
> The problem with setup_boot_capabilities() is that it could conflict with
> "coming soon" setup_boot_cpu_capabilities(). May be,
> 
> setup_boot_time_system_capabilities().

Maybe.  If no name leaps out as better, maybe it's not worth changing
it.

> >
> >   }
> >>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> >>@@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
> >>  	u32 cwg;
> >>  	int cls;
> >>-	/* Set the CPU feature capabilies */
> >>-	setup_feature_capabilities();
> >>-	enable_errata_workarounds();
> >>+	setup_system_capabilities();
> >>  	mark_const_caps_ready();
> >>  	setup_elf_hwcaps(arm64_elf_hwcaps);
> >
> >I wonder whether we could unify the elf hwcaps handling too.
> 
> I was thinking about it today. The only catch is how do we know
> if we have "the capability", as it is spread across multiple bitmasks.
> (HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).

An easy-ish solution might be to maintain our own bitmap in the style
of cpu_hwcaps, and set bits in parallel with the elf_hwcap etc. bits.
Or, add a method that knows how to set/query the appropriate bit.

I guess we could do this later.  It's certainly not urgent.

Cheers
---Dave

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
@ 2018-01-29 17:14         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 17:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 12:31:18PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 11:47, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
> >>So far we have had separate routes for triggering errata and feature
> >
> >"triggering errata" ? ;)
> >
> 
> :-). Should have been "triggering errata and feature capability *checks*.
> 
> >Maybe "[...] for determining whether to activate errata workarounds and
> >whether to enable feature capabilities."
> >
> 
> 
> >>capabilities. Also, we never allowed "features" based on local CPU
> >>and "errata" based on System wide safe registers. This patch
> >>groups the handling of errata and features and also allows them
> >>to have all the possible scopes.
> >>
> >>So, we now run through the arm64_features and arm64_errata:
> >
> >when?
> 
> with this patch.

I mean, when at runtime?

> >What about late cpus?
> >
> 
> We don't detect any new capabilities on them. They continue to get
> verified against the enabled capabilities.
> 
> >>  1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
> >>     via update_cpu_local_capabilities().
> >
> >"each [...] enabeld CPUs" -> "each [...] enabled CPU"
> >
> >Also, changing "boot time" -> "boot-time" helps avoid this being misread
> >as "on each boot", which could be taken to mean "each time a CPU comes
> >online".  I'm guessing that's not the intended meaning here.
> 
> OK

[...]

> >[Gaah, stupid git diff making function insertion look like function
> >modification.  Sometimes --patience does a better job, but there seems
> >no foolproof solution...  If you do a respin, it might be worth trying
> >it.]
> 
> Will try, thanks for the suggestion. I didn't know about that :-)

YMMV though.  The output is different, but it's not always better...

> >>-static void __init setup_feature_capabilities(void)
> >>+static void __init setup_system_capabilities(void)
> >>  {
> >>-	update_cpu_capabilities(arm64_features,
> >>-				ARM64_CPUCAP_TYPE_ALL, "detected feature:");
> >>-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_TYPE_ALL);
> >>+	/*
> >>+	 * We have finalised the system wide safe feature registers,
> >>+	 * finalise the capabilities that depend on it.
> >>+	 */
> >>+	update_system_capabilities();
> >>+	/* Enable all the available capabilities */
> >>+	enable_cpu_capabilities(ARM64_CPUCAP_TYPE_ALL);
> >
> >So setup_system_capabilities() enables _non_ system-wide capabilities/
> >errata workarounds too?
> 
> >Maybe this function should just have a different name, like
> >"setup_boot_capabilities" or similar?
> 
> The problem with setup_boot_capabilities() is that it could conflict with
> "coming soon" setup_boot_cpu_capabilities(). May be,
> 
> setup_boot_time_system_capabilities().

Maybe.  If no name leaps out as better, maybe it's not worth changing
it.

> >
> >   }
> >>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> >>@@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
> >>  	u32 cwg;
> >>  	int cls;
> >>-	/* Set the CPU feature capabilies */
> >>-	setup_feature_capabilities();
> >>-	enable_errata_workarounds();
> >>+	setup_system_capabilities();
> >>  	mark_const_caps_ready();
> >>  	setup_elf_hwcaps(arm64_elf_hwcaps);
> >
> >I wonder whether we could unify the elf hwcaps handling too.
> 
> I was thinking about it today. The only catch is how do we know
> if we have "the capability", as it is spread across multiple bitmasks.
> (HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).

An easy-ish solution might be to maintain our own bitmap in the style
of cpu_hwcaps, and set bits in parallel with the elf_hwcap etc. bits.
Or, add a method that knows how to set/query the appropriate bit.

I guess we could do this later.  It's certainly not urgent.

Cheers
---Dave

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

* Re: [PATCH 08/16] arm64: capabilities: Group handling of features and errata
  2018-01-29 17:14         ` Dave Martin
@ 2018-01-29 17:22           ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-29 17:22 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 29/01/18 17:14, Dave Martin wrote:
> On Fri, Jan 26, 2018 at 12:31:18PM +0000, Suzuki K Poulose wrote:
>> On 26/01/18 11:47, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
>>>> So far we have had separate routes for triggering errata and feature
>>>
>>> "triggering errata" ? ;)
>>>
>>
>> :-). Should have been "triggering errata and feature capability *checks*.
>>
>>> Maybe "[...] for determining whether to activate errata workarounds and
>>> whether to enable feature capabilities."
>>>
>>
>>
>>>> capabilities. Also, we never allowed "features" based on local CPU
>>>> and "errata" based on System wide safe registers. This patch
>>>> groups the handling of errata and features and also allows them
>>>> to have all the possible scopes.
>>>>
>>>> So, we now run through the arm64_features and arm64_errata:
>>>
>>> when?
>>
>> with this patch.
> 
> I mean, when at runtime?

Sorry, I thought that was evident from the comment below :

> 
>>> What about late cpus?
>>>
>>
>> We don't detect any new capabilities on them. They continue to get
>> verified against the enabled capabilities.
>>
>>>>   1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
>>>>      via update_cpu_local_capabilities().

Here ^^.  Earlier we ran only through the errata list. But now, we
run through errata and the features, using a type filter of SCOPE_LOCAL_CPU.

It also said :

   2) with SCOPE_SYSTEM filter only once after all boot time enabled
     CPUs are active.

(2) happens from setup_cpu_features(), just like it was done earlier, but
with a filter of SCOPE_SYSTEM.

>>>
>>> "each [...] enabeld CPUs" -> "each [...] enabled CPU"
>>>
>>> Also, changing "boot time" -> "boot-time" helps avoid this being misread
>>> as "on each boot", which could be taken to mean "each time a CPU comes
>>> online".  I'm guessing that's not the intended meaning here.
>>

>>>
>>>    }
>>>>   DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
>>>> @@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
>>>>   	u32 cwg;
>>>>   	int cls;
>>>> -	/* Set the CPU feature capabilies */
>>>> -	setup_feature_capabilities();
>>>> -	enable_errata_workarounds();
>>>> +	setup_system_capabilities();
>>>>   	mark_const_caps_ready();
>>>>   	setup_elf_hwcaps(arm64_elf_hwcaps);
>>>
>>> I wonder whether we could unify the elf hwcaps handling too.
>>
>> I was thinking about it today. The only catch is how do we know
>> if we have "the capability", as it is spread across multiple bitmasks.
>> (HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).
> 
> An easy-ish solution might be to maintain our own bitmap in the style
> of cpu_hwcaps, and set bits in parallel with the elf_hwcap etc. bits.
> Or, add a method that knows how to set/query the appropriate bit.
> 
> I guess we could do this later.  It's certainly not urgent.

Yes, I understand.

Cheers
Suzuki

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
@ 2018-01-29 17:22           ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-29 17:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 17:14, Dave Martin wrote:
> On Fri, Jan 26, 2018 at 12:31:18PM +0000, Suzuki K Poulose wrote:
>> On 26/01/18 11:47, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
>>>> So far we have had separate routes for triggering errata and feature
>>>
>>> "triggering errata" ? ;)
>>>
>>
>> :-). Should have been "triggering errata and feature capability *checks*.
>>
>>> Maybe "[...] for determining whether to activate errata workarounds and
>>> whether to enable feature capabilities."
>>>
>>
>>
>>>> capabilities. Also, we never allowed "features" based on local CPU
>>>> and "errata" based on System wide safe registers. This patch
>>>> groups the handling of errata and features and also allows them
>>>> to have all the possible scopes.
>>>>
>>>> So, we now run through the arm64_features and arm64_errata:
>>>
>>> when?
>>
>> with this patch.
> 
> I mean, when at runtime?

Sorry, I thought that was evident from the comment below :

> 
>>> What about late cpus?
>>>
>>
>> We don't detect any new capabilities on them. They continue to get
>> verified against the enabled capabilities.
>>
>>>>   1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
>>>>      via update_cpu_local_capabilities().

Here ^^.  Earlier we ran only through the errata list. But now, we
run through errata and the features, using a type filter of SCOPE_LOCAL_CPU.

It also said :

   2) with SCOPE_SYSTEM filter only once after all boot time enabled
     CPUs are active.

(2) happens from setup_cpu_features(), just like it was done earlier, but
with a filter of SCOPE_SYSTEM.

>>>
>>> "each [...] enabeld CPUs" -> "each [...] enabled CPU"
>>>
>>> Also, changing "boot time" -> "boot-time" helps avoid this being misread
>>> as "on each boot", which could be taken to mean "each time a CPU comes
>>> online".  I'm guessing that's not the intended meaning here.
>>

>>>
>>>    }
>>>>   DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
>>>> @@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
>>>>   	u32 cwg;
>>>>   	int cls;
>>>> -	/* Set the CPU feature capabilies */
>>>> -	setup_feature_capabilities();
>>>> -	enable_errata_workarounds();
>>>> +	setup_system_capabilities();
>>>>   	mark_const_caps_ready();
>>>>   	setup_elf_hwcaps(arm64_elf_hwcaps);
>>>
>>> I wonder whether we could unify the elf hwcaps handling too.
>>
>> I was thinking about it today. The only catch is how do we know
>> if we have "the capability", as it is spread across multiple bitmasks.
>> (HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).
> 
> An easy-ish solution might be to maintain our own bitmap in the style
> of cpu_hwcaps, and set bits in parallel with the elf_hwcap etc. bits.
> Or, add a method that knows how to set/query the appropriate bit.
> 
> I guess we could do this later.  It's certainly not urgent.

Yes, I understand.

Cheers
Suzuki

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

* Re: [PATCH 10/16] arm64: Make KPTI strict CPU local feature
  2018-01-26 15:46       ` Suzuki K Poulose
@ 2018-01-29 17:24         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 17:24 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 03:46:59PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 12:25, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:03PM +0000, Suzuki K Poulose wrote:
> >>KPTI capability is a security feature which should be enabled
> >>when at least one CPU on the system needs it. Any late CPU
> >>which needs the kernel support, should be prevented from
> >>booting (and thus making the system unsecure) if the feature
> >>was not already enabled.
> >
> >Is there an actual change to behaviour here?
> 
> Yes, we now prevent any new CPU from booting if it *matches* the capability,
> which we didn't do earlier.

Ok

> >
> >It's not very obvious from the commit message, or the patch when read in
> >isolation.
> >
> 
> I will fix the commit message to indicate the current behavior. How about :
> 
> "KPTI is treated as a system wide feature, where we enable the feature
> when all the CPUs on the system suffers from the security vulnerability,
> unless it is enabled via kernel command line. Also, we ignore a late CPU

Maybe "enabled" -> "forcibly enabled", if the command-line really is
supposed to have override semantics (which I guess it is).

> which might need the defense if the KPTI is not enabled, making the system
> insecure. This is not sufficient, as
> we should enable the defense when at least one CPU needs it. Also, if
> it is not enabled at boot-time, we can no longer enable it when a late
> CPU turns up. This patch makes sure that the KPTI is checked on all CPUs

There's some repetition here.  Does the following work:

"[...] command line.  Also, if a late CPU needs KPTI but KPTI was not
enabled at boot time, the CPU is currently allowed to boot, which is a
potential security vulnerability.  This patch ensures that late CPUs
are rejected as appropriate if they need KPTI but it wasn't enabled."

Hmmm.  That's no shorter after all.  Oh well :P

Cheers
---Dave

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

* [PATCH 10/16] arm64: Make KPTI strict CPU local feature
@ 2018-01-29 17:24         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-29 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 03:46:59PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 12:25, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:03PM +0000, Suzuki K Poulose wrote:
> >>KPTI capability is a security feature which should be enabled
> >>when at least one CPU on the system needs it. Any late CPU
> >>which needs the kernel support, should be prevented from
> >>booting (and thus making the system unsecure) if the feature
> >>was not already enabled.
> >
> >Is there an actual change to behaviour here?
> 
> Yes, we now prevent any new CPU from booting if it *matches* the capability,
> which we didn't do earlier.

Ok

> >
> >It's not very obvious from the commit message, or the patch when read in
> >isolation.
> >
> 
> I will fix the commit message to indicate the current behavior. How about :
> 
> "KPTI is treated as a system wide feature, where we enable the feature
> when all the CPUs on the system suffers from the security vulnerability,
> unless it is enabled via kernel command line. Also, we ignore a late CPU

Maybe "enabled" -> "forcibly enabled", if the command-line really is
supposed to have override semantics (which I guess it is).

> which might need the defense if the KPTI is not enabled, making the system
> insecure. This is not sufficient, as
> we should enable the defense when at least one CPU needs it. Also, if
> it is not enabled at boot-time, we can no longer enable it when a late
> CPU turns up. This patch makes sure that the KPTI is checked on all CPUs

There's some repetition here.  Does the following work:

"[...] command line.  Also, if a late CPU needs KPTI but KPTI was not
enabled at boot time, the CPU is currently allowed to boot, which is a
potential security vulnerability.  This patch ensures that late CPUs
are rejected as appropriate if they need KPTI but it wasn't enabled."

Hmmm.  That's no shorter after all.  Oh well :P

Cheers
---Dave

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

* Re: [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
  2018-01-26 10:10     ` Dave Martin
@ 2018-01-30 11:17       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 11:17 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 10:10, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
>> Add two different flags to indicate if the conflict of a capability
>> on a late CPU with the current system state
>>
>>   1) Can a CPU have a capability when the system doesn't have it ?
>>
>>      Most arm64 features could have this set. While erratum work arounds
>>      cannot have this, as we may miss work arounds.
>>
>>   2) Can a CPU miss a capability when the system has it ?
>>      This could be set for arm64 erratum work arounds as we don't
>>      care if a CPU doesn't need the work around. However it should
>>      be clear for features.
>>
>> These flags could be added to certain entries based on their nature.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
>>   1 file changed, 31 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 4fd5de8ef33e..27d037bb0451 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>>   #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>>   
>> -/* CPU errata detected at boot time based on feature of one or more CPUs */
>> -#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
>> -/* CPU feature detected at boot time based on system-wide value of a feature */
>> -#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
>> +/* Is it safe for a late CPU to have this capability when system doesn't already have */
>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
>> +/* Is it safe for a late CPU to miss this capability when system has it */
>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
> 
> Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?
> 
> Alternatively,
> 	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
> 	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU

Sounds better than what I have. I have picked them up.

Cheers
Suzuki

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

* [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
@ 2018-01-30 11:17       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 10:10, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
>> Add two different flags to indicate if the conflict of a capability
>> on a late CPU with the current system state
>>
>>   1) Can a CPU have a capability when the system doesn't have it ?
>>
>>      Most arm64 features could have this set. While erratum work arounds
>>      cannot have this, as we may miss work arounds.
>>
>>   2) Can a CPU miss a capability when the system has it ?
>>      This could be set for arm64 erratum work arounds as we don't
>>      care if a CPU doesn't need the work around. However it should
>>      be clear for features.
>>
>> These flags could be added to certain entries based on their nature.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
>>   1 file changed, 31 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 4fd5de8ef33e..27d037bb0451 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>>   #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>>   
>> -/* CPU errata detected at boot time based on feature of one or more CPUs */
>> -#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
>> -/* CPU feature detected at boot time based on system-wide value of a feature */
>> -#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
>> +/* Is it safe for a late CPU to have this capability when system doesn't already have */
>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
>> +/* Is it safe for a late CPU to miss this capability when system has it */
>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
> 
> Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?
> 
> Alternatively,
> 	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
> 	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU

Sounds better than what I have. I have picked them up.

Cheers
Suzuki

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

* Re: [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU
  2018-01-26 12:12     ` Dave Martin
@ 2018-01-30 11:25       ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 11:25 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair

On 26/01/18 12:12, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:02PM +0000, Suzuki K Poulose wrote:
>> Add type for features that are detected on individual CPUs,
>> rather than on a system wide safe features. This behavior
> 
> feature
> 
>> is similar to that of a strict cpu erratum, where a later
>> CPU is not allowed to boot if the system doesn't posses it.
>>
>> Use this for software prefetching capability.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 7 +++++++
>>   arch/arm64/kernel/cpufeature.c      | 2 +-
>>   2 files changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index a621d2184227..4c3d6987acfc 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -118,6 +118,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    */
>>   #define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
>>   	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
>> +/*
>> + * CPU feature detected at boot time based on feature of one or more CPUs.
>> + * It is not safe for a late CPU to have this feature, when the system doesn't
>> + * have it. But it is safe to miss the feature if the system has it.
>> + */
>> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> 
> "STRICT" seem quite odd here, since we never require all CPUs to have
> the feature.  The case we forbid is when the boot-time decision is that
> the system doesn't tolerate this feature.  So this feels erratum-like.
> 
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 7ae5cf9092d0..111f6c4b4cd7 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -951,7 +951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Software prefetching using PRFM",
>>   		.capability = ARM64_HAS_NO_HW_PREFETCH,
>> -		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
>> +		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
>>   		.matches = has_no_hw_prefetch,
> 
> For ARM64_HAS_NO_HW_PREFETCH this is more describing an implementation
> option that only affects performance -- in that case it's not obvious
> that we should be strict at all.
> 
> This suggests ARM64_CPUCAP_SCOPE_LOCAL_CPU |
> 	ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE |
> 	ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS.

You're right. This is more like a WEAK feature we add for DBM. I will switch it.

Cheers
Suzuki

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

* [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU
@ 2018-01-30 11:25       ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 11:25 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/01/18 12:12, Dave Martin wrote:
> On Tue, Jan 23, 2018 at 12:28:02PM +0000, Suzuki K Poulose wrote:
>> Add type for features that are detected on individual CPUs,
>> rather than on a system wide safe features. This behavior
> 
> feature
> 
>> is similar to that of a strict cpu erratum, where a later
>> CPU is not allowed to boot if the system doesn't posses it.
>>
>> Use this for software prefetching capability.
>>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 7 +++++++
>>   arch/arm64/kernel/cpufeature.c      | 2 +-
>>   2 files changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index a621d2184227..4c3d6987acfc 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -118,6 +118,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    */
>>   #define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	\
>>   	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
>> +/*
>> + * CPU feature detected at boot time based on feature of one or more CPUs.
>> + * It is not safe for a late CPU to have this feature, when the system doesn't
>> + * have it. But it is safe to miss the feature if the system has it.
>> + */
>> +#define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> 
> "STRICT" seem quite odd here, since we never require all CPUs to have
> the feature.  The case we forbid is when the boot-time decision is that
> the system doesn't tolerate this feature.  So this feels erratum-like.
> 
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 7ae5cf9092d0..111f6c4b4cd7 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -951,7 +951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Software prefetching using PRFM",
>>   		.capability = ARM64_HAS_NO_HW_PREFETCH,
>> -		.type = ARM64_CPUCAP_BOOT_SYSTEM_FEATURE,
>> +		.type = ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE,
>>   		.matches = has_no_hw_prefetch,
> 
> For ARM64_HAS_NO_HW_PREFETCH this is more describing an implementation
> option that only affects performance -- in that case it's not obvious
> that we should be strict at all.
> 
> This suggests ARM64_CPUCAP_SCOPE_LOCAL_CPU |
> 	ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE |
> 	ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS.

You're right. This is more like a WEAK feature we add for DBM. I will switch it.

Cheers
Suzuki

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

* Re: [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
  2018-01-30 11:17       ` Suzuki K Poulose
@ 2018-01-30 14:56         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 14:56 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Tue, Jan 30, 2018 at 11:17:38AM +0000, Suzuki K Poulose wrote:
> On 26/01/18 10:10, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
> >>Add two different flags to indicate if the conflict of a capability
> >>on a late CPU with the current system state
> >>
> >>  1) Can a CPU have a capability when the system doesn't have it ?
> >>
> >>     Most arm64 features could have this set. While erratum work arounds
> >>     cannot have this, as we may miss work arounds.
> >>
> >>  2) Can a CPU miss a capability when the system has it ?
> >>     This could be set for arm64 erratum work arounds as we don't
> >>     care if a CPU doesn't need the work around. However it should
> >>     be clear for features.
> >>
> >>These flags could be added to certain entries based on their nature.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
> >>  1 file changed, 31 insertions(+), 4 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 4fd5de8ef33e..27d037bb0451 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>  #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> >>  #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> >>-/* CPU errata detected at boot time based on feature of one or more CPUs */
> >>-#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> >>-/* CPU feature detected at boot time based on system-wide value of a feature */
> >>-#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
> >>+/* Is it safe for a late CPU to have this capability when system doesn't already have */
> >>+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
> >>+/* Is it safe for a late CPU to miss this capability when system has it */
> >>+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
> >
> >Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?
> >
> >Alternatively,
> >	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
> >	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU
> 
> Sounds better than what I have. I have picked them up.

Cool, I had resigned myself to probably not winning that one ;)

Cheers
---Dave

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

* [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
@ 2018-01-30 14:56         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 14:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 30, 2018 at 11:17:38AM +0000, Suzuki K Poulose wrote:
> On 26/01/18 10:10, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
> >>Add two different flags to indicate if the conflict of a capability
> >>on a late CPU with the current system state
> >>
> >>  1) Can a CPU have a capability when the system doesn't have it ?
> >>
> >>     Most arm64 features could have this set. While erratum work arounds
> >>     cannot have this, as we may miss work arounds.
> >>
> >>  2) Can a CPU miss a capability when the system has it ?
> >>     This could be set for arm64 erratum work arounds as we don't
> >>     care if a CPU doesn't need the work around. However it should
> >>     be clear for features.
> >>
> >>These flags could be added to certain entries based on their nature.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
> >>  1 file changed, 31 insertions(+), 4 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 4fd5de8ef33e..27d037bb0451 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>  #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> >>  #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> >>-/* CPU errata detected at boot time based on feature of one or more CPUs */
> >>-#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
> >>-/* CPU feature detected at boot time based on system-wide value of a feature */
> >>-#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
> >>+/* Is it safe for a late CPU to have this capability when system doesn't already have */
> >>+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
> >>+/* Is it safe for a late CPU to miss this capability when system has it */
> >>+#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
> >
> >Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?
> >
> >Alternatively,
> >	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
> >	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU
> 
> Sounds better than what I have. I have picked them up.

Cool, I had resigned myself to probably not winning that one ;)

Cheers
---Dave

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

* Re: [PATCH 08/16] arm64: capabilities: Group handling of features and errata
  2018-01-29 17:22           ` Suzuki K Poulose
@ 2018-01-30 15:06             ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:06 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Mon, Jan 29, 2018 at 05:22:26PM +0000, Suzuki K Poulose wrote:
> On 29/01/18 17:14, Dave Martin wrote:
> >On Fri, Jan 26, 2018 at 12:31:18PM +0000, Suzuki K Poulose wrote:
> >>On 26/01/18 11:47, Dave Martin wrote:
> >>>On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
> >>>>So far we have had separate routes for triggering errata and feature
> >>>
> >>>"triggering errata" ? ;)
> >>>
> >>
> >>:-). Should have been "triggering errata and feature capability *checks*.
> >>
> >>>Maybe "[...] for determining whether to activate errata workarounds and
> >>>whether to enable feature capabilities."
> >>>
> >>
> >>
> >>>>capabilities. Also, we never allowed "features" based on local CPU
> >>>>and "errata" based on System wide safe registers. This patch
> >>>>groups the handling of errata and features and also allows them
> >>>>to have all the possible scopes.
> >>>>
> >>>>So, we now run through the arm64_features and arm64_errata:
> >>>
> >>>when?
> >>
> >>with this patch.
> >
> >I mean, when at runtime?
> 
> Sorry, I thought that was evident from the comment below :

Sort of, but you talk about things being done on boot-time enabled CPUs,
rather than saying the check actually happens at boot time.  The
description isn't wrong, but I just ended up a bit unsure about exactly
what was being guaranteed.

My confusion was partly due to my understanding of the code still being
incomplete when I responsed to this patch.


Maybe say "we run through arm64_features and arm64_errata in two phases
during the boot process"

> 
> >
> >>>What about late cpus?
> >>>
> >>
> >>We don't detect any new capabilities on them. They continue to get
> >>verified against the enabled capabilities.

If this patch doesn't intentionally change what happens for late CPUs
after kernel boot, but nonetheless does unifiy the errata/feature
verification code for late CPUs then this may also be worth noting here.

> >>
> >>>>  1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
> >>>>     via update_cpu_local_capabilities().
> 
> Here ^^.  Earlier we ran only through the errata list. But now, we
> run through errata and the features, using a type filter of SCOPE_LOCAL_CPU.
> 
> It also said :
> 
>   2) with SCOPE_SYSTEM filter only once after all boot time enabled
>     CPUs are active.
> 
> (2) happens from setup_cpu_features(), just like it was done earlier, but
> with a filter of SCOPE_SYSTEM.
> 
> >>>
> >>>"each [...] enabeld CPUs" -> "each [...] enabled CPU"
> >>>
> >>>Also, changing "boot time" -> "boot-time" helps avoid this being misread
> >>>as "on each boot", which could be taken to mean "each time a CPU comes
> >>>online".  I'm guessing that's not the intended meaning here.
> >>
> 
> >>>
> >>>   }
> >>>>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> >>>>@@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
> >>>>  	u32 cwg;
> >>>>  	int cls;
> >>>>-	/* Set the CPU feature capabilies */
> >>>>-	setup_feature_capabilities();
> >>>>-	enable_errata_workarounds();
> >>>>+	setup_system_capabilities();
> >>>>  	mark_const_caps_ready();
> >>>>  	setup_elf_hwcaps(arm64_elf_hwcaps);
> >>>
> >>>I wonder whether we could unify the elf hwcaps handling too.
> >>
> >>I was thinking about it today. The only catch is how do we know
> >>if we have "the capability", as it is spread across multiple bitmasks.
> >>(HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).
> >
> >An easy-ish solution might be to maintain our own bitmap in the style
> >of cpu_hwcaps, and set bits in parallel with the elf_hwcap etc. bits.
> >Or, add a method that knows how to set/query the appropriate bit.
> >
> >I guess we could do this later.  It's certainly not urgent.
> 
> Yes, I understand.

OK, cool

Cheers
---Dave

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

* [PATCH 08/16] arm64: capabilities: Group handling of features and errata
@ 2018-01-30 15:06             ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 29, 2018 at 05:22:26PM +0000, Suzuki K Poulose wrote:
> On 29/01/18 17:14, Dave Martin wrote:
> >On Fri, Jan 26, 2018 at 12:31:18PM +0000, Suzuki K Poulose wrote:
> >>On 26/01/18 11:47, Dave Martin wrote:
> >>>On Tue, Jan 23, 2018 at 12:28:01PM +0000, Suzuki K Poulose wrote:
> >>>>So far we have had separate routes for triggering errata and feature
> >>>
> >>>"triggering errata" ? ;)
> >>>
> >>
> >>:-). Should have been "triggering errata and feature capability *checks*.
> >>
> >>>Maybe "[...] for determining whether to activate errata workarounds and
> >>>whether to enable feature capabilities."
> >>>
> >>
> >>
> >>>>capabilities. Also, we never allowed "features" based on local CPU
> >>>>and "errata" based on System wide safe registers. This patch
> >>>>groups the handling of errata and features and also allows them
> >>>>to have all the possible scopes.
> >>>>
> >>>>So, we now run through the arm64_features and arm64_errata:
> >>>
> >>>when?
> >>
> >>with this patch.
> >
> >I mean, when at runtime?
> 
> Sorry, I thought that was evident from the comment below :

Sort of, but you talk about things being done on boot-time enabled CPUs,
rather than saying the check actually happens at boot time.  The
description isn't wrong, but I just ended up a bit unsure about exactly
what was being guaranteed.

My confusion was partly due to my understanding of the code still being
incomplete when I responsed to this patch.


Maybe say "we run through arm64_features and arm64_errata in two phases
during the boot process"

> 
> >
> >>>What about late cpus?
> >>>
> >>
> >>We don't detect any new capabilities on them. They continue to get
> >>verified against the enabled capabilities.

If this patch doesn't intentionally change what happens for late CPUs
after kernel boot, but nonetheless does unifiy the errata/feature
verification code for late CPUs then this may also be worth noting here.

> >>
> >>>>  1) with SCOPE_LOCAL_CPU filter on each boot time enabeld CPUs,
> >>>>     via update_cpu_local_capabilities().
> 
> Here ^^.  Earlier we ran only through the errata list. But now, we
> run through errata and the features, using a type filter of SCOPE_LOCAL_CPU.
> 
> It also said :
> 
>   2) with SCOPE_SYSTEM filter only once after all boot time enabled
>     CPUs are active.
> 
> (2) happens from setup_cpu_features(), just like it was done earlier, but
> with a filter of SCOPE_SYSTEM.
> 
> >>>
> >>>"each [...] enabeld CPUs" -> "each [...] enabled CPU"
> >>>
> >>>Also, changing "boot time" -> "boot-time" helps avoid this being misread
> >>>as "on each boot", which could be taken to mean "each time a CPU comes
> >>>online".  I'm guessing that's not the intended meaning here.
> >>
> 
> >>>
> >>>   }
> >>>>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> >>>>@@ -1422,9 +1435,7 @@ void __init setup_cpu_features(void)
> >>>>  	u32 cwg;
> >>>>  	int cls;
> >>>>-	/* Set the CPU feature capabilies */
> >>>>-	setup_feature_capabilities();
> >>>>-	enable_errata_workarounds();
> >>>>+	setup_system_capabilities();
> >>>>  	mark_const_caps_ready();
> >>>>  	setup_elf_hwcaps(arm64_elf_hwcaps);
> >>>
> >>>I wonder whether we could unify the elf hwcaps handling too.
> >>
> >>I was thinking about it today. The only catch is how do we know
> >>if we have "the capability", as it is spread across multiple bitmasks.
> >>(HWCAP, COMPAT_HWCAP, COMPAT_HWCAP2).
> >
> >An easy-ish solution might be to maintain our own bitmap in the style
> >of cpu_hwcaps, and set bits in parallel with the elf_hwcap etc. bits.
> >Or, add a method that knows how to set/query the appropriate bit.
> >
> >I guess we could do this later.  It's certainly not urgent.
> 
> Yes, I understand.

OK, cool

Cheers
---Dave

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

* Re: [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
  2018-01-30 14:56         ` Dave Martin
@ 2018-01-30 15:06           ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 15:06 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 30/01/18 14:56, Dave Martin wrote:
> On Tue, Jan 30, 2018 at 11:17:38AM +0000, Suzuki K Poulose wrote:
>> On 26/01/18 10:10, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
>>>> Add two different flags to indicate if the conflict of a capability
>>>> on a late CPU with the current system state
>>>>
>>>>   1) Can a CPU have a capability when the system doesn't have it ?
>>>>
>>>>      Most arm64 features could have this set. While erratum work arounds
>>>>      cannot have this, as we may miss work arounds.
>>>>
>>>>   2) Can a CPU miss a capability when the system has it ?
>>>>      This could be set for arm64 erratum work arounds as we don't
>>>>      care if a CPU doesn't need the work around. However it should
>>>>      be clear for features.
>>>>
>>>> These flags could be added to certain entries based on their nature.
>>>>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
>>>>   1 file changed, 31 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index 4fd5de8ef33e..27d037bb0451 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>>>   #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>>>>   #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>>>> -/* CPU errata detected at boot time based on feature of one or more CPUs */
>>>> -#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
>>>> -/* CPU feature detected at boot time based on system-wide value of a feature */
>>>> -#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
>>>> +/* Is it safe for a late CPU to have this capability when system doesn't already have */
>>>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
>>>> +/* Is it safe for a late CPU to miss this capability when system has it */
>>>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
>>>
>>> Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?
>>>
>>> Alternatively,
>>> 	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
>>> 	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU
>>
>> Sounds better than what I have. I have picked them up.
> 
> Cool, I had resigned myself to probably not winning that one ;)

Well, you have won almost all in this series :-)

Cheers
Suzuki

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

* [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU
@ 2018-01-30 15:06           ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/18 14:56, Dave Martin wrote:
> On Tue, Jan 30, 2018 at 11:17:38AM +0000, Suzuki K Poulose wrote:
>> On 26/01/18 10:10, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:27:58PM +0000, Suzuki K Poulose wrote:
>>>> Add two different flags to indicate if the conflict of a capability
>>>> on a late CPU with the current system state
>>>>
>>>>   1) Can a CPU have a capability when the system doesn't have it ?
>>>>
>>>>      Most arm64 features could have this set. While erratum work arounds
>>>>      cannot have this, as we may miss work arounds.
>>>>
>>>>   2) Can a CPU miss a capability when the system has it ?
>>>>      This could be set for arm64 erratum work arounds as we don't
>>>>      care if a CPU doesn't need the work around. However it should
>>>>      be clear for features.
>>>>
>>>> These flags could be added to certain entries based on their nature.
>>>>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h | 35 +++++++++++++++++++++++++++++++----
>>>>   1 file changed, 31 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index 4fd5de8ef33e..27d037bb0451 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -94,10 +94,25 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>>>   #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>>>>   #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>>>> -/* CPU errata detected at boot time based on feature of one or more CPUs */
>>>> -#define ARM64_CPUCAP_STRICT_CPU_LOCAL_ERRATUM	(ARM64_CPUCAP_SCOPE_LOCAL_CPU)
>>>> -/* CPU feature detected at boot time based on system-wide value of a feature */
>>>> -#define ARM64_CPUCAP_BOOT_SYSTEM_FEATURE	(ARM64_CPUCAP_SCOPE_SYSTEM)
>>>> +/* Is it safe for a late CPU to have this capability when system doesn't already have */
>>>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE	BIT(2)
>>>> +/* Is it safe for a late CPU to miss this capability when system has it */
>>>> +#define ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	BIT(3)
>>>
>>> Maybe _OPTIONAL and _PERMITTED would be a bit less verbose?
>>>
>>> Alternatively,
>>> 	ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU
>>> 	ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU
>>
>> Sounds better than what I have. I have picked them up.
> 
> Cool, I had resigned myself to probably not winning that one ;)

Well, you have won almost all in this series :-)

Cheers
Suzuki

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

* Re: [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
  2018-01-26 15:57       ` Suzuki K Poulose
@ 2018-01-30 15:16         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:16 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 03:57:44PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 14:16, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
> >>Add helpers for detecting an errata on list of midr ranges
> >>of affected CPUs.
> >
> >This doesn't describe what the patch does: instead, helpers are being
> >added for checking whether an MIDR falls in one of multiple affected
> >model(s) and or revision(s).
> >
> >Doing this makes sense, but is it really worth it?
> 
> Well, we need th MIDR list helpers anyway for other things:
>   - White list of CPUs where we know KPTI is not needed
>   - Black list of CPUs where DBM shouldn't be enabled.
> 
> So all we do is add a new type which could reduce the number of entries.
> 
> >
> >We might save 100-200 bytes in the kernel image for now, but a common
> >workaround for errata on multiple unrelated cpus is surely a rare case.
> >
> >Only if there are many such lists, or if the lists become large does
> >this start to seem a clear win.
> >
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  1 +
> >>  arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
> >>  2 files changed, 25 insertions(+), 16 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index a3d54c2c411f..70712de687c7 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >
> >[...]
> >
> >>@@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
> >>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> >>  	{
> >>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> >>-		.enable = enable_psci_bp_hardening,
> >>-	},
> >>-	{
> >>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> >>-		.enable = enable_psci_bp_hardening,
> >>-	},
> >>-	{
> >>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> >>-		.enable = enable_psci_bp_hardening,
> >>-	},
> >>-	{
> >>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> >>+		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
> >
> >Could we just use a macro to generate multiple structs, instead of
> >inventing a new type of struct?
> 
> We could. Somehow, I don't think we are over engineering much here.

There is a flipside to this: I commented elsewhere that not allowing
mutiple match criteria per capability struct complicates verification
for late CPUs and/or makes it more costly.

Your changes here do implement support for multiple match criteria,
albeit only for the specific case of MIDR matching.

It could be worth generalising this in the future, but that's
probably not for this series.

OTOH, if MIDR matching is the only scenario where we have duplicate
cap structs with different match criteria and this patch allows all
those duplicates to be removed, then is there still a need to walk
the whole list in verify_local_cpu_features(), as introduced in
67948af41f2e ("arm64: capabilities: Handle duplicate entries for a
capability")?  Or can that now be simplified?

Cheers
---Dave

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
@ 2018-01-30 15:16         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 03:57:44PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 14:16, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
> >>Add helpers for detecting an errata on list of midr ranges
> >>of affected CPUs.
> >
> >This doesn't describe what the patch does: instead, helpers are being
> >added for checking whether an MIDR falls in one of multiple affected
> >model(s) and or revision(s).
> >
> >Doing this makes sense, but is it really worth it?
> 
> Well, we need th MIDR list helpers anyway for other things:
>   - White list of CPUs where we know KPTI is not needed
>   - Black list of CPUs where DBM shouldn't be enabled.
> 
> So all we do is add a new type which could reduce the number of entries.
> 
> >
> >We might save 100-200 bytes in the kernel image for now, but a common
> >workaround for errata on multiple unrelated cpus is surely a rare case.
> >
> >Only if there are many such lists, or if the lists become large does
> >this start to seem a clear win.
> >
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  1 +
> >>  arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
> >>  2 files changed, 25 insertions(+), 16 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index a3d54c2c411f..70712de687c7 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >
> >[...]
> >
> >>@@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
> >>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> >>  	{
> >>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> >>-		.enable = enable_psci_bp_hardening,
> >>-	},
> >>-	{
> >>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> >>-		.enable = enable_psci_bp_hardening,
> >>-	},
> >>-	{
> >>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> >>-		.enable = enable_psci_bp_hardening,
> >>-	},
> >>-	{
> >>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> >>+		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
> >
> >Could we just use a macro to generate multiple structs, instead of
> >inventing a new type of struct?
> 
> We could. Somehow, I don't think we are over engineering much here.

There is a flipside to this: I commented elsewhere that not allowing
mutiple match criteria per capability struct complicates verification
for late CPUs and/or makes it more costly.

Your changes here do implement support for multiple match criteria,
albeit only for the specific case of MIDR matching.

It could be worth generalising this in the future, but that's
probably not for this series.

OTOH, if MIDR matching is the only scenario where we have duplicate
cap structs with different match criteria and this patch allows all
those duplicates to be removed, then is there still a need to walk
the whole list in verify_local_cpu_features(), as introduced in
67948af41f2e ("arm64: capabilities: Handle duplicate entries for a
capability")?  Or can that now be simplified?

Cheers
---Dave

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

* Re: [PATCH 15/16] arm64: Delay enabling hardware DBM feature
  2018-01-26 16:05       ` Suzuki K Poulose
@ 2018-01-30 15:22         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:22 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 04:05:24PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 14:41, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:08PM +0000, Suzuki K Poulose wrote:
> >>We enable hardware DBM bit in a capable CPU, very early in the
> >>boot via __cpu_setup. This doesn't give us a flexibility of
> >>optionally disable the feature, as the clearing the bit
> >>is a bit costly as the TLB can cache the settings. Instead,
> >>we delay enabling the feature until the CPU is brought up
> >>into the kernel. We use the feature capability mechanism
> >>to handle it.
> >>
> >>The hardware DBM is a non-conflicting feature. i.e, the kernel
> >>can safely run with a mix of CPUs with some using the feature
> >>and the others don't. So, it is safe for a late CPU to have
> >>this capability and enable it, even if the active CPUs don't.
> >>
> >>To get this handled properly by the infrastructure, we
> >>unconditionally set the capability and only enable it
> >>on CPUs which really have the feature. Adds a new type
> >>of feature to the capability infrastructure which
> >>ignores the conflict in a late CPU.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpucaps.h    |  3 ++-
> >>  arch/arm64/include/asm/cpufeature.h |  8 +++++++
> >>  arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
> >>  arch/arm64/mm/proc.S                |  5 +----
> >>  4 files changed, 53 insertions(+), 5 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> >>index bb263820de13..8df80cc828ac 100644
> >>--- a/arch/arm64/include/asm/cpucaps.h
> >>+++ b/arch/arm64/include/asm/cpucaps.h
> >>@@ -45,7 +45,8 @@
> >>  #define ARM64_HARDEN_BRANCH_PREDICTOR		24
> >>  #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
> >>  #define ARM64_HAS_RAS_EXTN			26
> >>+#define ARM64_HW_DBM				27
> >>-#define ARM64_NCAPS				27
> >>+#define ARM64_NCAPS				28
> >>  #endif /* __ASM_CPUCAPS_H */
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 70712de687c7..243ec7c77c79 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>   */
> >>  #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
> >>  	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> >>+/*
> >>+ * CPU feature detected on each local CPU. It is safe for a late CPU to
> >>+ * either have it or not.
> >>+ */
> >>+#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
> >>+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
> >
> >OK, so this is similar to my suggestion for HAS_NO_HW_PREFETCH (though
> >that need not have the same answer -- I was speculating there).
> 
> Yes, I was under the assumption that HAS_NO_HW_PREFETCH is treated as
> a "Late CPU can't have the capability" type, hence the "STRICT_CPU_LOCAL",
> as we can't apply work-arounds anymore for this CPU. However, since
> we only suffer a performance impact, we could as well convert it to
> a WEAK one.

(Note: I'm not very familiar with ThunderX.  I may be assuming things I
don't understand when I assert that only performance is affected
here...)

[...]

> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 2627a836e99d..8af755b8219d 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
> >>  __setup("kpti=", parse_kpti);
> >>  #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
> >>+#ifdef CONFIG_ARM64_HW_AFDBM
> >>+static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
> >>+{
> >>+	/*
> >>+	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
> >>+	 * a mix of CPUs with and without the feature. So, we unconditionally
> >>+	 * enable the capability to allow any late CPU to use the feature.
> >>+	 * We only enable the control bits on the CPU, if it actually supports.
> >>+	 */
> >>+	return true;
> >>+}
> >>+
> >>+static inline void __cpu_enable_hw_dbm(void)
> >>+{
> >>+	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
> >>+
> >>+	write_sysreg(tcr, tcr_el1);
> >>+	isb();
> >
> >Do we need this isb?  Do we care exactly when setting TCR_HD appears
> >to take effect?
> 
> Practically no, as it doesn't matter if we use it or not. But, since the
> CPU is anyway booting, there is no harm in enforcing it to take effect.

Ok.  Just wondering whether there was a requirement here that I wasn't
understanding.

It would be worth a comment here explaining that the ISB is believed
only to be improving determinism here, rather than being required for
correctness.

[...]

> >>@@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> >>  		.enable = cpu_clear_disr,
> >>  	},
> >>  #endif /* CONFIG_ARM64_RAS_EXTN */
> >>+#ifdef CONFIG_ARM64_HW_AFDBM
> >>+	{
> >>+		.desc = "Hardware pagetable Dirty Bit Management",
> >>+		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
> >>+		.capability = ARM64_HW_DBM,
> >>+		.sys_reg = SYS_ID_AA64MMFR1_EL1,
> >>+		.sign = FTR_UNSIGNED,
> >>+		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
> >>+		.min_field_value = 2,
> >>+		.matches = has_hw_dbm,
> >
> >Can't we use has_cpuid_feature here?  Why do we need a fake .matches and
> >then code the check manually in the enable mathod?
> 
> We could, but then we need to add another *type*, where capabilities could
> be enabled by a late CPU, where something is not already enabled by the boot-time
> CPUs. i.e, if we boot a DBM capable CPU late, we won't be able to use the feature
> on it, with the current setup. I didn't want to complicate the infrastructure
> further just for this.

Fair enough.  For now this seems like a unique case.

[...]

Cheers
---Dave

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

* [PATCH 15/16] arm64: Delay enabling hardware DBM feature
@ 2018-01-30 15:22         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 04:05:24PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 14:41, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:08PM +0000, Suzuki K Poulose wrote:
> >>We enable hardware DBM bit in a capable CPU, very early in the
> >>boot via __cpu_setup. This doesn't give us a flexibility of
> >>optionally disable the feature, as the clearing the bit
> >>is a bit costly as the TLB can cache the settings. Instead,
> >>we delay enabling the feature until the CPU is brought up
> >>into the kernel. We use the feature capability mechanism
> >>to handle it.
> >>
> >>The hardware DBM is a non-conflicting feature. i.e, the kernel
> >>can safely run with a mix of CPUs with some using the feature
> >>and the others don't. So, it is safe for a late CPU to have
> >>this capability and enable it, even if the active CPUs don't.
> >>
> >>To get this handled properly by the infrastructure, we
> >>unconditionally set the capability and only enable it
> >>on CPUs which really have the feature. Adds a new type
> >>of feature to the capability infrastructure which
> >>ignores the conflict in a late CPU.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpucaps.h    |  3 ++-
> >>  arch/arm64/include/asm/cpufeature.h |  8 +++++++
> >>  arch/arm64/kernel/cpufeature.c      | 42 +++++++++++++++++++++++++++++++++++++
> >>  arch/arm64/mm/proc.S                |  5 +----
> >>  4 files changed, 53 insertions(+), 5 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> >>index bb263820de13..8df80cc828ac 100644
> >>--- a/arch/arm64/include/asm/cpucaps.h
> >>+++ b/arch/arm64/include/asm/cpucaps.h
> >>@@ -45,7 +45,8 @@
> >>  #define ARM64_HARDEN_BRANCH_PREDICTOR		24
> >>  #define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
> >>  #define ARM64_HAS_RAS_EXTN			26
> >>+#define ARM64_HW_DBM				27
> >>-#define ARM64_NCAPS				27
> >>+#define ARM64_NCAPS				28
> >>  #endif /* __ASM_CPUCAPS_H */
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 70712de687c7..243ec7c77c79 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -126,6 +126,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>   */
> >>  #define ARM64_CPUCAP_STRICT_CPU_LOCAL_FEATURE	\
> >>  	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS)
> >>+/*
> >>+ * CPU feature detected on each local CPU. It is safe for a late CPU to
> >>+ * either have it or not.
> >>+ */
> >>+#define ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE	 \
> >>+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_MISS	|\
> >>+	 ARM64_CPUCAP_LATE_CPU_SAFE_TO_HAVE)
> >
> >OK, so this is similar to my suggestion for HAS_NO_HW_PREFETCH (though
> >that need not have the same answer -- I was speculating there).
> 
> Yes, I was under the assumption that HAS_NO_HW_PREFETCH is treated as
> a "Late CPU can't have the capability" type, hence the "STRICT_CPU_LOCAL",
> as we can't apply work-arounds anymore for this CPU. However, since
> we only suffer a performance impact, we could as well convert it to
> a WEAK one.

(Note: I'm not very familiar with ThunderX.  I may be assuming things I
don't understand when I assert that only performance is affected
here...)

[...]

> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 2627a836e99d..8af755b8219d 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -894,6 +894,35 @@ static int __init parse_kpti(char *str)
> >>  __setup("kpti=", parse_kpti);
> >>  #endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
> >>+#ifdef CONFIG_ARM64_HW_AFDBM
> >>+static bool has_hw_dbm(const struct arm64_cpu_capabilities *entry, int scope)
> >>+{
> >>+	/*
> >>+	 * DBM is a non-conflicting feature. i.e, the kernel can safely run
> >>+	 * a mix of CPUs with and without the feature. So, we unconditionally
> >>+	 * enable the capability to allow any late CPU to use the feature.
> >>+	 * We only enable the control bits on the CPU, if it actually supports.
> >>+	 */
> >>+	return true;
> >>+}
> >>+
> >>+static inline void __cpu_enable_hw_dbm(void)
> >>+{
> >>+	u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
> >>+
> >>+	write_sysreg(tcr, tcr_el1);
> >>+	isb();
> >
> >Do we need this isb?  Do we care exactly when setting TCR_HD appears
> >to take effect?
> 
> Practically no, as it doesn't matter if we use it or not. But, since the
> CPU is anyway booting, there is no harm in enforcing it to take effect.

Ok.  Just wondering whether there was a requirement here that I wasn't
understanding.

It would be worth a comment here explaining that the ISB is believed
only to be improving determinism here, rather than being required for
correctness.

[...]

> >>@@ -1052,6 +1081,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> >>  		.enable = cpu_clear_disr,
> >>  	},
> >>  #endif /* CONFIG_ARM64_RAS_EXTN */
> >>+#ifdef CONFIG_ARM64_HW_AFDBM
> >>+	{
> >>+		.desc = "Hardware pagetable Dirty Bit Management",
> >>+		.type = ARM64_CPUCAP_WEAK_CPU_LOCAL_FEATURE,
> >>+		.capability = ARM64_HW_DBM,
> >>+		.sys_reg = SYS_ID_AA64MMFR1_EL1,
> >>+		.sign = FTR_UNSIGNED,
> >>+		.field_pos = ID_AA64MMFR1_HADBS_SHIFT,
> >>+		.min_field_value = 2,
> >>+		.matches = has_hw_dbm,
> >
> >Can't we use has_cpuid_feature here?  Why do we need a fake .matches and
> >then code the check manually in the enable mathod?
> 
> We could, but then we need to add another *type*, where capabilities could
> be enabled by a late CPU, where something is not already enabled by the boot-time
> CPUs. i.e, if we boot a DBM capable CPU late, we won't be able to use the feature
> on it, with the current setup. I didn't want to complicate the infrastructure
> further just for this.

Fair enough.  For now this seems like a unique case.

[...]

Cheers
---Dave

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

* Re: [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
  2018-01-26 16:29       ` Suzuki K Poulose
@ 2018-01-30 15:27         ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:27 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Fri, Jan 26, 2018 at 04:29:53PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 15:33, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:09PM +0000, Suzuki K Poulose wrote:
> >>Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
> >>from an erratum 1024718, which causes incorrect updates when DBM/AP
> >>bits in a page table entry is modified without a break-before-make
> >>sequence. The work around is to skip enabling the hardware DBM feature
> >>on the affected cores. The hardware Access Flag management features
> >>is not affected.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  Documentation/arm64/silicon-errata.txt |  1 +
> >>  arch/arm64/Kconfig                     | 14 ++++++++++++++
> >>  arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
> >>  3 files changed, 28 insertions(+), 1 deletion(-)
> >
> >[...]
> >
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 8af755b8219d..64f1e911c6af 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
> >>  	isb();
> >>  }
> >>+static bool cpu_has_erratum_1024718(void)
> >>+{
> >>+	static const struct midr_range __maybe_unused cpus[] = {
> >
> >Do you need __maybe_unused?  If #ifdef were used here then
> >__maybe_unused would be needed, but I thought that if code is optimised
> >out instead of conditionally copiled, this didn't apply.
> 
> Yep. I don't know if the compiler could optimise the array itself with
> the tag as a hint. I will double check.

I think the compiler should optimise cpus[] out as appropriate here,
even without the annotation.  It's scoped to this function and nothing
is done with it in the !IS_ENABLED() case.

I've relied heavily on this in the SVE code -- it massively reduces the
amount of #ifdefs and annotations required, which would otherwise clutter
the code a lot.

Since the kernel in general does rely on dead code elimination (and
presumably dead object elimination too) in order to avoid link failures,
I considered this reasonable.  The compiler did seem to do the right
thing for my code.

> 
> >
> >>+		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
> >>+		{},
> >>+	};
> >>+
> >>+	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
> >>+	       is_midr_in_range_list(read_cpuid_id(), cpus);
> >
> >Why have a list with just one entry?  Do you expect more entries over
> >time?
> 
> Yes. I should have mentioned it here. See [1]
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/554516.html

Right, that seemed the likely explanation!

Cheers
---Dave

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

* [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
@ 2018-01-30 15:27         ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 26, 2018 at 04:29:53PM +0000, Suzuki K Poulose wrote:
> On 26/01/18 15:33, Dave Martin wrote:
> >On Tue, Jan 23, 2018 at 12:28:09PM +0000, Suzuki K Poulose wrote:
> >>Some variants of the Arm Cortex-55 cores (r0p0, r0p1, r1p0) suffer
> >>from an erratum 1024718, which causes incorrect updates when DBM/AP
> >>bits in a page table entry is modified without a break-before-make
> >>sequence. The work around is to skip enabling the hardware DBM feature
> >>on the affected cores. The hardware Access Flag management features
> >>is not affected.
> >>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  Documentation/arm64/silicon-errata.txt |  1 +
> >>  arch/arm64/Kconfig                     | 14 ++++++++++++++
> >>  arch/arm64/kernel/cpufeature.c         | 14 +++++++++++++-
> >>  3 files changed, 28 insertions(+), 1 deletion(-)
> >
> >[...]
> >
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 8af755b8219d..64f1e911c6af 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -914,9 +914,21 @@ static inline void __cpu_enable_hw_dbm(void)
> >>  	isb();
> >>  }
> >>+static bool cpu_has_erratum_1024718(void)
> >>+{
> >>+	static const struct midr_range __maybe_unused cpus[] = {
> >
> >Do you need __maybe_unused?  If #ifdef were used here then
> >__maybe_unused would be needed, but I thought that if code is optimised
> >out instead of conditionally copiled, this didn't apply.
> 
> Yep. I don't know if the compiler could optimise the array itself with
> the tag as a hint. I will double check.

I think the compiler should optimise cpus[] out as appropriate here,
even without the annotation.  It's scoped to this function and nothing
is done with it in the !IS_ENABLED() case.

I've relied heavily on this in the SVE code -- it massively reduces the
amount of #ifdefs and annotations required, which would otherwise clutter
the code a lot.

Since the kernel in general does rely on dead code elimination (and
presumably dead object elimination too) in order to avoid link failures,
I considered this reasonable.  The compiler did seem to do the right
thing for my code.

> 
> >
> >>+		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),	// A55 r0p0 -r1p0
> >>+		{},
> >>+	};
> >>+
> >>+	return IS_ENABLED(CONFIG_ARM64_ERRATUM_1024718) &&
> >>+	       is_midr_in_range_list(read_cpuid_id(), cpus);
> >
> >Why have a list with just one entry?  Do you expect more entries over
> >time?
> 
> Yes. I should have mentioned it here. See [1]
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/554516.html

Right, that seemed the likely explanation!

Cheers
---Dave

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

* Re: [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
  2018-01-30 15:16         ` Dave Martin
@ 2018-01-30 15:38           ` Suzuki K Poulose
  -1 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 15:38 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 30/01/18 15:16, Dave Martin wrote:
> On Fri, Jan 26, 2018 at 03:57:44PM +0000, Suzuki K Poulose wrote:
>> On 26/01/18 14:16, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
>>>> Add helpers for detecting an errata on list of midr ranges
>>>> of affected CPUs.
>>>
>>> This doesn't describe what the patch does: instead, helpers are being
>>> added for checking whether an MIDR falls in one of multiple affected
>>> model(s) and or revision(s).
>>>
>>> Doing this makes sense, but is it really worth it?
>>
>> Well, we need th MIDR list helpers anyway for other things:
>>    - White list of CPUs where we know KPTI is not needed
>>    - Black list of CPUs where DBM shouldn't be enabled.
>>
>> So all we do is add a new type which could reduce the number of entries.
>>
>>>
>>> We might save 100-200 bytes in the kernel image for now, but a common
>>> workaround for errata on multiple unrelated cpus is surely a rare case.
>>>
>>> Only if there are many such lists, or if the lists become large does
>>> this start to seem a clear win.
>>>
>>>>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>>>   arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
>>>>   2 files changed, 25 insertions(+), 16 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index a3d54c2c411f..70712de687c7 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>
>>> [...]
>>>
>>>> @@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>>>   #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>>>>   	{
>>>>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
>>>> -		.enable = enable_psci_bp_hardening,
>>>> -	},
>>>> -	{
>>>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
>>>> -		.enable = enable_psci_bp_hardening,
>>>> -	},
>>>> -	{
>>>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
>>>> -		.enable = enable_psci_bp_hardening,
>>>> -	},
>>>> -	{
>>>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
>>>> +		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
>>>
>>> Could we just use a macro to generate multiple structs, instead of
>>> inventing a new type of struct?
>>
>> We could. Somehow, I don't think we are over engineering much here.
> 
> There is a flipside to this: I commented elsewhere that not allowing
> mutiple match criteria per capability struct complicates verification
> for late CPUs and/or makes it more costly.
> 
> Your changes here do implement support for multiple match criteria,
> albeit only for the specific case of MIDR matching.
> 
> It could be worth generalising this in the future, but that's
> probably not for this series.

It is not that complex, right now. See below.

> 
> OTOH, if MIDR matching is the only scenario where we have duplicate
> cap structs with different match criteria and this patch allows all
> those duplicates to be removed, then is there still a need to walk
> the whole list in verify_local_cpu_features(), as introduced in
> 67948af41f2e ("arm64: capabilities: Handle duplicate entries for a
> capability")?  Or can that now be simplified?

I have added support for this in my v2. So here is what I have done :

1) Continue to use midr_list for capability entries that just matches
MIDRS and share the same enable() call back.

  and

2) Add support for wrapper entries where a capability is determined
by two or more entries with different matches()/enable() call backs.

And that can get rid of the changes introduced in commit 67948af41f2e
("arm64: capabilities: Handle duplicate entries for a capability").

Cheers
Suzuki

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
@ 2018-01-30 15:38           ` Suzuki K Poulose
  0 siblings, 0 replies; 134+ messages in thread
From: Suzuki K Poulose @ 2018-01-30 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/18 15:16, Dave Martin wrote:
> On Fri, Jan 26, 2018 at 03:57:44PM +0000, Suzuki K Poulose wrote:
>> On 26/01/18 14:16, Dave Martin wrote:
>>> On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
>>>> Add helpers for detecting an errata on list of midr ranges
>>>> of affected CPUs.
>>>
>>> This doesn't describe what the patch does: instead, helpers are being
>>> added for checking whether an MIDR falls in one of multiple affected
>>> model(s) and or revision(s).
>>>
>>> Doing this makes sense, but is it really worth it?
>>
>> Well, we need th MIDR list helpers anyway for other things:
>>    - White list of CPUs where we know KPTI is not needed
>>    - Black list of CPUs where DBM shouldn't be enabled.
>>
>> So all we do is add a new type which could reduce the number of entries.
>>
>>>
>>> We might save 100-200 bytes in the kernel image for now, but a common
>>> workaround for errata on multiple unrelated cpus is surely a rare case.
>>>
>>> Only if there are many such lists, or if the lists become large does
>>> this start to seem a clear win.
>>>
>>>>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>>>   arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
>>>>   2 files changed, 25 insertions(+), 16 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index a3d54c2c411f..70712de687c7 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>
>>> [...]
>>>
>>>> @@ -330,22 +353,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>>>   #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>>>>   	{
>>>>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
>>>> -		.enable = enable_psci_bp_hardening,
>>>> -	},
>>>> -	{
>>>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
>>>> -		.enable = enable_psci_bp_hardening,
>>>> -	},
>>>> -	{
>>>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
>>>> -		.enable = enable_psci_bp_hardening,
>>>> -	},
>>>> -	{
>>>> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>>>> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
>>>> +		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
>>>
>>> Could we just use a macro to generate multiple structs, instead of
>>> inventing a new type of struct?
>>
>> We could. Somehow, I don't think we are over engineering much here.
> 
> There is a flipside to this: I commented elsewhere that not allowing
> mutiple match criteria per capability struct complicates verification
> for late CPUs and/or makes it more costly.
> 
> Your changes here do implement support for multiple match criteria,
> albeit only for the specific case of MIDR matching.
> 
> It could be worth generalising this in the future, but that's
> probably not for this series.

It is not that complex, right now. See below.

> 
> OTOH, if MIDR matching is the only scenario where we have duplicate
> cap structs with different match criteria and this patch allows all
> those duplicates to be removed, then is there still a need to walk
> the whole list in verify_local_cpu_features(), as introduced in
> 67948af41f2e ("arm64: capabilities: Handle duplicate entries for a
> capability")?  Or can that now be simplified?

I have added support for this in my v2. So here is what I have done :

1) Continue to use midr_list for capability entries that just matches
MIDRS and share the same enable() call back.

  and

2) Add support for wrapper entries where a capability is determined
by two or more entries with different matches()/enable() call backs.

And that can get rid of the changes introduced in commit 67948af41f2e
("arm64: capabilities: Handle duplicate entries for a capability").

Cheers
Suzuki

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

* Re: [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
  2018-01-30 15:38           ` Suzuki K Poulose
@ 2018-01-30 15:58             ` Dave Martin
  -1 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:58 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Tue, Jan 30, 2018 at 03:38:44PM +0000, Suzuki K Poulose wrote:
> On 30/01/18 15:16, Dave Martin wrote:
> >On Fri, Jan 26, 2018 at 03:57:44PM +0000, Suzuki K Poulose wrote:
> >>On 26/01/18 14:16, Dave Martin wrote:
> >>>On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
> >>>>Add helpers for detecting an errata on list of midr ranges
> >>>>of affected CPUs.
> >>>
> >>>This doesn't describe what the patch does: instead, helpers are being
> >>>added for checking whether an MIDR falls in one of multiple affected
> >>>model(s) and or revision(s).
> >>>
> >>>Doing this makes sense, but is it really worth it?
> >>
> >>Well, we need th MIDR list helpers anyway for other things:
> >>   - White list of CPUs where we know KPTI is not needed
> >>   - Black list of CPUs where DBM shouldn't be enabled.
> >>
> >>So all we do is add a new type which could reduce the number of entries.
> >>
> >>>
> >>>We might save 100-200 bytes in the kernel image for now, but a common
> >>>workaround for errata on multiple unrelated cpus is surely a rare case.
> >>>
> >>>Only if there are many such lists, or if the lists become large does
> >>>this start to seem a clear win.
> >>>
> >>>>
> >>>>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>>>---
> >>>>  arch/arm64/include/asm/cpufeature.h |  1 +
> >>>>  arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
> >>>>  2 files changed, 25 insertions(+), 16 deletions(-)
> >>>>
> >>>>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h

[...]

> >>>>-	{
> >>>>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>>>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> >>>>-		.enable = enable_psci_bp_hardening,
> >>>>-	},
> >>>>-	{
> >>>>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>>>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> >>>>+		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
> >>>
> >>>Could we just use a macro to generate multiple structs, instead of
> >>>inventing a new type of struct?
> >>
> >>We could. Somehow, I don't think we are over engineering much here.
> >
> >There is a flipside to this: I commented elsewhere that not allowing
> >mutiple match criteria per capability struct complicates verification
> >for late CPUs and/or makes it more costly.
> >
> >Your changes here do implement support for multiple match criteria,
> >albeit only for the specific case of MIDR matching.
> >
> >It could be worth generalising this in the future, but that's
> >probably not for this series.
> 
> It is not that complex, right now. See below.
> 
> >
> >OTOH, if MIDR matching is the only scenario where we have duplicate
> >cap structs with different match criteria and this patch allows all
> >those duplicates to be removed, then is there still a need to walk
> >the whole list in verify_local_cpu_features(), as introduced in
> >67948af41f2e ("arm64: capabilities: Handle duplicate entries for a
> >capability")?  Or can that now be simplified?
> 
> I have added support for this in my v2. So here is what I have done :
> 
> 1) Continue to use midr_list for capability entries that just matches
> MIDRS and share the same enable() call back.
> 
>  and
> 
> 2) Add support for wrapper entries where a capability is determined
> by two or more entries with different matches()/enable() call backs.
> 
> And that can get rid of the changes introduced in commit 67948af41f2e
> ("arm64: capabilities: Handle duplicate entries for a capability").

OK, cool.  I was presuming that might be too much work to be justified
here, but if not, great.

Cheers
---Dave

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

* [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS
@ 2018-01-30 15:58             ` Dave Martin
  0 siblings, 0 replies; 134+ messages in thread
From: Dave Martin @ 2018-01-30 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 30, 2018 at 03:38:44PM +0000, Suzuki K Poulose wrote:
> On 30/01/18 15:16, Dave Martin wrote:
> >On Fri, Jan 26, 2018 at 03:57:44PM +0000, Suzuki K Poulose wrote:
> >>On 26/01/18 14:16, Dave Martin wrote:
> >>>On Tue, Jan 23, 2018 at 12:28:06PM +0000, Suzuki K Poulose wrote:
> >>>>Add helpers for detecting an errata on list of midr ranges
> >>>>of affected CPUs.
> >>>
> >>>This doesn't describe what the patch does: instead, helpers are being
> >>>added for checking whether an MIDR falls in one of multiple affected
> >>>model(s) and or revision(s).
> >>>
> >>>Doing this makes sense, but is it really worth it?
> >>
> >>Well, we need th MIDR list helpers anyway for other things:
> >>   - White list of CPUs where we know KPTI is not needed
> >>   - Black list of CPUs where DBM shouldn't be enabled.
> >>
> >>So all we do is add a new type which could reduce the number of entries.
> >>
> >>>
> >>>We might save 100-200 bytes in the kernel image for now, but a common
> >>>workaround for errata on multiple unrelated cpus is surely a rare case.
> >>>
> >>>Only if there are many such lists, or if the lists become large does
> >>>this start to seem a clear win.
> >>>
> >>>>
> >>>>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>>>---
> >>>>  arch/arm64/include/asm/cpufeature.h |  1 +
> >>>>  arch/arm64/kernel/cpu_errata.c      | 40 ++++++++++++++++++++++---------------
> >>>>  2 files changed, 25 insertions(+), 16 deletions(-)
> >>>>
> >>>>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h

[...]

> >>>>-	{
> >>>>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>>>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> >>>>-		.enable = enable_psci_bp_hardening,
> >>>>-	},
> >>>>-	{
> >>>>-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> >>>>-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> >>>>+		ERRATA_MIDR_RANGE_LIST(cortex_bp_harden_cpus),
> >>>
> >>>Could we just use a macro to generate multiple structs, instead of
> >>>inventing a new type of struct?
> >>
> >>We could. Somehow, I don't think we are over engineering much here.
> >
> >There is a flipside to this: I commented elsewhere that not allowing
> >mutiple match criteria per capability struct complicates verification
> >for late CPUs and/or makes it more costly.
> >
> >Your changes here do implement support for multiple match criteria,
> >albeit only for the specific case of MIDR matching.
> >
> >It could be worth generalising this in the future, but that's
> >probably not for this series.
> 
> It is not that complex, right now. See below.
> 
> >
> >OTOH, if MIDR matching is the only scenario where we have duplicate
> >cap structs with different match criteria and this patch allows all
> >those duplicates to be removed, then is there still a need to walk
> >the whole list in verify_local_cpu_features(), as introduced in
> >67948af41f2e ("arm64: capabilities: Handle duplicate entries for a
> >capability")?  Or can that now be simplified?
> 
> I have added support for this in my v2. So here is what I have done :
> 
> 1) Continue to use midr_list for capability entries that just matches
> MIDRS and share the same enable() call back.
> 
>  and
> 
> 2) Add support for wrapper entries where a capability is determined
> by two or more entries with different matches()/enable() call backs.
> 
> And that can get rid of the changes introduced in commit 67948af41f2e
> ("arm64: capabilities: Handle duplicate entries for a capability").

OK, cool.  I was presuming that might be too much work to be justified
here, but if not, great.

Cheers
---Dave

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

end of thread, other threads:[~2018-01-30 15:58 UTC | newest]

Thread overview: 134+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-23 12:27 [PATCH 00/16] arm64: Rework cpu capabilities handling Suzuki K Poulose
2018-01-23 12:27 ` Suzuki K Poulose
2018-01-23 12:27 ` [PATCH 01/16] arm64: capabilities: Update prototype for enable call back Suzuki K Poulose
2018-01-23 12:27   ` Suzuki K Poulose
2018-01-23 14:52   ` Dave Martin
2018-01-23 14:52     ` Dave Martin
2018-01-23 15:38     ` Suzuki K Poulose
2018-01-23 15:38       ` Suzuki K Poulose
2018-01-25 15:36       ` Dave Martin
2018-01-25 15:36         ` Dave Martin
2018-01-25 16:57         ` Suzuki K Poulose
2018-01-25 16:57           ` Suzuki K Poulose
2018-01-29 16:35           ` Dave Martin
2018-01-29 16:35             ` Dave Martin
2018-01-23 12:27 ` [PATCH 02/16] arm64: Move errata work around check on boot CPU Suzuki K Poulose
2018-01-23 12:27   ` Suzuki K Poulose
2018-01-23 14:59   ` Dave Martin
2018-01-23 14:59     ` Dave Martin
2018-01-23 15:07     ` Suzuki K Poulose
2018-01-23 15:07       ` Suzuki K Poulose
2018-01-23 15:11       ` Dave Martin
2018-01-23 15:11         ` Dave Martin
2018-01-23 12:27 ` [PATCH 03/16] arm64: Move errata capability processing code Suzuki K Poulose
2018-01-23 12:27   ` Suzuki K Poulose
2018-01-23 12:27 ` [PATCH 04/16] arm64: capabilities: Prepare for fine grained capabilities Suzuki K Poulose
2018-01-23 12:27   ` Suzuki K Poulose
2018-01-23 17:33   ` Dave Martin
2018-01-23 17:33     ` Dave Martin
2018-01-24 18:45     ` Suzuki K Poulose
2018-01-24 18:45       ` Suzuki K Poulose
2018-01-25 13:43       ` Dave Martin
2018-01-25 13:43         ` Dave Martin
2018-01-25 17:08         ` Suzuki K Poulose
2018-01-25 17:08           ` Suzuki K Poulose
2018-01-25 17:38           ` Dave Martin
2018-01-25 17:38             ` Dave Martin
2018-01-25 17:33   ` Dave Martin
2018-01-25 17:33     ` Dave Martin
2018-01-25 17:56     ` Suzuki K Poulose
2018-01-25 17:56       ` Suzuki K Poulose
2018-01-26 10:00       ` Dave Martin
2018-01-26 10:00         ` Dave Martin
2018-01-26 12:13         ` Suzuki K Poulose
2018-01-26 12:13           ` Suzuki K Poulose
2018-01-23 12:27 ` [PATCH 05/16] arm64: Add flags to check the safety of a capability for late CPU Suzuki K Poulose
2018-01-23 12:27   ` Suzuki K Poulose
2018-01-26 10:10   ` Dave Martin
2018-01-26 10:10     ` Dave Martin
2018-01-30 11:17     ` Suzuki K Poulose
2018-01-30 11:17       ` Suzuki K Poulose
2018-01-30 14:56       ` Dave Martin
2018-01-30 14:56         ` Dave Martin
2018-01-30 15:06         ` Suzuki K Poulose
2018-01-30 15:06           ` Suzuki K Poulose
2018-01-23 12:27 ` [PATCH 06/16] arm64: capabilities: Unify the verification Suzuki K Poulose
2018-01-23 12:27   ` Suzuki K Poulose
2018-01-26 11:08   ` Dave Martin
2018-01-26 11:08     ` Dave Martin
2018-01-26 12:10     ` Suzuki K Poulose
2018-01-26 12:10       ` Suzuki K Poulose
2018-01-29 16:57       ` Dave Martin
2018-01-29 16:57         ` Dave Martin
2018-01-23 12:28 ` [PATCH 07/16] arm64: capabilities: Filter the entries based on a given type Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 11:22   ` Dave Martin
2018-01-26 11:22     ` Dave Martin
2018-01-26 12:21     ` Suzuki K Poulose
2018-01-26 12:21       ` Suzuki K Poulose
2018-01-29 17:06       ` Dave Martin
2018-01-29 17:06         ` Dave Martin
2018-01-23 12:28 ` [PATCH 08/16] arm64: capabilities: Group handling of features and errata Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 11:47   ` Dave Martin
2018-01-26 11:47     ` Dave Martin
2018-01-26 12:31     ` Suzuki K Poulose
2018-01-26 12:31       ` Suzuki K Poulose
2018-01-29 17:14       ` Dave Martin
2018-01-29 17:14         ` Dave Martin
2018-01-29 17:22         ` Suzuki K Poulose
2018-01-29 17:22           ` Suzuki K Poulose
2018-01-30 15:06           ` Dave Martin
2018-01-30 15:06             ` Dave Martin
2018-01-23 12:28 ` [PATCH 09/16] arm64: capabilities: Introduce strict features based on local CPU Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 12:12   ` Dave Martin
2018-01-26 12:12     ` Dave Martin
2018-01-30 11:25     ` Suzuki K Poulose
2018-01-30 11:25       ` Suzuki K Poulose
2018-01-23 12:28 ` [PATCH 10/16] arm64: Make KPTI strict CPU local feature Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 12:25   ` Dave Martin
2018-01-26 12:25     ` Dave Martin
2018-01-26 15:46     ` Suzuki K Poulose
2018-01-26 15:46       ` Suzuki K Poulose
2018-01-29 17:24       ` Dave Martin
2018-01-29 17:24         ` Dave Martin
2018-01-23 12:28 ` [PATCH 11/16] arm64: errata: Clean up midr range helpers Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 13:50   ` Dave Martin
2018-01-26 13:50     ` Dave Martin
2018-01-23 12:28 ` [PATCH 12/16] arm64: Add helpers for checking CPU MIDR against a range Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 14:08   ` Dave Martin
2018-01-26 14:08     ` Dave Martin
2018-01-23 12:28 ` [PATCH 13/16] arm64: Add support for checking errata based on a list of MIDRS Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 14:16   ` Dave Martin
2018-01-26 14:16     ` Dave Martin
2018-01-26 15:57     ` Suzuki K Poulose
2018-01-26 15:57       ` Suzuki K Poulose
2018-01-30 15:16       ` Dave Martin
2018-01-30 15:16         ` Dave Martin
2018-01-30 15:38         ` Suzuki K Poulose
2018-01-30 15:38           ` Suzuki K Poulose
2018-01-30 15:58           ` Dave Martin
2018-01-30 15:58             ` Dave Martin
2018-01-23 12:28 ` [PATCH 14/16] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35 Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-23 12:28 ` [PATCH 15/16] arm64: Delay enabling hardware DBM feature Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 14:41   ` Dave Martin
2018-01-26 14:41     ` Dave Martin
2018-01-26 16:05     ` Suzuki K Poulose
2018-01-26 16:05       ` Suzuki K Poulose
2018-01-30 15:22       ` Dave Martin
2018-01-30 15:22         ` Dave Martin
2018-01-23 12:28 ` [PATCH 16/16] arm64: Add work around for Arm Cortex-A55 Erratum 1024718 Suzuki K Poulose
2018-01-23 12:28   ` Suzuki K Poulose
2018-01-26 15:33   ` Dave Martin
2018-01-26 15:33     ` Dave Martin
2018-01-26 16:29     ` Suzuki K Poulose
2018-01-26 16:29       ` Suzuki K Poulose
2018-01-30 15:27       ` Dave Martin
2018-01-30 15:27         ` Dave Martin

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.