All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/20] arm64: Rework cpu capabilities handling
@ 2018-01-31 18:27 ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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.

The series also gets rid of duplicate entries for a single capability
by introducing a wrapper entry which takes care of managing a list
of entries with distinct matches/enable pair.

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.

Changes since V1
 - Pickup almost all suggestions by Dave.
 - Rename flags for handling conflicts
 - Rename the "enable" call back to cpu_enable
 - Update prototype for cpu_enable to void.
 - Handle capabilities with multiple table entries, simplifying the
   core logic.
 - Add capabilities based on Boot CPU.
 - Change the type for BP Hardening to accept late CPUs.
 - More usersfor midr_range list.
 - More commentary in the code.
 - Flip type of Software prefetching capability to Weak from Strict.


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

Suzuki K Poulose (19):
  arm64: capabilities: Move errata work around check on boot CPU
  arm64: capabilities: Move errata processing code
  arm64: capabilities: Prepare for fine grained capabilities
  arm64: capabilities: Add flags to handle the conflicts on late CPU
  arm64: capabilities: Unify the verification
  arm64: capabilities: Filter the entries based on a given mask
  arm64: capabilities: Group handling of features and errata
  arm64: capabilities: Introduce weak features based on local CPU
  arm64: capabilities: Restrict KPTI detection to boot-time CPUs
  arm64: capabilities: Add support for features enabled early
  arm64: capabilities: Change scope of VHE to Boot CPU feature
  arm64: capabilities: Clean up midr range helpers
  arm64: Add helpers for checking CPU MIDR against a range
  arm64: capabilities: Add support for checks based on a list of MIDRs
  arm64: Handle shared capability entries
  arm64: bp hardening: Allow late CPUs to enable work around
  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    | 237 +++++++++++++++++++++--
 arch/arm64/include/asm/cputype.h       |  42 +++++
 arch/arm64/include/asm/fpsimd.h        |   4 +-
 arch/arm64/include/asm/processor.h     |   7 +-
 arch/arm64/include/asm/virt.h          |   6 -
 arch/arm64/kernel/cpu_errata.c         | 284 +++++++++++++++-------------
 arch/arm64/kernel/cpufeature.c         | 333 +++++++++++++++++++++++++--------
 arch/arm64/kernel/fpsimd.c             |   5 +-
 arch/arm64/kernel/smp.c                |  44 -----
 arch/arm64/kernel/traps.c              |   4 +-
 arch/arm64/mm/fault.c                  |   3 +-
 arch/arm64/mm/proc.S                   |   9 +-
 15 files changed, 702 insertions(+), 294 deletions(-)

-- 
2.14.3

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

* [PATCH v2 00/20] arm64: Rework cpu capabilities handling
@ 2018-01-31 18:27 ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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.

The series also gets rid of duplicate entries for a single capability
by introducing a wrapper entry which takes care of managing a list
of entries with distinct matches/enable pair.

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.

Changes since V1
 - Pickup almost all suggestions by Dave.
 - Rename flags for handling conflicts
 - Rename the "enable" call back to cpu_enable
 - Update prototype for cpu_enable to void.
 - Handle capabilities with multiple table entries, simplifying the
   core logic.
 - Add capabilities based on Boot CPU.
 - Change the type for BP Hardening to accept late CPUs.
 - More usersfor midr_range list.
 - More commentary in the code.
 - Flip type of Software prefetching capability to Weak from Strict.


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

Suzuki K Poulose (19):
  arm64: capabilities: Move errata work around check on boot CPU
  arm64: capabilities: Move errata processing code
  arm64: capabilities: Prepare for fine grained capabilities
  arm64: capabilities: Add flags to handle the conflicts on late CPU
  arm64: capabilities: Unify the verification
  arm64: capabilities: Filter the entries based on a given mask
  arm64: capabilities: Group handling of features and errata
  arm64: capabilities: Introduce weak features based on local CPU
  arm64: capabilities: Restrict KPTI detection to boot-time CPUs
  arm64: capabilities: Add support for features enabled early
  arm64: capabilities: Change scope of VHE to Boot CPU feature
  arm64: capabilities: Clean up midr range helpers
  arm64: Add helpers for checking CPU MIDR against a range
  arm64: capabilities: Add support for checks based on a list of MIDRs
  arm64: Handle shared capability entries
  arm64: bp hardening: Allow late CPUs to enable work around
  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    | 237 +++++++++++++++++++++--
 arch/arm64/include/asm/cputype.h       |  42 +++++
 arch/arm64/include/asm/fpsimd.h        |   4 +-
 arch/arm64/include/asm/processor.h     |   7 +-
 arch/arm64/include/asm/virt.h          |   6 -
 arch/arm64/kernel/cpu_errata.c         | 284 +++++++++++++++-------------
 arch/arm64/kernel/cpufeature.c         | 333 +++++++++++++++++++++++++--------
 arch/arm64/kernel/fpsimd.c             |   5 +-
 arch/arm64/kernel/smp.c                |  44 -----
 arch/arm64/kernel/traps.c              |   4 +-
 arch/arm64/mm/fault.c                  |   3 +-
 arch/arm64/mm/proc.S                   |   9 +-
 15 files changed, 702 insertions(+), 294 deletions(-)

-- 
2.14.3

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

* [PATCH v2 01/20] arm64: capabilities: Update prototype for enable call back
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	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. Clean up the declaration of the call back to make it clear.

 1) Renamed to cpu_enable(), to imply taking necessary actions on the
    called CPU for the entry.
 2) Pass const pointer to the capability, to allow the call back to
    check the entry. (e.,g to check if any action is needed on the CPU)
 3) We don't care about the result of the call back, turning this to
    a void.

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, rename call back,
 drop call back results
]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 ++++++-
 arch/arm64/include/asm/fpsimd.h     |  4 +++-
 arch/arm64/include/asm/processor.h  |  7 ++++---
 arch/arm64/kernel/cpu_errata.c      | 41 +++++++++++++++----------------------
 arch/arm64/kernel/cpufeature.c      | 33 ++++++++++++++++-------------
 arch/arm64/kernel/fpsimd.c          |  5 ++---
 arch/arm64/kernel/traps.c           |  4 ++--
 arch/arm64/mm/fault.c               |  3 +--
 8 files changed, 54 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index ac67cfc2585a..f46eb7d1625f 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -97,7 +97,12 @@ 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 */
+	/*
+	 * Take the appropriate actions to enable this capability for this CPU.
+	 * For each successfully booted CPU, this method is called for each
+	 * globally detected capability.
+	 */
+	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
 	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..7623762f7fa6 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 void 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..83a3d2887ca6 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);
+void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
+void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
+void 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 ed6881882231..e34bee500692 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -53,11 +53,11 @@ 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 void cpu_enable_trap_ctr_access(
+	const struct arm64_cpu_capabilities *__unused)
 {
 	/* Clear SCTLR_EL1.UCT */
 	config_sctlr_el1(SCTLR_EL1_UCT, 0);
-	return 0;
 }
 
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
@@ -144,17 +144,13 @@ 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 void 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,
 				       __psci_hyp_bp_inval_start,
 				       __psci_hyp_bp_inval_end);
-
-	return 0;
 }
 
 static void qcom_link_stack_sanitization(void)
@@ -169,15 +165,12 @@ static void qcom_link_stack_sanitization(void)
 		     : "=&r" (tmp));
 }
 
-static int qcom_enable_link_stack_sanitization(void *data)
+static void 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);
-
-	return 0;
 }
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
@@ -204,7 +197,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "ARM errata 826319, 827319, 824069",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
-		.enable = cpu_enable_cache_maint_trap,
+		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_819472
@@ -213,7 +206,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "ARM errata 819472",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
-		.enable = cpu_enable_cache_maint_trap,
+		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_832075
@@ -294,7 +287,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
 		.matches = has_mismatched_cache_line_size,
 		.def_scope = SCOPE_LOCAL_CPU,
-		.enable = cpu_enable_trap_ctr_access,
+		.cpu_enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
 	{
@@ -333,27 +326,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
-		.enable = qcom_enable_link_stack_sanitization,
+		.cpu_enable = qcom_enable_link_stack_sanitization,
 	},
 	{
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
@@ -362,12 +355,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 #endif
 	{
@@ -385,8 +378,8 @@ void verify_local_cpu_errata_workarounds(void)
 
 	for (; caps->matches; caps++) {
 		if (cpus_have_cap(caps->capability)) {
-			if (caps->enable)
-				caps->enable((void *)caps);
+			if (caps->cpu_enable)
+				caps->cpu_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 4b6f9051cf0c..0b881d9fcde2 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -894,7 +894,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 void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * Copy register values that aren't redirected by hardware.
@@ -906,8 +906,6 @@ static int cpu_copy_el2regs(void *__unused)
 	 */
 	if (!alternatives_applied)
 		write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
-
-	return 0;
 }
 
 static const struct arm64_cpu_capabilities arm64_features[] = {
@@ -931,7 +929,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
 		.sign = FTR_UNSIGNED,
 		.min_field_value = 1,
-		.enable = cpu_enable_pan,
+		.cpu_enable = cpu_enable_pan,
 	},
 #endif /* CONFIG_ARM64_PAN */
 #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
@@ -979,7 +977,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
 		.def_scope = SCOPE_SYSTEM,
 		.matches = runs_at_el2,
-		.enable = cpu_copy_el2regs,
+		.cpu_enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
@@ -1033,7 +1031,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.field_pos = ID_AA64PFR0_SVE_SHIFT,
 		.min_field_value = ID_AA64PFR0_SVE,
 		.matches = has_cpuid_feature,
-		.enable = sve_kernel_enable,
+		.cpu_enable = sve_kernel_enable,
 	},
 #endif /* CONFIG_ARM64_SVE */
 #ifdef CONFIG_ARM64_RAS_EXTN
@@ -1046,7 +1044,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.sign = FTR_UNSIGNED,
 		.field_pos = ID_AA64PFR0_RAS_SHIFT,
 		.min_field_value = ID_AA64PFR0_RAS_V1,
-		.enable = cpu_clear_disr,
+		.cpu_enable = cpu_clear_disr,
 	},
 #endif /* CONFIG_ARM64_RAS_EXTN */
 	{},
@@ -1190,6 +1188,15 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+
+static int __enable_cpu_capability(void *arg)
+{
+	const struct arm64_cpu_capabilities *cap = arg;
+
+	cap->cpu_enable(cap);
+	return 0;
+}
+
 /*
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
@@ -1205,14 +1212,14 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 		/* Ensure cpus_have_const_cap(num) works */
 		static_branch_enable(&cpu_hwcap_keys[num]);
 
-		if (caps->enable) {
+		if (caps->cpu_enable) {
 			/*
 			 * Use stop_machine() as it schedules the work allowing
 			 * us to modify PSTATE, instead of on_each_cpu() which
 			 * 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);
 		}
 	}
 }
@@ -1255,8 +1262,8 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
 					smp_processor_id(), caps->desc);
 			cpu_die_early();
 		}
-		if (caps->enable)
-			caps->enable((void *)caps);
+		if (caps->cpu_enable)
+			caps->cpu_enable(caps);
 	}
 }
 
@@ -1479,10 +1486,8 @@ static int __init enable_mrs_emulation(void)
 
 core_initcall(enable_mrs_emulation);
 
-int cpu_clear_disr(void *__unused)
+void 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);
-
-	return 0;
 }
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 55fb544072f6..35c563536b0c 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,12 +758,10 @@ 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)
+void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
 {
 	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
 	isb();
-
-	return 0;
 }
 
 void __init sve_setup(void)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index bbb0fde2780e..a2f6492b4ea3 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,10 +375,9 @@ 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)
+void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
 {
 	config_sctlr_el1(SCTLR_EL1_UCI, 0);
-	return 0;
 }
 
 #define __user_cache_maint(insn, address, res)			\
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0e671ddf4855..ccfbe979be17 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)
+void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * We modify PSTATE. This won't work from irq context as the PSTATE
@@ -823,6 +823,5 @@ int cpu_enable_pan(void *__unused)
 
 	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
 	asm(SET_PSTATE_PAN(1));
-	return 0;
 }
 #endif /* CONFIG_ARM64_PAN */
-- 
2.14.3

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

* [PATCH v2 01/20] arm64: capabilities: Update prototype for enable call back
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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. Clean up the declaration of the call back to make it clear.

 1) Renamed to cpu_enable(), to imply taking necessary actions on the
    called CPU for the entry.
 2) Pass const pointer to the capability, to allow the call back to
    check the entry. (e.,g to check if any action is needed on the CPU)
 3) We don't care about the result of the call back, turning this to
    a void.

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, rename call back,
 drop call back results
]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 ++++++-
 arch/arm64/include/asm/fpsimd.h     |  4 +++-
 arch/arm64/include/asm/processor.h  |  7 ++++---
 arch/arm64/kernel/cpu_errata.c      | 41 +++++++++++++++----------------------
 arch/arm64/kernel/cpufeature.c      | 33 ++++++++++++++++-------------
 arch/arm64/kernel/fpsimd.c          |  5 ++---
 arch/arm64/kernel/traps.c           |  4 ++--
 arch/arm64/mm/fault.c               |  3 +--
 8 files changed, 54 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index ac67cfc2585a..f46eb7d1625f 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -97,7 +97,12 @@ 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 */
+	/*
+	 * Take the appropriate actions to enable this capability for this CPU.
+	 * For each successfully booted CPU, this method is called for each
+	 * globally detected capability.
+	 */
+	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
 	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..7623762f7fa6 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 void 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..83a3d2887ca6 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);
+void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
+void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
+void 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 ed6881882231..e34bee500692 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -53,11 +53,11 @@ 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 void cpu_enable_trap_ctr_access(
+	const struct arm64_cpu_capabilities *__unused)
 {
 	/* Clear SCTLR_EL1.UCT */
 	config_sctlr_el1(SCTLR_EL1_UCT, 0);
-	return 0;
 }
 
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
@@ -144,17 +144,13 @@ 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 void 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,
 				       __psci_hyp_bp_inval_start,
 				       __psci_hyp_bp_inval_end);
-
-	return 0;
 }
 
 static void qcom_link_stack_sanitization(void)
@@ -169,15 +165,12 @@ static void qcom_link_stack_sanitization(void)
 		     : "=&r" (tmp));
 }
 
-static int qcom_enable_link_stack_sanitization(void *data)
+static void 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);
-
-	return 0;
 }
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
@@ -204,7 +197,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "ARM errata 826319, 827319, 824069",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
-		.enable = cpu_enable_cache_maint_trap,
+		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_819472
@@ -213,7 +206,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "ARM errata 819472",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
-		.enable = cpu_enable_cache_maint_trap,
+		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_832075
@@ -294,7 +287,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
 		.matches = has_mismatched_cache_line_size,
 		.def_scope = SCOPE_LOCAL_CPU,
-		.enable = cpu_enable_trap_ctr_access,
+		.cpu_enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
 	{
@@ -333,27 +326,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
-		.enable = qcom_enable_link_stack_sanitization,
+		.cpu_enable = qcom_enable_link_stack_sanitization,
 	},
 	{
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
@@ -362,12 +355,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
-		.enable = enable_psci_bp_hardening,
+		.cpu_enable = enable_psci_bp_hardening,
 	},
 #endif
 	{
@@ -385,8 +378,8 @@ void verify_local_cpu_errata_workarounds(void)
 
 	for (; caps->matches; caps++) {
 		if (cpus_have_cap(caps->capability)) {
-			if (caps->enable)
-				caps->enable((void *)caps);
+			if (caps->cpu_enable)
+				caps->cpu_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 4b6f9051cf0c..0b881d9fcde2 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -894,7 +894,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 void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * Copy register values that aren't redirected by hardware.
@@ -906,8 +906,6 @@ static int cpu_copy_el2regs(void *__unused)
 	 */
 	if (!alternatives_applied)
 		write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
-
-	return 0;
 }
 
 static const struct arm64_cpu_capabilities arm64_features[] = {
@@ -931,7 +929,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
 		.sign = FTR_UNSIGNED,
 		.min_field_value = 1,
-		.enable = cpu_enable_pan,
+		.cpu_enable = cpu_enable_pan,
 	},
 #endif /* CONFIG_ARM64_PAN */
 #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
@@ -979,7 +977,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
 		.def_scope = SCOPE_SYSTEM,
 		.matches = runs_at_el2,
-		.enable = cpu_copy_el2regs,
+		.cpu_enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
@@ -1033,7 +1031,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.field_pos = ID_AA64PFR0_SVE_SHIFT,
 		.min_field_value = ID_AA64PFR0_SVE,
 		.matches = has_cpuid_feature,
-		.enable = sve_kernel_enable,
+		.cpu_enable = sve_kernel_enable,
 	},
 #endif /* CONFIG_ARM64_SVE */
 #ifdef CONFIG_ARM64_RAS_EXTN
@@ -1046,7 +1044,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.sign = FTR_UNSIGNED,
 		.field_pos = ID_AA64PFR0_RAS_SHIFT,
 		.min_field_value = ID_AA64PFR0_RAS_V1,
-		.enable = cpu_clear_disr,
+		.cpu_enable = cpu_clear_disr,
 	},
 #endif /* CONFIG_ARM64_RAS_EXTN */
 	{},
@@ -1190,6 +1188,15 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+
+static int __enable_cpu_capability(void *arg)
+{
+	const struct arm64_cpu_capabilities *cap = arg;
+
+	cap->cpu_enable(cap);
+	return 0;
+}
+
 /*
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
@@ -1205,14 +1212,14 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 		/* Ensure cpus_have_const_cap(num) works */
 		static_branch_enable(&cpu_hwcap_keys[num]);
 
-		if (caps->enable) {
+		if (caps->cpu_enable) {
 			/*
 			 * Use stop_machine() as it schedules the work allowing
 			 * us to modify PSTATE, instead of on_each_cpu() which
 			 * 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);
 		}
 	}
 }
@@ -1255,8 +1262,8 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
 					smp_processor_id(), caps->desc);
 			cpu_die_early();
 		}
-		if (caps->enable)
-			caps->enable((void *)caps);
+		if (caps->cpu_enable)
+			caps->cpu_enable(caps);
 	}
 }
 
@@ -1479,10 +1486,8 @@ static int __init enable_mrs_emulation(void)
 
 core_initcall(enable_mrs_emulation);
 
-int cpu_clear_disr(void *__unused)
+void 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);
-
-	return 0;
 }
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 55fb544072f6..35c563536b0c 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,12 +758,10 @@ 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)
+void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
 {
 	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
 	isb();
-
-	return 0;
 }
 
 void __init sve_setup(void)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index bbb0fde2780e..a2f6492b4ea3 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,10 +375,9 @@ 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)
+void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
 {
 	config_sctlr_el1(SCTLR_EL1_UCI, 0);
-	return 0;
 }
 
 #define __user_cache_maint(insn, address, res)			\
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0e671ddf4855..ccfbe979be17 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)
+void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
 	 * We modify PSTATE. This won't work from irq context as the PSTATE
@@ -823,6 +823,5 @@ int cpu_enable_pan(void *__unused)
 
 	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
 	asm(SET_PSTATE_PAN(1));
-	return 0;
 }
 #endif /* CONFIG_ARM64_PAN */
-- 
2.14.3

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

* [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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. While this
is correct, we can also do this from init_cpu_features() which
initilisation of the infrastructure, and is called only on the
Boot CPU. This helps to consolidate the CPU capability handling
to cpufeature.c. No functional changes.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
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 0b881d9fcde2..ef3cc48bc925 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.14.3

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

* [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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. While this
is correct, we can also do this from init_cpu_features() which
initilisation of the infrastructure, and is called only on the
Boot CPU. This helps to consolidate the CPU capability handling
to cpufeature.c. No functional changes.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
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 0b881d9fcde2..ef3cc48bc925 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.14.3

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

* [PATCH v2 03/20] arm64: capabilities: Move errata processing code
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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 code.
No functional changes.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
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 f46eb7d1625f..7925e40c6ded 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -238,15 +238,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 e34bee500692..9de0ee5d73c0 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -366,36 +366,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->cpu_enable)
-				caps->cpu_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 ef3cc48bc925..f0cd165c75e9 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 */
@@ -1181,7 +1184,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++) {
@@ -1207,7 +1210,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;
@@ -1290,6 +1293,39 @@ static void verify_sve_features(void)
 	/* Add checks on other ZCR bits here if necessary */
 }
 
+/*
+ * 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->cpu_enable)
+				caps->cpu_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.
-- 
2.14.3

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

* [PATCH v2 03/20] arm64: capabilities: Move errata processing code
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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 code.
No functional changes.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
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 f46eb7d1625f..7925e40c6ded 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -238,15 +238,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 e34bee500692..9de0ee5d73c0 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -366,36 +366,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->cpu_enable)
-				caps->cpu_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 ef3cc48bc925..f0cd165c75e9 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 */
@@ -1181,7 +1184,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++) {
@@ -1207,7 +1210,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;
@@ -1290,6 +1293,39 @@ static void verify_sve_features(void)
 	/* Add checks on other ZCR bits here if necessary */
 }
 
+/*
+ * 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->cpu_enable)
+				caps->cpu_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.
-- 
2.14.3

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

* [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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. Capabilities
have some properties that decide how they should be treated :

 1) Detection, i.e scope : A cap could be "detected" either :
    - if it is present on at least one CPU (SCOPE_LOCAL_CPU)
	Or
    - if it is present on all the CPUs (SCOPE_SYSTEM)

 2) When is it enabled ? - A cap is treated as "enabled" when the
  system takes some action based on whether the capability is detected or
  not. e.g, setting some control register, patching the kernel code.
  Right now, we treat all caps are enabled at boot-time, after all
  the CPUs are brought up by the kernel. But there are certain caps,
  which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
  and kernel starts using them, even before the secondary CPUs are brought
  up. We would need a way to describe this for each capability.

 3) Conflict on a late CPU - When a CPU is brought up, it is checked
  against the caps that are known to be enabled on the system (via
  verify_local_cpu_capabilities()). Based on the state of the capability
  on the CPU vs. that of System we could have the following combinations
  of conflict.

	x-----------------------------x
	| Type	| System   | Late CPU |
	------------------------------|
	|  a    |   y      |    n     |
	------------------------------|
	|  b    |   n      |    y     |
	x-----------------------------x

  Case (a) is not permitted for caps which are system features, which the
  system expects all the CPUs to have (e.g VHE). While (a) is ignored for
  all errata work arounds. However, there could be exceptions to the plain
  filtering approach. e.g, KPTI is an optional feature for a late CPU as
  long as the system already enables it.

  Case (b) is not permitted for errata work arounds which requires some
  work around, which cannot be delayed. And we ignore (b) for features. Here,
  yet again, KPTI is an exception, where if a late CPU needs KPTI we are too
  late to enable it (because we change the allocation of ASIDs etc).

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 (which cover
errata and features, not the ELF HWCAPs). This is a prepartory step
to get there. More bits would be added for the properties listed above.

We are going to use a bit-mask to encode all the properties of a capabilities.
This patch encodes the "SCOPE" of the capability.

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

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

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7925e40c6ded..05da54f1b4c7 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -86,16 +86,89 @@ struct arm64_ftr_reg {
 
 extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 
-/* scope of capability check */
-enum {
-	SCOPE_SYSTEM,
-	SCOPE_LOCAL_CPU,
-};
+/*
+ * CPU capabilities:
+ *
+ * We use arm64_cpu_capabilities to represent system features, errata work
+ * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
+ * ELF HWCAPs (which are exposed to user).
+ *
+ * To support systems with heterogeneous CPUs, we need to make sure that we
+ * detect the capabilities correctly on the system and take appropriate
+ * measures to ensure there are not incompatibilities.
+ *
+ * This comment tries to explain how we treat the capabilities.
+ * Each capability has the following list of attributes :
+ *
+ * 1) Scope of Detection : The system detects a given capability by performing
+ *    some checks at runtime. This could be, e.g, checking the value of a field
+ *    in CPU ID feature register or checking the cpu model. The capability
+ *    provides a call back ( @matches() ) to perform the check.
+ *    Scope defines how the checks should be performed. There are two cases:
+ *
+ *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
+ *        matches. This implies, we have to run the check on all the booting
+ *        CPUs, until the system decides that state of the capability is finalised.
+ *        (See section 2 below)
+ *		Or
+ *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
+ *        This implies, we run the check only once, when the system decides to
+ *        finalise the state of the capability. If the capability relies on a
+ *        field in one of the CPU ID feature registers, we use the sanitised
+ *        value of the register from the CPU feature infrastructure to make
+ *        the decision.
+ *    The process of detection is usually denoted by "update" capability state
+ *    in the code.
+ *
+ * 2) Finalise the state : The kernel should finalise the state of a capability
+ *    at some point during its execution and take necessary actions if any. Usually,
+ *    this is done, after all the boot-time enabled CPUs are brought up by the
+ *    kernel, so that it can make better decision based on the available set
+ *    of CPUs. However, there are some special cases, where the action is taken
+ *    during the early boot by the primary boot CPU. (e.g, running the kernel at
+ *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
+ *    any changes to the state of a capability once it finalises the capability
+ *    and takes any action, as it may be impossible to execute the actions safely.
+ *
+ * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
+ *    the kernel should make sure that it is safe to use the CPU, by verifying
+ *    that the CPU is compliant with the state of the capabilities established
+ *    already. This happens via :
+ *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
+ *      check_early_cpu_features() && verify_local_cpu_capabilities()
+ *
+ *    As explained in (2) above, capabilities could be finalised at different
+ *    points in the execution. Each CPU is verified against the "finalised"
+ *    capabilities and if there is a conflict, the kernel takes an action, based
+ *    on the severity (e.g, a CPU could be prevented from booting or cause a
+ *    kernel panic). The CPU is allowed to "affect" the state of the capability,
+ *    if it has not been finalised already.
+ *
+ * 4) Action: As mentioned in (2), the kernel can take an action for each detected
+ *    capability, on all CPUs on the system. This is always initiated only after
+ *    the capability is finalised. This is usally denoted by "enabling" the
+ *    capability. The actions are initiated as follows :
+ *	a) Action is triggered on all online CPUs, after the capability is
+ *	finalised, invoked within the stop_machine() context from
+ *	enable_cpu_capabilitie().
+ *
+ *	b) Any late CPU, brought up after (1), the action is triggered via:
+ *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
+ *
+ */
+
+
+/* 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		((u16)BIT(0))
+#define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
+#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
+#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
 
 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);
 	/*
 	 * Take the appropriate actions to enable this capability for this CPU.
@@ -120,6 +193,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 9de0ee5d73c0..328c5a031e45 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
-	.def_scope = SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
 	.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_SCOPE_LOCAL_CPU, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = 0, \
@@ -286,7 +286,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_SCOPE_LOCAL_CPU,
 		.cpu_enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -300,7 +300,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_SCOPE_LOCAL_CPU,
 		.midr_model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f0cd165c75e9..8d22f0ef0927 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -921,7 +921,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_SCOPE_SYSTEM,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -945,7 +945,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_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -956,14 +956,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_SCOPE_SYSTEM,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -977,21 +977,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_SCOPE_SYSTEM,
 		.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_SCOPE_SYSTEM,
 		.matches = runs_at_el2,
 		.cpu_enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
 		.capability = ARM64_HAS_32BIT_EL0,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1001,21 +1001,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_SCOPE_SYSTEM,
 		.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_SCOPE_SYSTEM,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1023,7 +1023,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_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR1_EL1,
 		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
@@ -1033,8 +1033,8 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_SVE
 	{
 		.desc = "Scalable Vector Extension",
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.capability = ARM64_SVE,
-		.def_scope = SCOPE_SYSTEM,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
 		.field_pos = ID_AA64PFR0_SVE_SHIFT,
@@ -1047,7 +1047,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_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1059,16 +1059,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_SCOPE_SYSTEM,		\
 		.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,					\
 	}
 
@@ -1161,7 +1161,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);
 }
 
@@ -1188,7 +1188,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.14.3

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

* [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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. Capabilities
have some properties that decide how they should be treated :

 1) Detection, i.e scope : A cap could be "detected" either :
    - if it is present on at least one CPU (SCOPE_LOCAL_CPU)
	Or
    - if it is present on all the CPUs (SCOPE_SYSTEM)

 2) When is it enabled ? - A cap is treated as "enabled" when the
  system takes some action based on whether the capability is detected or
  not. e.g, setting some control register, patching the kernel code.
  Right now, we treat all caps are enabled at boot-time, after all
  the CPUs are brought up by the kernel. But there are certain caps,
  which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
  and kernel starts using them, even before the secondary CPUs are brought
  up. We would need a way to describe this for each capability.

 3) Conflict on a late CPU - When a CPU is brought up, it is checked
  against the caps that are known to be enabled on the system (via
  verify_local_cpu_capabilities()). Based on the state of the capability
  on the CPU vs. that of System we could have the following combinations
  of conflict.

	x-----------------------------x
	| Type	| System   | Late CPU |
	------------------------------|
	|  a    |   y      |    n     |
	------------------------------|
	|  b    |   n      |    y     |
	x-----------------------------x

  Case (a) is not permitted for caps which are system features, which the
  system expects all the CPUs to have (e.g VHE). While (a) is ignored for
  all errata work arounds. However, there could be exceptions to the plain
  filtering approach. e.g, KPTI is an optional feature for a late CPU as
  long as the system already enables it.

  Case (b) is not permitted for errata work arounds which requires some
  work around, which cannot be delayed. And we ignore (b) for features. Here,
  yet again, KPTI is an exception, where if a late CPU needs KPTI we are too
  late to enable it (because we change the allocation of ASIDs etc).

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 (which cover
errata and features, not the ELF HWCAPs). This is a prepartory step
to get there. More bits would be added for the properties listed above.

We are going to use a bit-mask to encode all the properties of a capabilities.
This patch encodes the "SCOPE" of the capability.

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

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

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7925e40c6ded..05da54f1b4c7 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -86,16 +86,89 @@ struct arm64_ftr_reg {
 
 extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 
-/* scope of capability check */
-enum {
-	SCOPE_SYSTEM,
-	SCOPE_LOCAL_CPU,
-};
+/*
+ * CPU capabilities:
+ *
+ * We use arm64_cpu_capabilities to represent system features, errata work
+ * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
+ * ELF HWCAPs (which are exposed to user).
+ *
+ * To support systems with heterogeneous CPUs, we need to make sure that we
+ * detect the capabilities correctly on the system and take appropriate
+ * measures to ensure there are not incompatibilities.
+ *
+ * This comment tries to explain how we treat the capabilities.
+ * Each capability has the following list of attributes :
+ *
+ * 1) Scope of Detection : The system detects a given capability by performing
+ *    some checks at runtime. This could be, e.g, checking the value of a field
+ *    in CPU ID feature register or checking the cpu model. The capability
+ *    provides a call back ( @matches() ) to perform the check.
+ *    Scope defines how the checks should be performed. There are two cases:
+ *
+ *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
+ *        matches. This implies, we have to run the check on all the booting
+ *        CPUs, until the system decides that state of the capability is finalised.
+ *        (See section 2 below)
+ *		Or
+ *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
+ *        This implies, we run the check only once, when the system decides to
+ *        finalise the state of the capability. If the capability relies on a
+ *        field in one of the CPU ID feature registers, we use the sanitised
+ *        value of the register from the CPU feature infrastructure to make
+ *        the decision.
+ *    The process of detection is usually denoted by "update" capability state
+ *    in the code.
+ *
+ * 2) Finalise the state : The kernel should finalise the state of a capability
+ *    at some point during its execution and take necessary actions if any. Usually,
+ *    this is done, after all the boot-time enabled CPUs are brought up by the
+ *    kernel, so that it can make better decision based on the available set
+ *    of CPUs. However, there are some special cases, where the action is taken
+ *    during the early boot by the primary boot CPU. (e.g, running the kernel at
+ *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
+ *    any changes to the state of a capability once it finalises the capability
+ *    and takes any action, as it may be impossible to execute the actions safely.
+ *
+ * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
+ *    the kernel should make sure that it is safe to use the CPU, by verifying
+ *    that the CPU is compliant with the state of the capabilities established
+ *    already. This happens via :
+ *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
+ *      check_early_cpu_features() && verify_local_cpu_capabilities()
+ *
+ *    As explained in (2) above, capabilities could be finalised at different
+ *    points in the execution. Each CPU is verified against the "finalised"
+ *    capabilities and if there is a conflict, the kernel takes an action, based
+ *    on the severity (e.g, a CPU could be prevented from booting or cause a
+ *    kernel panic). The CPU is allowed to "affect" the state of the capability,
+ *    if it has not been finalised already.
+ *
+ * 4) Action: As mentioned in (2), the kernel can take an action for each detected
+ *    capability, on all CPUs on the system. This is always initiated only after
+ *    the capability is finalised. This is usally denoted by "enabling" the
+ *    capability. The actions are initiated as follows :
+ *	a) Action is triggered on all online CPUs, after the capability is
+ *	finalised, invoked within the stop_machine() context from
+ *	enable_cpu_capabilitie().
+ *
+ *	b) Any late CPU, brought up after (1), the action is triggered via:
+ *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
+ *
+ */
+
+
+/* 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		((u16)BIT(0))
+#define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
+#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
+#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
 
 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);
 	/*
 	 * Take the appropriate actions to enable this capability for this CPU.
@@ -120,6 +193,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 9de0ee5d73c0..328c5a031e45 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
-	.def_scope = SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
 	.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_SCOPE_LOCAL_CPU, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = 0, \
@@ -286,7 +286,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_SCOPE_LOCAL_CPU,
 		.cpu_enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -300,7 +300,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_SCOPE_LOCAL_CPU,
 		.midr_model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f0cd165c75e9..8d22f0ef0927 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -921,7 +921,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_SCOPE_SYSTEM,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -945,7 +945,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_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -956,14 +956,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_SCOPE_SYSTEM,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -977,21 +977,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_SCOPE_SYSTEM,
 		.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_SCOPE_SYSTEM,
 		.matches = runs_at_el2,
 		.cpu_enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
 		.capability = ARM64_HAS_32BIT_EL0,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1001,21 +1001,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_SCOPE_SYSTEM,
 		.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_SCOPE_SYSTEM,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.def_scope = SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1023,7 +1023,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_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR1_EL1,
 		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
@@ -1033,8 +1033,8 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_SVE
 	{
 		.desc = "Scalable Vector Extension",
+		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
 		.capability = ARM64_SVE,
-		.def_scope = SCOPE_SYSTEM,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
 		.field_pos = ID_AA64PFR0_SVE_SHIFT,
@@ -1047,7 +1047,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_SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1059,16 +1059,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_SCOPE_SYSTEM,		\
 		.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,					\
 	}
 
@@ -1161,7 +1161,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);
 }
 
@@ -1188,7 +1188,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.14.3

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

* [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

When a CPU is brought up, it is checked against the caps that are
known to be enabled on the system (via verify_local_cpu_capabilities()).
Based on the state of the capability on the CPU vs. that of System we
could have the following combinations of conflict.

	x-----------------------------x
	| Type  | System   | Late CPU |
	|-----------------------------|
	|  a    |   y      |    n     |
	|-----------------------------|
	|  b    |   n      |    y     |
	x-----------------------------x

Case (a) is not permitted for caps which are system features, which the
system expects all the CPUs to have (e.g VHE). While (a) is ignored for
all errata work arounds. However, there could be exceptions to the plain
filtering approach. e.g, KPTI is an optional feature for a late CPU as
long as the system already enables it.

Case (b) is not permitted for errata work arounds which requires some work
around, which cannot be delayed. And we ignore (b) for features. Here, yet
again, KPTI is an exception, where if a late CPU needs KPTI we are too late
to enable it (because we change the allocation of ASIDs etc).

Add two different flags to indicate how the conflict should be handled.

 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - CPUs may have the capability
 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - CPUs may not have the cappability.

Now that we have the flags to describe the behavior of the errata and
the features, as we treat them, define types for ERRATUM and FEATURE.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 61 ++++++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/cpu_errata.c      |  8 ++---
 arch/arm64/kernel/cpufeature.c      | 30 +++++++++---------
 3 files changed, 79 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 05da54f1b4c7..7460b1f7e611 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -142,7 +142,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *    capabilities and if there is a conflict, the kernel takes an action, based
  *    on the severity (e.g, a CPU could be prevented from booting or cause a
  *    kernel panic). The CPU is allowed to "affect" the state of the capability,
- *    if it has not been finalised already.
+ *    if it has not been finalised already. See section 5 for more details on
+ *    conflicts.
  *
  * 4) Action: As mentioned in (2), the kernel can take an action for each detected
  *    capability, on all CPUs on the system. This is always initiated only after
@@ -155,6 +156,32 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *	b) Any late CPU, brought up after (1), the action is triggered via:
  *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
  *
+ * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
+ *    state, we could have the following combinations :
+ *
+ *		x-----------------------------x
+ *		| Type  | System   | Late CPU |
+ *		|-----------------------------|
+ *		|  a    |   y      |    n     |
+ *		|-----------------------------|
+ *		|  b    |   n      |    y     |
+ *		x-----------------------------x
+ *
+ *     Case (a) is not permitted for capabilities which are usually system
+ *     features, which the system expects all CPUs to have. While (a) is ignored
+ *     for capabilities which represents an erratum work around.
+ *
+ *     Case (b) is not permitted for erratum capabilities, which might require
+ *     some work arounds which cannot be applied really late. Meanwhile, most
+ *     of the features could safely ignore (b), as the system doesn't use it
+ *     anyway.
+ *
+ *     However, there are some exceptions to the assumptions and require each
+ *     capability to define how the conflict should be addressed. So we use two
+ *     separate flag bits to indicate whether the above cases should be treated
+ *     as conflicts:
+ *		ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case(a) is safe
+ *		ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case(b) is safe
  */
 
 
@@ -165,6 +192,26 @@ 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
 
+/* Is it permitted for a late CPU to have this capability when system doesn't already have */
+#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
+/* Is it safe for a late CPU to miss this capability when system has it */
+#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
+
+/*
+ * 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_LOCAL_CPU_ERRATUM		\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
+/*
+ * 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_SYSTEM_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
@@ -198,6 +245,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_optional(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
+}
+
+static inline bool
+cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
+}
+
 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 328c5a031e45..22ec3960a0c5 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
-	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = min, \
 	.midr_range_max = max
 
 #define MIDR_ALL_VERSIONS(model) \
-	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = 0, \
@@ -286,7 +286,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,
-		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
 		.cpu_enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -300,7 +300,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
-		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_LOCAL_CPU_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 8d22f0ef0927..1b29b3f0a1bc 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -921,7 +921,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
 		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -945,7 +945,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "LSE atomic instructions",
 		.capability = ARM64_HAS_LSE_ATOMICS,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -956,14 +956,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -977,21 +977,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_PAN
 	{
 		.capability = ARM64_ALT_PAN_NOT_UAO,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = cpufeature_pan_not_uao,
 	},
 #endif /* CONFIG_ARM64_PAN */
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = runs_at_el2,
 		.cpu_enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
 		.capability = ARM64_HAS_32BIT_EL0,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1001,21 +1001,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Reduced HYP mapping offset",
 		.capability = ARM64_HYP_OFFSET_LOW,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = hyp_offset_low,
 	},
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1023,7 +1023,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Data cache clean to Point of Persistence",
 		.capability = ARM64_HAS_DCPOP,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR1_EL1,
 		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
@@ -1033,7 +1033,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_SVE
 	{
 		.desc = "Scalable Vector Extension",
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.capability = ARM64_SVE,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1047,7 +1047,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "RAS Extension Support",
 		.capability = ARM64_HAS_RAS_EXTN,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1062,7 +1062,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
 	{							\
 		.desc = #cap,					\
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,		\
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
 		.matches = has_cpuid_feature,			\
 		.sys_reg = reg,					\
 		.field_pos = field,				\
-- 
2.14.3

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

* [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

When a CPU is brought up, it is checked against the caps that are
known to be enabled on the system (via verify_local_cpu_capabilities()).
Based on the state of the capability on the CPU vs. that of System we
could have the following combinations of conflict.

	x-----------------------------x
	| Type  | System   | Late CPU |
	|-----------------------------|
	|  a    |   y      |    n     |
	|-----------------------------|
	|  b    |   n      |    y     |
	x-----------------------------x

Case (a) is not permitted for caps which are system features, which the
system expects all the CPUs to have (e.g VHE). While (a) is ignored for
all errata work arounds. However, there could be exceptions to the plain
filtering approach. e.g, KPTI is an optional feature for a late CPU as
long as the system already enables it.

Case (b) is not permitted for errata work arounds which requires some work
around, which cannot be delayed. And we ignore (b) for features. Here, yet
again, KPTI is an exception, where if a late CPU needs KPTI we are too late
to enable it (because we change the allocation of ASIDs etc).

Add two different flags to indicate how the conflict should be handled.

 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - CPUs may have the capability
 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - CPUs may not have the cappability.

Now that we have the flags to describe the behavior of the errata and
the features, as we treat them, define types for ERRATUM and FEATURE.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 61 ++++++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/cpu_errata.c      |  8 ++---
 arch/arm64/kernel/cpufeature.c      | 30 +++++++++---------
 3 files changed, 79 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 05da54f1b4c7..7460b1f7e611 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -142,7 +142,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *    capabilities and if there is a conflict, the kernel takes an action, based
  *    on the severity (e.g, a CPU could be prevented from booting or cause a
  *    kernel panic). The CPU is allowed to "affect" the state of the capability,
- *    if it has not been finalised already.
+ *    if it has not been finalised already. See section 5 for more details on
+ *    conflicts.
  *
  * 4) Action: As mentioned in (2), the kernel can take an action for each detected
  *    capability, on all CPUs on the system. This is always initiated only after
@@ -155,6 +156,32 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *	b) Any late CPU, brought up after (1), the action is triggered via:
  *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
  *
+ * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
+ *    state, we could have the following combinations :
+ *
+ *		x-----------------------------x
+ *		| Type  | System   | Late CPU |
+ *		|-----------------------------|
+ *		|  a    |   y      |    n     |
+ *		|-----------------------------|
+ *		|  b    |   n      |    y     |
+ *		x-----------------------------x
+ *
+ *     Case (a) is not permitted for capabilities which are usually system
+ *     features, which the system expects all CPUs to have. While (a) is ignored
+ *     for capabilities which represents an erratum work around.
+ *
+ *     Case (b) is not permitted for erratum capabilities, which might require
+ *     some work arounds which cannot be applied really late. Meanwhile, most
+ *     of the features could safely ignore (b), as the system doesn't use it
+ *     anyway.
+ *
+ *     However, there are some exceptions to the assumptions and require each
+ *     capability to define how the conflict should be addressed. So we use two
+ *     separate flag bits to indicate whether the above cases should be treated
+ *     as conflicts:
+ *		ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case(a) is safe
+ *		ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case(b) is safe
  */
 
 
@@ -165,6 +192,26 @@ 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
 
+/* Is it permitted for a late CPU to have this capability when system doesn't already have */
+#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
+/* Is it safe for a late CPU to miss this capability when system has it */
+#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
+
+/*
+ * 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_LOCAL_CPU_ERRATUM		\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
+/*
+ * 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_SYSTEM_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
@@ -198,6 +245,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_optional(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
+}
+
+static inline bool
+cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
+{
+	return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
+}
+
 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 328c5a031e45..22ec3960a0c5 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
-	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = min, \
 	.midr_range_max = max
 
 #define MIDR_ALL_VERSIONS(model) \
-	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
+	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = 0, \
@@ -286,7 +286,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,
-		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
 		.cpu_enable = cpu_enable_trap_ctr_access,
 	},
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -300,7 +300,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
-		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
+		.type = ARM64_CPUCAP_LOCAL_CPU_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 8d22f0ef0927..1b29b3f0a1bc 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -921,7 +921,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
 		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -945,7 +945,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "LSE atomic instructions",
 		.capability = ARM64_HAS_LSE_ATOMICS,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -956,14 +956,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -977,21 +977,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_PAN
 	{
 		.capability = ARM64_ALT_PAN_NOT_UAO,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = cpufeature_pan_not_uao,
 	},
 #endif /* CONFIG_ARM64_PAN */
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = runs_at_el2,
 		.cpu_enable = cpu_copy_el2regs,
 	},
 	{
 		.desc = "32-bit EL0 Support",
 		.capability = ARM64_HAS_32BIT_EL0,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1001,21 +1001,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Reduced HYP mapping offset",
 		.capability = ARM64_HYP_OFFSET_LOW,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = hyp_offset_low,
 	},
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = unmap_kernel_at_el0,
 	},
 #endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1023,7 +1023,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Data cache clean to Point of Persistence",
 		.capability = ARM64_HAS_DCPOP,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR1_EL1,
 		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
@@ -1033,7 +1033,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #ifdef CONFIG_ARM64_SVE
 	{
 		.desc = "Scalable Vector Extension",
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.capability = ARM64_SVE,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1047,7 +1047,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "RAS Extension Support",
 		.capability = ARM64_HAS_RAS_EXTN,
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.sign = FTR_UNSIGNED,
@@ -1062,7 +1062,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
 	{							\
 		.desc = #cap,					\
-		.type = ARM64_CPUCAP_SCOPE_SYSTEM,		\
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
 		.matches = has_cpuid_feature,			\
 		.sys_reg = reg,					\
 		.field_pos = field,				\
-- 
2.14.3

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

* [PATCH v2 06/20] arm64: capabilities: Unify the verification
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpufeature.c      | 89 +++++++++++++++++++++++--------------
 2 files changed, 57 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7460b1f7e611..69b5ce366598 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -155,6 +155,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *
  *	b) Any late CPU, brought up after (1), the action is triggered via:
  *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
+ *		  -> __verify_local_cpu_caps()
  *
  * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
  *    state, we could have the following combinations :
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 1b29b3f0a1bc..5e4d581c97f1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1233,6 +1233,56 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
 	}
 }
 
+/*
+ * Run through the list of capabilities to check for conflicts.
+ * If the system has already detected a capability, take necessary
+ * action on this CPU.
+ *
+ * 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_optional(caps))
+				break;
+			/*
+			 * We have to issue cpu_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->cpu_enable)
+				caps->cpu_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_permitted(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, 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.
@@ -1255,25 +1305,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->cpu_enable)
-			caps->cpu_enable(caps);
-	}
+	if (!__verify_local_cpu_caps(arm64_features))
+		cpu_die_early();
 }
 
 static void verify_sve_features(void)
@@ -1300,20 +1335,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->cpu_enable)
-				caps->cpu_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)
@@ -1337,7 +1360,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.14.3

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

* [PATCH v2 06/20] arm64: capabilities: Unify the verification
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpufeature.c      | 89 +++++++++++++++++++++++--------------
 2 files changed, 57 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7460b1f7e611..69b5ce366598 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -155,6 +155,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *
  *	b) Any late CPU, brought up after (1), the action is triggered via:
  *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
+ *		  -> __verify_local_cpu_caps()
  *
  * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
  *    state, we could have the following combinations :
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 1b29b3f0a1bc..5e4d581c97f1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1233,6 +1233,56 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
 	}
 }
 
+/*
+ * Run through the list of capabilities to check for conflicts.
+ * If the system has already detected a capability, take necessary
+ * action on this CPU.
+ *
+ * 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_optional(caps))
+				break;
+			/*
+			 * We have to issue cpu_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->cpu_enable)
+				caps->cpu_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_permitted(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, 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.
@@ -1255,25 +1305,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->cpu_enable)
-			caps->cpu_enable(caps);
-	}
+	if (!__verify_local_cpu_caps(arm64_features))
+		cpu_die_early();
 }
 
 static void verify_sve_features(void)
@@ -1300,20 +1335,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->cpu_enable)
-				caps->cpu_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)
@@ -1337,7 +1360,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.14.3

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

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

While processing the list of capabilities, it is useful to
filter out some of the entries based on the given mask for the
scope of the capabilities to allow better control. This can be
used later for handling LOCAL vs SYSTEM wide capabilities and more.
All capabilities should have their scope set to either LOCAL_CPU or
SYSTEM. No functional/flow change.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  2 ++
 arch/arm64/kernel/cpufeature.c      | 35 ++++++++++++++++++++++++-----------
 2 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 69b5ce366598..cda62b70d338 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -198,6 +198,8 @@ 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_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
 
+#define ARM64_CPUCAP_SCOPE_ALL			 \
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
 /*
  * 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 5e4d581c97f1..5163dc51b975 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1185,10 +1185,12 @@ 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 scope_mask, const char *info)
 {
+	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
-		if (!caps->matches(caps, cpucap_default_scope(caps)))
+		if (!(caps->type & scope_mask) ||
+		    !caps->matches(caps, cpucap_default_scope(caps)))
 			continue;
 
 		if (!cpus_have_cap(caps->capability) && caps->desc)
@@ -1210,12 +1212,14 @@ 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 scope_mask)
 {
+	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
 
-		if (!cpus_have_cap(num))
+		if (!(caps->type & scope_mask) || !cpus_have_cap(num))
 			continue;
 
 		/* Ensure cpus_have_const_cap(num) works */
@@ -1240,12 +1244,18 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
  *
  * 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 scope_mask)
 {
 	bool cpu_has_cap, system_has_cap;
 	const struct arm64_cpu_capabilities *caps = caps_list;
 
+	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
+
+		if (!(caps->type & scope_mask))
+			continue;
+
 		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
 		system_has_cap =  cpus_have_cap(caps->capability);
 
@@ -1307,7 +1317,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_SCOPE_ALL))
 		cpu_die_early();
 }
 
@@ -1335,18 +1345,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_SCOPE_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_SCOPE_ALL,
+				"enabling workaround for");
 }
 
 static void __init enable_errata_workarounds(void)
 {
-	enable_cpu_capabilities(arm64_errata);
+	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
 }
 
 /*
@@ -1395,8 +1407,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_SCOPE_ALL, "detected feature:");
+	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
-- 
2.14.3

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

* [PATCH v2 07/20] arm64: capabilities: Filter the entries based on a given mask
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 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 mask for the
scope of the capabilities to allow better control. This can be
used later for handling LOCAL vs SYSTEM wide capabilities and more.
All capabilities should have their scope set to either LOCAL_CPU or
SYSTEM. No functional/flow change.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  2 ++
 arch/arm64/kernel/cpufeature.c      | 35 ++++++++++++++++++++++++-----------
 2 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 69b5ce366598..cda62b70d338 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -198,6 +198,8 @@ 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_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
 
+#define ARM64_CPUCAP_SCOPE_ALL			 \
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
 /*
  * 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 5e4d581c97f1..5163dc51b975 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1185,10 +1185,12 @@ 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 scope_mask, const char *info)
 {
+	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
-		if (!caps->matches(caps, cpucap_default_scope(caps)))
+		if (!(caps->type & scope_mask) ||
+		    !caps->matches(caps, cpucap_default_scope(caps)))
 			continue;
 
 		if (!cpus_have_cap(caps->capability) && caps->desc)
@@ -1210,12 +1212,14 @@ 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 scope_mask)
 {
+	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
 		unsigned int num = caps->capability;
 
-		if (!cpus_have_cap(num))
+		if (!(caps->type & scope_mask) || !cpus_have_cap(num))
 			continue;
 
 		/* Ensure cpus_have_const_cap(num) works */
@@ -1240,12 +1244,18 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
  *
  * 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 scope_mask)
 {
 	bool cpu_has_cap, system_has_cap;
 	const struct arm64_cpu_capabilities *caps = caps_list;
 
+	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
+
+		if (!(caps->type & scope_mask))
+			continue;
+
 		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
 		system_has_cap =  cpus_have_cap(caps->capability);
 
@@ -1307,7 +1317,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_SCOPE_ALL))
 		cpu_die_early();
 }
 
@@ -1335,18 +1345,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_SCOPE_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_SCOPE_ALL,
+				"enabling workaround for");
 }
 
 static void __init enable_errata_workarounds(void)
 {
-	enable_cpu_capabilities(arm64_errata);
+	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
 }
 
 /*
@@ -1395,8 +1407,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_SCOPE_ALL, "detected feature:");
+	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
-- 
2.14.3

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

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

So far we have had separate routes for triggering errata and feature
capability detection. 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 both
arm64_features and arm64_errata, in two phases for detection.

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

 2) with SCOPE_SYSTEM filter only once after all boot time enabled
    CPUs are active, triggered from setup_cpu_features().

A late CPU goes through both the tables for verification against
established capabilities, as before.

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

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
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 5163dc51b975..c710ef28524e 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)
@@ -1184,8 +1184,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 scope_mask, const char *info)
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+				      u16 scope_mask, const char *info)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1199,6 +1199,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+static void update_cpu_capabilities(u16 scope_mask)
+{
+	__update_cpu_capabilities(arm64_features, scope_mask,
+				"detected feature:");
+	__update_cpu_capabilities(arm64_errata, scope_mask,
+				"enabling work around for");
+}
 
 static int __enable_cpu_capability(void *arg)
 {
@@ -1213,7 +1220,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1293,6 +1300,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+static bool verify_local_cpu_caps(u16 scope_mask)
+{
+	return __verify_local_cpu_caps(arm64_features, scope_mask) &&
+	       __verify_local_cpu_caps(arm64_errata, scope_mask);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1315,12 +1328,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_SCOPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1339,26 +1346,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_SCOPE_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_SCOPE_ALL,
-				"enabling workaround for");
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
 }
 
-static void __init enable_errata_workarounds(void)
+static void enable_cpu_capabilities(u16 scope_mask)
 {
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
+	__enable_cpu_capabilities(arm64_errata, scope_mask);
+	__enable_cpu_capabilities(arm64_features, scope_mask);
 }
 
 /*
@@ -1371,8 +1380,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_SCOPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1400,16 +1409,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_SCOPE_ALL, "detected feature:");
-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_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_SCOPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1433,9 +1446,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.14.3

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

* [PATCH v2 08/20] arm64: capabilities: Group handling of features and errata
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

So far we have had separate routes for triggering errata and feature
capability detection. 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 both
arm64_features and arm64_errata, in two phases for detection.

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

 2) with SCOPE_SYSTEM filter only once after all boot time enabled
    CPUs are active, triggered from setup_cpu_features().

A late CPU goes through both the tables for verification against
established capabilities, as before.

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

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
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 5163dc51b975..c710ef28524e 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)
@@ -1184,8 +1184,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 scope_mask, const char *info)
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+				      u16 scope_mask, const char *info)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1199,6 +1199,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+static void update_cpu_capabilities(u16 scope_mask)
+{
+	__update_cpu_capabilities(arm64_features, scope_mask,
+				"detected feature:");
+	__update_cpu_capabilities(arm64_errata, scope_mask,
+				"enabling work around for");
+}
 
 static int __enable_cpu_capability(void *arg)
 {
@@ -1213,7 +1220,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1293,6 +1300,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+static bool verify_local_cpu_caps(u16 scope_mask)
+{
+	return __verify_local_cpu_caps(arm64_features, scope_mask) &&
+	       __verify_local_cpu_caps(arm64_errata, scope_mask);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1315,12 +1328,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_SCOPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1339,26 +1346,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_SCOPE_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_SCOPE_ALL,
-				"enabling workaround for");
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
 }
 
-static void __init enable_errata_workarounds(void)
+static void enable_cpu_capabilities(u16 scope_mask)
 {
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
+	__enable_cpu_capabilities(arm64_errata, scope_mask);
+	__enable_cpu_capabilities(arm64_features, scope_mask);
 }
 
 /*
@@ -1371,8 +1380,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_SCOPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1400,16 +1409,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_SCOPE_ALL, "detected feature:");
-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_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_SCOPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1433,9 +1446,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.14.3

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

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

Now that we have the flexibility of defining system features based
on individual CPUs, introduce CPU feature type that can be detected
on a local SCOPE and ignores the conflict on late CPUs. This is
applicable for ARM64_HAS_NO_HW_PREFETCH, where it is fine for
the system to have CPUs without hardware prefetch turning up
later. We only suffer a performance penalty, nothing fatal.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 8 ++++++++
 arch/arm64/kernel/cpufeature.c      | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index cda62b70d338..7bb3fdec827e 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -214,6 +214,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 #define ARM64_CPUCAP_SYSTEM_FEATURE	\
 	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+/*
+ * CPU feature detected at boot time based on feature of one or more CPUs.
+ * All possible conflicts for a late CPU are ignored.
+ */
+#define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE		\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
+	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
+	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c710ef28524e..ecc87aa74c64 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -956,7 +956,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
-- 
2.14.3

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

* [PATCH v2 09/20] arm64: capabilities: Introduce weak features based on local CPU
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we have the flexibility of defining system features based
on individual CPUs, introduce CPU feature type that can be detected
on a local SCOPE and ignores the conflict on late CPUs. This is
applicable for ARM64_HAS_NO_HW_PREFETCH, where it is fine for
the system to have CPUs without hardware prefetch turning up
later. We only suffer a performance penalty, nothing fatal.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 8 ++++++++
 arch/arm64/kernel/cpufeature.c      | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index cda62b70d338..7bb3fdec827e 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -214,6 +214,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 #define ARM64_CPUCAP_SYSTEM_FEATURE	\
 	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+/*
+ * CPU feature detected at boot time based on feature of one or more CPUs.
+ * All possible conflicts for a late CPU are ignored.
+ */
+#define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE		\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
+	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
+	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
 
 struct arm64_cpu_capabilities {
 	const char *desc;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c710ef28524e..ecc87aa74c64 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -956,7 +956,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
-- 
2.14.3

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

* [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

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 forced via kernel 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.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  9 +++++++++
 arch/arm64/kernel/cpufeature.c      | 11 ++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7bb3fdec827e..71993dd4afae 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -223,6 +223,15 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
 	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
 
+/*
+ * CPU feature detected at boot time, on one or more CPUs. A late CPU
+ * is not allowed to have the capability when the system doesn't have it.
+ * It is Ok for a late CPU to miss the feature.
+ */
+#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
+	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index ecc87aa74c64..4a55492784b7 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) {
@@ -885,8 +884,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 	}
 
 	/* 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)
@@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_BOOT_RESTRICTED_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.14.3

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

* [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

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 forced via kernel 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.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  9 +++++++++
 arch/arm64/kernel/cpufeature.c      | 11 ++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7bb3fdec827e..71993dd4afae 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -223,6 +223,15 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
 	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
 
+/*
+ * CPU feature detected at boot time, on one or more CPUs. A late CPU
+ * is not allowed to have the capability when the system doesn't have it.
+ * It is Ok for a late CPU to miss the feature.
+ */
+#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE	\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
+	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index ecc87aa74c64..4a55492784b7 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) {
@@ -885,8 +884,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 	}
 
 	/* 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)
@@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Kernel page table isolation (KPTI)",
 		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_BOOT_RESTRICTED_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.14.3

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

* [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose, Julien Thierry

The kernel detects and uses some of the features based on the boot
CPU and expects that all the following CPUs conform to it. e.g,
with VHE and the boot CPU running at EL2, the kernel decides to
keep the kernel running at EL2. If another CPU is brought up without
this capability, we use custom hooks (via check_early_cpu_features())
to handle it. To handle such capabilities add support for detecting
and enabling capabilities based on the boot CPU.

A bit is added to indicate if the capability should be detected
early on the boot CPU. The infrastructure then ensures that such
capabilities are probed and "enabled" early on in the boot CPU
and, enabled on the subsequent CPUs.

Cc: Julien Thierry <julien.thierry@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
 arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
 2 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 71993dd4afae..04161aac0f06 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -104,7 +104,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *    some checks at runtime. This could be, e.g, checking the value of a field
  *    in CPU ID feature register or checking the cpu model. The capability
  *    provides a call back ( @matches() ) to perform the check.
- *    Scope defines how the checks should be performed. There are two cases:
+ *    Scope defines how the checks should be performed. There are three cases:
  *
  *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
  *        matches. This implies, we have to run the check on all the booting
@@ -117,6 +117,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *        field in one of the CPU ID feature registers, we use the sanitised
  *        value of the register from the CPU feature infrastructure to make
  *        the decision.
+ *		Or
+ *     c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the feature.
+ *        This category is for features that are "finalised" (or used) by the kernel
+ *        very early even before the SMP cpus are brought up.
+ *
  *    The process of detection is usually denoted by "update" capability state
  *    in the code.
  *
@@ -129,6 +134,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
  *    any changes to the state of a capability once it finalises the capability
  *    and takes any action, as it may be impossible to execute the actions safely.
+ *    At the moment there are two passes of finalising the capabilities.
+ *      a) Boot CPU scope capabilities - Finalised by primary boot CPU via
+ *         setup_boot_cpu_capabilities().
+ *      b) Everything except (a) - Run via setup_system_capabilities().
  *
  * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
  *    the kernel should make sure that it is safe to use the CPU, by verifying
@@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *
  *    As explained in (2) above, capabilities could be finalised at different
  *    points in the execution. Each CPU is verified against the "finalised"
- *    capabilities and if there is a conflict, the kernel takes an action, based
- *    on the severity (e.g, a CPU could be prevented from booting or cause a
- *    kernel panic). The CPU is allowed to "affect" the state of the capability,
- *    if it has not been finalised already. See section 5 for more details on
- *    conflicts.
+ *    capabilities.
+ *
+ *	x------------------------------------------------------------------- x
+ *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
+ *	|--------------------------------------------------------------------|
+ *	| Primary boot CPU    |          |                    |              |
+ *	|  capability         |   n      |      y             |       y      |
+ *	|--------------------------------------------------------------------|
+ *	| All others          |   n      |      n             |       y      |
+ *	x--------------------------------------------------------------------x
+ *
+ *
+ *    If there is a conflict, the kernel takes an action, based on the severity
+ *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
+ *    The CPU is allowed to "affect" the state of the capability, if it has not
+ *    been finalised already. See section 5 for more details on conflicts.
  *
  * 4) Action: As mentioned in (2), the kernel can take an action for each detected
  *    capability, on all CPUs on the system. This is always initiated only after
@@ -186,20 +206,28 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 
 
-/* Decide how the capability is detected. On a local CPU vs System wide */
-#define ARM64_CPUCAP_SCOPE_MASK			0x3
+/*
+ * Decide how the capability is detected.
+ * On any local CPU vs System wide vs the primary boot CPU
+ */
+#define ARM64_CPUCAP_SCOPE_MASK			0x7
 #define ARM64_CPUCAP_SCOPE_LOCAL_CPU		((u16)BIT(0))
 #define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
+/*
+ * The capabilitiy is detected on the Boot CPU and is used by kernel
+ * during early boot. i.e, the capability should be "detected" and "enabled"
+ * as early as possibly on all booting CPUs.
+ */
+#define ARM64_CPUCAP_SCOPE_BOOT_CPU		((u16)BIT(2))
 #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
 #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
+#define SCOPE_BOOT_CPU				ARM64_CPUCAP_SCOPE_BOOT_CPU
 
 /* Is it permitted for a late CPU to have this capability when system doesn't already have */
 #define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
 /* Is it safe for a late CPU to miss this capability when system has it */
 #define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
 
-#define ARM64_CPUCAP_SCOPE_ALL			 \
-	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
 /*
  * 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 4a55492784b7..6d759f068de1 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_local_capabilities(void);
+static void __init setup_boot_cpu_capabilities(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -550,10 +550,10 @@ 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.
+	 * Detect and enable early CPU features based on the boot CPU, after
+	 * we have initialised the CPU feature infrastructure.
 	 */
-	update_cpu_local_capabilities();
+	setup_boot_cpu_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1235,12 +1235,21 @@ __enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_m
 
 		if (caps->cpu_enable) {
 			/*
-			 * Use stop_machine() as it schedules the work allowing
-			 * us to modify PSTATE, instead of on_each_cpu() which
-			 * uses an IPI, giving us a PSTATE that disappears when
-			 * we return.
+			 * If we are dealing with EARLY detected features, we
+			 * have to enable this only on the Boot CPU, where it
+			 * is detected. All the secondaries enable it via
+			 * verify_early_cpu_capabilities().
+			 *
+			 * Otherwise, use stop_machine() as it schedules the
+			 * work allowing us to modify PSTATE, instead of
+			 * on_each_cpu() which uses an IPI, giving us a PSTATE
+			 * that disappears when we return.
 			 */
-			stop_machine(__enable_cpu_capability, (void *)caps, cpu_online_mask);
+			if (scope_mask & ARM64_CPUCAP_SCOPE_BOOT_CPU)
+				caps->cpu_enable(caps);
+			else
+				stop_machine(__enable_cpu_capability,
+					(void *)caps, cpu_online_mask);
 		}
 	}
 }
@@ -1315,6 +1324,12 @@ static void check_early_cpu_features(void)
 {
 	verify_cpu_run_el();
 	verify_cpu_asid_bits();
+	/*
+	 * Early features are used by the kernel already. If there
+	 * is a conflict, we cannot proceed further.
+	 */
+	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_BOOT_CPU))
+		cpu_panic_kernel();
 }
 
 static void
@@ -1381,7 +1396,7 @@ static void enable_cpu_capabilities(u16 scope_mask)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
+	if (!verify_local_cpu_caps(~ARM64_CPUCAP_SCOPE_BOOT_CPU))
 		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
@@ -1415,6 +1430,15 @@ void check_local_cpu_capabilities(void)
 		verify_local_cpu_capabilities();
 }
 
+static void __init setup_boot_cpu_capabilities(void)
+{
+	/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU |
+				 ARM64_CPUCAP_SCOPE_LOCAL_CPU);
+	/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
+	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU);
+}
+
 static void __init setup_system_capabilities(void)
 {
 	/*
@@ -1422,8 +1446,8 @@ static void __init setup_system_capabilities(void)
 	 * finalise the capabilities that depend on it.
 	 */
 	update_system_capabilities();
-	/* Enable all the available capabilities */
-	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_ALL);
+	/* Enable all the available capabilities, which are not already enabled. */
+	enable_cpu_capabilities(~ARM64_CPUCAP_SCOPE_BOOT_CPU);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
-- 
2.14.3

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

* [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

The kernel detects and uses some of the features based on the boot
CPU and expects that all the following CPUs conform to it. e.g,
with VHE and the boot CPU running at EL2, the kernel decides to
keep the kernel running at EL2. If another CPU is brought up without
this capability, we use custom hooks (via check_early_cpu_features())
to handle it. To handle such capabilities add support for detecting
and enabling capabilities based on the boot CPU.

A bit is added to indicate if the capability should be detected
early on the boot CPU. The infrastructure then ensures that such
capabilities are probed and "enabled" early on in the boot CPU
and, enabled on the subsequent CPUs.

Cc: Julien Thierry <julien.thierry@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
 arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
 2 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 71993dd4afae..04161aac0f06 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -104,7 +104,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *    some checks at runtime. This could be, e.g, checking the value of a field
  *    in CPU ID feature register or checking the cpu model. The capability
  *    provides a call back ( @matches() ) to perform the check.
- *    Scope defines how the checks should be performed. There are two cases:
+ *    Scope defines how the checks should be performed. There are three cases:
  *
  *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
  *        matches. This implies, we have to run the check on all the booting
@@ -117,6 +117,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *        field in one of the CPU ID feature registers, we use the sanitised
  *        value of the register from the CPU feature infrastructure to make
  *        the decision.
+ *		Or
+ *     c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the feature.
+ *        This category is for features that are "finalised" (or used) by the kernel
+ *        very early even before the SMP cpus are brought up.
+ *
  *    The process of detection is usually denoted by "update" capability state
  *    in the code.
  *
@@ -129,6 +134,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
  *    any changes to the state of a capability once it finalises the capability
  *    and takes any action, as it may be impossible to execute the actions safely.
+ *    At the moment there are two passes of finalising the capabilities.
+ *      a) Boot CPU scope capabilities - Finalised by primary boot CPU via
+ *         setup_boot_cpu_capabilities().
+ *      b) Everything except (a) - Run via setup_system_capabilities().
  *
  * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
  *    the kernel should make sure that it is safe to use the CPU, by verifying
@@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  *
  *    As explained in (2) above, capabilities could be finalised at different
  *    points in the execution. Each CPU is verified against the "finalised"
- *    capabilities and if there is a conflict, the kernel takes an action, based
- *    on the severity (e.g, a CPU could be prevented from booting or cause a
- *    kernel panic). The CPU is allowed to "affect" the state of the capability,
- *    if it has not been finalised already. See section 5 for more details on
- *    conflicts.
+ *    capabilities.
+ *
+ *	x------------------------------------------------------------------- x
+ *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
+ *	|--------------------------------------------------------------------|
+ *	| Primary boot CPU    |          |                    |              |
+ *	|  capability         |   n      |      y             |       y      |
+ *	|--------------------------------------------------------------------|
+ *	| All others          |   n      |      n             |       y      |
+ *	x--------------------------------------------------------------------x
+ *
+ *
+ *    If there is a conflict, the kernel takes an action, based on the severity
+ *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
+ *    The CPU is allowed to "affect" the state of the capability, if it has not
+ *    been finalised already. See section 5 for more details on conflicts.
  *
  * 4) Action: As mentioned in (2), the kernel can take an action for each detected
  *    capability, on all CPUs on the system. This is always initiated only after
@@ -186,20 +206,28 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  */
 
 
-/* Decide how the capability is detected. On a local CPU vs System wide */
-#define ARM64_CPUCAP_SCOPE_MASK			0x3
+/*
+ * Decide how the capability is detected.
+ * On any local CPU vs System wide vs the primary boot CPU
+ */
+#define ARM64_CPUCAP_SCOPE_MASK			0x7
 #define ARM64_CPUCAP_SCOPE_LOCAL_CPU		((u16)BIT(0))
 #define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
+/*
+ * The capabilitiy is detected on the Boot CPU and is used by kernel
+ * during early boot. i.e, the capability should be "detected" and "enabled"
+ * as early as possibly on all booting CPUs.
+ */
+#define ARM64_CPUCAP_SCOPE_BOOT_CPU		((u16)BIT(2))
 #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
 #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
+#define SCOPE_BOOT_CPU				ARM64_CPUCAP_SCOPE_BOOT_CPU
 
 /* Is it permitted for a late CPU to have this capability when system doesn't already have */
 #define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
 /* Is it safe for a late CPU to miss this capability when system has it */
 #define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
 
-#define ARM64_CPUCAP_SCOPE_ALL			 \
-	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
 /*
  * 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 4a55492784b7..6d759f068de1 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_local_capabilities(void);
+static void __init setup_boot_cpu_capabilities(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -550,10 +550,10 @@ 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.
+	 * Detect and enable early CPU features based on the boot CPU, after
+	 * we have initialised the CPU feature infrastructure.
 	 */
-	update_cpu_local_capabilities();
+	setup_boot_cpu_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1235,12 +1235,21 @@ __enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_m
 
 		if (caps->cpu_enable) {
 			/*
-			 * Use stop_machine() as it schedules the work allowing
-			 * us to modify PSTATE, instead of on_each_cpu() which
-			 * uses an IPI, giving us a PSTATE that disappears when
-			 * we return.
+			 * If we are dealing with EARLY detected features, we
+			 * have to enable this only on the Boot CPU, where it
+			 * is detected. All the secondaries enable it via
+			 * verify_early_cpu_capabilities().
+			 *
+			 * Otherwise, use stop_machine() as it schedules the
+			 * work allowing us to modify PSTATE, instead of
+			 * on_each_cpu() which uses an IPI, giving us a PSTATE
+			 * that disappears when we return.
 			 */
-			stop_machine(__enable_cpu_capability, (void *)caps, cpu_online_mask);
+			if (scope_mask & ARM64_CPUCAP_SCOPE_BOOT_CPU)
+				caps->cpu_enable(caps);
+			else
+				stop_machine(__enable_cpu_capability,
+					(void *)caps, cpu_online_mask);
 		}
 	}
 }
@@ -1315,6 +1324,12 @@ static void check_early_cpu_features(void)
 {
 	verify_cpu_run_el();
 	verify_cpu_asid_bits();
+	/*
+	 * Early features are used by the kernel already. If there
+	 * is a conflict, we cannot proceed further.
+	 */
+	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_BOOT_CPU))
+		cpu_panic_kernel();
 }
 
 static void
@@ -1381,7 +1396,7 @@ static void enable_cpu_capabilities(u16 scope_mask)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
+	if (!verify_local_cpu_caps(~ARM64_CPUCAP_SCOPE_BOOT_CPU))
 		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
@@ -1415,6 +1430,15 @@ void check_local_cpu_capabilities(void)
 		verify_local_cpu_capabilities();
 }
 
+static void __init setup_boot_cpu_capabilities(void)
+{
+	/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU |
+				 ARM64_CPUCAP_SCOPE_LOCAL_CPU);
+	/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
+	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU);
+}
+
 static void __init setup_system_capabilities(void)
 {
 	/*
@@ -1422,8 +1446,8 @@ static void __init setup_system_capabilities(void)
 	 * finalise the capabilities that depend on it.
 	 */
 	update_system_capabilities();
-	/* Enable all the available capabilities */
-	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_ALL);
+	/* Enable all the available capabilities, which are not already enabled. */
+	enable_cpu_capabilities(~ARM64_CPUCAP_SCOPE_BOOT_CPU);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
-- 
2.14.3

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

* [PATCH v2 12/20] arm64: capabilities: Change scope of VHE to Boot CPU feature
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:27   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

We expect all CPUs to be running at the same EL inside the kernel
with or without VHE enabled and we have strict checks to ensure
that any mismatch triggers a kernel panic. If VHE is enabled,
we use the feature based on the boot CPU and all other CPUs
should follow. This makes it a perfect candidate for a cpability
based on the boot CPU,  which should be matched by all the CPUs
(both when is ON and OFF). This saves us some not-so-pretty
hooks and special code, just for verifying the conflict.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 +++++++
 arch/arm64/include/asm/virt.h       |  6 ------
 arch/arm64/kernel/cpufeature.c      |  3 +--
 arch/arm64/kernel/smp.c             | 38 -------------------------------------
 4 files changed, 8 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 04161aac0f06..42292a0b93a4 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -260,6 +260,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
 	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
 
+/*
+ * Critical CPU feature used early in the boot based on the boot CPU.
+ * The feature should be matched by all booting CPU (both miss and hit
+ * cases).
+ */
+#define ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE ARM64_CPUCAP_SCOPE_BOOT_CPU
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index c5f89442785c..9d1e24e030b3 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -102,12 +102,6 @@ static inline bool has_vhe(void)
 	return false;
 }
 
-#ifdef CONFIG_ARM64_VHE
-extern void verify_cpu_run_el(void);
-#else
-static inline void verify_cpu_run_el(void) {}
-#endif
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* ! __ASM__VIRT_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6d759f068de1..247d34ea6b5e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -982,7 +982,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE,
 		.matches = runs_at_el2,
 		.cpu_enable = cpu_copy_el2regs,
 	},
@@ -1322,7 +1322,6 @@ static bool verify_local_cpu_caps(u16 scope_mask)
  */
 static void check_early_cpu_features(void)
 {
-	verify_cpu_run_el();
 	verify_cpu_asid_bits();
 	/*
 	 * Early features are used by the kernel already. If there
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 5cef11450183..f3e2e3aec0b0 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -85,43 +85,6 @@ enum ipi_msg_type {
 	IPI_WAKEUP
 };
 
-#ifdef CONFIG_ARM64_VHE
-
-/* Whether the boot CPU is running in HYP mode or not*/
-static bool boot_cpu_hyp_mode;
-
-static inline void save_boot_cpu_run_el(void)
-{
-	boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
-}
-
-static inline bool is_boot_cpu_in_hyp_mode(void)
-{
-	return boot_cpu_hyp_mode;
-}
-
-/*
- * Verify that a secondary CPU is running the kernel at the same
- * EL as that of the boot CPU.
- */
-void verify_cpu_run_el(void)
-{
-	bool in_el2 = is_kernel_in_hyp_mode();
-	bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
-
-	if (in_el2 ^ boot_cpu_el2) {
-		pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
-					smp_processor_id(),
-					in_el2 ? 2 : 1,
-					boot_cpu_el2 ? 2 : 1);
-		cpu_panic_kernel();
-	}
-}
-
-#else
-static inline void save_boot_cpu_run_el(void) {}
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 static int op_cpu_kill(unsigned int cpu);
 #else
@@ -447,7 +410,6 @@ void __init smp_prepare_boot_cpu(void)
 	 */
 	jump_label_init();
 	cpuinfo_store_boot_cpu();
-	save_boot_cpu_run_el();
 }
 
 static u64 __init of_get_cpu_mpidr(struct device_node *dn)
-- 
2.14.3

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

* [PATCH v2 12/20] arm64: capabilities: Change scope of VHE to Boot CPU feature
@ 2018-01-31 18:27   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

We expect all CPUs to be running at the same EL inside the kernel
with or without VHE enabled and we have strict checks to ensure
that any mismatch triggers a kernel panic. If VHE is enabled,
we use the feature based on the boot CPU and all other CPUs
should follow. This makes it a perfect candidate for a cpability
based on the boot CPU,  which should be matched by all the CPUs
(both when is ON and OFF). This saves us some not-so-pretty
hooks and special code, just for verifying the conflict.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  7 +++++++
 arch/arm64/include/asm/virt.h       |  6 ------
 arch/arm64/kernel/cpufeature.c      |  3 +--
 arch/arm64/kernel/smp.c             | 38 -------------------------------------
 4 files changed, 8 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 04161aac0f06..42292a0b93a4 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -260,6 +260,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
 	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
 
+/*
+ * Critical CPU feature used early in the boot based on the boot CPU.
+ * The feature should be matched by all booting CPU (both miss and hit
+ * cases).
+ */
+#define ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE ARM64_CPUCAP_SCOPE_BOOT_CPU
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index c5f89442785c..9d1e24e030b3 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -102,12 +102,6 @@ static inline bool has_vhe(void)
 	return false;
 }
 
-#ifdef CONFIG_ARM64_VHE
-extern void verify_cpu_run_el(void);
-#else
-static inline void verify_cpu_run_el(void) {}
-#endif
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* ! __ASM__VIRT_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6d759f068de1..247d34ea6b5e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -982,7 +982,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE,
 		.matches = runs_at_el2,
 		.cpu_enable = cpu_copy_el2regs,
 	},
@@ -1322,7 +1322,6 @@ static bool verify_local_cpu_caps(u16 scope_mask)
  */
 static void check_early_cpu_features(void)
 {
-	verify_cpu_run_el();
 	verify_cpu_asid_bits();
 	/*
 	 * Early features are used by the kernel already. If there
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 5cef11450183..f3e2e3aec0b0 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -85,43 +85,6 @@ enum ipi_msg_type {
 	IPI_WAKEUP
 };
 
-#ifdef CONFIG_ARM64_VHE
-
-/* Whether the boot CPU is running in HYP mode or not*/
-static bool boot_cpu_hyp_mode;
-
-static inline void save_boot_cpu_run_el(void)
-{
-	boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
-}
-
-static inline bool is_boot_cpu_in_hyp_mode(void)
-{
-	return boot_cpu_hyp_mode;
-}
-
-/*
- * Verify that a secondary CPU is running the kernel at the same
- * EL as that of the boot CPU.
- */
-void verify_cpu_run_el(void)
-{
-	bool in_el2 = is_kernel_in_hyp_mode();
-	bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
-
-	if (in_el2 ^ boot_cpu_el2) {
-		pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
-					smp_processor_id(),
-					in_el2 ? 2 : 1,
-					boot_cpu_el2 ? 2 : 1);
-		cpu_panic_kernel();
-	}
-}
-
-#else
-static inline void save_boot_cpu_run_el(void) {}
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 static int op_cpu_kill(unsigned int cpu);
 #else
@@ -447,7 +410,6 @@ void __init smp_prepare_boot_cpu(void)
 	 */
 	jump_label_init();
 	cpuinfo_store_boot_cpu();
-	save_boot_cpu_run_el();
 }
 
 static u64 __init of_get_cpu_mpidr(struct device_node *dn)
-- 
2.14.3

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

* [PATCH v2 13/20] arm64: capabilities: Clean up midr range helpers
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

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

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpu_errata.c | 100 +++++++++++++++++++++++------------------
 1 file changed, 56 insertions(+), 44 deletions(-)

diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 22ec3960a0c5..4351d48b0b0f 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -174,20 +174,35 @@ static void qcom_enable_link_stack_sanitization(
 }
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
-#define MIDR_RANGE(model, min, max) \
-	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
-	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = min, \
-	.midr_range_max = max
+#define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
+	.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)
 
-#define MIDR_ALL_VERSIONS(model) \
-	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
-	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = 0, \
+#define CAP_MIDR_ALL_VERSIONS(model)					\
+	.matches = is_affected_midr_range,				\
+	.midr_model = model,						\
+	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
 	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
 
+#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
+	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
+	CAP_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)	 \
+	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
+
+/* Errata affecting a single variant/revision of a model */
+#define ERRATA_MIDR_REV(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_LOCAL_CPU_ERRATUM,			\
+	CAP_MIDR_ALL_VERSIONS(model)
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
 	defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -196,7 +211,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),
 		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -205,7 +220,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),
 		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -214,9 +229,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
@@ -224,9 +239,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
@@ -234,7 +249,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
@@ -242,7 +257,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
@@ -250,15 +265,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_REV(MIDR_THUNDERX_81XX, 0x0, 0x0),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_30115
@@ -266,20 +281,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_REV(MIDR_THUNDERX_83XX, 0x0, 0x0),
 	},
 #endif
 	{
@@ -293,9 +309,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_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
@@ -309,9 +323,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_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
@@ -319,47 +331,47 @@ 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),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
 		.cpu_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),
 		.cpu_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),
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 #endif
-- 
2.14.3

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

* [PATCH v2 13/20] arm64: capabilities: Clean up midr range helpers
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

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

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpu_errata.c | 100 +++++++++++++++++++++++------------------
 1 file changed, 56 insertions(+), 44 deletions(-)

diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 22ec3960a0c5..4351d48b0b0f 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -174,20 +174,35 @@ static void qcom_enable_link_stack_sanitization(
 }
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
-#define MIDR_RANGE(model, min, max) \
-	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
-	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = min, \
-	.midr_range_max = max
+#define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
+	.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)
 
-#define MIDR_ALL_VERSIONS(model) \
-	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
-	.matches = is_affected_midr_range, \
-	.midr_model = model, \
-	.midr_range_min = 0, \
+#define CAP_MIDR_ALL_VERSIONS(model)					\
+	.matches = is_affected_midr_range,				\
+	.midr_model = model,						\
+	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
 	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
 
+#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
+	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
+	CAP_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)	 \
+	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
+
+/* Errata affecting a single variant/revision of a model */
+#define ERRATA_MIDR_REV(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_LOCAL_CPU_ERRATUM,			\
+	CAP_MIDR_ALL_VERSIONS(model)
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
 	defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -196,7 +211,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),
 		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -205,7 +220,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),
 		.cpu_enable = cpu_enable_cache_maint_trap,
 	},
 #endif
@@ -214,9 +229,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
@@ -224,9 +239,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
@@ -234,7 +249,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
@@ -242,7 +257,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
@@ -250,15 +265,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_REV(MIDR_THUNDERX_81XX, 0x0, 0x0),
 	},
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_30115
@@ -266,20 +281,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_REV(MIDR_THUNDERX_83XX, 0x0, 0x0),
 	},
 #endif
 	{
@@ -293,9 +309,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_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 	{
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
@@ -309,9 +323,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_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
@@ -319,47 +331,47 @@ 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),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
 		.cpu_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),
 		.cpu_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),
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 #endif
-- 
2.14.3

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

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

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

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
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 42292a0b93a4..0cfe42c3225c 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>
@@ -279,11 +280,7 @@ struct arm64_cpu_capabilities {
 	 */
 	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
 	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
@@ -115,6 +115,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
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 4351d48b0b0f..bc3f7dce42ba 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
@@ -176,15 +174,11 @@ static void qcom_enable_link_stack_sanitization(
 
 #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
 	.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)
 
 #define CAP_MIDR_ALL_VERSIONS(model)					\
 	.matches = is_affected_midr_range,				\
-	.midr_model = model,						\
-	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
-	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
+	.midr_range = MIDR_ALL_VERSIONS(model)
 
 #define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
@@ -315,7 +309,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
 		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
-		.midr_model = MIDR_QCOM_KRYO,
+		.midr_range.model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
 #endif
-- 
2.14.3

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

* [PATCH v2 14/20] arm64: Add helpers for checking CPU MIDR against a range
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
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 42292a0b93a4..0cfe42c3225c 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>
@@ -279,11 +280,7 @@ struct arm64_cpu_capabilities {
 	 */
 	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
 	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
@@ -115,6 +115,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
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 4351d48b0b0f..bc3f7dce42ba 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
@@ -176,15 +174,11 @@ static void qcom_enable_link_stack_sanitization(
 
 #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
 	.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)
 
 #define CAP_MIDR_ALL_VERSIONS(model)					\
 	.matches = is_affected_midr_range,				\
-	.midr_model = model,						\
-	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
-	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
+	.midr_range = MIDR_ALL_VERSIONS(model)
 
 #define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
@@ -315,7 +309,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "Qualcomm Technologies Kryo erratum 1003",
 		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
 		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
-		.midr_model = MIDR_QCOM_KRYO,
+		.midr_range.model = MIDR_QCOM_KRYO,
 		.matches = is_kryo_midr,
 	},
 #endif
-- 
2.14.3

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

* [PATCH v2 15/20] arm64: capabilities: Add support for checks based on a list of MIDRs
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

Add helpers for detecting an errata on list of midr ranges
of affected CPUs, with the same work around.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpu_errata.c      | 61 +++++++++++++++++++++----------------
 arch/arm64/kernel/cpufeature.c      | 10 +++---
 3 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 0cfe42c3225c..462c35d1a38c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -281,6 +281,7 @@ struct arm64_cpu_capabilities {
 	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
 	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 bc3f7dce42ba..eff5f4e380ac 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -28,6 +28,13 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 	return is_midr_in_range(read_cpuid_id(), &entry->midr_range);
 }
 
+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)
 {
@@ -184,6 +191,10 @@ static void qcom_enable_link_stack_sanitization(
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
 	CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)
 
+#define CAP_MIDR_RANGE_LIST(list)				\
+	.matches = is_affected_midr_range_list,			\
+	.midr_range_list = list
+
 /* 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)
@@ -197,6 +208,29 @@ static void qcom_enable_link_stack_sanitization(
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
 	CAP_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_LOCAL_CPU_ERRATUM,			\
+	CAP_MIDR_RANGE_LIST(midr_list)
+
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+
+/*
+ * List of CPUs where we need to issue a psci call to
+ * harden the branch predictor.
+ */
+static const struct midr_range arm64_bp_harden_psci_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),
+	MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+	MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+	{},
+};
+
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
 	defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -331,22 +365,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),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
@@ -358,16 +377,6 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
 		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
 #endif
 	{
 	}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 247d34ea6b5e..65a8e5cc600c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -864,6 +864,11 @@ 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 scope)
 {
+	/* List of CPUs that are not vulnerable and don't need KPTI */
+	static const struct midr_range kpti_safe_list[] = {
+		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+	};
 
 	/* Forced on command line? */
 	if (__kpti_forced) {
@@ -877,11 +882,8 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 		return true;
 
 	/* Don't force KPTI for CPUs that are not vulnerable */
-	switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
-	case MIDR_CAVIUM_THUNDERX2:
-	case MIDR_BRCM_VULCAN:
+	if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
 		return false;
-	}
 
 	/* Defer to CPU feature registers */
 	return !has_cpuid_feature(entry, scope);
-- 
2.14.3

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

* [PATCH v2 15/20] arm64: capabilities: Add support for checks based on a list of MIDRs
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

Add helpers for detecting an errata on list of midr ranges
of affected CPUs, with the same work around.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpu_errata.c      | 61 +++++++++++++++++++++----------------
 arch/arm64/kernel/cpufeature.c      | 10 +++---
 3 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 0cfe42c3225c..462c35d1a38c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -281,6 +281,7 @@ struct arm64_cpu_capabilities {
 	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
 	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 bc3f7dce42ba..eff5f4e380ac 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -28,6 +28,13 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 	return is_midr_in_range(read_cpuid_id(), &entry->midr_range);
 }
 
+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)
 {
@@ -184,6 +191,10 @@ static void qcom_enable_link_stack_sanitization(
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
 	CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)
 
+#define CAP_MIDR_RANGE_LIST(list)				\
+	.matches = is_affected_midr_range_list,			\
+	.midr_range_list = list
+
 /* 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)
@@ -197,6 +208,29 @@ static void qcom_enable_link_stack_sanitization(
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
 	CAP_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_LOCAL_CPU_ERRATUM,			\
+	CAP_MIDR_RANGE_LIST(midr_list)
+
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+
+/*
+ * List of CPUs where we need to issue a psci call to
+ * harden the branch predictor.
+ */
+static const struct midr_range arm64_bp_harden_psci_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),
+	MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+	MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+	{},
+};
+
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
 	defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -331,22 +365,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),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
 		.cpu_enable = enable_psci_bp_hardening,
 	},
 	{
@@ -358,16 +377,6 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
 		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
 #endif
 	{
 	}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 247d34ea6b5e..65a8e5cc600c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -864,6 +864,11 @@ 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 scope)
 {
+	/* List of CPUs that are not vulnerable and don't need KPTI */
+	static const struct midr_range kpti_safe_list[] = {
+		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+	};
 
 	/* Forced on command line? */
 	if (__kpti_forced) {
@@ -877,11 +882,8 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 		return true;
 
 	/* Don't force KPTI for CPUs that are not vulnerable */
-	switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
-	case MIDR_CAVIUM_THUNDERX2:
-	case MIDR_BRCM_VULCAN:
+	if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
 		return false;
-	}
 
 	/* Defer to CPU feature registers */
 	return !has_cpuid_feature(entry, scope);
-- 
2.14.3

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

Some capabilities have different criteria for detection and associated
actions based on the matching criteria, even though they all share the
same capability bit. So far we have used multiple entries with the same
capability bit to handle this. This is prone to errors, as the
cpu_enable is invoked for each entry, irrespective of whether the
detection rule applies to the CPU or not. And also this complicates
other helpers, e.g, __this_cpu_has_cap.

This patch adds a wrapper entry to cover all the possible variations
of a capability and ensures :
 1) The capabilitiy is set when at least one of the entry detects
 2) Action is only taken for the entries that detects.

This avoids explicit checks in the call backs. The only constraint
here is that, all the entries should have the same "type".

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
 arch/arm64/kernel/cpufeature.c      |  7 +++--
 3 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 462c35d1a38c..b73247c27f00 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
 			bool sign;
 			unsigned long hwcap;
 		};
+		const struct arm64_cpu_capabilities *cap_list;
 	};
 };
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index eff5f4e380ac..b4f1c1c1f8ca 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -213,6 +213,36 @@ static void qcom_enable_link_stack_sanitization(
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
 	CAP_MIDR_RANGE_LIST(midr_list)
 
+/*
+ * Generic helper for handling capabilties with multiple (match,enable) pairs
+ * of call backs, sharing the same capability bit.
+ * Iterate over each entry to see if at least one matches.
+ */
+static bool multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
+				    int scope)
+{
+	const struct arm64_cpu_capabilities *caps = entry->cap_list;
+
+	for (; caps->matches; caps++)
+		if (caps->matches(caps, scope))
+			return true;
+	return false;
+}
+
+/*
+ * Take appropriate action for all matching entries in the shared capability
+ * entry.
+ */
+static void multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry)
+{
+	const struct arm64_cpu_capabilities *caps = entry->cap_list;
+
+	for (; caps->matches; caps++)
+		if (caps->matches(caps, SCOPE_LOCAL_CPU) &&
+		    caps->cpu_enable)
+			caps->cpu_enable(caps);
+}
+
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 
 /*
@@ -229,6 +259,18 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
 	{},
 };
 
+static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
+	{
+		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
+		.cpu_enable = enable_psci_bp_hardening,
+	},
+	{
+		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		.cpu_enable = qcom_enable_link_stack_sanitization,
+	},
+	{},
+};
+
 #endif
 
 const struct arm64_cpu_capabilities arm64_errata[] = {
@@ -365,13 +407,10 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
-		.cpu_enable = qcom_enable_link_stack_sanitization,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.matches = multi_entry_cap_matches,
+		.cpu_enable = multi_entry_cap_cpu_enable,
+		.cap_list = arm64_bp_harden_list,
 	},
 	{
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 65a8e5cc600c..13e30c1b1e99 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 		return false;
 
 	for (caps = cap_array; caps->matches; caps++)
-		if (caps->capability == cap &&
-		    caps->matches(caps, SCOPE_LOCAL_CPU))
-			return true;
+		if (caps->capability == cap)
+			return caps->matches(caps, SCOPE_LOCAL_CPU);
 	return false;
 }
 
@@ -1275,7 +1274,7 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 		if (!(caps->type & scope_mask))
 			continue;
 
-		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
+		cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU);
 		system_has_cap =  cpus_have_cap(caps->capability);
 
 		if (system_has_cap) {
-- 
2.14.3

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

Some capabilities have different criteria for detection and associated
actions based on the matching criteria, even though they all share the
same capability bit. So far we have used multiple entries with the same
capability bit to handle this. This is prone to errors, as the
cpu_enable is invoked for each entry, irrespective of whether the
detection rule applies to the CPU or not. And also this complicates
other helpers, e.g, __this_cpu_has_cap.

This patch adds a wrapper entry to cover all the possible variations
of a capability and ensures :
 1) The capabilitiy is set when at least one of the entry detects
 2) Action is only taken for the entries that detects.

This avoids explicit checks in the call backs. The only constraint
here is that, all the entries should have the same "type".

Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  1 +
 arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
 arch/arm64/kernel/cpufeature.c      |  7 +++--
 3 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 462c35d1a38c..b73247c27f00 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
 			bool sign;
 			unsigned long hwcap;
 		};
+		const struct arm64_cpu_capabilities *cap_list;
 	};
 };
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index eff5f4e380ac..b4f1c1c1f8ca 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -213,6 +213,36 @@ static void qcom_enable_link_stack_sanitization(
 	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
 	CAP_MIDR_RANGE_LIST(midr_list)
 
+/*
+ * Generic helper for handling capabilties with multiple (match,enable) pairs
+ * of call backs, sharing the same capability bit.
+ * Iterate over each entry to see if at least one matches.
+ */
+static bool multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
+				    int scope)
+{
+	const struct arm64_cpu_capabilities *caps = entry->cap_list;
+
+	for (; caps->matches; caps++)
+		if (caps->matches(caps, scope))
+			return true;
+	return false;
+}
+
+/*
+ * Take appropriate action for all matching entries in the shared capability
+ * entry.
+ */
+static void multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry)
+{
+	const struct arm64_cpu_capabilities *caps = entry->cap_list;
+
+	for (; caps->matches; caps++)
+		if (caps->matches(caps, SCOPE_LOCAL_CPU) &&
+		    caps->cpu_enable)
+			caps->cpu_enable(caps);
+}
+
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 
 /*
@@ -229,6 +259,18 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
 	{},
 };
 
+static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
+	{
+		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
+		.cpu_enable = enable_psci_bp_hardening,
+	},
+	{
+		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		.cpu_enable = qcom_enable_link_stack_sanitization,
+	},
+	{},
+};
+
 #endif
 
 const struct arm64_cpu_capabilities arm64_errata[] = {
@@ -365,13 +407,10 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
-		.cpu_enable = enable_psci_bp_hardening,
-	},
-	{
-		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
-		.cpu_enable = qcom_enable_link_stack_sanitization,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.matches = multi_entry_cap_matches,
+		.cpu_enable = multi_entry_cap_cpu_enable,
+		.cap_list = arm64_bp_harden_list,
 	},
 	{
 		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 65a8e5cc600c..13e30c1b1e99 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
 		return false;
 
 	for (caps = cap_array; caps->matches; caps++)
-		if (caps->capability == cap &&
-		    caps->matches(caps, SCOPE_LOCAL_CPU))
-			return true;
+		if (caps->capability == cap)
+			return caps->matches(caps, SCOPE_LOCAL_CPU);
 	return false;
 }
 
@@ -1275,7 +1274,7 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 		if (!(caps->type & scope_mask))
 			continue;
 
-		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
+		cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU);
 		system_has_cap =  cpus_have_cap(caps->capability);
 
 		if (system_has_cap) {
-- 
2.14.3

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, jnair,
	Suzuki K Poulose

We defend against branch predictor training based exploits by
taking specific actions (based on the CPU model) to invalidate
the Branch predictor buffer (BPB). This is implemented by per-CPU
ptr, which installs the specific actions for the CPU model.

The core code can handle the following cases where:
 1) some CPUs doesn't need any work around
 2) a CPU can install the work around, when it is brought up,
    irrespective of how late that happens.

This concludes that it is safe to bring up a CPU which requires
bp hardening defense. However, with the current settings, we
reject a late CPU, if none of the active CPUs didn't need it.

This patch solves issue by changing the flags for the capability
to indicate that it is safe for a late CPU to turn up with the
capability. This is not sufficient to get things working, as
we cannot change the system wide state of the capability established
at the kernel boot. So, we "set" the capability unconditionally
and make sure that the call backs are only installed for those
CPUs which actually needs them. This is done by adding a dummy
entry at the end of the list of shared entries, which :
 a) Always returns true for matches, to ensure we turn this on.
 b) has an empty "cpu_enable" call back, so that we don't take
    any action on the CPUs which weren't matched with the real
    entries.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 10 ++++++++++
 arch/arm64/kernel/cpu_errata.c      | 19 ++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index b73247c27f00..262fa213b1b1 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -252,6 +252,16 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
 	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
 
+/*
+ * CPU errata work around detected at boot time based on one or more CPUs.
+ * All conflicts are ignored. This implies any work around shouldn't
+ * depend when a CPU could be brought up.
+ */
+#define ARM64_CPUCAP_WEAK_LOCAL_CPU_ERRATUM		\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
+	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
+	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+
 /*
  * CPU feature detected at boot time, on one or more CPUs. A late CPU
  * is not allowed to have the capability when the system doesn't have it.
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index b4f1c1c1f8ca..7f714a628480 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -259,6 +259,12 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
 	{},
 };
 
+static bool bp_hardening_always_on(const struct arm64_cpu_capabilities *cap,
+				   int scope)
+{
+	return true;
+}
+
 static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
 	{
 		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
@@ -268,6 +274,17 @@ static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
 		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 		.cpu_enable = qcom_enable_link_stack_sanitization,
 	},
+	/*
+	 * Always enable the capability to make sure a late CPU can
+	 * safely use the BP hardening call backs. Since we use per-CPU
+	 * pointers for the call backs, the work around only affects the
+	 * CPUs which have some methods installed by any real matching entries
+	 * above. As such we don't have any specific cpu_enable() callback
+	 * for this entry, as it is just to make sure we always "detect" it.
+	 */
+	{
+		.matches = bp_hardening_always_on,
+	},
 	{},
 };
 
@@ -407,7 +424,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_ERRATUM,
 		.matches = multi_entry_cap_matches,
 		.cpu_enable = multi_entry_cap_cpu_enable,
 		.cap_list = arm64_bp_harden_list,
-- 
2.14.3

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

We defend against branch predictor training based exploits by
taking specific actions (based on the CPU model) to invalidate
the Branch predictor buffer (BPB). This is implemented by per-CPU
ptr, which installs the specific actions for the CPU model.

The core code can handle the following cases where:
 1) some CPUs doesn't need any work around
 2) a CPU can install the work around, when it is brought up,
    irrespective of how late that happens.

This concludes that it is safe to bring up a CPU which requires
bp hardening defense. However, with the current settings, we
reject a late CPU, if none of the active CPUs didn't need it.

This patch solves issue by changing the flags for the capability
to indicate that it is safe for a late CPU to turn up with the
capability. This is not sufficient to get things working, as
we cannot change the system wide state of the capability established
at the kernel boot. So, we "set" the capability unconditionally
and make sure that the call backs are only installed for those
CPUs which actually needs them. This is done by adding a dummy
entry at the end of the list of shared entries, which :
 a) Always returns true for matches, to ensure we turn this on.
 b) has an empty "cpu_enable" call back, so that we don't take
    any action on the CPUs which weren't matched with the real
    entries.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 10 ++++++++++
 arch/arm64/kernel/cpu_errata.c      | 19 ++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index b73247c27f00..262fa213b1b1 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -252,6 +252,16 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
 	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
 
+/*
+ * CPU errata work around detected at boot time based on one or more CPUs.
+ * All conflicts are ignored. This implies any work around shouldn't
+ * depend when a CPU could be brought up.
+ */
+#define ARM64_CPUCAP_WEAK_LOCAL_CPU_ERRATUM		\
+	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
+	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
+	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+
 /*
  * CPU feature detected at boot time, on one or more CPUs. A late CPU
  * is not allowed to have the capability when the system doesn't have it.
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index b4f1c1c1f8ca..7f714a628480 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -259,6 +259,12 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
 	{},
 };
 
+static bool bp_hardening_always_on(const struct arm64_cpu_capabilities *cap,
+				   int scope)
+{
+	return true;
+}
+
 static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
 	{
 		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
@@ -268,6 +274,17 @@ static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
 		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
 		.cpu_enable = qcom_enable_link_stack_sanitization,
 	},
+	/*
+	 * Always enable the capability to make sure a late CPU can
+	 * safely use the BP hardening call backs. Since we use per-CPU
+	 * pointers for the call backs, the work around only affects the
+	 * CPUs which have some methods installed by any real matching entries
+	 * above. As such we don't have any specific cpu_enable() callback
+	 * for this entry, as it is just to make sure we always "detect" it.
+	 */
+	{
+		.matches = bp_hardening_always_on,
+	},
 	{},
 };
 
@@ -407,7 +424,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	{
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_ERRATUM,
 		.matches = multi_entry_cap_matches,
 		.cpu_enable = multi_entry_cap_cpu_enable,
 		.cap_list = arm64_bp_harden_list,
-- 
2.14.3

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

* [PATCH v2 18/20] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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.14.3

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

* [PATCH v2 18/20] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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.14.3

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

* [PATCH v2 19/20] arm64: Delay enabling hardware DBM feature
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/kernel/cpufeature.c   | 40 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/proc.S             |  9 +++------
 3 files changed, 45 insertions(+), 7 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/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 13e30c1b1e99..1f695a998eed 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -903,6 +903,33 @@ 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 void cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
+{
+	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
+		__cpu_enable_hw_dbm();
+}
+#endif
+
 static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
@@ -1059,6 +1086,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.cpu_enable = cpu_clear_disr,
 	},
 #endif /* CONFIG_ARM64_RAS_EXTN */
+#ifdef CONFIG_ARM64_HW_AFDBM
+	{
+		.desc = "Hardware pagetable Dirty Bit Management",
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_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,
+		.cpu_enable = cpu_enable_hw_dbm,
+	},
+#endif
 	{},
 };
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 9f177aac6390..68e08ad54944 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -253,12 +253,9 @@ 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
-2:
+	cbz	x9, 1f
+	orr	x10, x10, #TCR_HA		// hardware Access flag update
+1:
 #endif	/* CONFIG_ARM64_HW_AFDBM */
 	msr	tcr_el1, x10
 	ret					// return to head.S
-- 
2.14.3

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

* [PATCH v2 19/20] arm64: Delay enabling hardware DBM feature
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/kernel/cpufeature.c   | 40 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/proc.S             |  9 +++------
 3 files changed, 45 insertions(+), 7 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/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 13e30c1b1e99..1f695a998eed 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -903,6 +903,33 @@ 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 void cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
+{
+	if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
+		__cpu_enable_hw_dbm();
+}
+#endif
+
 static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 {
 	/*
@@ -1059,6 +1086,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.cpu_enable = cpu_clear_disr,
 	},
 #endif /* CONFIG_ARM64_RAS_EXTN */
+#ifdef CONFIG_ARM64_HW_AFDBM
+	{
+		.desc = "Hardware pagetable Dirty Bit Management",
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_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,
+		.cpu_enable = cpu_enable_hw_dbm,
+	},
+#endif
 	{},
 };
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 9f177aac6390..68e08ad54944 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -253,12 +253,9 @@ 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
-2:
+	cbz	x9, 1f
+	orr	x10, x10, #TCR_HA		// hardware Access flag update
+1:
 #endif	/* CONFIG_ARM64_HW_AFDBM */
 	msr	tcr_el1, x10
 	ret					// return to head.S
-- 
2.14.3

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

* [PATCH v2 20/20] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
  2018-01-31 18:27 ` Suzuki K Poulose
@ 2018-01-31 18:28   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, ard.biesheuvel, will.deacon, mark.rutland,
	marc.zyngier, catalin.marinas, ckadabi, dave.martin, 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. There are some other cores suffering from this
errata, which could be added to the midr_list to trigger the work
around.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: ckadabi@codeaurora.org
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 1f695a998eed..410fbddec129 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -923,9 +923,21 @@ static inline void __cpu_enable_hw_dbm(void)
 	isb();
 }
 
+static bool cpu_has_erratum_1024718(void)
+{
+	static const struct midr_range 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 void 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();
 }
 #endif
-- 
2.14.3

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

* [PATCH v2 20/20] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
@ 2018-01-31 18:28   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-01-31 18: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. There are some other cores suffering from this
errata, which could be added to the midr_list to trigger the work
around.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: ckadabi at codeaurora.org
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 1f695a998eed..410fbddec129 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -923,9 +923,21 @@ static inline void __cpu_enable_hw_dbm(void)
 	isb();
 }
 
+static bool cpu_has_erratum_1024718(void)
+{
+	static const struct midr_range 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 void 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();
 }
 #endif
-- 
2.14.3

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

* Re: [PATCH v2 01/20] arm64: capabilities: Update prototype for enable call back
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:37     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 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, dave.martin

On Wed, Jan 31, 2018 at 06:27:48PM +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. Clean up the declaration of the call back to make it clear.
> 
>  1) Renamed to cpu_enable(), to imply taking necessary actions on the
>     called CPU for the entry.
>  2) Pass const pointer to the capability, to allow the call back to
>     check the entry. (e.,g to check if any action is needed on the CPU)
>  3) We don't care about the result of the call back, turning this to
>     a void.
> 
> 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, rename call back,
>  drop call back results
> ]
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Ack for the changes.

Cheers
---Dave

> ---
>  arch/arm64/include/asm/cpufeature.h |  7 ++++++-
>  arch/arm64/include/asm/fpsimd.h     |  4 +++-
>  arch/arm64/include/asm/processor.h  |  7 ++++---
>  arch/arm64/kernel/cpu_errata.c      | 41 +++++++++++++++----------------------
>  arch/arm64/kernel/cpufeature.c      | 33 ++++++++++++++++-------------
>  arch/arm64/kernel/fpsimd.c          |  5 ++---
>  arch/arm64/kernel/traps.c           |  4 ++--
>  arch/arm64/mm/fault.c               |  3 +--
>  8 files changed, 54 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc2585a..f46eb7d1625f 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -97,7 +97,12 @@ 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 */
> +	/*
> +	 * Take the appropriate actions to enable this capability for this CPU.
> +	 * For each successfully booted CPU, this method is called for each
> +	 * globally detected capability.
> +	 */
> +	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>  	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..7623762f7fa6 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 void 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..83a3d2887ca6 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);
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
> +void 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 ed6881882231..e34bee500692 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -53,11 +53,11 @@ 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 void cpu_enable_trap_ctr_access(
> +	const struct arm64_cpu_capabilities *__unused)
>  {
>  	/* Clear SCTLR_EL1.UCT */
>  	config_sctlr_el1(SCTLR_EL1_UCT, 0);
> -	return 0;
>  }
>  
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> @@ -144,17 +144,13 @@ 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 void 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,
>  				       __psci_hyp_bp_inval_start,
>  				       __psci_hyp_bp_inval_end);
> -
> -	return 0;
>  }
>  
>  static void qcom_link_stack_sanitization(void)
> @@ -169,15 +165,12 @@ static void qcom_link_stack_sanitization(void)
>  		     : "=&r" (tmp));
>  }
>  
> -static int qcom_enable_link_stack_sanitization(void *data)
> +static void 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);
> -
> -	return 0;
>  }
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> @@ -204,7 +197,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.desc = "ARM errata 826319, 827319, 824069",
>  		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>  		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>  	},
>  #endif
>  #ifdef CONFIG_ARM64_ERRATUM_819472
> @@ -213,7 +206,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.desc = "ARM errata 819472",
>  		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>  		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>  	},
>  #endif
>  #ifdef CONFIG_ARM64_ERRATUM_832075
> @@ -294,7 +287,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
>  		.matches = has_mismatched_cache_line_size,
>  		.def_scope = SCOPE_LOCAL_CPU,
> -		.enable = cpu_enable_trap_ctr_access,
> +		.cpu_enable = cpu_enable_trap_ctr_access,
>  	},
>  #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
>  	{
> @@ -333,27 +326,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> -		.enable = qcom_enable_link_stack_sanitization,
> +		.cpu_enable = qcom_enable_link_stack_sanitization,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> @@ -362,12 +355,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  #endif
>  	{
> @@ -385,8 +378,8 @@ void verify_local_cpu_errata_workarounds(void)
>  
>  	for (; caps->matches; caps++) {
>  		if (cpus_have_cap(caps->capability)) {
> -			if (caps->enable)
> -				caps->enable((void *)caps);
> +			if (caps->cpu_enable)
> +				caps->cpu_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 4b6f9051cf0c..0b881d9fcde2 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -894,7 +894,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 void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>  {
>  	/*
>  	 * Copy register values that aren't redirected by hardware.
> @@ -906,8 +906,6 @@ static int cpu_copy_el2regs(void *__unused)
>  	 */
>  	if (!alternatives_applied)
>  		write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
> -
> -	return 0;
>  }
>  
>  static const struct arm64_cpu_capabilities arm64_features[] = {
> @@ -931,7 +929,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
>  		.sign = FTR_UNSIGNED,
>  		.min_field_value = 1,
> -		.enable = cpu_enable_pan,
> +		.cpu_enable = cpu_enable_pan,
>  	},
>  #endif /* CONFIG_ARM64_PAN */
>  #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
> @@ -979,7 +977,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.capability = ARM64_HAS_VIRT_HOST_EXTN,
>  		.def_scope = SCOPE_SYSTEM,
>  		.matches = runs_at_el2,
> -		.enable = cpu_copy_el2regs,
> +		.cpu_enable = cpu_copy_el2regs,
>  	},
>  	{
>  		.desc = "32-bit EL0 Support",
> @@ -1033,7 +1031,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.field_pos = ID_AA64PFR0_SVE_SHIFT,
>  		.min_field_value = ID_AA64PFR0_SVE,
>  		.matches = has_cpuid_feature,
> -		.enable = sve_kernel_enable,
> +		.cpu_enable = sve_kernel_enable,
>  	},
>  #endif /* CONFIG_ARM64_SVE */
>  #ifdef CONFIG_ARM64_RAS_EXTN
> @@ -1046,7 +1044,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.sign = FTR_UNSIGNED,
>  		.field_pos = ID_AA64PFR0_RAS_SHIFT,
>  		.min_field_value = ID_AA64PFR0_RAS_V1,
> -		.enable = cpu_clear_disr,
> +		.cpu_enable = cpu_clear_disr,
>  	},
>  #endif /* CONFIG_ARM64_RAS_EXTN */
>  	{},
> @@ -1190,6 +1188,15 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>  	}
>  }
>  
> +
> +static int __enable_cpu_capability(void *arg)
> +{
> +	const struct arm64_cpu_capabilities *cap = arg;
> +
> +	cap->cpu_enable(cap);
> +	return 0;
> +}
> +
>  /*
>   * Run through the enabled capabilities and enable() it on all active
>   * CPUs
> @@ -1205,14 +1212,14 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
>  		/* Ensure cpus_have_const_cap(num) works */
>  		static_branch_enable(&cpu_hwcap_keys[num]);
>  
> -		if (caps->enable) {
> +		if (caps->cpu_enable) {
>  			/*
>  			 * Use stop_machine() as it schedules the work allowing
>  			 * us to modify PSTATE, instead of on_each_cpu() which
>  			 * 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);
>  		}
>  	}
>  }
> @@ -1255,8 +1262,8 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
>  					smp_processor_id(), caps->desc);
>  			cpu_die_early();
>  		}
> -		if (caps->enable)
> -			caps->enable((void *)caps);
> +		if (caps->cpu_enable)
> +			caps->cpu_enable(caps);
>  	}
>  }
>  
> @@ -1479,10 +1486,8 @@ static int __init enable_mrs_emulation(void)
>  
>  core_initcall(enable_mrs_emulation);
>  
> -int cpu_clear_disr(void *__unused)
> +void 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);
> -
> -	return 0;
>  }
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 55fb544072f6..35c563536b0c 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,12 +758,10 @@ 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)
> +void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
>  {
>  	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
>  	isb();
> -
> -	return 0;
>  }
>  
>  void __init sve_setup(void)
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index bbb0fde2780e..a2f6492b4ea3 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,10 +375,9 @@ 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)
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
>  {
>  	config_sctlr_el1(SCTLR_EL1_UCI, 0);
> -	return 0;
>  }
>  
>  #define __user_cache_maint(insn, address, res)			\
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 0e671ddf4855..ccfbe979be17 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)
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>  {
>  	/*
>  	 * We modify PSTATE. This won't work from irq context as the PSTATE
> @@ -823,6 +823,5 @@ int cpu_enable_pan(void *__unused)
>  
>  	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
>  	asm(SET_PSTATE_PAN(1));
> -	return 0;
>  }
>  #endif /* CONFIG_ARM64_PAN */
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 01/20] arm64: capabilities: Update prototype for enable call back
@ 2018-02-07 10:37     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:48PM +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. Clean up the declaration of the call back to make it clear.
> 
>  1) Renamed to cpu_enable(), to imply taking necessary actions on the
>     called CPU for the entry.
>  2) Pass const pointer to the capability, to allow the call back to
>     check the entry. (e.,g to check if any action is needed on the CPU)
>  3) We don't care about the result of the call back, turning this to
>     a void.
> 
> 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, rename call back,
>  drop call back results
> ]
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Ack for the changes.

Cheers
---Dave

> ---
>  arch/arm64/include/asm/cpufeature.h |  7 ++++++-
>  arch/arm64/include/asm/fpsimd.h     |  4 +++-
>  arch/arm64/include/asm/processor.h  |  7 ++++---
>  arch/arm64/kernel/cpu_errata.c      | 41 +++++++++++++++----------------------
>  arch/arm64/kernel/cpufeature.c      | 33 ++++++++++++++++-------------
>  arch/arm64/kernel/fpsimd.c          |  5 ++---
>  arch/arm64/kernel/traps.c           |  4 ++--
>  arch/arm64/mm/fault.c               |  3 +--
>  8 files changed, 54 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc2585a..f46eb7d1625f 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -97,7 +97,12 @@ 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 */
> +	/*
> +	 * Take the appropriate actions to enable this capability for this CPU.
> +	 * For each successfully booted CPU, this method is called for each
> +	 * globally detected capability.
> +	 */
> +	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>  	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..7623762f7fa6 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 void 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..83a3d2887ca6 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);
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
> +void 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 ed6881882231..e34bee500692 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -53,11 +53,11 @@ 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 void cpu_enable_trap_ctr_access(
> +	const struct arm64_cpu_capabilities *__unused)
>  {
>  	/* Clear SCTLR_EL1.UCT */
>  	config_sctlr_el1(SCTLR_EL1_UCT, 0);
> -	return 0;
>  }
>  
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> @@ -144,17 +144,13 @@ 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 void 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,
>  				       __psci_hyp_bp_inval_start,
>  				       __psci_hyp_bp_inval_end);
> -
> -	return 0;
>  }
>  
>  static void qcom_link_stack_sanitization(void)
> @@ -169,15 +165,12 @@ static void qcom_link_stack_sanitization(void)
>  		     : "=&r" (tmp));
>  }
>  
> -static int qcom_enable_link_stack_sanitization(void *data)
> +static void 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);
> -
> -	return 0;
>  }
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> @@ -204,7 +197,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.desc = "ARM errata 826319, 827319, 824069",
>  		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>  		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>  	},
>  #endif
>  #ifdef CONFIG_ARM64_ERRATUM_819472
> @@ -213,7 +206,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.desc = "ARM errata 819472",
>  		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>  		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>  	},
>  #endif
>  #ifdef CONFIG_ARM64_ERRATUM_832075
> @@ -294,7 +287,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
>  		.matches = has_mismatched_cache_line_size,
>  		.def_scope = SCOPE_LOCAL_CPU,
> -		.enable = cpu_enable_trap_ctr_access,
> +		.cpu_enable = cpu_enable_trap_ctr_access,
>  	},
>  #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
>  	{
> @@ -333,27 +326,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> -		.enable = qcom_enable_link_stack_sanitization,
> +		.cpu_enable = qcom_enable_link_stack_sanitization,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> @@ -362,12 +355,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>  		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  #endif
>  	{
> @@ -385,8 +378,8 @@ void verify_local_cpu_errata_workarounds(void)
>  
>  	for (; caps->matches; caps++) {
>  		if (cpus_have_cap(caps->capability)) {
> -			if (caps->enable)
> -				caps->enable((void *)caps);
> +			if (caps->cpu_enable)
> +				caps->cpu_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 4b6f9051cf0c..0b881d9fcde2 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -894,7 +894,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 void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>  {
>  	/*
>  	 * Copy register values that aren't redirected by hardware.
> @@ -906,8 +906,6 @@ static int cpu_copy_el2regs(void *__unused)
>  	 */
>  	if (!alternatives_applied)
>  		write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
> -
> -	return 0;
>  }
>  
>  static const struct arm64_cpu_capabilities arm64_features[] = {
> @@ -931,7 +929,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
>  		.sign = FTR_UNSIGNED,
>  		.min_field_value = 1,
> -		.enable = cpu_enable_pan,
> +		.cpu_enable = cpu_enable_pan,
>  	},
>  #endif /* CONFIG_ARM64_PAN */
>  #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
> @@ -979,7 +977,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.capability = ARM64_HAS_VIRT_HOST_EXTN,
>  		.def_scope = SCOPE_SYSTEM,
>  		.matches = runs_at_el2,
> -		.enable = cpu_copy_el2regs,
> +		.cpu_enable = cpu_copy_el2regs,
>  	},
>  	{
>  		.desc = "32-bit EL0 Support",
> @@ -1033,7 +1031,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.field_pos = ID_AA64PFR0_SVE_SHIFT,
>  		.min_field_value = ID_AA64PFR0_SVE,
>  		.matches = has_cpuid_feature,
> -		.enable = sve_kernel_enable,
> +		.cpu_enable = sve_kernel_enable,
>  	},
>  #endif /* CONFIG_ARM64_SVE */
>  #ifdef CONFIG_ARM64_RAS_EXTN
> @@ -1046,7 +1044,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.sign = FTR_UNSIGNED,
>  		.field_pos = ID_AA64PFR0_RAS_SHIFT,
>  		.min_field_value = ID_AA64PFR0_RAS_V1,
> -		.enable = cpu_clear_disr,
> +		.cpu_enable = cpu_clear_disr,
>  	},
>  #endif /* CONFIG_ARM64_RAS_EXTN */
>  	{},
> @@ -1190,6 +1188,15 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>  	}
>  }
>  
> +
> +static int __enable_cpu_capability(void *arg)
> +{
> +	const struct arm64_cpu_capabilities *cap = arg;
> +
> +	cap->cpu_enable(cap);
> +	return 0;
> +}
> +
>  /*
>   * Run through the enabled capabilities and enable() it on all active
>   * CPUs
> @@ -1205,14 +1212,14 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
>  		/* Ensure cpus_have_const_cap(num) works */
>  		static_branch_enable(&cpu_hwcap_keys[num]);
>  
> -		if (caps->enable) {
> +		if (caps->cpu_enable) {
>  			/*
>  			 * Use stop_machine() as it schedules the work allowing
>  			 * us to modify PSTATE, instead of on_each_cpu() which
>  			 * 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);
>  		}
>  	}
>  }
> @@ -1255,8 +1262,8 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
>  					smp_processor_id(), caps->desc);
>  			cpu_die_early();
>  		}
> -		if (caps->enable)
> -			caps->enable((void *)caps);
> +		if (caps->cpu_enable)
> +			caps->cpu_enable(caps);
>  	}
>  }
>  
> @@ -1479,10 +1486,8 @@ static int __init enable_mrs_emulation(void)
>  
>  core_initcall(enable_mrs_emulation);
>  
> -int cpu_clear_disr(void *__unused)
> +void 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);
> -
> -	return 0;
>  }
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 55fb544072f6..35c563536b0c 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,12 +758,10 @@ 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)
> +void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
>  {
>  	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
>  	isb();
> -
> -	return 0;
>  }
>  
>  void __init sve_setup(void)
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index bbb0fde2780e..a2f6492b4ea3 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,10 +375,9 @@ 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)
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
>  {
>  	config_sctlr_el1(SCTLR_EL1_UCI, 0);
> -	return 0;
>  }
>  
>  #define __user_cache_maint(insn, address, res)			\
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 0e671ddf4855..ccfbe979be17 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)
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>  {
>  	/*
>  	 * We modify PSTATE. This won't work from irq context as the PSTATE
> @@ -823,6 +823,5 @@ int cpu_enable_pan(void *__unused)
>  
>  	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
>  	asm(SET_PSTATE_PAN(1));
> -	return 0;
>  }
>  #endif /* CONFIG_ARM64_PAN */
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:37     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:49PM +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. While this
> is correct, we can also do this from init_cpu_features() which
> initilisation of the infrastructure, and is called only on the

Typo or missing words here?

Should this be "which initialises the infrastructure" or "which is
called to initialise the infrastructure"?

With that (or any suitable rewording):

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> Boot CPU. This helps to consolidate the CPU capability handling
> to cpufeature.c. No functional changes.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> 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 0b881d9fcde2..ef3cc48bc925 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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU
@ 2018-02-07 10:37     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:49PM +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. While this
> is correct, we can also do this from init_cpu_features() which
> initilisation of the infrastructure, and is called only on the

Typo or missing words here?

Should this be "which initialises the infrastructure" or "which is
called to initialise the infrastructure"?

With that (or any suitable rewording):

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> Boot CPU. This helps to consolidate the CPU capability handling
> to cpufeature.c. No functional changes.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> 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 0b881d9fcde2..ef3cc48bc925 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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 03/20] arm64: capabilities: Move errata processing code
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:37     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:50PM +0000, Suzuki K Poulose wrote:
> 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 code.
> No functional changes.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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 f46eb7d1625f..7925e40c6ded 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -238,15 +238,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 e34bee500692..9de0ee5d73c0 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -366,36 +366,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->cpu_enable)
> -				caps->cpu_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 ef3cc48bc925..f0cd165c75e9 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 */
> @@ -1181,7 +1184,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++) {
> @@ -1207,7 +1210,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;
> @@ -1290,6 +1293,39 @@ static void verify_sve_features(void)
>  	/* Add checks on other ZCR bits here if necessary */
>  }
>  
> +/*
> + * 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->cpu_enable)
> +				caps->cpu_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.
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 03/20] arm64: capabilities: Move errata processing code
@ 2018-02-07 10:37     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:50PM +0000, Suzuki K Poulose wrote:
> 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 code.
> No functional changes.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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 f46eb7d1625f..7925e40c6ded 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -238,15 +238,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 e34bee500692..9de0ee5d73c0 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -366,36 +366,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->cpu_enable)
> -				caps->cpu_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 ef3cc48bc925..f0cd165c75e9 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 */
> @@ -1181,7 +1184,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++) {
> @@ -1207,7 +1210,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;
> @@ -1290,6 +1293,39 @@ static void verify_sve_features(void)
>  	/* Add checks on other ZCR bits here if necessary */
>  }
>  
> +/*
> + * 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->cpu_enable)
> +				caps->cpu_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.
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:37     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:51PM +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. Capabilities
> have some properties that decide how they should be treated :
> 
>  1) Detection, i.e scope : A cap could be "detected" either :
>     - if it is present on at least one CPU (SCOPE_LOCAL_CPU)
> 	Or
>     - if it is present on all the CPUs (SCOPE_SYSTEM)
> 
>  2) When is it enabled ? - A cap is treated as "enabled" when the
>   system takes some action based on whether the capability is detected or
>   not. e.g, setting some control register, patching the kernel code.
>   Right now, we treat all caps are enabled at boot-time, after all
>   the CPUs are brought up by the kernel. But there are certain caps,
>   which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
>   and kernel starts using them, even before the secondary CPUs are brought
>   up. We would need a way to describe this for each capability.
> 
>  3) Conflict on a late CPU - When a CPU is brought up, it is checked
>   against the caps that are known to be enabled on the system (via
>   verify_local_cpu_capabilities()). Based on the state of the capability
>   on the CPU vs. that of System we could have the following combinations
>   of conflict.
> 
> 	x-----------------------------x
> 	| Type	| System   | Late CPU |
> 	------------------------------|
> 	|  a    |   y      |    n     |
> 	------------------------------|
> 	|  b    |   n      |    y     |
> 	x-----------------------------x
> 
>   Case (a) is not permitted for caps which are system features, which the
>   system expects all the CPUs to have (e.g VHE). While (a) is ignored for
>   all errata work arounds. However, there could be exceptions to the plain
>   filtering approach. e.g, KPTI is an optional feature for a late CPU as
>   long as the system already enables it.
> 
>   Case (b) is not permitted for errata work arounds which requires some
>   work around, which cannot be delayed. And we ignore (b) for features. Here,
>   yet again, KPTI is an exception, where if a late CPU needs KPTI we are too
>   late to enable it (because we change the allocation of ASIDs etc).
> 
> 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 (which cover
> errata and features, not the ELF HWCAPs). This is a prepartory step
> to get there. More bits would be added for the properties listed above.
> 
> We are going to use a bit-mask to encode all the properties of a capabilities.
> This patch encodes the "SCOPE" of the capability.
> 
> As such there is no change in how the capabilities are treated.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

A few minor nits in the documentation, otherwise

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> ---
>  arch/arm64/include/asm/cpufeature.h | 90 ++++++++++++++++++++++++++++++++++---
>  arch/arm64/kernel/cpu_errata.c      |  8 ++--
>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++--------
>  3 files changed, 107 insertions(+), 29 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 7925e40c6ded..05da54f1b4c7 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -86,16 +86,89 @@ struct arm64_ftr_reg {
>  
>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  
> -/* scope of capability check */
> -enum {
> -	SCOPE_SYSTEM,
> -	SCOPE_LOCAL_CPU,
> -};
> +/*
> + * CPU capabilities:
> + *
> + * We use arm64_cpu_capabilities to represent system features, errata work
> + * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
> + * ELF HWCAPs (which are exposed to user).
> + *
> + * To support systems with heterogeneous CPUs, we need to make sure that we
> + * detect the capabilities correctly on the system and take appropriate
> + * measures to ensure there are not incompatibilities.
> + *
> + * This comment tries to explain how we treat the capabilities.
> + * Each capability has the following list of attributes :
> + *
> + * 1) Scope of Detection : The system detects a given capability by performing
> + *    some checks at runtime. This could be, e.g, checking the value of a field
> + *    in CPU ID feature register or checking the cpu model. The capability
> + *    provides a call back ( @matches() ) to perform the check.
> + *    Scope defines how the checks should be performed. There are two cases:
> + *
> + *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
> + *        matches. This implies, we have to run the check on all the booting
> + *        CPUs, until the system decides that state of the capability is finalised.
> + *        (See section 2 below)
> + *		Or
> + *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
> + *        This implies, we run the check only once, when the system decides to
> + *        finalise the state of the capability. If the capability relies on a
> + *        field in one of the CPU ID feature registers, we use the sanitised
> + *        value of the register from the CPU feature infrastructure to make
> + *        the decision.
> + *    The process of detection is usually denoted by "update" capability state
> + *    in the code.
> + *
> + * 2) Finalise the state : The kernel should finalise the state of a capability
> + *    at some point during its execution and take necessary actions if any. Usually,
> + *    this is done, after all the boot-time enabled CPUs are brought up by the
> + *    kernel, so that it can make better decision based on the available set
> + *    of CPUs. However, there are some special cases, where the action is taken
> + *    during the early boot by the primary boot CPU. (e.g, running the kernel at
> + *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
> + *    any changes to the state of a capability once it finalises the capability
> + *    and takes any action, as it may be impossible to execute the actions safely.
> + *
> + * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
> + *    the kernel should make sure that it is safe to use the CPU, by verifying
> + *    that the CPU is compliant with the state of the capabilities established

Nit: can we say "finalised" instead of "established"?

There could be doubt about precisely what "established" means.
"Finalised" is clearly defined in (2) -- I'm assuming that's the
intended meaning here (?)

> + *    already. This happens via :
> + *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
> + *      check_early_cpu_features() && verify_local_cpu_capabilities()

Nit: Maybe just say "via secondart_start_kernel()"?  Too much detail
about the exact code flow may become wrong in the future when someone
refactors the code.

> + *
> + *    As explained in (2) above, capabilities could be finalised at different
> + *    points in the execution. Each CPU is verified against the "finalised"
> + *    capabilities and if there is a conflict, the kernel takes an action, based
> + *    on the severity (e.g, a CPU could be prevented from booting or cause a
> + *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> + *    if it has not been finalised already.
> + *
> + * 4) Action: As mentioned in (2), the kernel can take an action for each detected
> + *    capability, on all CPUs on the system. This is always initiated only after

Nit: maybe clarify what an action is, e.g.
"Appropriate actions include patching in alternatives, turning on an
architectural feature or activating errata workarounds."

Can we can that it is the job of the cpu_enable() method to perform the
appropriate action, or is that not universally true?

> + *    the capability is finalised. This is usally denoted by "enabling" the
> + *    capability. The actions are initiated as follows :
> + *	a) Action is triggered on all online CPUs, after the capability is
> + *	finalised, invoked within the stop_machine() context from
> + *	enable_cpu_capabilitie().
> + *
> + *	b) Any late CPU, brought up after (1), the action is triggered via:
> + *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
> + *
> + */
> +
> +
> +/* 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		((u16)BIT(0))
> +#define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>  
>  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);
>  	/*
>  	 * Take the appropriate actions to enable this capability for this CPU.
> @@ -120,6 +193,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 9de0ee5d73c0..328c5a031e45 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
>  #define MIDR_RANGE(model, min, max) \
> -	.def_scope = SCOPE_LOCAL_CPU, \
> +	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
>  	.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_SCOPE_LOCAL_CPU, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
>  	.midr_range_min = 0, \
> @@ -286,7 +286,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_SCOPE_LOCAL_CPU,
>  		.cpu_enable = cpu_enable_trap_ctr_access,
>  	},
>  #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
> @@ -300,7 +300,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_SCOPE_LOCAL_CPU,
>  		.midr_model = MIDR_QCOM_KRYO,
>  		.matches = is_kryo_midr,
>  	},
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index f0cd165c75e9..8d22f0ef0927 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -921,7 +921,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_SCOPE_SYSTEM,
>  		.matches = has_useable_gicv3_cpuif,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.field_pos = ID_AA64PFR0_GIC_SHIFT,
> @@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Privileged Access Never",
>  		.capability = ARM64_HAS_PAN,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>  		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
> @@ -945,7 +945,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_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR0_EL1,
>  		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
> @@ -956,14 +956,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_SCOPE_SYSTEM,
>  		.matches = has_no_hw_prefetch,
>  	},
>  #ifdef CONFIG_ARM64_UAO
>  	{
>  		.desc = "User Access Override",
>  		.capability = ARM64_HAS_UAO,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR2_EL1,
>  		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
> @@ -977,21 +977,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_SCOPE_SYSTEM,
>  		.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_SCOPE_SYSTEM,
>  		.matches = runs_at_el2,
>  		.cpu_enable = cpu_copy_el2regs,
>  	},
>  	{
>  		.desc = "32-bit EL0 Support",
>  		.capability = ARM64_HAS_32BIT_EL0,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1001,21 +1001,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_SCOPE_SYSTEM,
>  		.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_SCOPE_SYSTEM,
>  		.matches = unmap_kernel_at_el0,
>  	},
>  #endif
>  	{
>  		/* FP/SIMD is not implemented */
>  		.capability = ARM64_HAS_NO_FPSIMD,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.min_field_value = 0,
>  		.matches = has_no_fpsimd,
>  	},
> @@ -1023,7 +1023,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_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR1_EL1,
>  		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
> @@ -1033,8 +1033,8 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #ifdef CONFIG_ARM64_SVE
>  	{
>  		.desc = "Scalable Vector Extension",
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.capability = ARM64_SVE,
> -		.def_scope = SCOPE_SYSTEM,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
>  		.field_pos = ID_AA64PFR0_SVE_SHIFT,
> @@ -1047,7 +1047,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_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1059,16 +1059,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_SCOPE_SYSTEM,		\
>  		.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,					\
>  	}
>  
> @@ -1161,7 +1161,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);
>  }
>  
> @@ -1188,7 +1188,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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-02-07 10:37     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:51PM +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. Capabilities
> have some properties that decide how they should be treated :
> 
>  1) Detection, i.e scope : A cap could be "detected" either :
>     - if it is present on at least one CPU (SCOPE_LOCAL_CPU)
> 	Or
>     - if it is present on all the CPUs (SCOPE_SYSTEM)
> 
>  2) When is it enabled ? - A cap is treated as "enabled" when the
>   system takes some action based on whether the capability is detected or
>   not. e.g, setting some control register, patching the kernel code.
>   Right now, we treat all caps are enabled at boot-time, after all
>   the CPUs are brought up by the kernel. But there are certain caps,
>   which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
>   and kernel starts using them, even before the secondary CPUs are brought
>   up. We would need a way to describe this for each capability.
> 
>  3) Conflict on a late CPU - When a CPU is brought up, it is checked
>   against the caps that are known to be enabled on the system (via
>   verify_local_cpu_capabilities()). Based on the state of the capability
>   on the CPU vs. that of System we could have the following combinations
>   of conflict.
> 
> 	x-----------------------------x
> 	| Type	| System   | Late CPU |
> 	------------------------------|
> 	|  a    |   y      |    n     |
> 	------------------------------|
> 	|  b    |   n      |    y     |
> 	x-----------------------------x
> 
>   Case (a) is not permitted for caps which are system features, which the
>   system expects all the CPUs to have (e.g VHE). While (a) is ignored for
>   all errata work arounds. However, there could be exceptions to the plain
>   filtering approach. e.g, KPTI is an optional feature for a late CPU as
>   long as the system already enables it.
> 
>   Case (b) is not permitted for errata work arounds which requires some
>   work around, which cannot be delayed. And we ignore (b) for features. Here,
>   yet again, KPTI is an exception, where if a late CPU needs KPTI we are too
>   late to enable it (because we change the allocation of ASIDs etc).
> 
> 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 (which cover
> errata and features, not the ELF HWCAPs). This is a prepartory step
> to get there. More bits would be added for the properties listed above.
> 
> We are going to use a bit-mask to encode all the properties of a capabilities.
> This patch encodes the "SCOPE" of the capability.
> 
> As such there is no change in how the capabilities are treated.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

A few minor nits in the documentation, otherwise

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> ---
>  arch/arm64/include/asm/cpufeature.h | 90 ++++++++++++++++++++++++++++++++++---
>  arch/arm64/kernel/cpu_errata.c      |  8 ++--
>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++--------
>  3 files changed, 107 insertions(+), 29 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 7925e40c6ded..05da54f1b4c7 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -86,16 +86,89 @@ struct arm64_ftr_reg {
>  
>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  
> -/* scope of capability check */
> -enum {
> -	SCOPE_SYSTEM,
> -	SCOPE_LOCAL_CPU,
> -};
> +/*
> + * CPU capabilities:
> + *
> + * We use arm64_cpu_capabilities to represent system features, errata work
> + * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
> + * ELF HWCAPs (which are exposed to user).
> + *
> + * To support systems with heterogeneous CPUs, we need to make sure that we
> + * detect the capabilities correctly on the system and take appropriate
> + * measures to ensure there are not incompatibilities.
> + *
> + * This comment tries to explain how we treat the capabilities.
> + * Each capability has the following list of attributes :
> + *
> + * 1) Scope of Detection : The system detects a given capability by performing
> + *    some checks at runtime. This could be, e.g, checking the value of a field
> + *    in CPU ID feature register or checking the cpu model. The capability
> + *    provides a call back ( @matches() ) to perform the check.
> + *    Scope defines how the checks should be performed. There are two cases:
> + *
> + *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
> + *        matches. This implies, we have to run the check on all the booting
> + *        CPUs, until the system decides that state of the capability is finalised.
> + *        (See section 2 below)
> + *		Or
> + *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
> + *        This implies, we run the check only once, when the system decides to
> + *        finalise the state of the capability. If the capability relies on a
> + *        field in one of the CPU ID feature registers, we use the sanitised
> + *        value of the register from the CPU feature infrastructure to make
> + *        the decision.
> + *    The process of detection is usually denoted by "update" capability state
> + *    in the code.
> + *
> + * 2) Finalise the state : The kernel should finalise the state of a capability
> + *    at some point during its execution and take necessary actions if any. Usually,
> + *    this is done, after all the boot-time enabled CPUs are brought up by the
> + *    kernel, so that it can make better decision based on the available set
> + *    of CPUs. However, there are some special cases, where the action is taken
> + *    during the early boot by the primary boot CPU. (e.g, running the kernel at
> + *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
> + *    any changes to the state of a capability once it finalises the capability
> + *    and takes any action, as it may be impossible to execute the actions safely.
> + *
> + * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
> + *    the kernel should make sure that it is safe to use the CPU, by verifying
> + *    that the CPU is compliant with the state of the capabilities established

Nit: can we say "finalised" instead of "established"?

There could be doubt about precisely what "established" means.
"Finalised" is clearly defined in (2) -- I'm assuming that's the
intended meaning here (?)

> + *    already. This happens via :
> + *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
> + *      check_early_cpu_features() && verify_local_cpu_capabilities()

Nit: Maybe just say "via secondart_start_kernel()"?  Too much detail
about the exact code flow may become wrong in the future when someone
refactors the code.

> + *
> + *    As explained in (2) above, capabilities could be finalised at different
> + *    points in the execution. Each CPU is verified against the "finalised"
> + *    capabilities and if there is a conflict, the kernel takes an action, based
> + *    on the severity (e.g, a CPU could be prevented from booting or cause a
> + *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> + *    if it has not been finalised already.
> + *
> + * 4) Action: As mentioned in (2), the kernel can take an action for each detected
> + *    capability, on all CPUs on the system. This is always initiated only after

Nit: maybe clarify what an action is, e.g.
"Appropriate actions include patching in alternatives, turning on an
architectural feature or activating errata workarounds."

Can we can that it is the job of the cpu_enable() method to perform the
appropriate action, or is that not universally true?

> + *    the capability is finalised. This is usally denoted by "enabling" the
> + *    capability. The actions are initiated as follows :
> + *	a) Action is triggered on all online CPUs, after the capability is
> + *	finalised, invoked within the stop_machine() context from
> + *	enable_cpu_capabilitie().
> + *
> + *	b) Any late CPU, brought up after (1), the action is triggered via:
> + *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
> + *
> + */
> +
> +
> +/* 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		((u16)BIT(0))
> +#define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
> +#define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
> +#define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
>  
>  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);
>  	/*
>  	 * Take the appropriate actions to enable this capability for this CPU.
> @@ -120,6 +193,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 9de0ee5d73c0..328c5a031e45 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
>  #define MIDR_RANGE(model, min, max) \
> -	.def_scope = SCOPE_LOCAL_CPU, \
> +	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
>  	.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_SCOPE_LOCAL_CPU, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
>  	.midr_range_min = 0, \
> @@ -286,7 +286,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_SCOPE_LOCAL_CPU,
>  		.cpu_enable = cpu_enable_trap_ctr_access,
>  	},
>  #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
> @@ -300,7 +300,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_SCOPE_LOCAL_CPU,
>  		.midr_model = MIDR_QCOM_KRYO,
>  		.matches = is_kryo_midr,
>  	},
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index f0cd165c75e9..8d22f0ef0927 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -921,7 +921,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_SCOPE_SYSTEM,
>  		.matches = has_useable_gicv3_cpuif,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.field_pos = ID_AA64PFR0_GIC_SHIFT,
> @@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Privileged Access Never",
>  		.capability = ARM64_HAS_PAN,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>  		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
> @@ -945,7 +945,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_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR0_EL1,
>  		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
> @@ -956,14 +956,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_SCOPE_SYSTEM,
>  		.matches = has_no_hw_prefetch,
>  	},
>  #ifdef CONFIG_ARM64_UAO
>  	{
>  		.desc = "User Access Override",
>  		.capability = ARM64_HAS_UAO,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR2_EL1,
>  		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
> @@ -977,21 +977,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_SCOPE_SYSTEM,
>  		.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_SCOPE_SYSTEM,
>  		.matches = runs_at_el2,
>  		.cpu_enable = cpu_copy_el2regs,
>  	},
>  	{
>  		.desc = "32-bit EL0 Support",
>  		.capability = ARM64_HAS_32BIT_EL0,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1001,21 +1001,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_SCOPE_SYSTEM,
>  		.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_SCOPE_SYSTEM,
>  		.matches = unmap_kernel_at_el0,
>  	},
>  #endif
>  	{
>  		/* FP/SIMD is not implemented */
>  		.capability = ARM64_HAS_NO_FPSIMD,
> -		.def_scope = SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.min_field_value = 0,
>  		.matches = has_no_fpsimd,
>  	},
> @@ -1023,7 +1023,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_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR1_EL1,
>  		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
> @@ -1033,8 +1033,8 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #ifdef CONFIG_ARM64_SVE
>  	{
>  		.desc = "Scalable Vector Extension",
> +		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>  		.capability = ARM64_SVE,
> -		.def_scope = SCOPE_SYSTEM,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
>  		.field_pos = ID_AA64PFR0_SVE_SHIFT,
> @@ -1047,7 +1047,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_SCOPE_SYSTEM,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1059,16 +1059,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_SCOPE_SYSTEM,		\
>  		.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,					\
>  	}
>  
> @@ -1161,7 +1161,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);
>  }
>  
> @@ -1188,7 +1188,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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:52PM +0000, Suzuki K Poulose wrote:
> When a CPU is brought up, it is checked against the caps that are
> known to be enabled on the system (via verify_local_cpu_capabilities()).
> Based on the state of the capability on the CPU vs. that of System we
> could have the following combinations of conflict.
> 
> 	x-----------------------------x
> 	| Type  | System   | Late CPU |
> 	|-----------------------------|
> 	|  a    |   y      |    n     |
> 	|-----------------------------|
> 	|  b    |   n      |    y     |
> 	x-----------------------------x
> 
> Case (a) is not permitted for caps which are system features, which the
> system expects all the CPUs to have (e.g VHE). While (a) is ignored for
> all errata work arounds. However, there could be exceptions to the plain
> filtering approach. e.g, KPTI is an optional feature for a late CPU as
> long as the system already enables it.
> 
> Case (b) is not permitted for errata work arounds which requires some work
> around, which cannot be delayed. And we ignore (b) for features. Here, yet

Nit, maybe:

"Case (b) is not permitted for any errata workaround that cannot be
activated if the kernel has finished booting and has not already enabled
it."

> again, KPTI is an exception, where if a late CPU needs KPTI we are too late
> to enable it (because we change the allocation of ASIDs etc).
> 
> Add two different flags to indicate how the conflict should be handled.
> 
>  ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - CPUs may have the capability
>  ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - CPUs may not have the cappability.
> 
> Now that we have the flags to describe the behavior of the errata and
> the features, as we treat them, define types for ERRATUM and FEATURE.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

All my suggestions in this patch are rewordings of comments, so they're
not vital, and anyway you may disagree that they make the meaning
clearer.  So I don't think they're essential.

For the actual code

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> ---
>  arch/arm64/include/asm/cpufeature.h | 61 ++++++++++++++++++++++++++++++++++++-
>  arch/arm64/kernel/cpu_errata.c      |  8 ++---
>  arch/arm64/kernel/cpufeature.c      | 30 +++++++++---------
>  3 files changed, 79 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 05da54f1b4c7..7460b1f7e611 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -142,7 +142,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *    capabilities and if there is a conflict, the kernel takes an action, based
>   *    on the severity (e.g, a CPU could be prevented from booting or cause a
>   *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> - *    if it has not been finalised already.
> + *    if it has not been finalised already. See section 5 for more details on
> + *    conflicts.
>   *
>   * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>   *    capability, on all CPUs on the system. This is always initiated only after
> @@ -155,6 +156,32 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *	b) Any late CPU, brought up after (1), the action is triggered via:
>   *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
>   *
> + * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
> + *    state, we could have the following combinations :
> + *
> + *		x-----------------------------x
> + *		| Type  | System   | Late CPU |
> + *		|-----------------------------|
> + *		|  a    |   y      |    n     |
> + *		|-----------------------------|
> + *		|  b    |   n      |    y     |
> + *		x-----------------------------x

Nit: I find this a bit hard to follow.  Maybe reordering things a bit
would help but putting the rule (the precise bit) first, and the
rationale (necessarily more vague) afterward:

"Two capability type flag bits are defined to indicate whether each kind
of conflict can be tolerated:

		ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case (a) is allowed
		ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case (b) is allowed."

> + *
> + *     Case (a) is not permitted for capabilities which are usually system
> + *     features, which the system expects all CPUs to have. While (a) is ignored
> + *     for capabilities which represents an erratum work around.

Similarly "Case (a) is not permitted for a capability that the system
requires all CPUs to have in order for the capability to be enabled.
This is typical for capabilities that represent enhanced functionality."

> + *
> + *     Case (b) is not permitted for erratum capabilities, which might require
> + *     some work arounds which cannot be applied really late. Meanwhile, most
> + *     of the features could safely ignore (b), as the system doesn't use it
> + *     anyway.

and

"Case (b) is not permitted for a capability that the system must enable
during boot if any CPU in the system requires it in order to run safely.
This is typical for erratum workarounds that cannot be enabled after the
corresponding capability is finalised.

In some non-typical cases, either both (a) and (b), or neither, should
be permitted.  This can be described by including neither or both flags
in the capability's type field."

[...]

>  
>  
> @@ -165,6 +192,26 @@ 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
>  
> +/* Is it permitted for a late CPU to have this capability when system doesn't already have */

"doesn't already have" -> "hasn't already enabled it"?

> +#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
> +/* Is it safe for a late CPU to miss this capability when system has it */
> +#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
> +
> +/*
> + * 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

Can we around using the word "feature" to describe errata here?

Maybe "CPU errata workarounds that need to be enabled at boot time if
one or more CPUs in the system requires the workaround.  When one of
these workaround capabilities has been enabled, it is safe to allow any
CPU to boot that does not require the workaround."

> + * have it. But it is safe to miss the feature if the system has it.
> + */
> +#define ARM64_CPUCAP_LOCAL_CPU_ERRATUM		\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
> +/*
> + * 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.

"hasn't enabled it, although the feature will not be used by Linux
in this case.  If the system has enabled this feature already then every
late CPU must have it."

> + */
> +#define ARM64_CPUCAP_SYSTEM_FEATURE	\
> +	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
> +
>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> @@ -198,6 +245,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_optional(const struct arm64_cpu_capabilities *cap)
> +{
> +	return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
> +}
> +
> +static inline bool
> +cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
> +{
> +	return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
> +}
> +
>  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 328c5a031e45..22ec3960a0c5 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
>  #define MIDR_RANGE(model, min, max) \
> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
>  	.midr_range_min = min, \
>  	.midr_range_max = max
>  
>  #define MIDR_ALL_VERSIONS(model) \
> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
>  	.midr_range_min = 0, \
> @@ -286,7 +286,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,
> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> +		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
>  		.cpu_enable = cpu_enable_trap_ctr_access,
>  	},
>  #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
> @@ -300,7 +300,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  	{
>  		.desc = "Qualcomm Technologies Kryo erratum 1003",
>  		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> +		.type = ARM64_CPUCAP_LOCAL_CPU_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 8d22f0ef0927..1b29b3f0a1bc 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -921,7 +921,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "GIC system register CPU interface",
>  		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_useable_gicv3_cpuif,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.field_pos = ID_AA64PFR0_GIC_SHIFT,
> @@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Privileged Access Never",
>  		.capability = ARM64_HAS_PAN,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>  		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
> @@ -945,7 +945,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "LSE atomic instructions",
>  		.capability = ARM64_HAS_LSE_ATOMICS,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR0_EL1,
>  		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
> @@ -956,14 +956,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Software prefetching using PRFM",
>  		.capability = ARM64_HAS_NO_HW_PREFETCH,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_no_hw_prefetch,
>  	},
>  #ifdef CONFIG_ARM64_UAO
>  	{
>  		.desc = "User Access Override",
>  		.capability = ARM64_HAS_UAO,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR2_EL1,
>  		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
> @@ -977,21 +977,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #ifdef CONFIG_ARM64_PAN
>  	{
>  		.capability = ARM64_ALT_PAN_NOT_UAO,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = cpufeature_pan_not_uao,
>  	},
>  #endif /* CONFIG_ARM64_PAN */
>  	{
>  		.desc = "Virtualization Host Extensions",
>  		.capability = ARM64_HAS_VIRT_HOST_EXTN,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = runs_at_el2,
>  		.cpu_enable = cpu_copy_el2regs,
>  	},
>  	{
>  		.desc = "32-bit EL0 Support",
>  		.capability = ARM64_HAS_32BIT_EL0,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1001,21 +1001,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Reduced HYP mapping offset",
>  		.capability = ARM64_HYP_OFFSET_LOW,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = hyp_offset_low,
>  	},
>  #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>  	{
>  		.desc = "Kernel page table isolation (KPTI)",
>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = unmap_kernel_at_el0,
>  	},
>  #endif
>  	{
>  		/* FP/SIMD is not implemented */
>  		.capability = ARM64_HAS_NO_FPSIMD,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.min_field_value = 0,
>  		.matches = has_no_fpsimd,
>  	},
> @@ -1023,7 +1023,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Data cache clean to Point of Persistence",
>  		.capability = ARM64_HAS_DCPOP,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR1_EL1,
>  		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
> @@ -1033,7 +1033,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #ifdef CONFIG_ARM64_SVE
>  	{
>  		.desc = "Scalable Vector Extension",
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.capability = ARM64_SVE,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1047,7 +1047,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "RAS Extension Support",
>  		.capability = ARM64_HAS_RAS_EXTN,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1062,7 +1062,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
>  	{							\
>  		.desc = #cap,					\
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,		\
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
>  		.matches = has_cpuid_feature,			\
>  		.sys_reg = reg,					\
>  		.field_pos = field,				\
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:52PM +0000, Suzuki K Poulose wrote:
> When a CPU is brought up, it is checked against the caps that are
> known to be enabled on the system (via verify_local_cpu_capabilities()).
> Based on the state of the capability on the CPU vs. that of System we
> could have the following combinations of conflict.
> 
> 	x-----------------------------x
> 	| Type  | System   | Late CPU |
> 	|-----------------------------|
> 	|  a    |   y      |    n     |
> 	|-----------------------------|
> 	|  b    |   n      |    y     |
> 	x-----------------------------x
> 
> Case (a) is not permitted for caps which are system features, which the
> system expects all the CPUs to have (e.g VHE). While (a) is ignored for
> all errata work arounds. However, there could be exceptions to the plain
> filtering approach. e.g, KPTI is an optional feature for a late CPU as
> long as the system already enables it.
> 
> Case (b) is not permitted for errata work arounds which requires some work
> around, which cannot be delayed. And we ignore (b) for features. Here, yet

Nit, maybe:

"Case (b) is not permitted for any errata workaround that cannot be
activated if the kernel has finished booting and has not already enabled
it."

> again, KPTI is an exception, where if a late CPU needs KPTI we are too late
> to enable it (because we change the allocation of ASIDs etc).
> 
> Add two different flags to indicate how the conflict should be handled.
> 
>  ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - CPUs may have the capability
>  ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - CPUs may not have the cappability.
> 
> Now that we have the flags to describe the behavior of the errata and
> the features, as we treat them, define types for ERRATUM and FEATURE.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

All my suggestions in this patch are rewordings of comments, so they're
not vital, and anyway you may disagree that they make the meaning
clearer.  So I don't think they're essential.

For the actual code

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> ---
>  arch/arm64/include/asm/cpufeature.h | 61 ++++++++++++++++++++++++++++++++++++-
>  arch/arm64/kernel/cpu_errata.c      |  8 ++---
>  arch/arm64/kernel/cpufeature.c      | 30 +++++++++---------
>  3 files changed, 79 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 05da54f1b4c7..7460b1f7e611 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -142,7 +142,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *    capabilities and if there is a conflict, the kernel takes an action, based
>   *    on the severity (e.g, a CPU could be prevented from booting or cause a
>   *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> - *    if it has not been finalised already.
> + *    if it has not been finalised already. See section 5 for more details on
> + *    conflicts.
>   *
>   * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>   *    capability, on all CPUs on the system. This is always initiated only after
> @@ -155,6 +156,32 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *	b) Any late CPU, brought up after (1), the action is triggered via:
>   *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
>   *
> + * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
> + *    state, we could have the following combinations :
> + *
> + *		x-----------------------------x
> + *		| Type  | System   | Late CPU |
> + *		|-----------------------------|
> + *		|  a    |   y      |    n     |
> + *		|-----------------------------|
> + *		|  b    |   n      |    y     |
> + *		x-----------------------------x

Nit: I find this a bit hard to follow.  Maybe reordering things a bit
would help but putting the rule (the precise bit) first, and the
rationale (necessarily more vague) afterward:

"Two capability type flag bits are defined to indicate whether each kind
of conflict can be tolerated:

		ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case (a) is allowed
		ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case (b) is allowed."

> + *
> + *     Case (a) is not permitted for capabilities which are usually system
> + *     features, which the system expects all CPUs to have. While (a) is ignored
> + *     for capabilities which represents an erratum work around.

Similarly "Case (a) is not permitted for a capability that the system
requires all CPUs to have in order for the capability to be enabled.
This is typical for capabilities that represent enhanced functionality."

> + *
> + *     Case (b) is not permitted for erratum capabilities, which might require
> + *     some work arounds which cannot be applied really late. Meanwhile, most
> + *     of the features could safely ignore (b), as the system doesn't use it
> + *     anyway.

and

"Case (b) is not permitted for a capability that the system must enable
during boot if any CPU in the system requires it in order to run safely.
This is typical for erratum workarounds that cannot be enabled after the
corresponding capability is finalised.

In some non-typical cases, either both (a) and (b), or neither, should
be permitted.  This can be described by including neither or both flags
in the capability's type field."

[...]

>  
>  
> @@ -165,6 +192,26 @@ 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
>  
> +/* Is it permitted for a late CPU to have this capability when system doesn't already have */

"doesn't already have" -> "hasn't already enabled it"?

> +#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
> +/* Is it safe for a late CPU to miss this capability when system has it */
> +#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
> +
> +/*
> + * 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

Can we around using the word "feature" to describe errata here?

Maybe "CPU errata workarounds that need to be enabled at boot time if
one or more CPUs in the system requires the workaround.  When one of
these workaround capabilities has been enabled, it is safe to allow any
CPU to boot that does not require the workaround."

> + * have it. But it is safe to miss the feature if the system has it.
> + */
> +#define ARM64_CPUCAP_LOCAL_CPU_ERRATUM		\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
> +/*
> + * 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.

"hasn't enabled it, although the feature will not be used by Linux
in this case.  If the system has enabled this feature already then every
late CPU must have it."

> + */
> +#define ARM64_CPUCAP_SYSTEM_FEATURE	\
> +	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
> +
>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> @@ -198,6 +245,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_optional(const struct arm64_cpu_capabilities *cap)
> +{
> +	return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
> +}
> +
> +static inline bool
> +cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
> +{
> +	return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
> +}
> +
>  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 328c5a031e45..22ec3960a0c5 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
>  #define MIDR_RANGE(model, min, max) \
> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
>  	.midr_range_min = min, \
>  	.midr_range_max = max
>  
>  #define MIDR_ALL_VERSIONS(model) \
> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>  	.matches = is_affected_midr_range, \
>  	.midr_model = model, \
>  	.midr_range_min = 0, \
> @@ -286,7 +286,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,
> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> +		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
>  		.cpu_enable = cpu_enable_trap_ctr_access,
>  	},
>  #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
> @@ -300,7 +300,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  	{
>  		.desc = "Qualcomm Technologies Kryo erratum 1003",
>  		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> +		.type = ARM64_CPUCAP_LOCAL_CPU_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 8d22f0ef0927..1b29b3f0a1bc 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -921,7 +921,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "GIC system register CPU interface",
>  		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_useable_gicv3_cpuif,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.field_pos = ID_AA64PFR0_GIC_SHIFT,
> @@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Privileged Access Never",
>  		.capability = ARM64_HAS_PAN,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>  		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
> @@ -945,7 +945,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "LSE atomic instructions",
>  		.capability = ARM64_HAS_LSE_ATOMICS,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR0_EL1,
>  		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
> @@ -956,14 +956,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Software prefetching using PRFM",
>  		.capability = ARM64_HAS_NO_HW_PREFETCH,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_no_hw_prefetch,
>  	},
>  #ifdef CONFIG_ARM64_UAO
>  	{
>  		.desc = "User Access Override",
>  		.capability = ARM64_HAS_UAO,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64MMFR2_EL1,
>  		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
> @@ -977,21 +977,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #ifdef CONFIG_ARM64_PAN
>  	{
>  		.capability = ARM64_ALT_PAN_NOT_UAO,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = cpufeature_pan_not_uao,
>  	},
>  #endif /* CONFIG_ARM64_PAN */
>  	{
>  		.desc = "Virtualization Host Extensions",
>  		.capability = ARM64_HAS_VIRT_HOST_EXTN,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = runs_at_el2,
>  		.cpu_enable = cpu_copy_el2regs,
>  	},
>  	{
>  		.desc = "32-bit EL0 Support",
>  		.capability = ARM64_HAS_32BIT_EL0,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1001,21 +1001,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Reduced HYP mapping offset",
>  		.capability = ARM64_HYP_OFFSET_LOW,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = hyp_offset_low,
>  	},
>  #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>  	{
>  		.desc = "Kernel page table isolation (KPTI)",
>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = unmap_kernel_at_el0,
>  	},
>  #endif
>  	{
>  		/* FP/SIMD is not implemented */
>  		.capability = ARM64_HAS_NO_FPSIMD,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.min_field_value = 0,
>  		.matches = has_no_fpsimd,
>  	},
> @@ -1023,7 +1023,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Data cache clean to Point of Persistence",
>  		.capability = ARM64_HAS_DCPOP,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64ISAR1_EL1,
>  		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
> @@ -1033,7 +1033,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #ifdef CONFIG_ARM64_SVE
>  	{
>  		.desc = "Scalable Vector Extension",
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.capability = ARM64_SVE,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1047,7 +1047,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "RAS Extension Support",
>  		.capability = ARM64_HAS_RAS_EXTN,
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_cpuid_feature,
>  		.sys_reg = SYS_ID_AA64PFR0_EL1,
>  		.sign = FTR_UNSIGNED,
> @@ -1062,7 +1062,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
>  	{							\
>  		.desc = #cap,					\
> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,		\
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
>  		.matches = has_cpuid_feature,			\
>  		.sys_reg = reg,					\
>  		.field_pos = field,				\
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 06/20] arm64: capabilities: Unify the verification
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:53PM +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.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpufeature.c      | 89 +++++++++++++++++++++++--------------
>  2 files changed, 57 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 1b29b3f0a1bc..5e4d581c97f1 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1233,6 +1233,56 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>  	}
>  }
>  
> +/*
> + * Run through the list of capabilities to check for conflicts.
> + * If the system has already detected a capability, take necessary
> + * action on this CPU.
> + *
> + * 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);

Nit: Odd spacing?

[...]

Otherwise,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

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

* [PATCH v2 06/20] arm64: capabilities: Unify the verification
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:53PM +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.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpufeature.c      | 89 +++++++++++++++++++++++--------------
>  2 files changed, 57 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 1b29b3f0a1bc..5e4d581c97f1 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1233,6 +1233,56 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>  	}
>  }
>  
> +/*
> + * Run through the list of capabilities to check for conflicts.
> + * If the system has already detected a capability, take necessary
> + * action on this CPU.
> + *
> + * 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);

Nit: Odd spacing?

[...]

Otherwise,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

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

* Re: [PATCH v2 07/20] arm64: capabilities: Filter the entries based on a given mask
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:54PM +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 mask for the
> scope of the capabilities to allow better control. This can be
> used later for handling LOCAL vs SYSTEM wide capabilities and more.
> All capabilities should have their scope set to either LOCAL_CPU or
> SYSTEM. No functional/flow change.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  2 ++
>  arch/arm64/kernel/cpufeature.c      | 35 ++++++++++++++++++++++++-----------
>  2 files changed, 26 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 69b5ce366598..cda62b70d338 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -198,6 +198,8 @@ 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_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>  
> +#define ARM64_CPUCAP_SCOPE_ALL			 \
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)

Perhaps we could just use _MASK rather than having a separate #define,
but it's good either way.

Is there a situation in which _ALL and _MASK would need to be
different?

>  /*
>   * 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 5e4d581c97f1..5163dc51b975 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1185,10 +1185,12 @@ 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 scope_mask, const char *info)
>  {
> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> -		if (!caps->matches(caps, cpucap_default_scope(caps)))
> +		if (!(caps->type & scope_mask) ||
> +		    !caps->matches(caps, cpucap_default_scope(caps)))
>  			continue;
>  
>  		if (!cpus_have_cap(caps->capability) && caps->desc)
> @@ -1210,12 +1212,14 @@ 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 scope_mask)
>  {
> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
>  		unsigned int num = caps->capability;
>  
> -		if (!cpus_have_cap(num))
> +		if (!(caps->type & scope_mask) || !cpus_have_cap(num))
>  			continue;
>  
>  		/* Ensure cpus_have_const_cap(num) works */
> @@ -1240,12 +1244,18 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>   *
>   * 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 scope_mask)
>  {
>  	bool cpu_has_cap, system_has_cap;
>  	const struct arm64_cpu_capabilities *caps = caps_list;
>  
> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> +

Nit: extra blank line?

[...]

With that fixed,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

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

* [PATCH v2 07/20] arm64: capabilities: Filter the entries based on a given mask
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:54PM +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 mask for the
> scope of the capabilities to allow better control. This can be
> used later for handling LOCAL vs SYSTEM wide capabilities and more.
> All capabilities should have their scope set to either LOCAL_CPU or
> SYSTEM. No functional/flow change.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  2 ++
>  arch/arm64/kernel/cpufeature.c      | 35 ++++++++++++++++++++++++-----------
>  2 files changed, 26 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 69b5ce366598..cda62b70d338 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -198,6 +198,8 @@ 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_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>  
> +#define ARM64_CPUCAP_SCOPE_ALL			 \
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)

Perhaps we could just use _MASK rather than having a separate #define,
but it's good either way.

Is there a situation in which _ALL and _MASK would need to be
different?

>  /*
>   * 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 5e4d581c97f1..5163dc51b975 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1185,10 +1185,12 @@ 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 scope_mask, const char *info)
>  {
> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> -		if (!caps->matches(caps, cpucap_default_scope(caps)))
> +		if (!(caps->type & scope_mask) ||
> +		    !caps->matches(caps, cpucap_default_scope(caps)))
>  			continue;
>  
>  		if (!cpus_have_cap(caps->capability) && caps->desc)
> @@ -1210,12 +1212,14 @@ 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 scope_mask)
>  {
> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
>  		unsigned int num = caps->capability;
>  
> -		if (!cpus_have_cap(num))
> +		if (!(caps->type & scope_mask) || !cpus_have_cap(num))
>  			continue;
>  
>  		/* Ensure cpus_have_const_cap(num) works */
> @@ -1240,12 +1244,18 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>   *
>   * 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 scope_mask)
>  {
>  	bool cpu_has_cap, system_has_cap;
>  	const struct arm64_cpu_capabilities *caps = caps_list;
>  
> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> +

Nit: extra blank line?

[...]

With that fixed,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

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

* Re: [PATCH v2 08/20] arm64: capabilities: Group handling of features and errata
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:55PM +0000, Suzuki K Poulose wrote:
> So far we have had separate routes for triggering errata and feature
> capability detection. 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 both
> arm64_features and arm64_errata, in two phases for detection.
> 
>  1) with SCOPE_LOCAL_CPU filter on each boot time enabled CPUs,
>     via update_cpu_local_capabilities().
> 
>  2) with SCOPE_SYSTEM filter only once after all boot time enabled
>     CPUs are active, triggered from setup_cpu_features().
> 
> A late CPU goes through both the tables for verification against
> established capabilities, as before.
> 
> We could ideally merge the two tables into one. But leave it as
> it is for easy access to the list of particular type.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

I don't know if there's a way of splitting or refactoring this patch to
make it easier to understand the changes, but I think I get what's going
on here now.

So,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

(But if you can see a good way to split it, I'll be happy to take
another look.)

> ---
>  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 5163dc51b975..c710ef28524e 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)
> @@ -1184,8 +1184,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 scope_mask, const char *info)
> +static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> +				      u16 scope_mask, const char *info)
>  {
>  	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> @@ -1199,6 +1199,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>  	}
>  }
>  
> +static void update_cpu_capabilities(u16 scope_mask)
> +{
> +	__update_cpu_capabilities(arm64_features, scope_mask,
> +				"detected feature:");
> +	__update_cpu_capabilities(arm64_errata, scope_mask,
> +				"enabling work around for");
> +}
>  
>  static int __enable_cpu_capability(void *arg)
>  {
> @@ -1213,7 +1220,7 @@ static int __enable_cpu_capability(void *arg)
>   * CPUs
>   */
>  static void __init
> -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
> +__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
>  {
>  	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> @@ -1293,6 +1300,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>  	return true;
>  }
>  
> +static bool verify_local_cpu_caps(u16 scope_mask)
> +{
> +	return __verify_local_cpu_caps(arm64_features, scope_mask) &&
> +	       __verify_local_cpu_caps(arm64_errata, scope_mask);
> +}
> +
>  /*
>   * Check for CPU features that are used in early boot
>   * based on the Boot CPU value.
> @@ -1315,12 +1328,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_SCOPE_ALL))
> -		cpu_die_early();
> -}
> -
>  static void verify_sve_features(void)
>  {
>  	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
> @@ -1339,26 +1346,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_SCOPE_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_SCOPE_ALL,
> -				"enabling workaround for");
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
>  }
>  
> -static void __init enable_errata_workarounds(void)
> +static void enable_cpu_capabilities(u16 scope_mask)
>  {
> -	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
> +	__enable_cpu_capabilities(arm64_errata, scope_mask);
> +	__enable_cpu_capabilities(arm64_features, scope_mask);
>  }
>  
>  /*
> @@ -1371,8 +1380,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_SCOPE_ALL))
> +		cpu_die_early();
>  	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>  
>  	if (system_supports_32bit_el0())
> @@ -1400,16 +1409,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_SCOPE_ALL, "detected feature:");
> -	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_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_SCOPE_ALL);
>  }
>  
>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> @@ -1433,9 +1446,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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 08/20] arm64: capabilities: Group handling of features and errata
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:55PM +0000, Suzuki K Poulose wrote:
> So far we have had separate routes for triggering errata and feature
> capability detection. 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 both
> arm64_features and arm64_errata, in two phases for detection.
> 
>  1) with SCOPE_LOCAL_CPU filter on each boot time enabled CPUs,
>     via update_cpu_local_capabilities().
> 
>  2) with SCOPE_SYSTEM filter only once after all boot time enabled
>     CPUs are active, triggered from setup_cpu_features().
> 
> A late CPU goes through both the tables for verification against
> established capabilities, as before.
> 
> We could ideally merge the two tables into one. But leave it as
> it is for easy access to the list of particular type.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

I don't know if there's a way of splitting or refactoring this patch to
make it easier to understand the changes, but I think I get what's going
on here now.

So,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

(But if you can see a good way to split it, I'll be happy to take
another look.)

> ---
>  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 5163dc51b975..c710ef28524e 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)
> @@ -1184,8 +1184,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 scope_mask, const char *info)
> +static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
> +				      u16 scope_mask, const char *info)
>  {
>  	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> @@ -1199,6 +1199,13 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>  	}
>  }
>  
> +static void update_cpu_capabilities(u16 scope_mask)
> +{
> +	__update_cpu_capabilities(arm64_features, scope_mask,
> +				"detected feature:");
> +	__update_cpu_capabilities(arm64_errata, scope_mask,
> +				"enabling work around for");
> +}
>  
>  static int __enable_cpu_capability(void *arg)
>  {
> @@ -1213,7 +1220,7 @@ static int __enable_cpu_capability(void *arg)
>   * CPUs
>   */
>  static void __init
> -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
> +__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
>  {
>  	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>  	for (; caps->matches; caps++) {
> @@ -1293,6 +1300,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>  	return true;
>  }
>  
> +static bool verify_local_cpu_caps(u16 scope_mask)
> +{
> +	return __verify_local_cpu_caps(arm64_features, scope_mask) &&
> +	       __verify_local_cpu_caps(arm64_errata, scope_mask);
> +}
> +
>  /*
>   * Check for CPU features that are used in early boot
>   * based on the Boot CPU value.
> @@ -1315,12 +1328,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_SCOPE_ALL))
> -		cpu_die_early();
> -}
> -
>  static void verify_sve_features(void)
>  {
>  	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
> @@ -1339,26 +1346,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_SCOPE_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_SCOPE_ALL,
> -				"enabling workaround for");
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
>  }
>  
> -static void __init enable_errata_workarounds(void)
> +static void enable_cpu_capabilities(u16 scope_mask)
>  {
> -	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
> +	__enable_cpu_capabilities(arm64_errata, scope_mask);
> +	__enable_cpu_capabilities(arm64_features, scope_mask);
>  }
>  
>  /*
> @@ -1371,8 +1380,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_SCOPE_ALL))
> +		cpu_die_early();
>  	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>  
>  	if (system_supports_32bit_el0())
> @@ -1400,16 +1409,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_SCOPE_ALL, "detected feature:");
> -	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_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_SCOPE_ALL);
>  }
>  
>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
> @@ -1433,9 +1446,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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 09/20] arm64: capabilities: Introduce weak features based on local CPU
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:56PM +0000, Suzuki K Poulose wrote:
> Now that we have the flexibility of defining system features based
> on individual CPUs, introduce CPU feature type that can be detected
> on a local SCOPE and ignores the conflict on late CPUs. This is
> applicable for ARM64_HAS_NO_HW_PREFETCH, where it is fine for
> the system to have CPUs without hardware prefetch turning up
> later. We only suffer a performance penalty, nothing fatal.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> ---
>  arch/arm64/include/asm/cpufeature.h | 8 ++++++++
>  arch/arm64/kernel/cpufeature.c      | 2 +-
>  2 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index cda62b70d338..7bb3fdec827e 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -214,6 +214,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  #define ARM64_CPUCAP_SYSTEM_FEATURE	\
>  	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
> +/*
> + * CPU feature detected at boot time based on feature of one or more CPUs.
> + * All possible conflicts for a late CPU are ignored.
> + */
> +#define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE		\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
> +	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>  
>  struct arm64_cpu_capabilities {
>  	const char *desc;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index c710ef28524e..ecc87aa74c64 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -956,7 +956,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Software prefetching using PRFM",
>  		.capability = ARM64_HAS_NO_HW_PREFETCH,
> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
>  		.matches = has_no_hw_prefetch,
>  	},
>  #ifdef CONFIG_ARM64_UAO
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 09/20] arm64: capabilities: Introduce weak features based on local CPU
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:56PM +0000, Suzuki K Poulose wrote:
> Now that we have the flexibility of defining system features based
> on individual CPUs, introduce CPU feature type that can be detected
> on a local SCOPE and ignores the conflict on late CPUs. This is
> applicable for ARM64_HAS_NO_HW_PREFETCH, where it is fine for
> the system to have CPUs without hardware prefetch turning up
> later. We only suffer a performance penalty, nothing fatal.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> ---
>  arch/arm64/include/asm/cpufeature.h | 8 ++++++++
>  arch/arm64/kernel/cpufeature.c      | 2 +-
>  2 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index cda62b70d338..7bb3fdec827e 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -214,6 +214,14 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  #define ARM64_CPUCAP_SYSTEM_FEATURE	\
>  	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
> +/*
> + * CPU feature detected at boot time based on feature of one or more CPUs.
> + * All possible conflicts for a late CPU are ignored.
> + */
> +#define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE		\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
> +	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>  
>  struct arm64_cpu_capabilities {
>  	const char *desc;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index c710ef28524e..ecc87aa74c64 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -956,7 +956,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Software prefetching using PRFM",
>  		.capability = ARM64_HAS_NO_HW_PREFETCH,
> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
>  		.matches = has_no_hw_prefetch,
>  	},
>  #ifdef CONFIG_ARM64_UAO
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:57PM +0000, Suzuki K Poulose wrote:
> 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,

Should that be "when any CPU"?

> unless it is forced via kernel 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.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  9 +++++++++
>  arch/arm64/kernel/cpufeature.c      | 11 ++++++-----
>  2 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 7bb3fdec827e..71993dd4afae 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -223,6 +223,15 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
>  	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>  
> +/*
> + * CPU feature detected at boot time, on one or more CPUs. A late CPU
> + * is not allowed to have the capability when the system doesn't have it.
> + * It is Ok for a late CPU to miss the feature.
> + */
> +#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE	\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
> +
>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index ecc87aa74c64..4a55492784b7 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) {
> @@ -885,8 +884,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>  	}
>  
>  	/* 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)
> @@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Kernel page table isolation (KPTI)",
>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
> +		.sys_reg = SYS_ID_AA64PFR0_EL1,
> +		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
> +		.min_field_value = 1,
>  		.matches = unmap_kernel_at_el0,

Minor nit, but:

Can we have a comment here to explain that .min_field_value is the
minimum value that indicates that KPTI is _not_ required by this cpu?
This is the opposite of the usual semantics for this field.

Otherwise, this inversion of meaning is not obvious without digging into
unmap_kernel_at_el0() and spotting the ! in !has_cpuid_feature().

With that, or if this usage of !has_cpuid_feature() is already well-
established so that a comment is deemed unnecessary:

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Cheers
---Dave

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

* [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:57PM +0000, Suzuki K Poulose wrote:
> 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,

Should that be "when any CPU"?

> unless it is forced via kernel 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.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  9 +++++++++
>  arch/arm64/kernel/cpufeature.c      | 11 ++++++-----
>  2 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 7bb3fdec827e..71993dd4afae 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -223,6 +223,15 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
>  	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>  
> +/*
> + * CPU feature detected at boot time, on one or more CPUs. A late CPU
> + * is not allowed to have the capability when the system doesn't have it.
> + * It is Ok for a late CPU to miss the feature.
> + */
> +#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE	\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
> +
>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index ecc87aa74c64..4a55492784b7 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) {
> @@ -885,8 +884,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>  	}
>  
>  	/* 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)
> @@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Kernel page table isolation (KPTI)",
>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
> +		.sys_reg = SYS_ID_AA64PFR0_EL1,
> +		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
> +		.min_field_value = 1,
>  		.matches = unmap_kernel_at_el0,

Minor nit, but:

Can we have a comment here to explain that .min_field_value is the
minimum value that indicates that KPTI is _not_ required by this cpu?
This is the opposite of the usual semantics for this field.

Otherwise, this inversion of meaning is not obvious without digging into
unmap_kernel_at_el0() and spotting the ! in !has_cpuid_feature().

With that, or if this usage of !has_cpuid_feature() is already well-
established so that a comment is deemed unnecessary:

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Cheers
---Dave

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

* Re: [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:38     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-arm-kernel, mark.rutland, Julien Thierry, ckadabi,
	ard.biesheuvel, marc.zyngier, catalin.marinas, will.deacon,
	linux-kernel, jnair, dave.martin

On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:
> The kernel detects and uses some of the features based on the boot
> CPU and expects that all the following CPUs conform to it. e.g,
> with VHE and the boot CPU running at EL2, the kernel decides to
> keep the kernel running at EL2. If another CPU is brought up without
> this capability, we use custom hooks (via check_early_cpu_features())
> to handle it. To handle such capabilities add support for detecting
> and enabling capabilities based on the boot CPU.
> 
> A bit is added to indicate if the capability should be detected
> early on the boot CPU. The infrastructure then ensures that such
> capabilities are probed and "enabled" early on in the boot CPU
> and, enabled on the subsequent CPUs.
> 
> Cc: Julien Thierry <julien.thierry@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
>  arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
>  2 files changed, 74 insertions(+), 22 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 71993dd4afae..04161aac0f06 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -104,7 +104,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *    some checks at runtime. This could be, e.g, checking the value of a field
>   *    in CPU ID feature register or checking the cpu model. The capability
>   *    provides a call back ( @matches() ) to perform the check.
> - *    Scope defines how the checks should be performed. There are two cases:
> + *    Scope defines how the checks should be performed. There are three cases:
>   *
>   *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
>   *        matches. This implies, we have to run the check on all the booting
> @@ -117,6 +117,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *        field in one of the CPU ID feature registers, we use the sanitised
>   *        value of the register from the CPU feature infrastructure to make
>   *        the decision.
> + *		Or
> + *     c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the feature.
> + *        This category is for features that are "finalised" (or used) by the kernel
> + *        very early even before the SMP cpus are brought up.
> + *
>   *    The process of detection is usually denoted by "update" capability state
>   *    in the code.
>   *
> @@ -129,6 +134,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
>   *    any changes to the state of a capability once it finalises the capability
>   *    and takes any action, as it may be impossible to execute the actions safely.
> + *    At the moment there are two passes of finalising the capabilities.
> + *      a) Boot CPU scope capabilities - Finalised by primary boot CPU via
> + *         setup_boot_cpu_capabilities().
> + *      b) Everything except (a) - Run via setup_system_capabilities().
>   *
>   * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>   *    the kernel should make sure that it is safe to use the CPU, by verifying
> @@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *
>   *    As explained in (2) above, capabilities could be finalised at different
>   *    points in the execution. Each CPU is verified against the "finalised"
> - *    capabilities and if there is a conflict, the kernel takes an action, based
> - *    on the severity (e.g, a CPU could be prevented from booting or cause a
> - *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> - *    if it has not been finalised already. See section 5 for more details on
> - *    conflicts.
> + *    capabilities.
> + *
> + *	x------------------------------------------------------------------- x
> + *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
> + *	|--------------------------------------------------------------------|
> + *	| Primary boot CPU    |          |                    |              |
> + *	|  capability         |   n      |      y             |       y      |
> + *	|--------------------------------------------------------------------|
> + *	| All others          |   n      |      n             |       y      |
> + *	x--------------------------------------------------------------------x

Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
means "conflict".

Could we have blank cell versus "X" (with a note saying what that
means), or "ok" versus "CONFLICT"?

> + *
> + *
> + *    If there is a conflict, the kernel takes an action, based on the severity
> + *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
> + *    The CPU is allowed to "affect" the state of the capability, if it has not
> + *    been finalised already. See section 5 for more details on conflicts.
>   *
>   * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>   *    capability, on all CPUs on the system. This is always initiated only after
> @@ -186,20 +206,28 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  
>  
> -/* Decide how the capability is detected. On a local CPU vs System wide */
> -#define ARM64_CPUCAP_SCOPE_MASK			0x3
> +/*
> + * Decide how the capability is detected.
> + * On any local CPU vs System wide vs the primary boot CPU
> + */
> +#define ARM64_CPUCAP_SCOPE_MASK			0x7

Minor nit: magic number.  Could we do

#define ARM64_CPUCAP_SCOPE_MASK		\
	(ARM64_CPUCAP_SCOPE_LOCAL_CPU |	\
	 ARM64_CPUCAP_SCOPE_SYSTEM |	\
	 ARM64_CPUCAP_SCOPE_BOOT_CPU)

below?
	 
>  #define ARM64_CPUCAP_SCOPE_LOCAL_CPU		((u16)BIT(0))
>  #define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
> +/*
> + * The capabilitiy is detected on the Boot CPU and is used by kernel
> + * during early boot. i.e, the capability should be "detected" and "enabled"
> + * as early as possibly on all booting CPUs.
> + */
> +#define ARM64_CPUCAP_SCOPE_BOOT_CPU		((u16)BIT(2))
>  #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>  #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> +#define SCOPE_BOOT_CPU				ARM64_CPUCAP_SCOPE_BOOT_CPU
>  
>  /* Is it permitted for a late CPU to have this capability when system doesn't already have */
>  #define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
>  /* Is it safe for a late CPU to miss this capability when system has it */
>  #define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>  
> -#define ARM64_CPUCAP_SCOPE_ALL			 \
> -	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
>  /*
>   * 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 4a55492784b7..6d759f068de1 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_local_capabilities(void);
> +static void __init setup_boot_cpu_capabilities(void);
>  
>  void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  {
> @@ -550,10 +550,10 @@ 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.
> +	 * Detect and enable early CPU features based on the boot CPU, after
> +	 * we have initialised the CPU feature infrastructure.
>  	 */
> -	update_cpu_local_capabilities();
> +	setup_boot_cpu_capabilities();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1235,12 +1235,21 @@ __enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_m
>  
>  		if (caps->cpu_enable) {
>  			/*
> -			 * Use stop_machine() as it schedules the work allowing
> -			 * us to modify PSTATE, instead of on_each_cpu() which
> -			 * uses an IPI, giving us a PSTATE that disappears when
> -			 * we return.
> +			 * If we are dealing with EARLY detected features, we
> +			 * have to enable this only on the Boot CPU, where it
> +			 * is detected. All the secondaries enable it via
> +			 * verify_early_cpu_capabilities().
> +			 *
> +			 * Otherwise, use stop_machine() as it schedules the
> +			 * work allowing us to modify PSTATE, instead of
> +			 * on_each_cpu() which uses an IPI, giving us a PSTATE
> +			 * that disappears when we return.
>  			 */
> -			stop_machine(__enable_cpu_capability, (void *)caps, cpu_online_mask);
> +			if (scope_mask & ARM64_CPUCAP_SCOPE_BOOT_CPU)
> +				caps->cpu_enable(caps);
> +			else
> +				stop_machine(__enable_cpu_capability,
> +					(void *)caps, cpu_online_mask);
>  		}
>  	}
>  }
> @@ -1315,6 +1324,12 @@ static void check_early_cpu_features(void)
>  {
>  	verify_cpu_run_el();
>  	verify_cpu_asid_bits();
> +	/*
> +	 * Early features are used by the kernel already. If there
> +	 * is a conflict, we cannot proceed further.
> +	 */
> +	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_BOOT_CPU))
> +		cpu_panic_kernel();
>  }
>  
>  static void
> @@ -1381,7 +1396,7 @@ static void enable_cpu_capabilities(u16 scope_mask)
>   */
>  static void verify_local_cpu_capabilities(void)
>  {
> -	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
> +	if (!verify_local_cpu_caps(~ARM64_CPUCAP_SCOPE_BOOT_CPU))

[1] This is neat, but would it be clearer to say _ALL & ~_BOOT_CPU?

Otherwise, this is passing (u16)0xfffb, which feels invalid,
particularly since it includes _{PERMITTED,OPTIONAL}_FOR_LATE_CPU which
don't make sense here, even if we know they get masked off.

There could be future pitfalls here if ~_BOOT_CPU by itself is pasted
in other places where the *_FOR_LATE_CPU bits are significant.

>  		cpu_die_early();
>  	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>  
> @@ -1415,6 +1430,15 @@ void check_local_cpu_capabilities(void)
>  		verify_local_cpu_capabilities();
>  }
>  
> +static void __init setup_boot_cpu_capabilities(void)
> +{
> +	/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU |
> +				 ARM64_CPUCAP_SCOPE_LOCAL_CPU);
> +	/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
> +	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU);
> +}
> +
>  static void __init setup_system_capabilities(void)
>  {
>  	/*
> @@ -1422,8 +1446,8 @@ static void __init setup_system_capabilities(void)
>  	 * finalise the capabilities that depend on it.
>  	 */
>  	update_system_capabilities();
> -	/* Enable all the available capabilities */
> -	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_ALL);
> +	/* Enable all the available capabilities, which are not already enabled. */
> +	enable_cpu_capabilities(~ARM64_CPUCAP_SCOPE_BOOT_CPU);

As [1] above.

Cheers
---Dave

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

* [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
@ 2018-02-07 10:38     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:
> The kernel detects and uses some of the features based on the boot
> CPU and expects that all the following CPUs conform to it. e.g,
> with VHE and the boot CPU running at EL2, the kernel decides to
> keep the kernel running at EL2. If another CPU is brought up without
> this capability, we use custom hooks (via check_early_cpu_features())
> to handle it. To handle such capabilities add support for detecting
> and enabling capabilities based on the boot CPU.
> 
> A bit is added to indicate if the capability should be detected
> early on the boot CPU. The infrastructure then ensures that such
> capabilities are probed and "enabled" early on in the boot CPU
> and, enabled on the subsequent CPUs.
> 
> Cc: Julien Thierry <julien.thierry@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
>  arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
>  2 files changed, 74 insertions(+), 22 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 71993dd4afae..04161aac0f06 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -104,7 +104,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *    some checks at runtime. This could be, e.g, checking the value of a field
>   *    in CPU ID feature register or checking the cpu model. The capability
>   *    provides a call back ( @matches() ) to perform the check.
> - *    Scope defines how the checks should be performed. There are two cases:
> + *    Scope defines how the checks should be performed. There are three cases:
>   *
>   *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
>   *        matches. This implies, we have to run the check on all the booting
> @@ -117,6 +117,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *        field in one of the CPU ID feature registers, we use the sanitised
>   *        value of the register from the CPU feature infrastructure to make
>   *        the decision.
> + *		Or
> + *     c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the feature.
> + *        This category is for features that are "finalised" (or used) by the kernel
> + *        very early even before the SMP cpus are brought up.
> + *
>   *    The process of detection is usually denoted by "update" capability state
>   *    in the code.
>   *
> @@ -129,6 +134,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
>   *    any changes to the state of a capability once it finalises the capability
>   *    and takes any action, as it may be impossible to execute the actions safely.
> + *    At the moment there are two passes of finalising the capabilities.
> + *      a) Boot CPU scope capabilities - Finalised by primary boot CPU via
> + *         setup_boot_cpu_capabilities().
> + *      b) Everything except (a) - Run via setup_system_capabilities().
>   *
>   * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>   *    the kernel should make sure that it is safe to use the CPU, by verifying
> @@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   *
>   *    As explained in (2) above, capabilities could be finalised at different
>   *    points in the execution. Each CPU is verified against the "finalised"
> - *    capabilities and if there is a conflict, the kernel takes an action, based
> - *    on the severity (e.g, a CPU could be prevented from booting or cause a
> - *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> - *    if it has not been finalised already. See section 5 for more details on
> - *    conflicts.
> + *    capabilities.
> + *
> + *	x------------------------------------------------------------------- x
> + *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
> + *	|--------------------------------------------------------------------|
> + *	| Primary boot CPU    |          |                    |              |
> + *	|  capability         |   n      |      y             |       y      |
> + *	|--------------------------------------------------------------------|
> + *	| All others          |   n      |      n             |       y      |
> + *	x--------------------------------------------------------------------x

Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
means "conflict".

Could we have blank cell versus "X" (with a note saying what that
means), or "ok" versus "CONFLICT"?

> + *
> + *
> + *    If there is a conflict, the kernel takes an action, based on the severity
> + *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
> + *    The CPU is allowed to "affect" the state of the capability, if it has not
> + *    been finalised already. See section 5 for more details on conflicts.
>   *
>   * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>   *    capability, on all CPUs on the system. This is always initiated only after
> @@ -186,20 +206,28 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>   */
>  
>  
> -/* Decide how the capability is detected. On a local CPU vs System wide */
> -#define ARM64_CPUCAP_SCOPE_MASK			0x3
> +/*
> + * Decide how the capability is detected.
> + * On any local CPU vs System wide vs the primary boot CPU
> + */
> +#define ARM64_CPUCAP_SCOPE_MASK			0x7

Minor nit: magic number.  Could we do

#define ARM64_CPUCAP_SCOPE_MASK		\
	(ARM64_CPUCAP_SCOPE_LOCAL_CPU |	\
	 ARM64_CPUCAP_SCOPE_SYSTEM |	\
	 ARM64_CPUCAP_SCOPE_BOOT_CPU)

below?
	 
>  #define ARM64_CPUCAP_SCOPE_LOCAL_CPU		((u16)BIT(0))
>  #define ARM64_CPUCAP_SCOPE_SYSTEM		((u16)BIT(1))
> +/*
> + * The capabilitiy is detected on the Boot CPU and is used by kernel
> + * during early boot. i.e, the capability should be "detected" and "enabled"
> + * as early as possibly on all booting CPUs.
> + */
> +#define ARM64_CPUCAP_SCOPE_BOOT_CPU		((u16)BIT(2))
>  #define SCOPE_SYSTEM				ARM64_CPUCAP_SCOPE_SYSTEM
>  #define SCOPE_LOCAL_CPU				ARM64_CPUCAP_SCOPE_LOCAL_CPU
> +#define SCOPE_BOOT_CPU				ARM64_CPUCAP_SCOPE_BOOT_CPU
>  
>  /* Is it permitted for a late CPU to have this capability when system doesn't already have */
>  #define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
>  /* Is it safe for a late CPU to miss this capability when system has it */
>  #define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>  
> -#define ARM64_CPUCAP_SCOPE_ALL			 \
> -	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
>  /*
>   * 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 4a55492784b7..6d759f068de1 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_local_capabilities(void);
> +static void __init setup_boot_cpu_capabilities(void);
>  
>  void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  {
> @@ -550,10 +550,10 @@ 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.
> +	 * Detect and enable early CPU features based on the boot CPU, after
> +	 * we have initialised the CPU feature infrastructure.
>  	 */
> -	update_cpu_local_capabilities();
> +	setup_boot_cpu_capabilities();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1235,12 +1235,21 @@ __enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_m
>  
>  		if (caps->cpu_enable) {
>  			/*
> -			 * Use stop_machine() as it schedules the work allowing
> -			 * us to modify PSTATE, instead of on_each_cpu() which
> -			 * uses an IPI, giving us a PSTATE that disappears when
> -			 * we return.
> +			 * If we are dealing with EARLY detected features, we
> +			 * have to enable this only on the Boot CPU, where it
> +			 * is detected. All the secondaries enable it via
> +			 * verify_early_cpu_capabilities().
> +			 *
> +			 * Otherwise, use stop_machine() as it schedules the
> +			 * work allowing us to modify PSTATE, instead of
> +			 * on_each_cpu() which uses an IPI, giving us a PSTATE
> +			 * that disappears when we return.
>  			 */
> -			stop_machine(__enable_cpu_capability, (void *)caps, cpu_online_mask);
> +			if (scope_mask & ARM64_CPUCAP_SCOPE_BOOT_CPU)
> +				caps->cpu_enable(caps);
> +			else
> +				stop_machine(__enable_cpu_capability,
> +					(void *)caps, cpu_online_mask);
>  		}
>  	}
>  }
> @@ -1315,6 +1324,12 @@ static void check_early_cpu_features(void)
>  {
>  	verify_cpu_run_el();
>  	verify_cpu_asid_bits();
> +	/*
> +	 * Early features are used by the kernel already. If there
> +	 * is a conflict, we cannot proceed further.
> +	 */
> +	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_BOOT_CPU))
> +		cpu_panic_kernel();
>  }
>  
>  static void
> @@ -1381,7 +1396,7 @@ static void enable_cpu_capabilities(u16 scope_mask)
>   */
>  static void verify_local_cpu_capabilities(void)
>  {
> -	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
> +	if (!verify_local_cpu_caps(~ARM64_CPUCAP_SCOPE_BOOT_CPU))

[1] This is neat, but would it be clearer to say _ALL & ~_BOOT_CPU?

Otherwise, this is passing (u16)0xfffb, which feels invalid,
particularly since it includes _{PERMITTED,OPTIONAL}_FOR_LATE_CPU which
don't make sense here, even if we know they get masked off.

There could be future pitfalls here if ~_BOOT_CPU by itself is pasted
in other places where the *_FOR_LATE_CPU bits are significant.

>  		cpu_die_early();
>  	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>  
> @@ -1415,6 +1430,15 @@ void check_local_cpu_capabilities(void)
>  		verify_local_cpu_capabilities();
>  }
>  
> +static void __init setup_boot_cpu_capabilities(void)
> +{
> +	/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU |
> +				 ARM64_CPUCAP_SCOPE_LOCAL_CPU);
> +	/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
> +	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU);
> +}
> +
>  static void __init setup_system_capabilities(void)
>  {
>  	/*
> @@ -1422,8 +1446,8 @@ static void __init setup_system_capabilities(void)
>  	 * finalise the capabilities that depend on it.
>  	 */
>  	update_system_capabilities();
> -	/* Enable all the available capabilities */
> -	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_ALL);
> +	/* Enable all the available capabilities, which are not already enabled. */
> +	enable_cpu_capabilities(~ARM64_CPUCAP_SCOPE_BOOT_CPU);

As [1] above.

Cheers
---Dave

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

* Re: [PATCH v2 12/20] arm64: capabilities: Change scope of VHE to Boot CPU feature
  2018-01-31 18:27   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:27:59PM +0000, Suzuki K Poulose wrote:
> We expect all CPUs to be running at the same EL inside the kernel
> with or without VHE enabled and we have strict checks to ensure
> that any mismatch triggers a kernel panic. If VHE is enabled,
> we use the feature based on the boot CPU and all other CPUs
> should follow. This makes it a perfect candidate for a cpability
> based on the boot CPU,  which should be matched by all the CPUs
> (both when is ON and OFF). This saves us some not-so-pretty
> hooks and special code, just for verifying the conflict.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  7 +++++++
>  arch/arm64/include/asm/virt.h       |  6 ------
>  arch/arm64/kernel/cpufeature.c      |  3 +--
>  arch/arm64/kernel/smp.c             | 38 -------------------------------------
>  4 files changed, 8 insertions(+), 46 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 04161aac0f06..42292a0b93a4 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -260,6 +260,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
>  	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
>  
> +/*
> + * Critical CPU feature used early in the boot based on the boot CPU.
> + * The feature should be matched by all booting CPU (both miss and hit
> + * cases).
> + */
> +#define ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE ARM64_CPUCAP_SCOPE_BOOT_CPU
> +
>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
> index c5f89442785c..9d1e24e030b3 100644
> --- a/arch/arm64/include/asm/virt.h
> +++ b/arch/arm64/include/asm/virt.h
> @@ -102,12 +102,6 @@ static inline bool has_vhe(void)
>  	return false;
>  }
>  
> -#ifdef CONFIG_ARM64_VHE
> -extern void verify_cpu_run_el(void);
> -#else
> -static inline void verify_cpu_run_el(void) {}
> -#endif
> -
>  #endif /* __ASSEMBLY__ */
>  
>  #endif /* ! __ASM__VIRT_H */
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 6d759f068de1..247d34ea6b5e 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -982,7 +982,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Virtualization Host Extensions",
>  		.capability = ARM64_HAS_VIRT_HOST_EXTN,
> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE,
>  		.matches = runs_at_el2,
>  		.cpu_enable = cpu_copy_el2regs,
>  	},

Could this feature block now be #ifdef CONFIG_ARM64_VHE?

I don't think the lack of #ifdef breaks anything here though, because
in that case head.S drops down to EL1 runs_at_el2() returns false on
all CPUs.

> @@ -1322,7 +1322,6 @@ static bool verify_local_cpu_caps(u16 scope_mask)
>   */
>  static void check_early_cpu_features(void)
>  {
> -	verify_cpu_run_el();
>  	verify_cpu_asid_bits();
>  	/*
>  	 * Early features are used by the kernel already. If there
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 5cef11450183..f3e2e3aec0b0 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -85,43 +85,6 @@ enum ipi_msg_type {
>  	IPI_WAKEUP
>  };
>  
> -#ifdef CONFIG_ARM64_VHE
> -
> -/* Whether the boot CPU is running in HYP mode or not*/
> -static bool boot_cpu_hyp_mode;
> -
> -static inline void save_boot_cpu_run_el(void)
> -{
> -	boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
> -}
> -
> -static inline bool is_boot_cpu_in_hyp_mode(void)
> -{
> -	return boot_cpu_hyp_mode;
> -}
> -
> -/*
> - * Verify that a secondary CPU is running the kernel at the same
> - * EL as that of the boot CPU.
> - */
> -void verify_cpu_run_el(void)
> -{
> -	bool in_el2 = is_kernel_in_hyp_mode();
> -	bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
> -
> -	if (in_el2 ^ boot_cpu_el2) {
> -		pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
> -					smp_processor_id(),
> -					in_el2 ? 2 : 1,
> -					boot_cpu_el2 ? 2 : 1);
> -		cpu_panic_kernel();
> -	}
> -}
> -
> -#else
> -static inline void save_boot_cpu_run_el(void) {}
> -#endif
> -
>  #ifdef CONFIG_HOTPLUG_CPU
>  static int op_cpu_kill(unsigned int cpu);
>  #else
> @@ -447,7 +410,6 @@ void __init smp_prepare_boot_cpu(void)
>  	 */
>  	jump_label_init();
>  	cpuinfo_store_boot_cpu();
> -	save_boot_cpu_run_el();

Nice diffstat, assuming I didn't miss anything.

Cheers
---Dave

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

* [PATCH v2 12/20] arm64: capabilities: Change scope of VHE to Boot CPU feature
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:27:59PM +0000, Suzuki K Poulose wrote:
> We expect all CPUs to be running at the same EL inside the kernel
> with or without VHE enabled and we have strict checks to ensure
> that any mismatch triggers a kernel panic. If VHE is enabled,
> we use the feature based on the boot CPU and all other CPUs
> should follow. This makes it a perfect candidate for a cpability
> based on the boot CPU,  which should be matched by all the CPUs
> (both when is ON and OFF). This saves us some not-so-pretty
> hooks and special code, just for verifying the conflict.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  7 +++++++
>  arch/arm64/include/asm/virt.h       |  6 ------
>  arch/arm64/kernel/cpufeature.c      |  3 +--
>  arch/arm64/kernel/smp.c             | 38 -------------------------------------
>  4 files changed, 8 insertions(+), 46 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 04161aac0f06..42292a0b93a4 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -260,6 +260,13 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
>  	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
>  
> +/*
> + * Critical CPU feature used early in the boot based on the boot CPU.
> + * The feature should be matched by all booting CPU (both miss and hit
> + * cases).
> + */
> +#define ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE ARM64_CPUCAP_SCOPE_BOOT_CPU
> +
>  struct arm64_cpu_capabilities {
>  	const char *desc;
>  	u16 capability;
> diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
> index c5f89442785c..9d1e24e030b3 100644
> --- a/arch/arm64/include/asm/virt.h
> +++ b/arch/arm64/include/asm/virt.h
> @@ -102,12 +102,6 @@ static inline bool has_vhe(void)
>  	return false;
>  }
>  
> -#ifdef CONFIG_ARM64_VHE
> -extern void verify_cpu_run_el(void);
> -#else
> -static inline void verify_cpu_run_el(void) {}
> -#endif
> -
>  #endif /* __ASSEMBLY__ */
>  
>  #endif /* ! __ASM__VIRT_H */
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 6d759f068de1..247d34ea6b5e 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -982,7 +982,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  	{
>  		.desc = "Virtualization Host Extensions",
>  		.capability = ARM64_HAS_VIRT_HOST_EXTN,
> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.type = ARM64_CPUCAP_CRITICAL_BOOT_CPU_FEATURE,
>  		.matches = runs_at_el2,
>  		.cpu_enable = cpu_copy_el2regs,
>  	},

Could this feature block now be #ifdef CONFIG_ARM64_VHE?

I don't think the lack of #ifdef breaks anything here though, because
in that case head.S drops down to EL1 runs_at_el2() returns false on
all CPUs.

> @@ -1322,7 +1322,6 @@ static bool verify_local_cpu_caps(u16 scope_mask)
>   */
>  static void check_early_cpu_features(void)
>  {
> -	verify_cpu_run_el();
>  	verify_cpu_asid_bits();
>  	/*
>  	 * Early features are used by the kernel already. If there
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 5cef11450183..f3e2e3aec0b0 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -85,43 +85,6 @@ enum ipi_msg_type {
>  	IPI_WAKEUP
>  };
>  
> -#ifdef CONFIG_ARM64_VHE
> -
> -/* Whether the boot CPU is running in HYP mode or not*/
> -static bool boot_cpu_hyp_mode;
> -
> -static inline void save_boot_cpu_run_el(void)
> -{
> -	boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
> -}
> -
> -static inline bool is_boot_cpu_in_hyp_mode(void)
> -{
> -	return boot_cpu_hyp_mode;
> -}
> -
> -/*
> - * Verify that a secondary CPU is running the kernel at the same
> - * EL as that of the boot CPU.
> - */
> -void verify_cpu_run_el(void)
> -{
> -	bool in_el2 = is_kernel_in_hyp_mode();
> -	bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
> -
> -	if (in_el2 ^ boot_cpu_el2) {
> -		pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
> -					smp_processor_id(),
> -					in_el2 ? 2 : 1,
> -					boot_cpu_el2 ? 2 : 1);
> -		cpu_panic_kernel();
> -	}
> -}
> -
> -#else
> -static inline void save_boot_cpu_run_el(void) {}
> -#endif
> -
>  #ifdef CONFIG_HOTPLUG_CPU
>  static int op_cpu_kill(unsigned int cpu);
>  #else
> @@ -447,7 +410,6 @@ void __init smp_prepare_boot_cpu(void)
>  	 */
>  	jump_label_init();
>  	cpuinfo_store_boot_cpu();
> -	save_boot_cpu_run_el();

Nice diffstat, assuming I didn't miss anything.

Cheers
---Dave

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

* Re: [PATCH v2 13/20] arm64: capabilities: Clean up midr range helpers
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:00PM +0000, Suzuki K Poulose wrote:
> We are about to introduce generic MIDR range helpers. Clean
> up the existing helpers in erratum handling, preparing them
> to use generic version.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpu_errata.c | 100 +++++++++++++++++++++++------------------
>  1 file changed, 56 insertions(+), 44 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 22ec3960a0c5..4351d48b0b0f 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -174,20 +174,35 @@ static void qcom_enable_link_stack_sanitization(
>  }
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> -#define MIDR_RANGE(model, min, max) \
> -	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
> -	.matches = is_affected_midr_range, \
> -	.midr_model = model, \
> -	.midr_range_min = min, \
> -	.midr_range_max = max
> +#define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
> +	.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)
>  
> -#define MIDR_ALL_VERSIONS(model) \
> -	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
> -	.matches = is_affected_midr_range, \
> -	.midr_model = model, \
> -	.midr_range_min = 0, \
> +#define CAP_MIDR_ALL_VERSIONS(model)					\
> +	.matches = is_affected_midr_range,				\
> +	.midr_model = model,						\
> +	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
>  	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
>  
> +#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
> +	CAP_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)	 \
> +	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
> +
> +/* Errata affecting a single variant/revision of a model */
> +#define ERRATA_MIDR_REV(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_LOCAL_CPU_ERRATUM,			\
> +	CAP_MIDR_ALL_VERSIONS(model)
> +
>  const struct arm64_cpu_capabilities arm64_errata[] = {
>  #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
>  	defined(CONFIG_ARM64_ERRATUM_827319) || \
> @@ -196,7 +211,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),

Nit: since you're mostly ommiting the redundant 0x0* prefixes in new
ERRATA_MIDR_RANGE(), maybe it's worth getting rid of all of them.
Not a big deal though.

The prefixes are a bit random prior to this patch (0x00 versus 0x0
etc.)

[...]

Otherwise,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Cheers
---Dave

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

* [PATCH v2 13/20] arm64: capabilities: Clean up midr range helpers
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:00PM +0000, Suzuki K Poulose wrote:
> We are about to introduce generic MIDR range helpers. Clean
> up the existing helpers in erratum handling, preparing them
> to use generic version.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpu_errata.c | 100 +++++++++++++++++++++++------------------
>  1 file changed, 56 insertions(+), 44 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 22ec3960a0c5..4351d48b0b0f 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -174,20 +174,35 @@ static void qcom_enable_link_stack_sanitization(
>  }
>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> -#define MIDR_RANGE(model, min, max) \
> -	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
> -	.matches = is_affected_midr_range, \
> -	.midr_model = model, \
> -	.midr_range_min = min, \
> -	.midr_range_max = max
> +#define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
> +	.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)
>  
> -#define MIDR_ALL_VERSIONS(model) \
> -	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
> -	.matches = is_affected_midr_range, \
> -	.midr_model = model, \
> -	.midr_range_min = 0, \
> +#define CAP_MIDR_ALL_VERSIONS(model)					\
> +	.matches = is_affected_midr_range,				\
> +	.midr_model = model,						\
> +	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
>  	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
>  
> +#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
> +	CAP_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)	 \
> +	ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
> +
> +/* Errata affecting a single variant/revision of a model */
> +#define ERRATA_MIDR_REV(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_LOCAL_CPU_ERRATUM,			\
> +	CAP_MIDR_ALL_VERSIONS(model)
> +
>  const struct arm64_cpu_capabilities arm64_errata[] = {
>  #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
>  	defined(CONFIG_ARM64_ERRATUM_827319) || \
> @@ -196,7 +211,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),

Nit: since you're mostly ommiting the redundant 0x0* prefixes in new
ERRATA_MIDR_RANGE(), maybe it's worth getting rid of all of them.
Not a big deal though.

The prefixes are a bit random prior to this patch (0x00 versus 0x0
etc.)

[...]

Otherwise,

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Cheers
---Dave

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

* Re: [PATCH v2 14/20] arm64: Add helpers for checking CPU MIDR against a range
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:01PM +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.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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 42292a0b93a4..0cfe42c3225c 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>
> @@ -279,11 +280,7 @@ struct arm64_cpu_capabilities {
>  	 */
>  	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>  	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
> @@ -115,6 +115,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
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 4351d48b0b0f..bc3f7dce42ba 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
> @@ -176,15 +174,11 @@ static void qcom_enable_link_stack_sanitization(
>  
>  #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
>  	.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)
>  
>  #define CAP_MIDR_ALL_VERSIONS(model)					\
>  	.matches = is_affected_midr_range,				\
> -	.midr_model = model,						\
> -	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
> -	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
> +	.midr_range = MIDR_ALL_VERSIONS(model)
>  
>  #define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
> @@ -315,7 +309,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.desc = "Qualcomm Technologies Kryo erratum 1003",
>  		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
>  		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
> -		.midr_model = MIDR_QCOM_KRYO,
> +		.midr_range.model = MIDR_QCOM_KRYO,
>  		.matches = is_kryo_midr,
>  	},
>  #endif
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 14/20] arm64: Add helpers for checking CPU MIDR against a range
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:01PM +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.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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 42292a0b93a4..0cfe42c3225c 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>
> @@ -279,11 +280,7 @@ struct arm64_cpu_capabilities {
>  	 */
>  	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>  	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
> @@ -115,6 +115,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
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 4351d48b0b0f..bc3f7dce42ba 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
> @@ -176,15 +174,11 @@ static void qcom_enable_link_stack_sanitization(
>  
>  #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
>  	.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)
>  
>  #define CAP_MIDR_ALL_VERSIONS(model)					\
>  	.matches = is_affected_midr_range,				\
> -	.midr_model = model,						\
> -	.midr_range_min = MIDR_CPU_VAR_REV(0, 0),			\
> -	.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
> +	.midr_range = MIDR_ALL_VERSIONS(model)
>  
>  #define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max)		\
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
> @@ -315,7 +309,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.desc = "Qualcomm Technologies Kryo erratum 1003",
>  		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
>  		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
> -		.midr_model = MIDR_QCOM_KRYO,
> +		.midr_range.model = MIDR_QCOM_KRYO,
>  		.matches = is_kryo_midr,
>  	},
>  #endif
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 15/20] arm64: capabilities: Add support for checks based on a list of MIDRs
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:02PM +0000, Suzuki K Poulose wrote:
> Add helpers for detecting an errata on list of midr ranges
> of affected CPUs, with the same work around.

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpu_errata.c      | 61 +++++++++++++++++++++----------------
>  arch/arm64/kernel/cpufeature.c      | 10 +++---
>  3 files changed, 42 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 0cfe42c3225c..462c35d1a38c 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -281,6 +281,7 @@ struct arm64_cpu_capabilities {
>  	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>  	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 bc3f7dce42ba..eff5f4e380ac 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -28,6 +28,13 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
>  	return is_midr_in_range(read_cpuid_id(), &entry->midr_range);
>  }
>  
> +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)
>  {
> @@ -184,6 +191,10 @@ static void qcom_enable_link_stack_sanitization(
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
>  	CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)
>  
> +#define CAP_MIDR_RANGE_LIST(list)				\
> +	.matches = is_affected_midr_range_list,			\
> +	.midr_range_list = list
> +
>  /* 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)
> @@ -197,6 +208,29 @@ static void qcom_enable_link_stack_sanitization(
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
>  	CAP_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_LOCAL_CPU_ERRATUM,			\
> +	CAP_MIDR_RANGE_LIST(midr_list)
> +
> +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> +
> +/*
> + * List of CPUs where we need to issue a psci call to
> + * harden the branch predictor.
> + */
> +static const struct midr_range arm64_bp_harden_psci_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),
> +	MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> +	MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> +	{},
> +};
> +
> +#endif
> +
>  const struct arm64_cpu_capabilities arm64_errata[] = {
>  #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
>  	defined(CONFIG_ARM64_ERRATUM_827319) || \
> @@ -331,22 +365,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),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> +		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
>  		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
> @@ -358,16 +377,6 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
>  		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
>  	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
>  #endif
>  	{
>  	}
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 247d34ea6b5e..65a8e5cc600c 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -864,6 +864,11 @@ 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 scope)
>  {
> +	/* List of CPUs that are not vulnerable and don't need KPTI */
> +	static const struct midr_range kpti_safe_list[] = {
> +		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> +		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> +	};
>  
>  	/* Forced on command line? */
>  	if (__kpti_forced) {
> @@ -877,11 +882,8 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>  		return true;
>  
>  	/* Don't force KPTI for CPUs that are not vulnerable */
> -	switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
> -	case MIDR_CAVIUM_THUNDERX2:
> -	case MIDR_BRCM_VULCAN:
> +	if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
>  		return false;
> -	}
>  
>  	/* Defer to CPU feature registers */
>  	return !has_cpuid_feature(entry, scope);
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 15/20] arm64: capabilities: Add support for checks based on a list of MIDRs
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:02PM +0000, Suzuki K Poulose wrote:
> Add helpers for detecting an errata on list of midr ranges
> of affected CPUs, with the same work around.

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpu_errata.c      | 61 +++++++++++++++++++++----------------
>  arch/arm64/kernel/cpufeature.c      | 10 +++---
>  3 files changed, 42 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 0cfe42c3225c..462c35d1a38c 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -281,6 +281,7 @@ struct arm64_cpu_capabilities {
>  	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>  	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 bc3f7dce42ba..eff5f4e380ac 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -28,6 +28,13 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
>  	return is_midr_in_range(read_cpuid_id(), &entry->midr_range);
>  }
>  
> +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)
>  {
> @@ -184,6 +191,10 @@ static void qcom_enable_link_stack_sanitization(
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,				\
>  	CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)
>  
> +#define CAP_MIDR_RANGE_LIST(list)				\
> +	.matches = is_affected_midr_range_list,			\
> +	.midr_range_list = list
> +
>  /* 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)
> @@ -197,6 +208,29 @@ static void qcom_enable_link_stack_sanitization(
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
>  	CAP_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_LOCAL_CPU_ERRATUM,			\
> +	CAP_MIDR_RANGE_LIST(midr_list)
> +
> +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> +
> +/*
> + * List of CPUs where we need to issue a psci call to
> + * harden the branch predictor.
> + */
> +static const struct midr_range arm64_bp_harden_psci_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),
> +	MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> +	MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> +	{},
> +};
> +
> +#endif
> +
>  const struct arm64_cpu_capabilities arm64_errata[] = {
>  #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
>  	defined(CONFIG_ARM64_ERRATUM_827319) || \
> @@ -331,22 +365,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),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> +		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
>  		.cpu_enable = enable_psci_bp_hardening,
>  	},
>  	{
> @@ -358,16 +377,6 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
>  		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
>  	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
>  #endif
>  	{
>  	}
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 247d34ea6b5e..65a8e5cc600c 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -864,6 +864,11 @@ 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 scope)
>  {
> +	/* List of CPUs that are not vulnerable and don't need KPTI */
> +	static const struct midr_range kpti_safe_list[] = {
> +		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> +		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> +	};
>  
>  	/* Forced on command line? */
>  	if (__kpti_forced) {
> @@ -877,11 +882,8 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>  		return true;
>  
>  	/* Don't force KPTI for CPUs that are not vulnerable */
> -	switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
> -	case MIDR_CAVIUM_THUNDERX2:
> -	case MIDR_BRCM_VULCAN:
> +	if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
>  		return false;
> -	}
>  
>  	/* Defer to CPU feature registers */
>  	return !has_cpuid_feature(entry, scope);
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> Some capabilities have different criteria for detection and associated
> actions based on the matching criteria, even though they all share the
> same capability bit. So far we have used multiple entries with the same
> capability bit to handle this. This is prone to errors, as the
> cpu_enable is invoked for each entry, irrespective of whether the
> detection rule applies to the CPU or not. And also this complicates
> other helpers, e.g, __this_cpu_has_cap.
> 
> This patch adds a wrapper entry to cover all the possible variations
> of a capability and ensures :
>  1) The capabilitiy is set when at least one of the entry detects
>  2) Action is only taken for the entries that detects.

I guess this means that where we have a single cpu_enable() method
but complex match criteria that require multiple entries, then that
cpu_enable() method might get called multiple times on a given CPU.

Could be worth a comment if cpu_enable() methods must be robust
against this.

> This avoids explicit checks in the call backs. The only constraint
> here is that, all the entries should have the same "type".
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
>  arch/arm64/kernel/cpufeature.c      |  7 +++--
>  3 files changed, 50 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 462c35d1a38c..b73247c27f00 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
>  			bool sign;
>  			unsigned long hwcap;
>  		};
> +		const struct arm64_cpu_capabilities *cap_list;

Should desc, capability, def_scope and/or cpu_enable match for every cap
in such a group?

I'd expected something maybe like this:

struct arm64_cpu_capabilities {
	const char *desc;
	u16 capability;
	struct arm64_capability_match {
		bool (*matches)(const struct arm64_cpu_capabilities *, int);
		int (*cpu_enable)(void);
		union {
			struct { ... midr ... };
			struct { ... sysreg ... };
			const struct arm64_capability_match *list;
		};
>  	};
>  };
>  
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index eff5f4e380ac..b4f1c1c1f8ca 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -213,6 +213,36 @@ static void qcom_enable_link_stack_sanitization(
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
>  	CAP_MIDR_RANGE_LIST(midr_list)
>  
> +/*
> + * Generic helper for handling capabilties with multiple (match,enable) pairs
> + * of call backs, sharing the same capability bit.
> + * Iterate over each entry to see if at least one matches.
> + */
> +static bool multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
> +				    int scope)
> +{
> +	const struct arm64_cpu_capabilities *caps = entry->cap_list;
> +
> +	for (; caps->matches; caps++)
> +		if (caps->matches(caps, scope))
> +			return true;
> +	return false;
> +}
> +
> +/*
> + * Take appropriate action for all matching entries in the shared capability
> + * entry.
> + */
> +static void multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry)
> +{
> +	const struct arm64_cpu_capabilities *caps = entry->cap_list;
> +
> +	for (; caps->matches; caps++)
> +		if (caps->matches(caps, SCOPE_LOCAL_CPU) &&
> +		    caps->cpu_enable)
> +			caps->cpu_enable(caps);
> +}
> +
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>  
>  /*
> @@ -229,6 +259,18 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
>  	{},
>  };
>  
> +static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
> +	{
> +		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
> +		.cpu_enable = enable_psci_bp_hardening,
> +	},
> +	{
> +		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> +		.cpu_enable = qcom_enable_link_stack_sanitization,
> +	},
> +	{},
> +};
> +
>  #endif
>  
>  const struct arm64_cpu_capabilities arm64_errata[] = {
> @@ -365,13 +407,10 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> -		.cpu_enable = qcom_enable_link_stack_sanitization,
> +		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
> +		.matches = multi_entry_cap_matches,
> +		.cpu_enable = multi_entry_cap_cpu_enable,
> +		.cap_list = arm64_bp_harden_list,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 65a8e5cc600c..13e30c1b1e99 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>  		return false;
>  
>  	for (caps = cap_array; caps->matches; caps++)
> -		if (caps->capability == cap &&
> -		    caps->matches(caps, SCOPE_LOCAL_CPU))
> -			return true;
> +		if (caps->capability == cap)
> +			return caps->matches(caps, SCOPE_LOCAL_CPU);

If we went for my capability { cap; match criteria or list; } approach,
would it still be necessary to iterate over the whole list here?

This seems preferable if this function is used by other paths that
don't expect it to be so costly.  Currently I only see a call in
arch/arm64/kvm/handle_exit.c:handle_exit_early() for the SError case --
which is probably not expected to be a fast path.

[...]

Cheers
---Dave

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> Some capabilities have different criteria for detection and associated
> actions based on the matching criteria, even though they all share the
> same capability bit. So far we have used multiple entries with the same
> capability bit to handle this. This is prone to errors, as the
> cpu_enable is invoked for each entry, irrespective of whether the
> detection rule applies to the CPU or not. And also this complicates
> other helpers, e.g, __this_cpu_has_cap.
> 
> This patch adds a wrapper entry to cover all the possible variations
> of a capability and ensures :
>  1) The capabilitiy is set when at least one of the entry detects
>  2) Action is only taken for the entries that detects.

I guess this means that where we have a single cpu_enable() method
but complex match criteria that require multiple entries, then that
cpu_enable() method might get called multiple times on a given CPU.

Could be worth a comment if cpu_enable() methods must be robust
against this.

> This avoids explicit checks in the call backs. The only constraint
> here is that, all the entries should have the same "type".
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  1 +
>  arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
>  arch/arm64/kernel/cpufeature.c      |  7 +++--
>  3 files changed, 50 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 462c35d1a38c..b73247c27f00 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
>  			bool sign;
>  			unsigned long hwcap;
>  		};
> +		const struct arm64_cpu_capabilities *cap_list;

Should desc, capability, def_scope and/or cpu_enable match for every cap
in such a group?

I'd expected something maybe like this:

struct arm64_cpu_capabilities {
	const char *desc;
	u16 capability;
	struct arm64_capability_match {
		bool (*matches)(const struct arm64_cpu_capabilities *, int);
		int (*cpu_enable)(void);
		union {
			struct { ... midr ... };
			struct { ... sysreg ... };
			const struct arm64_capability_match *list;
		};
>  	};
>  };
>  
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index eff5f4e380ac..b4f1c1c1f8ca 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -213,6 +213,36 @@ static void qcom_enable_link_stack_sanitization(
>  	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,			\
>  	CAP_MIDR_RANGE_LIST(midr_list)
>  
> +/*
> + * Generic helper for handling capabilties with multiple (match,enable) pairs
> + * of call backs, sharing the same capability bit.
> + * Iterate over each entry to see if at least one matches.
> + */
> +static bool multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
> +				    int scope)
> +{
> +	const struct arm64_cpu_capabilities *caps = entry->cap_list;
> +
> +	for (; caps->matches; caps++)
> +		if (caps->matches(caps, scope))
> +			return true;
> +	return false;
> +}
> +
> +/*
> + * Take appropriate action for all matching entries in the shared capability
> + * entry.
> + */
> +static void multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry)
> +{
> +	const struct arm64_cpu_capabilities *caps = entry->cap_list;
> +
> +	for (; caps->matches; caps++)
> +		if (caps->matches(caps, SCOPE_LOCAL_CPU) &&
> +		    caps->cpu_enable)
> +			caps->cpu_enable(caps);
> +}
> +
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>  
>  /*
> @@ -229,6 +259,18 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
>  	{},
>  };
>  
> +static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
> +	{
> +		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
> +		.cpu_enable = enable_psci_bp_hardening,
> +	},
> +	{
> +		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> +		.cpu_enable = qcom_enable_link_stack_sanitization,
> +	},
> +	{},
> +};
> +
>  #endif
>  
>  const struct arm64_cpu_capabilities arm64_errata[] = {
> @@ -365,13 +407,10 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
>  	{
>  		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
> -		.cpu_enable = enable_psci_bp_hardening,
> -	},
> -	{
> -		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
> -		ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> -		.cpu_enable = qcom_enable_link_stack_sanitization,
> +		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
> +		.matches = multi_entry_cap_matches,
> +		.cpu_enable = multi_entry_cap_cpu_enable,
> +		.cap_list = arm64_bp_harden_list,
>  	},
>  	{
>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 65a8e5cc600c..13e30c1b1e99 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>  		return false;
>  
>  	for (caps = cap_array; caps->matches; caps++)
> -		if (caps->capability == cap &&
> -		    caps->matches(caps, SCOPE_LOCAL_CPU))
> -			return true;
> +		if (caps->capability == cap)
> +			return caps->matches(caps, SCOPE_LOCAL_CPU);

If we went for my capability { cap; match criteria or list; } approach,
would it still be necessary to iterate over the whole list here?

This seems preferable if this function is used by other paths that
don't expect it to be so costly.  Currently I only see a call in
arch/arm64/kvm/handle_exit.c:handle_exit_early() for the SError case --
which is probably not expected to be a fast path.

[...]

Cheers
---Dave

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

* Re: [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
> We defend against branch predictor training based exploits by
> taking specific actions (based on the CPU model) to invalidate
> the Branch predictor buffer (BPB). This is implemented by per-CPU
> ptr, which installs the specific actions for the CPU model.
> 
> The core code can handle the following cases where:
>  1) some CPUs doesn't need any work around
>  2) a CPU can install the work around, when it is brought up,
>     irrespective of how late that happens.
> 
> This concludes that it is safe to bring up a CPU which requires
> bp hardening defense. However, with the current settings, we
> reject a late CPU, if none of the active CPUs didn't need it.

Should this be "[...] reject a late CPU that needs the defense, if none
of the active CPUs needed it." ?

> 
> This patch solves issue by changing the flags for the capability
> to indicate that it is safe for a late CPU to turn up with the
> capability. This is not sufficient to get things working, as
> we cannot change the system wide state of the capability established
> at the kernel boot. So, we "set" the capability unconditionally
> and make sure that the call backs are only installed for those
> CPUs which actually needs them. This is done by adding a dummy
> entry at the end of the list of shared entries, which :
>  a) Always returns true for matches, to ensure we turn this on.
>  b) has an empty "cpu_enable" call back, so that we don't take
>     any action on the CPUs which weren't matched with the real
>     entries.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 10 ++++++++++
>  arch/arm64/kernel/cpu_errata.c      | 19 ++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index b73247c27f00..262fa213b1b1 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -252,6 +252,16 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
>  	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>  
> +/*
> + * CPU errata work around detected at boot time based on one or more CPUs.
> + * All conflicts are ignored. This implies any work around shouldn't
> + * depend when a CPU could be brought up.
> + */
> +#define ARM64_CPUCAP_WEAK_LOCAL_CPU_ERRATUM		\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
> +	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
> +
>  /*
>   * CPU feature detected at boot time, on one or more CPUs. A late CPU
>   * is not allowed to have the capability when the system doesn't have it.
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index b4f1c1c1f8ca..7f714a628480 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -259,6 +259,12 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
>  	{},
>  };
>  
> +static bool bp_hardening_always_on(const struct arm64_cpu_capabilities *cap,
> +				   int scope)
> +{
> +	return true;
> +}
> +
>  static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>  	{
>  		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
> @@ -268,6 +274,17 @@ static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>  		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
>  		.cpu_enable = qcom_enable_link_stack_sanitization,
>  	},
> +	/*
> +	 * Always enable the capability to make sure a late CPU can
> +	 * safely use the BP hardening call backs. Since we use per-CPU
> +	 * pointers for the call backs, the work around only affects the
> +	 * CPUs which have some methods installed by any real matching entries
> +	 * above. As such we don't have any specific cpu_enable() callback
> +	 * for this entry, as it is just to make sure we always "detect" it.
> +	 */
> +	{
> +		.matches = bp_hardening_always_on,

This function could simply be called "always_on", since it expresses
something entirely generic and is static.

> +	},

This feels like a bit of a hack: really there is no global on/off
state for a cap like this: it's truly independent for each cpu.

OTOH, your code does achieve that, and the comment gives a good
explanation.

The alternative would be to add a cap type flag to indicate that
this cap is purely CPU-local, but it may not be worth it at this
stage.

[...]

Cheers
---Dave

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
> We defend against branch predictor training based exploits by
> taking specific actions (based on the CPU model) to invalidate
> the Branch predictor buffer (BPB). This is implemented by per-CPU
> ptr, which installs the specific actions for the CPU model.
> 
> The core code can handle the following cases where:
>  1) some CPUs doesn't need any work around
>  2) a CPU can install the work around, when it is brought up,
>     irrespective of how late that happens.
> 
> This concludes that it is safe to bring up a CPU which requires
> bp hardening defense. However, with the current settings, we
> reject a late CPU, if none of the active CPUs didn't need it.

Should this be "[...] reject a late CPU that needs the defense, if none
of the active CPUs needed it." ?

> 
> This patch solves issue by changing the flags for the capability
> to indicate that it is safe for a late CPU to turn up with the
> capability. This is not sufficient to get things working, as
> we cannot change the system wide state of the capability established
> at the kernel boot. So, we "set" the capability unconditionally
> and make sure that the call backs are only installed for those
> CPUs which actually needs them. This is done by adding a dummy
> entry at the end of the list of shared entries, which :
>  a) Always returns true for matches, to ensure we turn this on.
>  b) has an empty "cpu_enable" call back, so that we don't take
>     any action on the CPUs which weren't matched with the real
>     entries.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h | 10 ++++++++++
>  arch/arm64/kernel/cpu_errata.c      | 19 ++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index b73247c27f00..262fa213b1b1 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -252,6 +252,16 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>  	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
>  	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>  
> +/*
> + * CPU errata work around detected at boot time based on one or more CPUs.
> + * All conflicts are ignored. This implies any work around shouldn't
> + * depend when a CPU could be brought up.
> + */
> +#define ARM64_CPUCAP_WEAK_LOCAL_CPU_ERRATUM		\
> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
> +	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
> +
>  /*
>   * CPU feature detected at boot time, on one or more CPUs. A late CPU
>   * is not allowed to have the capability when the system doesn't have it.
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index b4f1c1c1f8ca..7f714a628480 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -259,6 +259,12 @@ static const struct midr_range arm64_bp_harden_psci_cpus[] = {
>  	{},
>  };
>  
> +static bool bp_hardening_always_on(const struct arm64_cpu_capabilities *cap,
> +				   int scope)
> +{
> +	return true;
> +}
> +
>  static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>  	{
>  		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
> @@ -268,6 +274,17 @@ static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>  		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
>  		.cpu_enable = qcom_enable_link_stack_sanitization,
>  	},
> +	/*
> +	 * Always enable the capability to make sure a late CPU can
> +	 * safely use the BP hardening call backs. Since we use per-CPU
> +	 * pointers for the call backs, the work around only affects the
> +	 * CPUs which have some methods installed by any real matching entries
> +	 * above. As such we don't have any specific cpu_enable() callback
> +	 * for this entry, as it is just to make sure we always "detect" it.
> +	 */
> +	{
> +		.matches = bp_hardening_always_on,

This function could simply be called "always_on", since it expresses
something entirely generic and is static.

> +	},

This feels like a bit of a hack: really there is no global on/off
state for a cap like this: it's truly independent for each cpu.

OTOH, your code does achieve that, and the comment gives a good
explanation.

The alternative would be to add a cap type flag to indicate that
this cap is purely CPU-local, but it may not be worth it at this
stage.

[...]

Cheers
---Dave

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

* Re: [PATCH v2 18/20] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:39     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:05PM +0000, Suzuki K Poulose wrote:
> Update the MIDR encodings for the Cortex-A55 and Cortex-A35
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 18/20] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
@ 2018-02-07 10:39     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:05PM +0000, Suzuki K Poulose wrote:
> Update the MIDR encodings for the Cortex-A55 and Cortex-A35
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 19/20] arm64: Delay enabling hardware DBM feature
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:40     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:40 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:06PM +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.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpucaps.h |  3 ++-
>  arch/arm64/kernel/cpufeature.c   | 40 ++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/proc.S             |  9 +++------
>  3 files changed, 45 insertions(+), 7 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/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 13e30c1b1e99..1f695a998eed 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -903,6 +903,33 @@ 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;

As for bp hardening, can we just use a generic "always on" function
here?

[...]

Cheers
---Dave

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

* [PATCH v2 19/20] arm64: Delay enabling hardware DBM feature
@ 2018-02-07 10:40     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:06PM +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.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpucaps.h |  3 ++-
>  arch/arm64/kernel/cpufeature.c   | 40 ++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/proc.S             |  9 +++------
>  3 files changed, 45 insertions(+), 7 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/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 13e30c1b1e99..1f695a998eed 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -903,6 +903,33 @@ 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;

As for bp hardening, can we just use a generic "always on" function
here?

[...]

Cheers
---Dave

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

* Re: [PATCH v2 20/20] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-07 10:40     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:40 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,
	dave.martin

On Wed, Jan 31, 2018 at 06:28:07PM +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. There are some other cores suffering from this
> errata, which could be added to the midr_list to trigger the work
> around.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: ckadabi@codeaurora.org
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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 1f695a998eed..410fbddec129 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -923,9 +923,21 @@ static inline void __cpu_enable_hw_dbm(void)
>  	isb();
>  }
>  
> +static bool cpu_has_erratum_1024718(void)
> +{
> +	static const struct midr_range 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 void 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();
>  }
>  #endif
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 20/20] arm64: Add work around for Arm Cortex-A55 Erratum 1024718
@ 2018-02-07 10:40     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 10:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:07PM +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. There are some other cores suffering from this
> errata, which could be added to the midr_list to trigger the work
> around.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: ckadabi at codeaurora.org
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Reviewed-by: Dave Martin <Dave.Martin@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 1f695a998eed..410fbddec129 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -923,9 +923,21 @@ static inline void __cpu_enable_hw_dbm(void)
>  	isb();
>  }
>  
> +static bool cpu_has_erratum_1024718(void)
> +{
> +	static const struct midr_range 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 void 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();
>  }
>  #endif
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

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

On 31/01/18 18:27, 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. Clean up the declaration of the call back to make it clear.
> 
>   1) Renamed to cpu_enable(), to imply taking necessary actions on the
>      called CPU for the entry.
>   2) Pass const pointer to the capability, to allow the call back to
>      check the entry. (e.,g to check if any action is needed on the CPU)
>   3) We don't care about the result of the call back, turning this to
>      a void.

The verbosity does make me wish that the coding style didn't forbid

   typedef const struct arm64_cpu_capabilities * cpu_cap;

but other than that whinge and a trivial nitpick over the spurious blank 
line above __enable_cpu_capability(), this now looks about as clean as 
it's going to get; thanks!

Acked-by: Robin Murphy <robin.murphy@arm.com>

> 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, rename call back,
>   drop call back results
> ]
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>   arch/arm64/include/asm/cpufeature.h |  7 ++++++-
>   arch/arm64/include/asm/fpsimd.h     |  4 +++-
>   arch/arm64/include/asm/processor.h  |  7 ++++---
>   arch/arm64/kernel/cpu_errata.c      | 41 +++++++++++++++----------------------
>   arch/arm64/kernel/cpufeature.c      | 33 ++++++++++++++++-------------
>   arch/arm64/kernel/fpsimd.c          |  5 ++---
>   arch/arm64/kernel/traps.c           |  4 ++--
>   arch/arm64/mm/fault.c               |  3 +--
>   8 files changed, 54 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc2585a..f46eb7d1625f 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -97,7 +97,12 @@ 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 */
> +	/*
> +	 * Take the appropriate actions to enable this capability for this CPU.
> +	 * For each successfully booted CPU, this method is called for each
> +	 * globally detected capability.
> +	 */
> +	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>   	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..7623762f7fa6 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 void 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..83a3d2887ca6 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);
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
> +void 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 ed6881882231..e34bee500692 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -53,11 +53,11 @@ 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 void cpu_enable_trap_ctr_access(
> +	const struct arm64_cpu_capabilities *__unused)
>   {
>   	/* Clear SCTLR_EL1.UCT */
>   	config_sctlr_el1(SCTLR_EL1_UCT, 0);
> -	return 0;
>   }
>   
>   #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> @@ -144,17 +144,13 @@ 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 void 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,
>   				       __psci_hyp_bp_inval_start,
>   				       __psci_hyp_bp_inval_end);
> -
> -	return 0;
>   }
>   
>   static void qcom_link_stack_sanitization(void)
> @@ -169,15 +165,12 @@ static void qcom_link_stack_sanitization(void)
>   		     : "=&r" (tmp));
>   }
>   
> -static int qcom_enable_link_stack_sanitization(void *data)
> +static void 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);
> -
> -	return 0;
>   }
>   #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>   
> @@ -204,7 +197,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   		.desc = "ARM errata 826319, 827319, 824069",
>   		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>   		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>   	},
>   #endif
>   #ifdef CONFIG_ARM64_ERRATUM_819472
> @@ -213,7 +206,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   		.desc = "ARM errata 819472",
>   		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>   		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>   	},
>   #endif
>   #ifdef CONFIG_ARM64_ERRATUM_832075
> @@ -294,7 +287,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
>   		.matches = has_mismatched_cache_line_size,
>   		.def_scope = SCOPE_LOCAL_CPU,
> -		.enable = cpu_enable_trap_ctr_access,
> +		.cpu_enable = cpu_enable_trap_ctr_access,
>   	},
>   #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
>   	{
> @@ -333,27 +326,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> -		.enable = qcom_enable_link_stack_sanitization,
> +		.cpu_enable = qcom_enable_link_stack_sanitization,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> @@ -362,12 +355,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   #endif
>   	{
> @@ -385,8 +378,8 @@ void verify_local_cpu_errata_workarounds(void)
>   
>   	for (; caps->matches; caps++) {
>   		if (cpus_have_cap(caps->capability)) {
> -			if (caps->enable)
> -				caps->enable((void *)caps);
> +			if (caps->cpu_enable)
> +				caps->cpu_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 4b6f9051cf0c..0b881d9fcde2 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -894,7 +894,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 void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>   {
>   	/*
>   	 * Copy register values that aren't redirected by hardware.
> @@ -906,8 +906,6 @@ static int cpu_copy_el2regs(void *__unused)
>   	 */
>   	if (!alternatives_applied)
>   		write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
> -
> -	return 0;
>   }
>   
>   static const struct arm64_cpu_capabilities arm64_features[] = {
> @@ -931,7 +929,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
>   		.sign = FTR_UNSIGNED,
>   		.min_field_value = 1,
> -		.enable = cpu_enable_pan,
> +		.cpu_enable = cpu_enable_pan,
>   	},
>   #endif /* CONFIG_ARM64_PAN */
>   #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
> @@ -979,7 +977,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.capability = ARM64_HAS_VIRT_HOST_EXTN,
>   		.def_scope = SCOPE_SYSTEM,
>   		.matches = runs_at_el2,
> -		.enable = cpu_copy_el2regs,
> +		.cpu_enable = cpu_copy_el2regs,
>   	},
>   	{
>   		.desc = "32-bit EL0 Support",
> @@ -1033,7 +1031,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.field_pos = ID_AA64PFR0_SVE_SHIFT,
>   		.min_field_value = ID_AA64PFR0_SVE,
>   		.matches = has_cpuid_feature,
> -		.enable = sve_kernel_enable,
> +		.cpu_enable = sve_kernel_enable,
>   	},
>   #endif /* CONFIG_ARM64_SVE */
>   #ifdef CONFIG_ARM64_RAS_EXTN
> @@ -1046,7 +1044,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.sign = FTR_UNSIGNED,
>   		.field_pos = ID_AA64PFR0_RAS_SHIFT,
>   		.min_field_value = ID_AA64PFR0_RAS_V1,
> -		.enable = cpu_clear_disr,
> +		.cpu_enable = cpu_clear_disr,
>   	},
>   #endif /* CONFIG_ARM64_RAS_EXTN */
>   	{},
> @@ -1190,6 +1188,15 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>   	}
>   }
>   
> +
> +static int __enable_cpu_capability(void *arg)
> +{
> +	const struct arm64_cpu_capabilities *cap = arg;
> +
> +	cap->cpu_enable(cap);
> +	return 0;
> +}
> +
>   /*
>    * Run through the enabled capabilities and enable() it on all active
>    * CPUs
> @@ -1205,14 +1212,14 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
>   		/* Ensure cpus_have_const_cap(num) works */
>   		static_branch_enable(&cpu_hwcap_keys[num]);
>   
> -		if (caps->enable) {
> +		if (caps->cpu_enable) {
>   			/*
>   			 * Use stop_machine() as it schedules the work allowing
>   			 * us to modify PSTATE, instead of on_each_cpu() which
>   			 * 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);
>   		}
>   	}
>   }
> @@ -1255,8 +1262,8 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
>   					smp_processor_id(), caps->desc);
>   			cpu_die_early();
>   		}
> -		if (caps->enable)
> -			caps->enable((void *)caps);
> +		if (caps->cpu_enable)
> +			caps->cpu_enable(caps);
>   	}
>   }
>   
> @@ -1479,10 +1486,8 @@ static int __init enable_mrs_emulation(void)
>   
>   core_initcall(enable_mrs_emulation);
>   
> -int cpu_clear_disr(void *__unused)
> +void 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);
> -
> -	return 0;
>   }
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 55fb544072f6..35c563536b0c 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,12 +758,10 @@ 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)
> +void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
>   {
>   	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
>   	isb();
> -
> -	return 0;
>   }
>   
>   void __init sve_setup(void)
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index bbb0fde2780e..a2f6492b4ea3 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,10 +375,9 @@ 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)
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
>   {
>   	config_sctlr_el1(SCTLR_EL1_UCI, 0);
> -	return 0;
>   }
>   
>   #define __user_cache_maint(insn, address, res)			\
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 0e671ddf4855..ccfbe979be17 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)
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>   {
>   	/*
>   	 * We modify PSTATE. This won't work from irq context as the PSTATE
> @@ -823,6 +823,5 @@ int cpu_enable_pan(void *__unused)
>   
>   	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
>   	asm(SET_PSTATE_PAN(1));
> -	return 0;
>   }
>   #endif /* CONFIG_ARM64_PAN */
> 

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

* [PATCH v2 01/20] arm64: capabilities: Update prototype for enable call back
@ 2018-02-07 11:23     ` Robin Murphy
  0 siblings, 0 replies; 156+ messages in thread
From: Robin Murphy @ 2018-02-07 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 31/01/18 18:27, 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. Clean up the declaration of the call back to make it clear.
> 
>   1) Renamed to cpu_enable(), to imply taking necessary actions on the
>      called CPU for the entry.
>   2) Pass const pointer to the capability, to allow the call back to
>      check the entry. (e.,g to check if any action is needed on the CPU)
>   3) We don't care about the result of the call back, turning this to
>      a void.

The verbosity does make me wish that the coding style didn't forbid

   typedef const struct arm64_cpu_capabilities * cpu_cap;

but other than that whinge and a trivial nitpick over the spurious blank 
line above __enable_cpu_capability(), this now looks about as clean as 
it's going to get; thanks!

Acked-by: Robin Murphy <robin.murphy@arm.com>

> 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, rename call back,
>   drop call back results
> ]
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>   arch/arm64/include/asm/cpufeature.h |  7 ++++++-
>   arch/arm64/include/asm/fpsimd.h     |  4 +++-
>   arch/arm64/include/asm/processor.h  |  7 ++++---
>   arch/arm64/kernel/cpu_errata.c      | 41 +++++++++++++++----------------------
>   arch/arm64/kernel/cpufeature.c      | 33 ++++++++++++++++-------------
>   arch/arm64/kernel/fpsimd.c          |  5 ++---
>   arch/arm64/kernel/traps.c           |  4 ++--
>   arch/arm64/mm/fault.c               |  3 +--
>   8 files changed, 54 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc2585a..f46eb7d1625f 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -97,7 +97,12 @@ 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 */
> +	/*
> +	 * Take the appropriate actions to enable this capability for this CPU.
> +	 * For each successfully booted CPU, this method is called for each
> +	 * globally detected capability.
> +	 */
> +	void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>   	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..7623762f7fa6 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 void 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..83a3d2887ca6 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);
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
> +void 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 ed6881882231..e34bee500692 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -53,11 +53,11 @@ 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 void cpu_enable_trap_ctr_access(
> +	const struct arm64_cpu_capabilities *__unused)
>   {
>   	/* Clear SCTLR_EL1.UCT */
>   	config_sctlr_el1(SCTLR_EL1_UCT, 0);
> -	return 0;
>   }
>   
>   #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> @@ -144,17 +144,13 @@ 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 void 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,
>   				       __psci_hyp_bp_inval_start,
>   				       __psci_hyp_bp_inval_end);
> -
> -	return 0;
>   }
>   
>   static void qcom_link_stack_sanitization(void)
> @@ -169,15 +165,12 @@ static void qcom_link_stack_sanitization(void)
>   		     : "=&r" (tmp));
>   }
>   
> -static int qcom_enable_link_stack_sanitization(void *data)
> +static void 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);
> -
> -	return 0;
>   }
>   #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>   
> @@ -204,7 +197,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   		.desc = "ARM errata 826319, 827319, 824069",
>   		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>   		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>   	},
>   #endif
>   #ifdef CONFIG_ARM64_ERRATUM_819472
> @@ -213,7 +206,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   		.desc = "ARM errata 819472",
>   		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
>   		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
> -		.enable = cpu_enable_cache_maint_trap,
> +		.cpu_enable = cpu_enable_cache_maint_trap,
>   	},
>   #endif
>   #ifdef CONFIG_ARM64_ERRATUM_832075
> @@ -294,7 +287,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
>   		.matches = has_mismatched_cache_line_size,
>   		.def_scope = SCOPE_LOCAL_CPU,
> -		.enable = cpu_enable_trap_ctr_access,
> +		.cpu_enable = cpu_enable_trap_ctr_access,
>   	},
>   #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
>   	{
> @@ -333,27 +326,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
> -		.enable = qcom_enable_link_stack_sanitization,
> +		.cpu_enable = qcom_enable_link_stack_sanitization,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> @@ -362,12 +355,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   	{
>   		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
>   		MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
> -		.enable = enable_psci_bp_hardening,
> +		.cpu_enable = enable_psci_bp_hardening,
>   	},
>   #endif
>   	{
> @@ -385,8 +378,8 @@ void verify_local_cpu_errata_workarounds(void)
>   
>   	for (; caps->matches; caps++) {
>   		if (cpus_have_cap(caps->capability)) {
> -			if (caps->enable)
> -				caps->enable((void *)caps);
> +			if (caps->cpu_enable)
> +				caps->cpu_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 4b6f9051cf0c..0b881d9fcde2 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -894,7 +894,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 void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
>   {
>   	/*
>   	 * Copy register values that aren't redirected by hardware.
> @@ -906,8 +906,6 @@ static int cpu_copy_el2regs(void *__unused)
>   	 */
>   	if (!alternatives_applied)
>   		write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
> -
> -	return 0;
>   }
>   
>   static const struct arm64_cpu_capabilities arm64_features[] = {
> @@ -931,7 +929,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
>   		.sign = FTR_UNSIGNED,
>   		.min_field_value = 1,
> -		.enable = cpu_enable_pan,
> +		.cpu_enable = cpu_enable_pan,
>   	},
>   #endif /* CONFIG_ARM64_PAN */
>   #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
> @@ -979,7 +977,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.capability = ARM64_HAS_VIRT_HOST_EXTN,
>   		.def_scope = SCOPE_SYSTEM,
>   		.matches = runs_at_el2,
> -		.enable = cpu_copy_el2regs,
> +		.cpu_enable = cpu_copy_el2regs,
>   	},
>   	{
>   		.desc = "32-bit EL0 Support",
> @@ -1033,7 +1031,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.field_pos = ID_AA64PFR0_SVE_SHIFT,
>   		.min_field_value = ID_AA64PFR0_SVE,
>   		.matches = has_cpuid_feature,
> -		.enable = sve_kernel_enable,
> +		.cpu_enable = sve_kernel_enable,
>   	},
>   #endif /* CONFIG_ARM64_SVE */
>   #ifdef CONFIG_ARM64_RAS_EXTN
> @@ -1046,7 +1044,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.sign = FTR_UNSIGNED,
>   		.field_pos = ID_AA64PFR0_RAS_SHIFT,
>   		.min_field_value = ID_AA64PFR0_RAS_V1,
> -		.enable = cpu_clear_disr,
> +		.cpu_enable = cpu_clear_disr,
>   	},
>   #endif /* CONFIG_ARM64_RAS_EXTN */
>   	{},
> @@ -1190,6 +1188,15 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>   	}
>   }
>   
> +
> +static int __enable_cpu_capability(void *arg)
> +{
> +	const struct arm64_cpu_capabilities *cap = arg;
> +
> +	cap->cpu_enable(cap);
> +	return 0;
> +}
> +
>   /*
>    * Run through the enabled capabilities and enable() it on all active
>    * CPUs
> @@ -1205,14 +1212,14 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
>   		/* Ensure cpus_have_const_cap(num) works */
>   		static_branch_enable(&cpu_hwcap_keys[num]);
>   
> -		if (caps->enable) {
> +		if (caps->cpu_enable) {
>   			/*
>   			 * Use stop_machine() as it schedules the work allowing
>   			 * us to modify PSTATE, instead of on_each_cpu() which
>   			 * 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);
>   		}
>   	}
>   }
> @@ -1255,8 +1262,8 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
>   					smp_processor_id(), caps->desc);
>   			cpu_die_early();
>   		}
> -		if (caps->enable)
> -			caps->enable((void *)caps);
> +		if (caps->cpu_enable)
> +			caps->cpu_enable(caps);
>   	}
>   }
>   
> @@ -1479,10 +1486,8 @@ static int __init enable_mrs_emulation(void)
>   
>   core_initcall(enable_mrs_emulation);
>   
> -int cpu_clear_disr(void *__unused)
> +void 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);
> -
> -	return 0;
>   }
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 55fb544072f6..35c563536b0c 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,12 +758,10 @@ 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)
> +void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
>   {
>   	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
>   	isb();
> -
> -	return 0;
>   }
>   
>   void __init sve_setup(void)
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index bbb0fde2780e..a2f6492b4ea3 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,10 +375,9 @@ 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)
> +void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
>   {
>   	config_sctlr_el1(SCTLR_EL1_UCI, 0);
> -	return 0;
>   }
>   
>   #define __user_cache_maint(insn, address, res)			\
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 0e671ddf4855..ccfbe979be17 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)
> +void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>   {
>   	/*
>   	 * We modify PSTATE. This won't work from irq context as the PSTATE
> @@ -823,6 +823,5 @@ int cpu_enable_pan(void *__unused)
>   
>   	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
>   	asm(SET_PSTATE_PAN(1));
> -	return 0;
>   }
>   #endif /* CONFIG_ARM64_PAN */
> 

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

* Re: [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
  2018-02-07 10:38     ` Dave Martin
@ 2018-02-07 11:31       ` Robin Murphy
  -1 siblings, 0 replies; 156+ messages in thread
From: Robin Murphy @ 2018-02-07 11:31 UTC (permalink / raw)
  To: Dave Martin, Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:52PM +0000, Suzuki K Poulose wrote:
>> When a CPU is brought up, it is checked against the caps that are
>> known to be enabled on the system (via verify_local_cpu_capabilities()).
>> Based on the state of the capability on the CPU vs. that of System we
>> could have the following combinations of conflict.
>>
>> 	x-----------------------------x
>> 	| Type  | System   | Late CPU |
>> 	|-----------------------------|
>> 	|  a    |   y      |    n     |
>> 	|-----------------------------|
>> 	|  b    |   n      |    y     |
>> 	x-----------------------------x
>>
>> Case (a) is not permitted for caps which are system features, which the
>> system expects all the CPUs to have (e.g VHE). While (a) is ignored for
>> all errata work arounds. However, there could be exceptions to the plain
>> filtering approach. e.g, KPTI is an optional feature for a late CPU as
>> long as the system already enables it.
>>
>> Case (b) is not permitted for errata work arounds which requires some work
>> around, which cannot be delayed. And we ignore (b) for features. Here, yet
> 
> Nit, maybe:
> 
> "Case (b) is not permitted for any errata workaround that cannot be
> activated if the kernel has finished booting and has not already enabled
> it."

Nit^2: I think it would suffice to say "...that cannot be activated 
after the kernel has finished booting." - since we don't really have the 
concept of *de*activating workarounds, it is already implicit in that 
statement that the one in question wasn't activated *before* the kernel 
finished booting.

Robin.

>> again, KPTI is an exception, where if a late CPU needs KPTI we are too late
>> to enable it (because we change the allocation of ASIDs etc).
>>
>> Add two different flags to indicate how the conflict should be handled.
>>
>>   ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - CPUs may have the capability
>>   ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - CPUs may not have the cappability.
>>
>> Now that we have the flags to describe the behavior of the errata and
>> the features, as we treat them, define types for ERRATUM and FEATURE.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> All my suggestions in this patch are rewordings of comments, so they're
> not vital, and anyway you may disagree that they make the meaning
> clearer.  So I don't think they're essential.
> 
> For the actual code
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> 
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 61 ++++++++++++++++++++++++++++++++++++-
>>   arch/arm64/kernel/cpu_errata.c      |  8 ++---
>>   arch/arm64/kernel/cpufeature.c      | 30 +++++++++---------
>>   3 files changed, 79 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 05da54f1b4c7..7460b1f7e611 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -142,7 +142,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *    capabilities and if there is a conflict, the kernel takes an action, based
>>    *    on the severity (e.g, a CPU could be prevented from booting or cause a
>>    *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>> - *    if it has not been finalised already.
>> + *    if it has not been finalised already. See section 5 for more details on
>> + *    conflicts.
>>    *
>>    * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>>    *    capability, on all CPUs on the system. This is always initiated only after
>> @@ -155,6 +156,32 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *	b) Any late CPU, brought up after (1), the action is triggered via:
>>    *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
>>    *
>> + * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
>> + *    state, we could have the following combinations :
>> + *
>> + *		x-----------------------------x
>> + *		| Type  | System   | Late CPU |
>> + *		|-----------------------------|
>> + *		|  a    |   y      |    n     |
>> + *		|-----------------------------|
>> + *		|  b    |   n      |    y     |
>> + *		x-----------------------------x
> 
> Nit: I find this a bit hard to follow.  Maybe reordering things a bit
> would help but putting the rule (the precise bit) first, and the
> rationale (necessarily more vague) afterward:
> 
> "Two capability type flag bits are defined to indicate whether each kind
> of conflict can be tolerated:
> 
> 		ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case (a) is allowed
> 		ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case (b) is allowed."
> 
>> + *
>> + *     Case (a) is not permitted for capabilities which are usually system
>> + *     features, which the system expects all CPUs to have. While (a) is ignored
>> + *     for capabilities which represents an erratum work around.
> 
> Similarly "Case (a) is not permitted for a capability that the system
> requires all CPUs to have in order for the capability to be enabled.
> This is typical for capabilities that represent enhanced functionality."
> 
>> + *
>> + *     Case (b) is not permitted for erratum capabilities, which might require
>> + *     some work arounds which cannot be applied really late. Meanwhile, most
>> + *     of the features could safely ignore (b), as the system doesn't use it
>> + *     anyway.
> 
> and
> 
> "Case (b) is not permitted for a capability that the system must enable
> during boot if any CPU in the system requires it in order to run safely.
> This is typical for erratum workarounds that cannot be enabled after the
> corresponding capability is finalised.
> 
> In some non-typical cases, either both (a) and (b), or neither, should
> be permitted.  This can be described by including neither or both flags
> in the capability's type field."
> 
> [...]
> 
>>   
>>   
>> @@ -165,6 +192,26 @@ 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
>>   
>> +/* Is it permitted for a late CPU to have this capability when system doesn't already have */
> 
> "doesn't already have" -> "hasn't already enabled it"?
> 
>> +#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
>> +/* Is it safe for a late CPU to miss this capability when system has it */
>> +#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>> +
>> +/*
>> + * 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
> 
> Can we around using the word "feature" to describe errata here?
> 
> Maybe "CPU errata workarounds that need to be enabled at boot time if
> one or more CPUs in the system requires the workaround.  When one of
> these workaround capabilities has been enabled, it is safe to allow any
> CPU to boot that does not require the workaround."
> 
>> + * have it. But it is safe to miss the feature if the system has it.
>> + */
>> +#define ARM64_CPUCAP_LOCAL_CPU_ERRATUM		\
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
>> +/*
>> + * 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.
> 
> "hasn't enabled it, although the feature will not be used by Linux
> in this case.  If the system has enabled this feature already then every
> late CPU must have it."
> 
>> + */
>> +#define ARM64_CPUCAP_SYSTEM_FEATURE	\
>> +	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>> +
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>>   	u16 capability;
>> @@ -198,6 +245,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_optional(const struct arm64_cpu_capabilities *cap)
>> +{
>> +	return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
>> +}
>> +
>> +static inline bool
>> +cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
>> +{
>> +	return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
>> +}
>> +
>>   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 328c5a031e45..22ec3960a0c5 100644
>> --- a/arch/arm64/kernel/cpu_errata.c
>> +++ b/arch/arm64/kernel/cpu_errata.c
>> @@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
>>   #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>>   
>>   #define MIDR_RANGE(model, min, max) \
>> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
>> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>>   	.matches = is_affected_midr_range, \
>>   	.midr_model = model, \
>>   	.midr_range_min = min, \
>>   	.midr_range_max = max
>>   
>>   #define MIDR_ALL_VERSIONS(model) \
>> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
>> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>>   	.matches = is_affected_midr_range, \
>>   	.midr_model = model, \
>>   	.midr_range_min = 0, \
>> @@ -286,7 +286,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,
>> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
>> +		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
>>   		.cpu_enable = cpu_enable_trap_ctr_access,
>>   	},
>>   #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
>> @@ -300,7 +300,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>   	{
>>   		.desc = "Qualcomm Technologies Kryo erratum 1003",
>>   		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
>> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
>> +		.type = ARM64_CPUCAP_LOCAL_CPU_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 8d22f0ef0927..1b29b3f0a1bc 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -921,7 +921,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "GIC system register CPU interface",
>>   		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_useable_gicv3_cpuif,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.field_pos = ID_AA64PFR0_GIC_SHIFT,
>> @@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Privileged Access Never",
>>   		.capability = ARM64_HAS_PAN,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>>   		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
>> @@ -945,7 +945,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "LSE atomic instructions",
>>   		.capability = ARM64_HAS_LSE_ATOMICS,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64ISAR0_EL1,
>>   		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
>> @@ -956,14 +956,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Software prefetching using PRFM",
>>   		.capability = ARM64_HAS_NO_HW_PREFETCH,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_no_hw_prefetch,
>>   	},
>>   #ifdef CONFIG_ARM64_UAO
>>   	{
>>   		.desc = "User Access Override",
>>   		.capability = ARM64_HAS_UAO,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64MMFR2_EL1,
>>   		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
>> @@ -977,21 +977,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   #ifdef CONFIG_ARM64_PAN
>>   	{
>>   		.capability = ARM64_ALT_PAN_NOT_UAO,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = cpufeature_pan_not_uao,
>>   	},
>>   #endif /* CONFIG_ARM64_PAN */
>>   	{
>>   		.desc = "Virtualization Host Extensions",
>>   		.capability = ARM64_HAS_VIRT_HOST_EXTN,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = runs_at_el2,
>>   		.cpu_enable = cpu_copy_el2regs,
>>   	},
>>   	{
>>   		.desc = "32-bit EL0 Support",
>>   		.capability = ARM64_HAS_32BIT_EL0,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.sign = FTR_UNSIGNED,
>> @@ -1001,21 +1001,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Reduced HYP mapping offset",
>>   		.capability = ARM64_HYP_OFFSET_LOW,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = hyp_offset_low,
>>   	},
>>   #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>>   	{
>>   		.desc = "Kernel page table isolation (KPTI)",
>>   		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = unmap_kernel_at_el0,
>>   	},
>>   #endif
>>   	{
>>   		/* FP/SIMD is not implemented */
>>   		.capability = ARM64_HAS_NO_FPSIMD,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.min_field_value = 0,
>>   		.matches = has_no_fpsimd,
>>   	},
>> @@ -1023,7 +1023,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Data cache clean to Point of Persistence",
>>   		.capability = ARM64_HAS_DCPOP,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64ISAR1_EL1,
>>   		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
>> @@ -1033,7 +1033,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   #ifdef CONFIG_ARM64_SVE
>>   	{
>>   		.desc = "Scalable Vector Extension",
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.capability = ARM64_SVE,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.sign = FTR_UNSIGNED,
>> @@ -1047,7 +1047,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "RAS Extension Support",
>>   		.capability = ARM64_HAS_RAS_EXTN,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.sign = FTR_UNSIGNED,
>> @@ -1062,7 +1062,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
>>   	{							\
>>   		.desc = #cap,					\
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,		\
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
>>   		.matches = has_cpuid_feature,			\
>>   		.sys_reg = reg,					\
>>   		.field_pos = field,				\
>> -- 
>> 2.14.3
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
@ 2018-02-07 11:31       ` Robin Murphy
  0 siblings, 0 replies; 156+ messages in thread
From: Robin Murphy @ 2018-02-07 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:52PM +0000, Suzuki K Poulose wrote:
>> When a CPU is brought up, it is checked against the caps that are
>> known to be enabled on the system (via verify_local_cpu_capabilities()).
>> Based on the state of the capability on the CPU vs. that of System we
>> could have the following combinations of conflict.
>>
>> 	x-----------------------------x
>> 	| Type  | System   | Late CPU |
>> 	|-----------------------------|
>> 	|  a    |   y      |    n     |
>> 	|-----------------------------|
>> 	|  b    |   n      |    y     |
>> 	x-----------------------------x
>>
>> Case (a) is not permitted for caps which are system features, which the
>> system expects all the CPUs to have (e.g VHE). While (a) is ignored for
>> all errata work arounds. However, there could be exceptions to the plain
>> filtering approach. e.g, KPTI is an optional feature for a late CPU as
>> long as the system already enables it.
>>
>> Case (b) is not permitted for errata work arounds which requires some work
>> around, which cannot be delayed. And we ignore (b) for features. Here, yet
> 
> Nit, maybe:
> 
> "Case (b) is not permitted for any errata workaround that cannot be
> activated if the kernel has finished booting and has not already enabled
> it."

Nit^2: I think it would suffice to say "...that cannot be activated 
after the kernel has finished booting." - since we don't really have the 
concept of *de*activating workarounds, it is already implicit in that 
statement that the one in question wasn't activated *before* the kernel 
finished booting.

Robin.

>> again, KPTI is an exception, where if a late CPU needs KPTI we are too late
>> to enable it (because we change the allocation of ASIDs etc).
>>
>> Add two different flags to indicate how the conflict should be handled.
>>
>>   ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - CPUs may have the capability
>>   ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - CPUs may not have the cappability.
>>
>> Now that we have the flags to describe the behavior of the errata and
>> the features, as we treat them, define types for ERRATUM and FEATURE.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> All my suggestions in this patch are rewordings of comments, so they're
> not vital, and anyway you may disagree that they make the meaning
> clearer.  So I don't think they're essential.
> 
> For the actual code
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> 
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 61 ++++++++++++++++++++++++++++++++++++-
>>   arch/arm64/kernel/cpu_errata.c      |  8 ++---
>>   arch/arm64/kernel/cpufeature.c      | 30 +++++++++---------
>>   3 files changed, 79 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 05da54f1b4c7..7460b1f7e611 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -142,7 +142,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *    capabilities and if there is a conflict, the kernel takes an action, based
>>    *    on the severity (e.g, a CPU could be prevented from booting or cause a
>>    *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>> - *    if it has not been finalised already.
>> + *    if it has not been finalised already. See section 5 for more details on
>> + *    conflicts.
>>    *
>>    * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>>    *    capability, on all CPUs on the system. This is always initiated only after
>> @@ -155,6 +156,32 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *	b) Any late CPU, brought up after (1), the action is triggered via:
>>    *		check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
>>    *
>> + * 5) Conflicts: Based on the state of the capability on a late CPU vs. the system
>> + *    state, we could have the following combinations :
>> + *
>> + *		x-----------------------------x
>> + *		| Type  | System   | Late CPU |
>> + *		|-----------------------------|
>> + *		|  a    |   y      |    n     |
>> + *		|-----------------------------|
>> + *		|  b    |   n      |    y     |
>> + *		x-----------------------------x
> 
> Nit: I find this a bit hard to follow.  Maybe reordering things a bit
> would help but putting the rule (the precise bit) first, and the
> rationale (necessarily more vague) afterward:
> 
> "Two capability type flag bits are defined to indicate whether each kind
> of conflict can be tolerated:
> 
> 		ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case (a) is allowed
> 		ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case (b) is allowed."
> 
>> + *
>> + *     Case (a) is not permitted for capabilities which are usually system
>> + *     features, which the system expects all CPUs to have. While (a) is ignored
>> + *     for capabilities which represents an erratum work around.
> 
> Similarly "Case (a) is not permitted for a capability that the system
> requires all CPUs to have in order for the capability to be enabled.
> This is typical for capabilities that represent enhanced functionality."
> 
>> + *
>> + *     Case (b) is not permitted for erratum capabilities, which might require
>> + *     some work arounds which cannot be applied really late. Meanwhile, most
>> + *     of the features could safely ignore (b), as the system doesn't use it
>> + *     anyway.
> 
> and
> 
> "Case (b) is not permitted for a capability that the system must enable
> during boot if any CPU in the system requires it in order to run safely.
> This is typical for erratum workarounds that cannot be enabled after the
> corresponding capability is finalised.
> 
> In some non-typical cases, either both (a) and (b), or neither, should
> be permitted.  This can be described by including neither or both flags
> in the capability's type field."
> 
> [...]
> 
>>   
>>   
>> @@ -165,6 +192,26 @@ 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
>>   
>> +/* Is it permitted for a late CPU to have this capability when system doesn't already have */
> 
> "doesn't already have" -> "hasn't already enabled it"?
> 
>> +#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU	((u16)BIT(4))
>> +/* Is it safe for a late CPU to miss this capability when system has it */
>> +#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>> +
>> +/*
>> + * 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
> 
> Can we around using the word "feature" to describe errata here?
> 
> Maybe "CPU errata workarounds that need to be enabled at boot time if
> one or more CPUs in the system requires the workaround.  When one of
> these workaround capabilities has been enabled, it is safe to allow any
> CPU to boot that does not require the workaround."
> 
>> + * have it. But it is safe to miss the feature if the system has it.
>> + */
>> +#define ARM64_CPUCAP_LOCAL_CPU_ERRATUM		\
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
>> +/*
>> + * 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.
> 
> "hasn't enabled it, although the feature will not be used by Linux
> in this case.  If the system has enabled this feature already then every
> late CPU must have it."
> 
>> + */
>> +#define ARM64_CPUCAP_SYSTEM_FEATURE	\
>> +	(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>> +
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>>   	u16 capability;
>> @@ -198,6 +245,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_optional(const struct arm64_cpu_capabilities *cap)
>> +{
>> +	return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
>> +}
>> +
>> +static inline bool
>> +cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
>> +{
>> +	return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
>> +}
>> +
>>   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 328c5a031e45..22ec3960a0c5 100644
>> --- a/arch/arm64/kernel/cpu_errata.c
>> +++ b/arch/arm64/kernel/cpu_errata.c
>> @@ -175,14 +175,14 @@ static void qcom_enable_link_stack_sanitization(
>>   #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
>>   
>>   #define MIDR_RANGE(model, min, max) \
>> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
>> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>>   	.matches = is_affected_midr_range, \
>>   	.midr_model = model, \
>>   	.midr_range_min = min, \
>>   	.midr_range_max = max
>>   
>>   #define MIDR_ALL_VERSIONS(model) \
>> -	.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
>> +	.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
>>   	.matches = is_affected_midr_range, \
>>   	.midr_model = model, \
>>   	.midr_range_min = 0, \
>> @@ -286,7 +286,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,
>> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
>> +		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
>>   		.cpu_enable = cpu_enable_trap_ctr_access,
>>   	},
>>   #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
>> @@ -300,7 +300,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>   	{
>>   		.desc = "Qualcomm Technologies Kryo erratum 1003",
>>   		.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
>> -		.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
>> +		.type = ARM64_CPUCAP_LOCAL_CPU_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 8d22f0ef0927..1b29b3f0a1bc 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -921,7 +921,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "GIC system register CPU interface",
>>   		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_useable_gicv3_cpuif,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.field_pos = ID_AA64PFR0_GIC_SHIFT,
>> @@ -932,7 +932,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Privileged Access Never",
>>   		.capability = ARM64_HAS_PAN,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64MMFR1_EL1,
>>   		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
>> @@ -945,7 +945,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "LSE atomic instructions",
>>   		.capability = ARM64_HAS_LSE_ATOMICS,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64ISAR0_EL1,
>>   		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
>> @@ -956,14 +956,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Software prefetching using PRFM",
>>   		.capability = ARM64_HAS_NO_HW_PREFETCH,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_no_hw_prefetch,
>>   	},
>>   #ifdef CONFIG_ARM64_UAO
>>   	{
>>   		.desc = "User Access Override",
>>   		.capability = ARM64_HAS_UAO,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64MMFR2_EL1,
>>   		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
>> @@ -977,21 +977,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   #ifdef CONFIG_ARM64_PAN
>>   	{
>>   		.capability = ARM64_ALT_PAN_NOT_UAO,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = cpufeature_pan_not_uao,
>>   	},
>>   #endif /* CONFIG_ARM64_PAN */
>>   	{
>>   		.desc = "Virtualization Host Extensions",
>>   		.capability = ARM64_HAS_VIRT_HOST_EXTN,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = runs_at_el2,
>>   		.cpu_enable = cpu_copy_el2regs,
>>   	},
>>   	{
>>   		.desc = "32-bit EL0 Support",
>>   		.capability = ARM64_HAS_32BIT_EL0,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.sign = FTR_UNSIGNED,
>> @@ -1001,21 +1001,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Reduced HYP mapping offset",
>>   		.capability = ARM64_HYP_OFFSET_LOW,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = hyp_offset_low,
>>   	},
>>   #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>>   	{
>>   		.desc = "Kernel page table isolation (KPTI)",
>>   		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = unmap_kernel_at_el0,
>>   	},
>>   #endif
>>   	{
>>   		/* FP/SIMD is not implemented */
>>   		.capability = ARM64_HAS_NO_FPSIMD,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.min_field_value = 0,
>>   		.matches = has_no_fpsimd,
>>   	},
>> @@ -1023,7 +1023,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Data cache clean to Point of Persistence",
>>   		.capability = ARM64_HAS_DCPOP,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64ISAR1_EL1,
>>   		.field_pos = ID_AA64ISAR1_DPB_SHIFT,
>> @@ -1033,7 +1033,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   #ifdef CONFIG_ARM64_SVE
>>   	{
>>   		.desc = "Scalable Vector Extension",
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.capability = ARM64_SVE,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.sign = FTR_UNSIGNED,
>> @@ -1047,7 +1047,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "RAS Extension Support",
>>   		.capability = ARM64_HAS_RAS_EXTN,
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>>   		.matches = has_cpuid_feature,
>>   		.sys_reg = SYS_ID_AA64PFR0_EL1,
>>   		.sign = FTR_UNSIGNED,
>> @@ -1062,7 +1062,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
>>   	{							\
>>   		.desc = #cap,					\
>> -		.type = ARM64_CPUCAP_SCOPE_SYSTEM,		\
>> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
>>   		.matches = has_cpuid_feature,			\
>>   		.sys_reg = reg,					\
>>   		.field_pos = field,				\
>> -- 
>> 2.14.3
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU
  2018-02-07 10:37     ` Dave Martin
@ 2018-02-07 14:47       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 14:47 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 07/02/18 10:37, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:49PM +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. While this
>> is correct, we can also do this from init_cpu_features() which
>> initilisation of the infrastructure, and is called only on the
> 
> Typo or missing words here?
> 
> Should this be "which initialises the infrastructure" or "which is
> called to initialise the infrastructure"?
> 
> With that (or any suitable rewording):

Correct. Will fix it.

> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks
Suzuki

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

* [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU
@ 2018-02-07 14:47       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:37, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:49PM +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. While this
>> is correct, we can also do this from init_cpu_features() which
>> initilisation of the infrastructure, and is called only on the
> 
> Typo or missing words here?
> 
> Should this be "which initialises the infrastructure" or "which is
> called to initialise the infrastructure"?
> 
> With that (or any suitable rewording):

Correct. Will fix it.

> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks
Suzuki

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

* Re: [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
  2018-02-07 10:37     ` Dave Martin
@ 2018-02-07 15:16       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 15:16 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 07/02/18 10:37, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:51PM +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. Capabilities
>> have some properties that decide how they should be treated :
>>
>>   1) Detection, i.e scope : A cap could be "detected" either :
>>      - if it is present on at least one CPU (SCOPE_LOCAL_CPU)
>> 	Or
>>      - if it is present on all the CPUs (SCOPE_SYSTEM)
>>
>>   2) When is it enabled ? - A cap is treated as "enabled" when the
>>    system takes some action based on whether the capability is detected or
>>    not. e.g, setting some control register, patching the kernel code.
>>    Right now, we treat all caps are enabled at boot-time, after all
>>    the CPUs are brought up by the kernel. But there are certain caps,
>>    which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
>>    and kernel starts using them, even before the secondary CPUs are brought
>>    up. We would need a way to describe this for each capability.
>>
>>   3) Conflict on a late CPU - When a CPU is brought up, it is checked
>>    against the caps that are known to be enabled on the system (via
>>    verify_local_cpu_capabilities()). Based on the state of the capability
>>    on the CPU vs. that of System we could have the following combinations
>>    of conflict.
>>
>> 	x-----------------------------x
>> 	| Type	| System   | Late CPU |
>> 	------------------------------|
>> 	|  a    |   y      |    n     |
>> 	------------------------------|
>> 	|  b    |   n      |    y     |
>> 	x-----------------------------x
>>
>>    Case (a) is not permitted for caps which are system features, which the
>>    system expects all the CPUs to have (e.g VHE). While (a) is ignored for
>>    all errata work arounds. However, there could be exceptions to the plain
>>    filtering approach. e.g, KPTI is an optional feature for a late CPU as
>>    long as the system already enables it.
>>
>>    Case (b) is not permitted for errata work arounds which requires some
>>    work around, which cannot be delayed. And we ignore (b) for features. Here,
>>    yet again, KPTI is an exception, where if a late CPU needs KPTI we are too
>>    late to enable it (because we change the allocation of ASIDs etc).
>>
>> 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 (which cover
>> errata and features, not the ELF HWCAPs). This is a prepartory step
>> to get there. More bits would be added for the properties listed above.
>>
>> We are going to use a bit-mask to encode all the properties of a capabilities.
>> This patch encodes the "SCOPE" of the capability.
>>
>> As such there is no change in how the capabilities are treated.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> A few minor nits in the documentation, otherwise
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> 
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 90 ++++++++++++++++++++++++++++++++++---
>>   arch/arm64/kernel/cpu_errata.c      |  8 ++--
>>   arch/arm64/kernel/cpufeature.c      | 38 ++++++++--------
>>   3 files changed, 107 insertions(+), 29 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 7925e40c6ded..05da54f1b4c7 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -86,16 +86,89 @@ struct arm64_ftr_reg {
>>   
>>   extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   
>> -/* scope of capability check */
>> -enum {
>> -	SCOPE_SYSTEM,
>> -	SCOPE_LOCAL_CPU,
>> -};
>> +/*
>> + * CPU capabilities:
>> + *
>> + * We use arm64_cpu_capabilities to represent system features, errata work
>> + * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
>> + * ELF HWCAPs (which are exposed to user).
>> + *
>> + * To support systems with heterogeneous CPUs, we need to make sure that we
>> + * detect the capabilities correctly on the system and take appropriate
>> + * measures to ensure there are not incompatibilities.
>> + *
>> + * This comment tries to explain how we treat the capabilities.
>> + * Each capability has the following list of attributes :
>> + *
>> + * 1) Scope of Detection : The system detects a given capability by performing
>> + *    some checks at runtime. This could be, e.g, checking the value of a field
>> + *    in CPU ID feature register or checking the cpu model. The capability
>> + *    provides a call back ( @matches() ) to perform the check.
>> + *    Scope defines how the checks should be performed. There are two cases:
>> + *
>> + *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
>> + *        matches. This implies, we have to run the check on all the booting
>> + *        CPUs, until the system decides that state of the capability is finalised.
>> + *        (See section 2 below)
>> + *		Or
>> + *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
>> + *        This implies, we run the check only once, when the system decides to
>> + *        finalise the state of the capability. If the capability relies on a
>> + *        field in one of the CPU ID feature registers, we use the sanitised
>> + *        value of the register from the CPU feature infrastructure to make
>> + *        the decision.
>> + *    The process of detection is usually denoted by "update" capability state
>> + *    in the code.
>> + *
>> + * 2) Finalise the state : The kernel should finalise the state of a capability
>> + *    at some point during its execution and take necessary actions if any. Usually,
>> + *    this is done, after all the boot-time enabled CPUs are brought up by the
>> + *    kernel, so that it can make better decision based on the available set
>> + *    of CPUs. However, there are some special cases, where the action is taken
>> + *    during the early boot by the primary boot CPU. (e.g, running the kernel at
>> + *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
>> + *    any changes to the state of a capability once it finalises the capability
>> + *    and takes any action, as it may be impossible to execute the actions safely.
>> + *
>> + * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>> + *    the kernel should make sure that it is safe to use the CPU, by verifying
>> + *    that the CPU is compliant with the state of the capabilities established
> 
> Nit: can we say "finalised" instead of "established"?
> 
> There could be doubt about precisely what "established" means.
> "Finalised" is clearly defined in (2) -- I'm assuming that's the
> intended meaning here (?)

You're right. It should be "Finalised".

> 
>> + *    already. This happens via :
>> + *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
>> + *      check_early_cpu_features() && verify_local_cpu_capabilities()
> 
> Nit: Maybe just say "via secondart_start_kernel()"?  Too much detail
> about the exact code flow may become wrong in the future when someone
> refactors the code.

Sure. We could say secondary_start_kernel-> check_local_cpu_capabilities().

> 
>> + *
>> + *    As explained in (2) above, capabilities could be finalised at different
>> + *    points in the execution. Each CPU is verified against the "finalised"
>> + *    capabilities and if there is a conflict, the kernel takes an action, based
>> + *    on the severity (e.g, a CPU could be prevented from booting or cause a
>> + *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>> + *    if it has not been finalised already.
>> + *
>> + * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>> + *    capability, on all CPUs on the system. This is always initiated only after
> 
> Nit: maybe clarify what an action is, e.g.
> "Appropriate actions include patching in alternatives, turning on an
> architectural feature or activating errata workarounds."

See below.

> 
> Can we can that it is the job of the cpu_enable() method to perform the
> appropriate action, or is that not universally true?
> 

It is not completely true. e.g we don't patch in alternatives from "enable" call back.
They are batched and performed after we have "taken actions" (i.e after
enable_cpu_capabilites() ). But all CPU control specific changes are performed from
cpu_enable().

So we could say:

"Appropriate actions include turning on an architectural feature or changing the CPU
control bits (e.g SCTLR or TCR). Patching in alternatives for the capabilities are
batched and is performed separately"

Cheers
Suzuki

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

* [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-02-07 15:16       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:37, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:51PM +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. Capabilities
>> have some properties that decide how they should be treated :
>>
>>   1) Detection, i.e scope : A cap could be "detected" either :
>>      - if it is present on at least one CPU (SCOPE_LOCAL_CPU)
>> 	Or
>>      - if it is present on all the CPUs (SCOPE_SYSTEM)
>>
>>   2) When is it enabled ? - A cap is treated as "enabled" when the
>>    system takes some action based on whether the capability is detected or
>>    not. e.g, setting some control register, patching the kernel code.
>>    Right now, we treat all caps are enabled at boot-time, after all
>>    the CPUs are brought up by the kernel. But there are certain caps,
>>    which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
>>    and kernel starts using them, even before the secondary CPUs are brought
>>    up. We would need a way to describe this for each capability.
>>
>>   3) Conflict on a late CPU - When a CPU is brought up, it is checked
>>    against the caps that are known to be enabled on the system (via
>>    verify_local_cpu_capabilities()). Based on the state of the capability
>>    on the CPU vs. that of System we could have the following combinations
>>    of conflict.
>>
>> 	x-----------------------------x
>> 	| Type	| System   | Late CPU |
>> 	------------------------------|
>> 	|  a    |   y      |    n     |
>> 	------------------------------|
>> 	|  b    |   n      |    y     |
>> 	x-----------------------------x
>>
>>    Case (a) is not permitted for caps which are system features, which the
>>    system expects all the CPUs to have (e.g VHE). While (a) is ignored for
>>    all errata work arounds. However, there could be exceptions to the plain
>>    filtering approach. e.g, KPTI is an optional feature for a late CPU as
>>    long as the system already enables it.
>>
>>    Case (b) is not permitted for errata work arounds which requires some
>>    work around, which cannot be delayed. And we ignore (b) for features. Here,
>>    yet again, KPTI is an exception, where if a late CPU needs KPTI we are too
>>    late to enable it (because we change the allocation of ASIDs etc).
>>
>> 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 (which cover
>> errata and features, not the ELF HWCAPs). This is a prepartory step
>> to get there. More bits would be added for the properties listed above.
>>
>> We are going to use a bit-mask to encode all the properties of a capabilities.
>> This patch encodes the "SCOPE" of the capability.
>>
>> As such there is no change in how the capabilities are treated.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> A few minor nits in the documentation, otherwise
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> 
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 90 ++++++++++++++++++++++++++++++++++---
>>   arch/arm64/kernel/cpu_errata.c      |  8 ++--
>>   arch/arm64/kernel/cpufeature.c      | 38 ++++++++--------
>>   3 files changed, 107 insertions(+), 29 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 7925e40c6ded..05da54f1b4c7 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -86,16 +86,89 @@ struct arm64_ftr_reg {
>>   
>>   extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   
>> -/* scope of capability check */
>> -enum {
>> -	SCOPE_SYSTEM,
>> -	SCOPE_LOCAL_CPU,
>> -};
>> +/*
>> + * CPU capabilities:
>> + *
>> + * We use arm64_cpu_capabilities to represent system features, errata work
>> + * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
>> + * ELF HWCAPs (which are exposed to user).
>> + *
>> + * To support systems with heterogeneous CPUs, we need to make sure that we
>> + * detect the capabilities correctly on the system and take appropriate
>> + * measures to ensure there are not incompatibilities.
>> + *
>> + * This comment tries to explain how we treat the capabilities.
>> + * Each capability has the following list of attributes :
>> + *
>> + * 1) Scope of Detection : The system detects a given capability by performing
>> + *    some checks at runtime. This could be, e.g, checking the value of a field
>> + *    in CPU ID feature register or checking the cpu model. The capability
>> + *    provides a call back ( @matches() ) to perform the check.
>> + *    Scope defines how the checks should be performed. There are two cases:
>> + *
>> + *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
>> + *        matches. This implies, we have to run the check on all the booting
>> + *        CPUs, until the system decides that state of the capability is finalised.
>> + *        (See section 2 below)
>> + *		Or
>> + *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
>> + *        This implies, we run the check only once, when the system decides to
>> + *        finalise the state of the capability. If the capability relies on a
>> + *        field in one of the CPU ID feature registers, we use the sanitised
>> + *        value of the register from the CPU feature infrastructure to make
>> + *        the decision.
>> + *    The process of detection is usually denoted by "update" capability state
>> + *    in the code.
>> + *
>> + * 2) Finalise the state : The kernel should finalise the state of a capability
>> + *    at some point during its execution and take necessary actions if any. Usually,
>> + *    this is done, after all the boot-time enabled CPUs are brought up by the
>> + *    kernel, so that it can make better decision based on the available set
>> + *    of CPUs. However, there are some special cases, where the action is taken
>> + *    during the early boot by the primary boot CPU. (e.g, running the kernel at
>> + *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
>> + *    any changes to the state of a capability once it finalises the capability
>> + *    and takes any action, as it may be impossible to execute the actions safely.
>> + *
>> + * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>> + *    the kernel should make sure that it is safe to use the CPU, by verifying
>> + *    that the CPU is compliant with the state of the capabilities established
> 
> Nit: can we say "finalised" instead of "established"?
> 
> There could be doubt about precisely what "established" means.
> "Finalised" is clearly defined in (2) -- I'm assuming that's the
> intended meaning here (?)

You're right. It should be "Finalised".

> 
>> + *    already. This happens via :
>> + *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
>> + *      check_early_cpu_features() && verify_local_cpu_capabilities()
> 
> Nit: Maybe just say "via secondart_start_kernel()"?  Too much detail
> about the exact code flow may become wrong in the future when someone
> refactors the code.

Sure. We could say secondary_start_kernel-> check_local_cpu_capabilities().

> 
>> + *
>> + *    As explained in (2) above, capabilities could be finalised at different
>> + *    points in the execution. Each CPU is verified against the "finalised"
>> + *    capabilities and if there is a conflict, the kernel takes an action, based
>> + *    on the severity (e.g, a CPU could be prevented from booting or cause a
>> + *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>> + *    if it has not been finalised already.
>> + *
>> + * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>> + *    capability, on all CPUs on the system. This is always initiated only after
> 
> Nit: maybe clarify what an action is, e.g.
> "Appropriate actions include patching in alternatives, turning on an
> architectural feature or activating errata workarounds."

See below.

> 
> Can we can that it is the job of the cpu_enable() method to perform the
> appropriate action, or is that not universally true?
> 

It is not completely true. e.g we don't patch in alternatives from "enable" call back.
They are batched and performed after we have "taken actions" (i.e after
enable_cpu_capabilites() ). But all CPU control specific changes are performed from
cpu_enable().

So we could say:

"Appropriate actions include turning on an architectural feature or changing the CPU
control bits (e.g SCTLR or TCR). Patching in alternatives for the capabilities are
batched and is performed separately"

Cheers
Suzuki

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

* Re: [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
  2018-02-07 15:16       ` Suzuki K Poulose
@ 2018-02-07 15:39         ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 15:39 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, Feb 07, 2018 at 03:16:39PM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:37, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:27:51PM +0000, Suzuki K Poulose wrote:

[...]

> >>As such there is no change in how the capabilities are treated.
> >>
> >>Cc: Dave Martin <dave.martin@arm.com>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >
> >A few minor nits in the documentation, otherwise
> >
> >Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> >
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 90 ++++++++++++++++++++++++++++++++++---
> >>  arch/arm64/kernel/cpu_errata.c      |  8 ++--
> >>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++--------
> >>  3 files changed, 107 insertions(+), 29 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 7925e40c6ded..05da54f1b4c7 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -86,16 +86,89 @@ struct arm64_ftr_reg {
> >>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>-/* scope of capability check */
> >>-enum {
> >>-	SCOPE_SYSTEM,
> >>-	SCOPE_LOCAL_CPU,
> >>-};
> >>+/*
> >>+ * CPU capabilities:
> >>+ *
> >>+ * We use arm64_cpu_capabilities to represent system features, errata work
> >>+ * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
> >>+ * ELF HWCAPs (which are exposed to user).
> >>+ *
> >>+ * To support systems with heterogeneous CPUs, we need to make sure that we
> >>+ * detect the capabilities correctly on the system and take appropriate
> >>+ * measures to ensure there are not incompatibilities.
> >>+ *
> >>+ * This comment tries to explain how we treat the capabilities.
> >>+ * Each capability has the following list of attributes :
> >>+ *
> >>+ * 1) Scope of Detection : The system detects a given capability by performing
> >>+ *    some checks at runtime. This could be, e.g, checking the value of a field
> >>+ *    in CPU ID feature register or checking the cpu model. The capability
> >>+ *    provides a call back ( @matches() ) to perform the check.
> >>+ *    Scope defines how the checks should be performed. There are two cases:
> >>+ *
> >>+ *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
> >>+ *        matches. This implies, we have to run the check on all the booting
> >>+ *        CPUs, until the system decides that state of the capability is finalised.
> >>+ *        (See section 2 below)
> >>+ *		Or
> >>+ *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
> >>+ *        This implies, we run the check only once, when the system decides to
> >>+ *        finalise the state of the capability. If the capability relies on a
> >>+ *        field in one of the CPU ID feature registers, we use the sanitised
> >>+ *        value of the register from the CPU feature infrastructure to make
> >>+ *        the decision.
> >>+ *    The process of detection is usually denoted by "update" capability state
> >>+ *    in the code.
> >>+ *
> >>+ * 2) Finalise the state : The kernel should finalise the state of a capability
> >>+ *    at some point during its execution and take necessary actions if any. Usually,
> >>+ *    this is done, after all the boot-time enabled CPUs are brought up by the
> >>+ *    kernel, so that it can make better decision based on the available set
> >>+ *    of CPUs. However, there are some special cases, where the action is taken
> >>+ *    during the early boot by the primary boot CPU. (e.g, running the kernel at
> >>+ *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
> >>+ *    any changes to the state of a capability once it finalises the capability
> >>+ *    and takes any action, as it may be impossible to execute the actions safely.
> >>+ *
> >>+ * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
> >>+ *    the kernel should make sure that it is safe to use the CPU, by verifying
> >>+ *    that the CPU is compliant with the state of the capabilities established
> >
> >Nit: can we say "finalised" instead of "established"?
> >
> >There could be doubt about precisely what "established" means.
> >"Finalised" is clearly defined in (2) -- I'm assuming that's the
> >intended meaning here (?)
> 
> You're right. It should be "Finalised".
> 
> >
> >>+ *    already. This happens via :
> >>+ *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
> >>+ *      check_early_cpu_features() && verify_local_cpu_capabilities()
> >
> >Nit: Maybe just say "via secondart_start_kernel()"?  Too much detail
> >about the exact code flow may become wrong in the future when someone
> >refactors the code.
> 
> Sure. We could say secondary_start_kernel-> check_local_cpu_capabilities().

Yes, that seems enough.

> >
> >>+ *
> >>+ *    As explained in (2) above, capabilities could be finalised at different
> >>+ *    points in the execution. Each CPU is verified against the "finalised"
> >>+ *    capabilities and if there is a conflict, the kernel takes an action, based
> >>+ *    on the severity (e.g, a CPU could be prevented from booting or cause a
> >>+ *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> >>+ *    if it has not been finalised already.
> >>+ *
> >>+ * 4) Action: As mentioned in (2), the kernel can take an action for each detected
> >>+ *    capability, on all CPUs on the system. This is always initiated only after
> >
> >Nit: maybe clarify what an action is, e.g.
> >"Appropriate actions include patching in alternatives, turning on an
> >architectural feature or activating errata workarounds."
> 
> See below.
> 
> >
> >Can we can that it is the job of the cpu_enable() method to perform the
> >appropriate action, or is that not universally true?
> >
> 
> It is not completely true. e.g we don't patch in alternatives from "enable" call back.
> They are batched and performed after we have "taken actions" (i.e after
> enable_cpu_capabilites() ). But all CPU control specific changes are performed from
> cpu_enable().
> 
> So we could say:
> 
> "Appropriate actions include turning on an architectural feature or
> changing the CPU control bits (e.g SCTLR or TCR). Patching in
> alternatives for the capabilities are

are -> is ?

> batched and is performed separately"

Ah, OK.  Yes that seems fine.

Happy to keep my Reviewed-by with those edits.

Cheers
---Dave

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

* [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities
@ 2018-02-07 15:39         ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-07 15:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 07, 2018 at 03:16:39PM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:37, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:27:51PM +0000, Suzuki K Poulose wrote:

[...]

> >>As such there is no change in how the capabilities are treated.
> >>
> >>Cc: Dave Martin <dave.martin@arm.com>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >
> >A few minor nits in the documentation, otherwise
> >
> >Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> >
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 90 ++++++++++++++++++++++++++++++++++---
> >>  arch/arm64/kernel/cpu_errata.c      |  8 ++--
> >>  arch/arm64/kernel/cpufeature.c      | 38 ++++++++--------
> >>  3 files changed, 107 insertions(+), 29 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 7925e40c6ded..05da54f1b4c7 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -86,16 +86,89 @@ struct arm64_ftr_reg {
> >>  extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>-/* scope of capability check */
> >>-enum {
> >>-	SCOPE_SYSTEM,
> >>-	SCOPE_LOCAL_CPU,
> >>-};
> >>+/*
> >>+ * CPU capabilities:
> >>+ *
> >>+ * We use arm64_cpu_capabilities to represent system features, errata work
> >>+ * arounds (both used internally by kernel and tracked in cpu_hwcaps) and
> >>+ * ELF HWCAPs (which are exposed to user).
> >>+ *
> >>+ * To support systems with heterogeneous CPUs, we need to make sure that we
> >>+ * detect the capabilities correctly on the system and take appropriate
> >>+ * measures to ensure there are not incompatibilities.
> >>+ *
> >>+ * This comment tries to explain how we treat the capabilities.
> >>+ * Each capability has the following list of attributes :
> >>+ *
> >>+ * 1) Scope of Detection : The system detects a given capability by performing
> >>+ *    some checks at runtime. This could be, e.g, checking the value of a field
> >>+ *    in CPU ID feature register or checking the cpu model. The capability
> >>+ *    provides a call back ( @matches() ) to perform the check.
> >>+ *    Scope defines how the checks should be performed. There are two cases:
> >>+ *
> >>+ *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
> >>+ *        matches. This implies, we have to run the check on all the booting
> >>+ *        CPUs, until the system decides that state of the capability is finalised.
> >>+ *        (See section 2 below)
> >>+ *		Or
> >>+ *     b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs matches.
> >>+ *        This implies, we run the check only once, when the system decides to
> >>+ *        finalise the state of the capability. If the capability relies on a
> >>+ *        field in one of the CPU ID feature registers, we use the sanitised
> >>+ *        value of the register from the CPU feature infrastructure to make
> >>+ *        the decision.
> >>+ *    The process of detection is usually denoted by "update" capability state
> >>+ *    in the code.
> >>+ *
> >>+ * 2) Finalise the state : The kernel should finalise the state of a capability
> >>+ *    at some point during its execution and take necessary actions if any. Usually,
> >>+ *    this is done, after all the boot-time enabled CPUs are brought up by the
> >>+ *    kernel, so that it can make better decision based on the available set
> >>+ *    of CPUs. However, there are some special cases, where the action is taken
> >>+ *    during the early boot by the primary boot CPU. (e.g, running the kernel at
> >>+ *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
> >>+ *    any changes to the state of a capability once it finalises the capability
> >>+ *    and takes any action, as it may be impossible to execute the actions safely.
> >>+ *
> >>+ * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
> >>+ *    the kernel should make sure that it is safe to use the CPU, by verifying
> >>+ *    that the CPU is compliant with the state of the capabilities established
> >
> >Nit: can we say "finalised" instead of "established"?
> >
> >There could be doubt about precisely what "established" means.
> >"Finalised" is clearly defined in (2) -- I'm assuming that's the
> >intended meaning here (?)
> 
> You're right. It should be "Finalised".
> 
> >
> >>+ *    already. This happens via :
> >>+ *    secondary_start_kernel()-> check_local_cpu_capabilities()	->
> >>+ *      check_early_cpu_features() && verify_local_cpu_capabilities()
> >
> >Nit: Maybe just say "via secondart_start_kernel()"?  Too much detail
> >about the exact code flow may become wrong in the future when someone
> >refactors the code.
> 
> Sure. We could say secondary_start_kernel-> check_local_cpu_capabilities().

Yes, that seems enough.

> >
> >>+ *
> >>+ *    As explained in (2) above, capabilities could be finalised at different
> >>+ *    points in the execution. Each CPU is verified against the "finalised"
> >>+ *    capabilities and if there is a conflict, the kernel takes an action, based
> >>+ *    on the severity (e.g, a CPU could be prevented from booting or cause a
> >>+ *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> >>+ *    if it has not been finalised already.
> >>+ *
> >>+ * 4) Action: As mentioned in (2), the kernel can take an action for each detected
> >>+ *    capability, on all CPUs on the system. This is always initiated only after
> >
> >Nit: maybe clarify what an action is, e.g.
> >"Appropriate actions include patching in alternatives, turning on an
> >architectural feature or activating errata workarounds."
> 
> See below.
> 
> >
> >Can we can that it is the job of the cpu_enable() method to perform the
> >appropriate action, or is that not universally true?
> >
> 
> It is not completely true. e.g we don't patch in alternatives from "enable" call back.
> They are batched and performed after we have "taken actions" (i.e after
> enable_cpu_capabilites() ). But all CPU control specific changes are performed from
> cpu_enable().
> 
> So we could say:
> 
> "Appropriate actions include turning on an architectural feature or
> changing the CPU control bits (e.g SCTLR or TCR). Patching in
> alternatives for the capabilities are

are -> is ?

> batched and is performed separately"

Ah, OK.  Yes that seems fine.

Happy to keep my Reviewed-by with those edits.

Cheers
---Dave

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

* Re: [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
  2018-02-07 11:31       ` Robin Murphy
@ 2018-02-07 16:53         ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 16:53 UTC (permalink / raw)
  To: Robin Murphy, Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 07/02/18 11:31, Robin Murphy wrote:
> On 07/02/18 10:38, Dave Martin wrote:
>> On Wed, Jan 31, 2018 at 06:27:52PM +0000, Suzuki K Poulose wrote:

...

>>> Case (b) is not permitted for errata work arounds which requires some work
>>> around, which cannot be delayed. And we ignore (b) for features. Here, yet
>>
>> Nit, maybe:
>>
>> "Case (b) is not permitted for any errata workaround that cannot be
>> activated if the kernel has finished booting and has not already enabled
>> it."
> 
> Nit^2: I think it would suffice to say "...that cannot be activated after the kernel has finished booting." - since we don't really have the concept of *de*activating workarounds, it is already implicit in that statement that the one in question wasn't activated *before* the kernel finished booting.

Robin, Dave,

I have updated the comments accordingly.

Thanks a lot for the review

Suzuki

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

* [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU
@ 2018-02-07 16:53         ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 11:31, Robin Murphy wrote:
> On 07/02/18 10:38, Dave Martin wrote:
>> On Wed, Jan 31, 2018 at 06:27:52PM +0000, Suzuki K Poulose wrote:

...

>>> Case (b) is not permitted for errata work arounds which requires some work
>>> around, which cannot be delayed. And we ignore (b) for features. Here, yet
>>
>> Nit, maybe:
>>
>> "Case (b) is not permitted for any errata workaround that cannot be
>> activated if the kernel has finished booting and has not already enabled
>> it."
> 
> Nit^2: I think it would suffice to say "...that cannot be activated after the kernel has finished booting." - since we don't really have the concept of *de*activating workarounds, it is already implicit in that statement that the one in question wasn't activated *before* the kernel finished booting.

Robin, Dave,

I have updated the comments accordingly.

Thanks a lot for the review

Suzuki

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

* Re: [PATCH v2 06/20] arm64: capabilities: Unify the verification
  2018-02-07 10:38     ` Dave Martin
@ 2018-02-07 16:56       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 16: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 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:53PM +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.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>   arch/arm64/kernel/cpufeature.c      | 89 +++++++++++++++++++++++--------------
>>   2 files changed, 57 insertions(+), 33 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 1b29b3f0a1bc..5e4d581c97f1 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1233,6 +1233,56 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>>   	}
>>   }
>>   
>> +/*
>> + * Run through the list of capabilities to check for conflicts.
>> + * If the system has already detected a capability, take necessary
>> + * action on this CPU.
>> + *
>> + * 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);
> 
> Nit: Odd spacing?

Fixed

> 
> [...]
> 
> Otherwise,
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks
Suzuki

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

* [PATCH v2 06/20] arm64: capabilities: Unify the verification
@ 2018-02-07 16:56       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 16:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:53PM +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.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>   arch/arm64/kernel/cpufeature.c      | 89 +++++++++++++++++++++++--------------
>>   2 files changed, 57 insertions(+), 33 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 1b29b3f0a1bc..5e4d581c97f1 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1233,6 +1233,56 @@ static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *
>>   	}
>>   }
>>   
>> +/*
>> + * Run through the list of capabilities to check for conflicts.
>> + * If the system has already detected a capability, take necessary
>> + * action on this CPU.
>> + *
>> + * 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);
> 
> Nit: Odd spacing?

Fixed

> 
> [...]
> 
> Otherwise,
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks
Suzuki

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

* Re: [PATCH v2 07/20] arm64: capabilities: Filter the entries based on a given mask
  2018-02-07 10:38     ` Dave Martin
@ 2018-02-07 17:01       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 17:01 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 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:54PM +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 mask for the
>> scope of the capabilities to allow better control. This can be
>> used later for handling LOCAL vs SYSTEM wide capabilities and more.
>> All capabilities should have their scope set to either LOCAL_CPU or
>> SYSTEM. No functional/flow change.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  2 ++
>>   arch/arm64/kernel/cpufeature.c      | 35 ++++++++++++++++++++++++-----------
>>   2 files changed, 26 insertions(+), 11 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 69b5ce366598..cda62b70d338 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -198,6 +198,8 @@ 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_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>>   
>> +#define ARM64_CPUCAP_SCOPE_ALL			 \
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
> 
> Perhaps we could just use _MASK rather than having a separate #define,
> but it's good either way.
> 
> Is there a situation in which _ALL and _MASK would need to be
> different?

No, it just makes it easier to read the code. I have switched to:

>> -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 scope_mask)
>>   {
>>   	bool cpu_has_cap, system_has_cap;
>>   	const struct arm64_cpu_capabilities *caps = caps_list;
>>   
>> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>>   	for (; caps->matches; caps++) {
>> +
> 
> Nit: extra blank line?

Fixed.

> 
> [...]
> 
> With that fixed,
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks
Suzuki

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

* [PATCH v2 07/20] arm64: capabilities: Filter the entries based on a given mask
@ 2018-02-07 17:01       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 17:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:54PM +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 mask for the
>> scope of the capabilities to allow better control. This can be
>> used later for handling LOCAL vs SYSTEM wide capabilities and more.
>> All capabilities should have their scope set to either LOCAL_CPU or
>> SYSTEM. No functional/flow change.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  2 ++
>>   arch/arm64/kernel/cpufeature.c      | 35 ++++++++++++++++++++++++-----------
>>   2 files changed, 26 insertions(+), 11 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 69b5ce366598..cda62b70d338 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -198,6 +198,8 @@ 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_OPTIONAL_FOR_LATE_CPU	((u16)BIT(5))
>>   
>> +#define ARM64_CPUCAP_SCOPE_ALL			 \
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_SCOPE_SYSTEM)
> 
> Perhaps we could just use _MASK rather than having a separate #define,
> but it's good either way.
> 
> Is there a situation in which _ALL and _MASK would need to be
> different?

No, it just makes it easier to read the code. I have switched to:

>> -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 scope_mask)
>>   {
>>   	bool cpu_has_cap, system_has_cap;
>>   	const struct arm64_cpu_capabilities *caps = caps_list;
>>   
>> +	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>>   	for (; caps->matches; caps++) {
>> +
> 
> Nit: extra blank line?

Fixed.

> 
> [...]
> 
> With that fixed,
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks
Suzuki

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

* Re: [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
  2018-02-07 10:38     ` Dave Martin
@ 2018-02-07 18:15       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 18:15 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 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:57PM +0000, Suzuki K Poulose wrote:
>> 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,
> 
> Should that be "when any CPU"?
> 

Without this patch, we need all the CPUs to mandate the defense (as this
is a system feature). This patch changes it. I will change it to :

"KPTI is treated as a system wide feature and is only "detected" if all
the CPUs on the system needs the defense. This is not sufficient, as the
KPTI is turned off on a system with a mix of CPUs, where some CPUs can
defend and others can't,

>> unless it is forced via kernel 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

" This patch ensures that KPTI is turned on if at least one CPU requires the
defense and any late CPUs are rejected..."
.
>> that late CPUs are rejected as appropriate if they need KPTI but it wasn't
>> enabled.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  9 +++++++++
>>   arch/arm64/kernel/cpufeature.c      | 11 ++++++-----
>>   2 files changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 7bb3fdec827e..71993dd4afae 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -223,6 +223,15 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
>>   	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>>   
>> +/*
>> + * CPU feature detected at boot time, on one or more CPUs. A late CPU
>> + * is not allowed to have the capability when the system doesn't have it.
>> + * It is Ok for a late CPU to miss the feature.
>> + */
>> +#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE	\
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
>> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
>> +
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>>   	u16 capability;
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index ecc87aa74c64..4a55492784b7 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) {
>> @@ -885,8 +884,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>>   	}
>>   
>>   	/* 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)
>> @@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Kernel page table isolation (KPTI)",
>>   		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
>> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>> +		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
>> +		.sys_reg = SYS_ID_AA64PFR0_EL1,
>> +		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
>> +		.min_field_value = 1,
>>   		.matches = unmap_kernel_at_el0,
> 
> Minor nit, but:
> 
> Can we have a comment here to explain that .min_field_value is the
> minimum value that indicates that KPTI is _not_ required by this cpu?
> This is the opposite of the usual semantics for this field.

Sure, will add it.

> 
> Otherwise, this inversion of meaning is not obvious without digging into
> unmap_kernel_at_el0() and spotting the ! in !has_cpuid_feature().
> 
> With that, or if this usage of !has_cpuid_feature() is already well-
> established so that a comment is deemed unnecessary:

This is the first time we have used it.

Cheers
Suzuki

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

* [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
@ 2018-02-07 18:15       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 18:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:57PM +0000, Suzuki K Poulose wrote:
>> 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,
> 
> Should that be "when any CPU"?
> 

Without this patch, we need all the CPUs to mandate the defense (as this
is a system feature). This patch changes it. I will change it to :

"KPTI is treated as a system wide feature and is only "detected" if all
the CPUs on the system needs the defense. This is not sufficient, as the
KPTI is turned off on a system with a mix of CPUs, where some CPUs can
defend and others can't,

>> unless it is forced via kernel 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

" This patch ensures that KPTI is turned on if at least one CPU requires the
defense and any late CPUs are rejected..."
.
>> that late CPUs are rejected as appropriate if they need KPTI but it wasn't
>> enabled.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  9 +++++++++
>>   arch/arm64/kernel/cpufeature.c      | 11 ++++++-----
>>   2 files changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 7bb3fdec827e..71993dd4afae 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -223,6 +223,15 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>   	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU	|	\
>>   	 ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
>>   
>> +/*
>> + * CPU feature detected at boot time, on one or more CPUs. A late CPU
>> + * is not allowed to have the capability when the system doesn't have it.
>> + * It is Ok for a late CPU to miss the feature.
>> + */
>> +#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE	\
>> +	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
>> +	 ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
>> +
>>   struct arm64_cpu_capabilities {
>>   	const char *desc;
>>   	u16 capability;
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index ecc87aa74c64..4a55492784b7 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) {
>> @@ -885,8 +884,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>>   	}
>>   
>>   	/* 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)
>> @@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>>   	{
>>   		.desc = "Kernel page table isolation (KPTI)",
>>   		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
>> -		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>> +		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
>> +		.sys_reg = SYS_ID_AA64PFR0_EL1,
>> +		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
>> +		.min_field_value = 1,
>>   		.matches = unmap_kernel_at_el0,
> 
> Minor nit, but:
> 
> Can we have a comment here to explain that .min_field_value is the
> minimum value that indicates that KPTI is _not_ required by this cpu?
> This is the opposite of the usual semantics for this field.

Sure, will add it.

> 
> Otherwise, this inversion of meaning is not obvious without digging into
> unmap_kernel_at_el0() and spotting the ! in !has_cpuid_feature().
> 
> With that, or if this usage of !has_cpuid_feature() is already well-
> established so that a comment is deemed unnecessary:

This is the first time we have used it.

Cheers
Suzuki

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

* Re: [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
  2018-02-07 10:38     ` Dave Martin
@ 2018-02-07 18:34       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 18:34 UTC (permalink / raw)
  To: Dave Martin
  Cc: linux-arm-kernel, mark.rutland, Julien Thierry, ckadabi,
	ard.biesheuvel, marc.zyngier, catalin.marinas, will.deacon,
	linux-kernel, jnair

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:
>> The kernel detects and uses some of the features based on the boot
>> CPU and expects that all the following CPUs conform to it. e.g,
>> with VHE and the boot CPU running at EL2, the kernel decides to
>> keep the kernel running at EL2. If another CPU is brought up without
>> this capability, we use custom hooks (via check_early_cpu_features())
>> to handle it. To handle such capabilities add support for detecting
>> and enabling capabilities based on the boot CPU.
>>
>> A bit is added to indicate if the capability should be detected
>> early on the boot CPU. The infrastructure then ensures that such
>> capabilities are probed and "enabled" early on in the boot CPU
>> and, enabled on the subsequent CPUs.
>>
>> Cc: Julien Thierry <julien.thierry@arm.com>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
>>   arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
>>   2 files changed, 74 insertions(+), 22 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 71993dd4afae..04161aac0f06 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -104,7 +104,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *    some checks at runtime. This could be, e.g, checking the value of a field
>>    *    in CPU ID feature register or checking the cpu model. The capability
>>    *    provides a call back ( @matches() ) to perform the check.
>> - *    Scope defines how the checks should be performed. There are two cases:
>> + *    Scope defines how the checks should be performed. There are three cases:
>>    *
>>    *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
>>    *        matches. This implies, we have to run the check on all the booting
>> @@ -117,6 +117,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *        field in one of the CPU ID feature registers, we use the sanitised
>>    *        value of the register from the CPU feature infrastructure to make
>>    *        the decision.
>> + *		Or
>> + *     c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the feature.
>> + *        This category is for features that are "finalised" (or used) by the kernel
>> + *        very early even before the SMP cpus are brought up.
>> + *
>>    *    The process of detection is usually denoted by "update" capability state
>>    *    in the code.
>>    *
>> @@ -129,6 +134,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
>>    *    any changes to the state of a capability once it finalises the capability
>>    *    and takes any action, as it may be impossible to execute the actions safely.
>> + *    At the moment there are two passes of finalising the capabilities.
>> + *      a) Boot CPU scope capabilities - Finalised by primary boot CPU via
>> + *         setup_boot_cpu_capabilities().
>> + *      b) Everything except (a) - Run via setup_system_capabilities().
>>    *
>>    * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>>    *    the kernel should make sure that it is safe to use the CPU, by verifying
>> @@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *
>>    *    As explained in (2) above, capabilities could be finalised at different
>>    *    points in the execution. Each CPU is verified against the "finalised"
>> - *    capabilities and if there is a conflict, the kernel takes an action, based
>> - *    on the severity (e.g, a CPU could be prevented from booting or cause a
>> - *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>> - *    if it has not been finalised already. See section 5 for more details on
>> - *    conflicts.
>> + *    capabilities.
>> + *
>> + *	x------------------------------------------------------------------- x
>> + *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
>> + *	|--------------------------------------------------------------------|
>> + *	| Primary boot CPU    |          |                    |              |
>> + *	|  capability         |   n      |      y             |       y      |
>> + *	|--------------------------------------------------------------------|
>> + *	| All others          |   n      |      n             |       y      |
>> + *	x--------------------------------------------------------------------x
> 
> Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
> means "conflict".
> 
> Could we have blank cell versus "X" (with a note saying what that
> means), or "ok" versus "CONFLICT"?

This is not strictly about conflicts, but about what each CPU get verified against.
Since there are multiple stages of "finalisation" for the capabilities, the table
shows how the CPUs get verified.

Would it help if I changed the description above the table to :

  *    As explained in (2) above, capabilities could be finalised at different
  *    points in the execution. Each CPU is verified against the "finalised"
  *    capabilities. The following table shows, the capabilities verified
  *    against each CPU in the system.
  *
  *      x------------------------------------------------------------------- x
  *      | Verified against:   | Boot CPU | SMP CPUs by kernel | CPUs by user |

.....


> 
>> + *
>> + *
>> + *    If there is a conflict, the kernel takes an action, based on the severity
>> + *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
>> + *    The CPU is allowed to "affect" the state of the capability, if it has not
>> + *    been finalised already. See section 5 for more details on conflicts.
>>    *
>>    * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>>    *    capability, on all CPUs on the system. This is always initiated only after
>> @@ -186,20 +206,28 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    */
>>   
>>   
>> -/* Decide how the capability is detected. On a local CPU vs System wide */
>> -#define ARM64_CPUCAP_SCOPE_MASK			0x3
>> +/*
>> + * Decide how the capability is detected.
>> + * On any local CPU vs System wide vs the primary boot CPU
>> + */
>> +#define ARM64_CPUCAP_SCOPE_MASK			0x7
> 
> Minor nit: magic number.  Could we do
> 
> #define ARM64_CPUCAP_SCOPE_MASK		\
> 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU |	\
> 	 ARM64_CPUCAP_SCOPE_SYSTEM |	\
> 	 ARM64_CPUCAP_SCOPE_BOOT_CPU)
> 
> below?

Sure, I will move it.

>>   static void verify_local_cpu_capabilities(void)
>>   {
>> -	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
>> +	if (!verify_local_cpu_caps(~ARM64_CPUCAP_SCOPE_BOOT_CPU))
> 
> [1] This is neat, but would it be clearer to say _ALL & ~_BOOT_CPU?
> 
> Otherwise, this is passing (u16)0xfffb, which feels invalid,
> particularly since it includes _{PERMITTED,OPTIONAL}_FOR_LATE_CPU which
> don't make sense here, even if we know they get masked off.
> 
> There could be future pitfalls here if ~_BOOT_CPU by itself is pasted
> in other places where the *_FOR_LATE_CPU bits are significant.

Sure, I chose it for keeping the lines shorter ;-). I will switch it.

> 
>>   		cpu_die_early();
>>   	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>>   
>> @@ -1415,6 +1430,15 @@ void check_local_cpu_capabilities(void)
>>   		verify_local_cpu_capabilities();
>>   }
>>   
>> +static void __init setup_boot_cpu_capabilities(void)
>> +{
>> +	/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
>> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU |
>> +				 ARM64_CPUCAP_SCOPE_LOCAL_CPU);
>> +	/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
>> +	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU);
>> +}
>> +
>>   static void __init setup_system_capabilities(void)
>>   {
>>   	/*
>> @@ -1422,8 +1446,8 @@ static void __init setup_system_capabilities(void)
>>   	 * finalise the capabilities that depend on it.
>>   	 */
>>   	update_system_capabilities();
>> -	/* Enable all the available capabilities */
>> -	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_ALL);
>> +	/* Enable all the available capabilities, which are not already enabled. */
>> +	enable_cpu_capabilities(~ARM64_CPUCAP_SCOPE_BOOT_CPU);
> 
> As [1] above.
> 

Cheers
Suzuki

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

* [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
@ 2018-02-07 18:34       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-07 18:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:
>> The kernel detects and uses some of the features based on the boot
>> CPU and expects that all the following CPUs conform to it. e.g,
>> with VHE and the boot CPU running at EL2, the kernel decides to
>> keep the kernel running at EL2. If another CPU is brought up without
>> this capability, we use custom hooks (via check_early_cpu_features())
>> to handle it. To handle such capabilities add support for detecting
>> and enabling capabilities based on the boot CPU.
>>
>> A bit is added to indicate if the capability should be detected
>> early on the boot CPU. The infrastructure then ensures that such
>> capabilities are probed and "enabled" early on in the boot CPU
>> and, enabled on the subsequent CPUs.
>>
>> Cc: Julien Thierry <julien.thierry@arm.com>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
>>   arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
>>   2 files changed, 74 insertions(+), 22 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 71993dd4afae..04161aac0f06 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -104,7 +104,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *    some checks at runtime. This could be, e.g, checking the value of a field
>>    *    in CPU ID feature register or checking the cpu model. The capability
>>    *    provides a call back ( @matches() ) to perform the check.
>> - *    Scope defines how the checks should be performed. There are two cases:
>> + *    Scope defines how the checks should be performed. There are three cases:
>>    *
>>    *     a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
>>    *        matches. This implies, we have to run the check on all the booting
>> @@ -117,6 +117,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *        field in one of the CPU ID feature registers, we use the sanitised
>>    *        value of the register from the CPU feature infrastructure to make
>>    *        the decision.
>> + *		Or
>> + *     c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the feature.
>> + *        This category is for features that are "finalised" (or used) by the kernel
>> + *        very early even before the SMP cpus are brought up.
>> + *
>>    *    The process of detection is usually denoted by "update" capability state
>>    *    in the code.
>>    *
>> @@ -129,6 +134,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *    EL2 with Virtualisation Host Extensions). The kernel usually disallows
>>    *    any changes to the state of a capability once it finalises the capability
>>    *    and takes any action, as it may be impossible to execute the actions safely.
>> + *    At the moment there are two passes of finalising the capabilities.
>> + *      a) Boot CPU scope capabilities - Finalised by primary boot CPU via
>> + *         setup_boot_cpu_capabilities().
>> + *      b) Everything except (a) - Run via setup_system_capabilities().
>>    *
>>    * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>>    *    the kernel should make sure that it is safe to use the CPU, by verifying
>> @@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    *
>>    *    As explained in (2) above, capabilities could be finalised at different
>>    *    points in the execution. Each CPU is verified against the "finalised"
>> - *    capabilities and if there is a conflict, the kernel takes an action, based
>> - *    on the severity (e.g, a CPU could be prevented from booting or cause a
>> - *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>> - *    if it has not been finalised already. See section 5 for more details on
>> - *    conflicts.
>> + *    capabilities.
>> + *
>> + *	x------------------------------------------------------------------- x
>> + *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
>> + *	|--------------------------------------------------------------------|
>> + *	| Primary boot CPU    |          |                    |              |
>> + *	|  capability         |   n      |      y             |       y      |
>> + *	|--------------------------------------------------------------------|
>> + *	| All others          |   n      |      n             |       y      |
>> + *	x--------------------------------------------------------------------x
> 
> Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
> means "conflict".
> 
> Could we have blank cell versus "X" (with a note saying what that
> means), or "ok" versus "CONFLICT"?

This is not strictly about conflicts, but about what each CPU get verified against.
Since there are multiple stages of "finalisation" for the capabilities, the table
shows how the CPUs get verified.

Would it help if I changed the description above the table to :

  *    As explained in (2) above, capabilities could be finalised at different
  *    points in the execution. Each CPU is verified against the "finalised"
  *    capabilities. The following table shows, the capabilities verified
  *    against each CPU in the system.
  *
  *      x------------------------------------------------------------------- x
  *      | Verified against:   | Boot CPU | SMP CPUs by kernel | CPUs by user |

.....


> 
>> + *
>> + *
>> + *    If there is a conflict, the kernel takes an action, based on the severity
>> + *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
>> + *    The CPU is allowed to "affect" the state of the capability, if it has not
>> + *    been finalised already. See section 5 for more details on conflicts.
>>    *
>>    * 4) Action: As mentioned in (2), the kernel can take an action for each detected
>>    *    capability, on all CPUs on the system. This is always initiated only after
>> @@ -186,20 +206,28 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>    */
>>   
>>   
>> -/* Decide how the capability is detected. On a local CPU vs System wide */
>> -#define ARM64_CPUCAP_SCOPE_MASK			0x3
>> +/*
>> + * Decide how the capability is detected.
>> + * On any local CPU vs System wide vs the primary boot CPU
>> + */
>> +#define ARM64_CPUCAP_SCOPE_MASK			0x7
> 
> Minor nit: magic number.  Could we do
> 
> #define ARM64_CPUCAP_SCOPE_MASK		\
> 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU |	\
> 	 ARM64_CPUCAP_SCOPE_SYSTEM |	\
> 	 ARM64_CPUCAP_SCOPE_BOOT_CPU)
> 
> below?

Sure, I will move it.

>>   static void verify_local_cpu_capabilities(void)
>>   {
>> -	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
>> +	if (!verify_local_cpu_caps(~ARM64_CPUCAP_SCOPE_BOOT_CPU))
> 
> [1] This is neat, but would it be clearer to say _ALL & ~_BOOT_CPU?
> 
> Otherwise, this is passing (u16)0xfffb, which feels invalid,
> particularly since it includes _{PERMITTED,OPTIONAL}_FOR_LATE_CPU which
> don't make sense here, even if we know they get masked off.
> 
> There could be future pitfalls here if ~_BOOT_CPU by itself is pasted
> in other places where the *_FOR_LATE_CPU bits are significant.

Sure, I chose it for keeping the lines shorter ;-). I will switch it.

> 
>>   		cpu_die_early();
>>   	verify_local_elf_hwcaps(arm64_elf_hwcaps);
>>   
>> @@ -1415,6 +1430,15 @@ void check_local_cpu_capabilities(void)
>>   		verify_local_cpu_capabilities();
>>   }
>>   
>> +static void __init setup_boot_cpu_capabilities(void)
>> +{
>> +	/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
>> +	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU |
>> +				 ARM64_CPUCAP_SCOPE_LOCAL_CPU);
>> +	/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
>> +	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_BOOT_CPU);
>> +}
>> +
>>   static void __init setup_system_capabilities(void)
>>   {
>>   	/*
>> @@ -1422,8 +1446,8 @@ static void __init setup_system_capabilities(void)
>>   	 * finalise the capabilities that depend on it.
>>   	 */
>>   	update_system_capabilities();
>> -	/* Enable all the available capabilities */
>> -	enable_cpu_capabilities(ARM64_CPUCAP_SCOPE_ALL);
>> +	/* Enable all the available capabilities, which are not already enabled. */
>> +	enable_cpu_capabilities(~ARM64_CPUCAP_SCOPE_BOOT_CPU);
> 
> As [1] above.
> 

Cheers
Suzuki

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

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-02-07 10:39     ` Dave Martin
@ 2018-02-08 10:53       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 10:53 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 07/02/18 10:39, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
>> Some capabilities have different criteria for detection and associated
>> actions based on the matching criteria, even though they all share the
>> same capability bit. So far we have used multiple entries with the same
>> capability bit to handle this. This is prone to errors, as the
>> cpu_enable is invoked for each entry, irrespective of whether the
>> detection rule applies to the CPU or not. And also this complicates
>> other helpers, e.g, __this_cpu_has_cap.
>>
>> This patch adds a wrapper entry to cover all the possible variations
>> of a capability and ensures :
>>   1) The capabilitiy is set when at least one of the entry detects
>>   2) Action is only taken for the entries that detects.
> 
> I guess this means that where we have a single cpu_enable() method
> but complex match criteria that require multiple entries, then that
> cpu_enable() method might get called multiple times on a given CPU.

A CPU executes cpu_enable() only for the "matching" entries in the list,
unlike earlier. So as long as there is a single entry "matching" the given
CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
that a CPU cannot be matched by multiple entries.

> 
> Could be worth a comment if cpu_enable() methods must be robust
> against this.
> 
>> This avoids explicit checks in the call backs. The only constraint
>> here is that, all the entries should have the same "type".
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>   arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
>>   arch/arm64/kernel/cpufeature.c      |  7 +++--
>>   3 files changed, 50 insertions(+), 11 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 462c35d1a38c..b73247c27f00 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
>>   			bool sign;
>>   			unsigned long hwcap;
>>   		};
>> +		const struct arm64_cpu_capabilities *cap_list;
> 
> Should desc, capability, def_scope and/or cpu_enable match for every cap
> in such a group?

As mentioned above, the "type" field should match, which implies scope
must match. The code ignores the scope, capability and desc of the individual
entries in the list. They should be shared by the parent entry.

cpu_enable could be duplicated as long as a CPU is not matched by multiple
entries.

> 
> I'd expected something maybe like this:
> 
> struct arm64_cpu_capabilities {
> 	const char *desc;
> 	u16 capability;
> 	struct arm64_capability_match {
> 		bool (*matches)(const struct arm64_cpu_capabilities *, int);
> 		int (*cpu_enable)(void);
> 		union {
> 			struct { ... midr ... };
> 			struct { ... sysreg ... };
> 			const struct arm64_capability_match *list;
> 		};
>>   	};
>>   };

Yes, thats makes it more explicit. However, it makes the "matches()"
complicated, as we have to change the prototype for matches to accept
struct arm64_capability_match *, to point to the right "matches" for
items in the list. And that makes a bit more of an invasive change, where
each matches() would then loose a way to get to the "capabilities" entry,
as they could be called with either the "match" in the top level or
the one in the list.

>>   		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 65a8e5cc600c..13e30c1b1e99 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>>   		return false;
>>   
>>   	for (caps = cap_array; caps->matches; caps++)
>> -		if (caps->capability == cap &&
>> -		    caps->matches(caps, SCOPE_LOCAL_CPU))
>> -			return true;
>> +		if (caps->capability == cap)
>> +			return caps->matches(caps, SCOPE_LOCAL_CPU);
> 
> If we went for my capability { cap; match criteria or list; } approach,
> would it still be necessary to iterate over the whole list here?

Sorry, I couldn't follow this. With this patch, we already stop scanning
the list as soon as we find the first entry. It is upto "the entry" to run
individual match criteria to decide.

> 
> This seems preferable if this function is used by other paths that
> don't expect it to be so costly.  Currently I only see a call in
> arch/arm64/kvm/handle_exit.c:handle_exit_early() for the SError case --
> which is probably not expected to be a fast path.
uu>
> [...]
> 
> Cheers
> ---Dave
> 

Cheers
Suzuki

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-08 10:53       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:39, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
>> Some capabilities have different criteria for detection and associated
>> actions based on the matching criteria, even though they all share the
>> same capability bit. So far we have used multiple entries with the same
>> capability bit to handle this. This is prone to errors, as the
>> cpu_enable is invoked for each entry, irrespective of whether the
>> detection rule applies to the CPU or not. And also this complicates
>> other helpers, e.g, __this_cpu_has_cap.
>>
>> This patch adds a wrapper entry to cover all the possible variations
>> of a capability and ensures :
>>   1) The capabilitiy is set when at least one of the entry detects
>>   2) Action is only taken for the entries that detects.
> 
> I guess this means that where we have a single cpu_enable() method
> but complex match criteria that require multiple entries, then that
> cpu_enable() method might get called multiple times on a given CPU.

A CPU executes cpu_enable() only for the "matching" entries in the list,
unlike earlier. So as long as there is a single entry "matching" the given
CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
that a CPU cannot be matched by multiple entries.

> 
> Could be worth a comment if cpu_enable() methods must be robust
> against this.
> 
>> This avoids explicit checks in the call backs. The only constraint
>> here is that, all the entries should have the same "type".
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>   arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
>>   arch/arm64/kernel/cpufeature.c      |  7 +++--
>>   3 files changed, 50 insertions(+), 11 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 462c35d1a38c..b73247c27f00 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
>>   			bool sign;
>>   			unsigned long hwcap;
>>   		};
>> +		const struct arm64_cpu_capabilities *cap_list;
> 
> Should desc, capability, def_scope and/or cpu_enable match for every cap
> in such a group?

As mentioned above, the "type" field should match, which implies scope
must match. The code ignores the scope, capability and desc of the individual
entries in the list. They should be shared by the parent entry.

cpu_enable could be duplicated as long as a CPU is not matched by multiple
entries.

> 
> I'd expected something maybe like this:
> 
> struct arm64_cpu_capabilities {
> 	const char *desc;
> 	u16 capability;
> 	struct arm64_capability_match {
> 		bool (*matches)(const struct arm64_cpu_capabilities *, int);
> 		int (*cpu_enable)(void);
> 		union {
> 			struct { ... midr ... };
> 			struct { ... sysreg ... };
> 			const struct arm64_capability_match *list;
> 		};
>>   	};
>>   };

Yes, thats makes it more explicit. However, it makes the "matches()"
complicated, as we have to change the prototype for matches to accept
struct arm64_capability_match *, to point to the right "matches" for
items in the list. And that makes a bit more of an invasive change, where
each matches() would then loose a way to get to the "capabilities" entry,
as they could be called with either the "match" in the top level or
the one in the list.

>>   		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 65a8e5cc600c..13e30c1b1e99 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>>   		return false;
>>   
>>   	for (caps = cap_array; caps->matches; caps++)
>> -		if (caps->capability == cap &&
>> -		    caps->matches(caps, SCOPE_LOCAL_CPU))
>> -			return true;
>> +		if (caps->capability == cap)
>> +			return caps->matches(caps, SCOPE_LOCAL_CPU);
> 
> If we went for my capability { cap; match criteria or list; } approach,
> would it still be necessary to iterate over the whole list here?

Sorry, I couldn't follow this. With this patch, we already stop scanning
the list as soon as we find the first entry. It is upto "the entry" to run
individual match criteria to decide.

> 
> This seems preferable if this function is used by other paths that
> don't expect it to be so costly.  Currently I only see a call in
> arch/arm64/kvm/handle_exit.c:handle_exit_early() for the SError case --
> which is probably not expected to be a fast path.
uu>
> [...]
> 
> Cheers
> ---Dave
> 

Cheers
Suzuki

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

* Re: [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
  2018-02-07 18:15       ` Suzuki K Poulose
@ 2018-02-08 11:05         ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 11:05 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, Feb 07, 2018 at 06:15:58PM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:38, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:27:57PM +0000, Suzuki K Poulose wrote:
> >>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,
> >
> >Should that be "when any CPU"?
> >
> 
> Without this patch, we need all the CPUs to mandate the defense (as this
> is a system feature). This patch changes it. I will change it to :
> 
> "KPTI is treated as a system wide feature and is only "detected" if all
> the CPUs on the system needs the defense. This is not sufficient, as the
> KPTI is turned off on a system with a mix of CPUs, where some CPUs can
> defend and others can't,
> 
> >>unless it is forced via kernel 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
> 
> " This patch ensures that KPTI is turned on if at least one CPU requires the
> defense and any late CPUs are rejected..."
> .

Yes, that makes sense.

[...]

> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index ecc87aa74c64..4a55492784b7 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c

[...]

> >>@@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> >>  	{
> >>  		.desc = "Kernel page table isolation (KPTI)",
> >>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> >>-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> >>+		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
> >>+		.sys_reg = SYS_ID_AA64PFR0_EL1,
> >>+		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
> >>+		.min_field_value = 1,
> >>  		.matches = unmap_kernel_at_el0,
> >
> >Minor nit, but:
> >
> >Can we have a comment here to explain that .min_field_value is the
> >minimum value that indicates that KPTI is _not_ required by this cpu?
> >This is the opposite of the usual semantics for this field.
> 
> Sure, will add it.
> 
> >
> >Otherwise, this inversion of meaning is not obvious without digging into
> >unmap_kernel_at_el0() and spotting the ! in !has_cpuid_feature().
> >
> >With that, or if this usage of !has_cpuid_feature() is already well-
> >established so that a comment is deemed unnecessary:
> 
> This is the first time we have used it.

Thought so, but I wasn't ruling out the possibility that I had missed
it!

Cheers
---Dave

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

* [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs
@ 2018-02-08 11:05         ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 07, 2018 at 06:15:58PM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:38, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:27:57PM +0000, Suzuki K Poulose wrote:
> >>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,
> >
> >Should that be "when any CPU"?
> >
> 
> Without this patch, we need all the CPUs to mandate the defense (as this
> is a system feature). This patch changes it. I will change it to :
> 
> "KPTI is treated as a system wide feature and is only "detected" if all
> the CPUs on the system needs the defense. This is not sufficient, as the
> KPTI is turned off on a system with a mix of CPUs, where some CPUs can
> defend and others can't,
> 
> >>unless it is forced via kernel 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
> 
> " This patch ensures that KPTI is turned on if at least one CPU requires the
> defense and any late CPUs are rejected..."
> .

Yes, that makes sense.

[...]

> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index ecc87aa74c64..4a55492784b7 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c

[...]

> >>@@ -1008,7 +1006,10 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> >>  	{
> >>  		.desc = "Kernel page table isolation (KPTI)",
> >>  		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
> >>-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> >>+		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
> >>+		.sys_reg = SYS_ID_AA64PFR0_EL1,
> >>+		.field_pos = ID_AA64PFR0_CSV3_SHIFT,
> >>+		.min_field_value = 1,
> >>  		.matches = unmap_kernel_at_el0,
> >
> >Minor nit, but:
> >
> >Can we have a comment here to explain that .min_field_value is the
> >minimum value that indicates that KPTI is _not_ required by this cpu?
> >This is the opposite of the usual semantics for this field.
> 
> Sure, will add it.
> 
> >
> >Otherwise, this inversion of meaning is not obvious without digging into
> >unmap_kernel_at_el0() and spotting the ! in !has_cpuid_feature().
> >
> >With that, or if this usage of !has_cpuid_feature() is already well-
> >established so that a comment is deemed unnecessary:
> 
> This is the first time we have used it.

Thought so, but I wasn't ruling out the possibility that I had missed
it!

Cheers
---Dave

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

* Re: [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
  2018-02-07 18:34       ` Suzuki K Poulose
@ 2018-02-08 11:35         ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 11:35 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, Julien Thierry, will.deacon, linux-kernel,
	jnair, linux-arm-kernel

On Wed, Feb 07, 2018 at 06:34:37PM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:38, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:
> >>The kernel detects and uses some of the features based on the boot
> >>CPU and expects that all the following CPUs conform to it. e.g,
> >>with VHE and the boot CPU running at EL2, the kernel decides to
> >>keep the kernel running at EL2. If another CPU is brought up without
> >>this capability, we use custom hooks (via check_early_cpu_features())
> >>to handle it. To handle such capabilities add support for detecting
> >>and enabling capabilities based on the boot CPU.
> >>
> >>A bit is added to indicate if the capability should be detected
> >>early on the boot CPU. The infrastructure then ensures that such
> >>capabilities are probed and "enabled" early on in the boot CPU
> >>and, enabled on the subsequent CPUs.
> >>
> >>Cc: Julien Thierry <julien.thierry@arm.com>
> >>Cc: Dave Martin <dave.martin@arm.com>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>Cc: Marc Zyngier <marc.zyngier@arm.com>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
> >>  arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
> >>  2 files changed, 74 insertions(+), 22 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h

[...]

> >>   * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
> >>   *    the kernel should make sure that it is safe to use the CPU, by verifying
> >>@@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>   *
> >>   *    As explained in (2) above, capabilities could be finalised at different
> >>   *    points in the execution. Each CPU is verified against the "finalised"
> >>- *    capabilities and if there is a conflict, the kernel takes an action, based
> >>- *    on the severity (e.g, a CPU could be prevented from booting or cause a
> >>- *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> >>- *    if it has not been finalised already. See section 5 for more details on
> >>- *    conflicts.
> >>+ *    capabilities.
> >>+ *
> >>+ *	x------------------------------------------------------------------- x
> >>+ *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
> >>+ *	|--------------------------------------------------------------------|
> >>+ *	| Primary boot CPU    |          |                    |              |
> >>+ *	|  capability         |   n      |      y             |       y      |
> >>+ *	|--------------------------------------------------------------------|
> >>+ *	| All others          |   n      |      n             |       y      |
> >>+ *	x--------------------------------------------------------------------x
> >
> >Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
> >means "conflict".
> >
> >Could we have blank cell versus "X" (with a note saying what that
> >means), or "ok" versus "CONFLICT"?
> 
> This is not strictly about conflicts, but about what each CPU get
> verified against.  Since there are multiple stages of "finalisation"

You're right: I meant something like "potential conflict", but I hadn't
read the previous paragraph carefully enough and didn't explain what I
meant very well.

> for the capabilities, the table shows how the CPUs get verified.
> 
> Would it help if I changed the description above the table to :
> 
>  *    As explained in (2) above, capabilities could be finalised at different
>  *    points in the execution. Each CPU is verified against the "finalised"
>  *    capabilities. The following table shows, the capabilities verified
>  *    against each CPU in the system.
>  *
>  *      x------------------------------------------------------------------- x
>  *      | Verified against:   | Boot CPU | SMP CPUs by kernel | CPUs by user |

I still find it a bit cryptic.

Would it be simpler just to write this out in prose, with reference to
the actual capability types?  I feel that things have to be abbreviated
a bit to fit nicely into the table otherwise.

What about:

 * As explained in (2) above, capabilities could be finalised at different
 * points in the execution, depending on the capability type. Each newly booted
 * CPU is verified against those capabilities that have been finalised by the
 * time that CPU boots:
 *
 *	* SCOPE_BOOT_CPU: all CPUs are verified against the capability except
 *	  for the primary boot CPU.
 *
 *	* SCOPE_LOCAL_CPU, SCOPE_SYSTEM: all CPUs hotplugged on by the user
 *	  after kernel boot are verified against the capability.

> >>+ *    If there is a conflict, the kernel takes an action, based on the severity
> >>+ *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
> >>+ *    The CPU is allowed to "affect" the state of the capability, if it has not
> >>+ *    been finalised already. See section 5 for more details on conflicts.
> >>   *
> >>   * 4) Action: As mentioned in (2), the kernel can take an action for each detected
> >>   *    capability, on all CPUs on the system. This is always initiated only after

[...]

Cheers
---Dave

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

* [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
@ 2018-02-08 11:35         ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 11:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 07, 2018 at 06:34:37PM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:38, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:
> >>The kernel detects and uses some of the features based on the boot
> >>CPU and expects that all the following CPUs conform to it. e.g,
> >>with VHE and the boot CPU running at EL2, the kernel decides to
> >>keep the kernel running at EL2. If another CPU is brought up without
> >>this capability, we use custom hooks (via check_early_cpu_features())
> >>to handle it. To handle such capabilities add support for detecting
> >>and enabling capabilities based on the boot CPU.
> >>
> >>A bit is added to indicate if the capability should be detected
> >>early on the boot CPU. The infrastructure then ensures that such
> >>capabilities are probed and "enabled" early on in the boot CPU
> >>and, enabled on the subsequent CPUs.
> >>
> >>Cc: Julien Thierry <julien.thierry@arm.com>
> >>Cc: Dave Martin <dave.martin@arm.com>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>Cc: Marc Zyngier <marc.zyngier@arm.com>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h | 48 +++++++++++++++++++++++++++++--------
> >>  arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++++++++----------
> >>  2 files changed, 74 insertions(+), 22 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h

[...]

> >>   * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
> >>   *    the kernel should make sure that it is safe to use the CPU, by verifying
> >>@@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
> >>   *
> >>   *    As explained in (2) above, capabilities could be finalised at different
> >>   *    points in the execution. Each CPU is verified against the "finalised"
> >>- *    capabilities and if there is a conflict, the kernel takes an action, based
> >>- *    on the severity (e.g, a CPU could be prevented from booting or cause a
> >>- *    kernel panic). The CPU is allowed to "affect" the state of the capability,
> >>- *    if it has not been finalised already. See section 5 for more details on
> >>- *    conflicts.
> >>+ *    capabilities.
> >>+ *
> >>+ *	x------------------------------------------------------------------- x
> >>+ *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
> >>+ *	|--------------------------------------------------------------------|
> >>+ *	| Primary boot CPU    |          |                    |              |
> >>+ *	|  capability         |   n      |      y             |       y      |
> >>+ *	|--------------------------------------------------------------------|
> >>+ *	| All others          |   n      |      n             |       y      |
> >>+ *	x--------------------------------------------------------------------x
> >
> >Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
> >means "conflict".
> >
> >Could we have blank cell versus "X" (with a note saying what that
> >means), or "ok" versus "CONFLICT"?
> 
> This is not strictly about conflicts, but about what each CPU get
> verified against.  Since there are multiple stages of "finalisation"

You're right: I meant something like "potential conflict", but I hadn't
read the previous paragraph carefully enough and didn't explain what I
meant very well.

> for the capabilities, the table shows how the CPUs get verified.
> 
> Would it help if I changed the description above the table to :
> 
>  *    As explained in (2) above, capabilities could be finalised at different
>  *    points in the execution. Each CPU is verified against the "finalised"
>  *    capabilities. The following table shows, the capabilities verified
>  *    against each CPU in the system.
>  *
>  *      x------------------------------------------------------------------- x
>  *      | Verified against:   | Boot CPU | SMP CPUs by kernel | CPUs by user |

I still find it a bit cryptic.

Would it be simpler just to write this out in prose, with reference to
the actual capability types?  I feel that things have to be abbreviated
a bit to fit nicely into the table otherwise.

What about:

 * As explained in (2) above, capabilities could be finalised at different
 * points in the execution, depending on the capability type. Each newly booted
 * CPU is verified against those capabilities that have been finalised by the
 * time that CPU boots:
 *
 *	* SCOPE_BOOT_CPU: all CPUs are verified against the capability except
 *	  for the primary boot CPU.
 *
 *	* SCOPE_LOCAL_CPU, SCOPE_SYSTEM: all CPUs hotplugged on by the user
 *	  after kernel boot are verified against the capability.

> >>+ *    If there is a conflict, the kernel takes an action, based on the severity
> >>+ *    (e.g, a CPU could be prevented from booting or cause a kernel panic).
> >>+ *    The CPU is allowed to "affect" the state of the capability, if it has not
> >>+ *    been finalised already. See section 5 for more details on conflicts.
> >>   *
> >>   * 4) Action: As mentioned in (2), the kernel can take an action for each detected
> >>   *    capability, on all CPUs on the system. This is always initiated only after

[...]

Cheers
---Dave

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

* Re: [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
  2018-02-08 11:35         ` Dave Martin
@ 2018-02-08 11:43           ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 11:43 UTC (permalink / raw)
  To: Dave Martin
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, Julien Thierry, will.deacon, linux-kernel,
	jnair, linux-arm-kernel

On 08/02/18 11:35, Dave Martin wrote:
> On Wed, Feb 07, 2018 at 06:34:37PM +0000, Suzuki K Poulose wrote:
>> On 07/02/18 10:38, Dave Martin wrote:
>>> On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:

>>>>    * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>>>>    *    the kernel should make sure that it is safe to use the CPU, by verifying
>>>> @@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>>>    *
>>>>    *    As explained in (2) above, capabilities could be finalised at different
>>>>    *    points in the execution. Each CPU is verified against the "finalised"
>>>> - *    capabilities and if there is a conflict, the kernel takes an action, based
>>>> - *    on the severity (e.g, a CPU could be prevented from booting or cause a
>>>> - *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>>>> - *    if it has not been finalised already. See section 5 for more details on
>>>> - *    conflicts.
>>>> + *    capabilities.
>>>> + *
>>>> + *	x------------------------------------------------------------------- x
>>>> + *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
>>>> + *	|--------------------------------------------------------------------|
>>>> + *	| Primary boot CPU    |          |                    |              |
>>>> + *	|  capability         |   n      |      y             |       y      |
>>>> + *	|--------------------------------------------------------------------|
>>>> + *	| All others          |   n      |      n             |       y      |
>>>> + *	x--------------------------------------------------------------------x
>>>
>>> Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
>>> means "conflict".
>>>
>>> Could we have blank cell versus "X" (with a note saying what that
>>> means), or "ok" versus "CONFLICT"?
>>
>> This is not strictly about conflicts, but about what each CPU get
>> verified against.  Since there are multiple stages of "finalisation"
> 
> You're right: I meant something like "potential conflict", but I hadn't
> read the previous paragraph carefully enough and didn't explain what I
> meant very well.
> 
>> for the capabilities, the table shows how the CPUs get verified.
>>
>> Would it help if I changed the description above the table to :
>>
>>   *    As explained in (2) above, capabilities could be finalised at different
>>   *    points in the execution. Each CPU is verified against the "finalised"
>>   *    capabilities. The following table shows, the capabilities verified
>>   *    against each CPU in the system.
>>   *
>>   *      x------------------------------------------------------------------- x
>>   *      | Verified against:   | Boot CPU | SMP CPUs by kernel | CPUs by user |
> 
> I still find it a bit cryptic.
> 
> Would it be simpler just to write this out in prose, with reference to
> the actual capability types?  I feel that things have to be abbreviated
> a bit to fit nicely into the table otherwise.
> 
> What about:
> 
>   * As explained in (2) above, capabilities could be finalised at different
>   * points in the execution, depending on the capability type. Each newly booted
>   * CPU is verified against those capabilities that have been finalised by the
>   * time that CPU boots:
>   *
>   *	* SCOPE_BOOT_CPU: all CPUs are verified against the capability except
>   *	  for the primary boot CPU.
>   *
>   *	* SCOPE_LOCAL_CPU, SCOPE_SYSTEM: all CPUs hotplugged on by the user
>   *	  after kernel boot are verified against the capability.

Sure, looks better.

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

* [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early
@ 2018-02-08 11:43           ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 11:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 11:35, Dave Martin wrote:
> On Wed, Feb 07, 2018 at 06:34:37PM +0000, Suzuki K Poulose wrote:
>> On 07/02/18 10:38, Dave Martin wrote:
>>> On Wed, Jan 31, 2018 at 06:27:58PM +0000, Suzuki K Poulose wrote:

>>>>    * 3) Verification: When a CPU is brought online (e.g, by user or by the kernel),
>>>>    *    the kernel should make sure that it is safe to use the CPU, by verifying
>>>> @@ -139,11 +148,22 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
>>>>    *
>>>>    *    As explained in (2) above, capabilities could be finalised at different
>>>>    *    points in the execution. Each CPU is verified against the "finalised"
>>>> - *    capabilities and if there is a conflict, the kernel takes an action, based
>>>> - *    on the severity (e.g, a CPU could be prevented from booting or cause a
>>>> - *    kernel panic). The CPU is allowed to "affect" the state of the capability,
>>>> - *    if it has not been finalised already. See section 5 for more details on
>>>> - *    conflicts.
>>>> + *    capabilities.
>>>> + *
>>>> + *	x------------------------------------------------------------------- x
>>>> + *	| Verification:       | Boot CPU | SMP CPUs by kernel | CPUs by user |
>>>> + *	|--------------------------------------------------------------------|
>>>> + *	| Primary boot CPU    |          |                    |              |
>>>> + *	|  capability         |   n      |      y             |       y      |
>>>> + *	|--------------------------------------------------------------------|
>>>> + *	| All others          |   n      |      n             |       y      |
>>>> + *	x--------------------------------------------------------------------x
>>>
>>> Minor clarify nit: it's not obvious that "n" means "no conflict" and "y"
>>> means "conflict".
>>>
>>> Could we have blank cell versus "X" (with a note saying what that
>>> means), or "ok" versus "CONFLICT"?
>>
>> This is not strictly about conflicts, but about what each CPU get
>> verified against.  Since there are multiple stages of "finalisation"
> 
> You're right: I meant something like "potential conflict", but I hadn't
> read the previous paragraph carefully enough and didn't explain what I
> meant very well.
> 
>> for the capabilities, the table shows how the CPUs get verified.
>>
>> Would it help if I changed the description above the table to :
>>
>>   *    As explained in (2) above, capabilities could be finalised at different
>>   *    points in the execution. Each CPU is verified against the "finalised"
>>   *    capabilities. The following table shows, the capabilities verified
>>   *    against each CPU in the system.
>>   *
>>   *      x------------------------------------------------------------------- x
>>   *      | Verified against:   | Boot CPU | SMP CPUs by kernel | CPUs by user |
> 
> I still find it a bit cryptic.
> 
> Would it be simpler just to write this out in prose, with reference to
> the actual capability types?  I feel that things have to be abbreviated
> a bit to fit nicely into the table otherwise.
> 
> What about:
> 
>   * As explained in (2) above, capabilities could be finalised at different
>   * points in the execution, depending on the capability type. Each newly booted
>   * CPU is verified against those capabilities that have been finalised by the
>   * time that CPU boots:
>   *
>   *	* SCOPE_BOOT_CPU: all CPUs are verified against the capability except
>   *	  for the primary boot CPU.
>   *
>   *	* SCOPE_LOCAL_CPU, SCOPE_SYSTEM: all CPUs hotplugged on by the user
>   *	  after kernel boot are verified against the capability.

Sure, looks better.

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

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-02-08 10:53       ` Suzuki K Poulose
@ 2018-02-08 12:01         ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 12:01 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, Feb 08, 2018 at 10:53:52AM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:39, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> >>Some capabilities have different criteria for detection and associated
> >>actions based on the matching criteria, even though they all share the
> >>same capability bit. So far we have used multiple entries with the same
> >>capability bit to handle this. This is prone to errors, as the
> >>cpu_enable is invoked for each entry, irrespective of whether the
> >>detection rule applies to the CPU or not. And also this complicates
> >>other helpers, e.g, __this_cpu_has_cap.
> >>
> >>This patch adds a wrapper entry to cover all the possible variations
> >>of a capability and ensures :
> >>  1) The capabilitiy is set when at least one of the entry detects
> >>  2) Action is only taken for the entries that detects.
> >
> >I guess this means that where we have a single cpu_enable() method
> >but complex match criteria that require multiple entries, then that
> >cpu_enable() method might get called multiple times on a given CPU.
> 
> A CPU executes cpu_enable() only for the "matching" entries in the list,
> unlike earlier. So as long as there is a single entry "matching" the given
> CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
> that a CPU cannot be matched by multiple entries.
> 
> >
> >Could be worth a comment if cpu_enable() methods must be robust
> >against this.

Could we say something like:

"Where a single capability has multiple entries, mutiple cpu_enable()
methods may be called if more than one entry matches.  Where this is
not desired, care should be taken to ensure that the entries are
mutually exclusive: for example, two entries for a single capability
that match on MIDR should be configured to match MIDR ranges that do
not overlap."

This is more verbose than I would like however.  Maybe there's a simpler
way to say it.

> >>This avoids explicit checks in the call backs. The only constraint
> >>here is that, all the entries should have the same "type".
> >>
> >>Cc: Dave Martin <dave.martin@arm.com>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  1 +
> >>  arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
> >>  arch/arm64/kernel/cpufeature.c      |  7 +++--
> >>  3 files changed, 50 insertions(+), 11 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 462c35d1a38c..b73247c27f00 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
> >>  			bool sign;
> >>  			unsigned long hwcap;
> >>  		};
> >>+		const struct arm64_cpu_capabilities *cap_list;
> >
> >Should desc, capability, def_scope and/or cpu_enable match for every cap
> >in such a group?
> 
> As mentioned above, the "type" field should match, which implies scope
> must match. The code ignores the scope, capability and desc of the individual
> entries in the list. They should be shared by the parent entry.
> 
> cpu_enable could be duplicated as long as a CPU is not matched by multiple
> entries.
> 
> >
> >I'd expected something maybe like this:
> >
> >struct arm64_cpu_capabilities {
> >	const char *desc;
> >	u16 capability;
> >	struct arm64_capability_match {
> >		bool (*matches)(const struct arm64_cpu_capabilities *, int);
> >		int (*cpu_enable)(void);
> >		union {
> >			struct { ... midr ... };
> >			struct { ... sysreg ... };
> >			const struct arm64_capability_match *list;
> >		};
> >>  	};
> >>  };
> 
> Yes, thats makes it more explicit. However, it makes the "matches()"
> complicated, as we have to change the prototype for matches to accept
> struct arm64_capability_match *, to point to the right "matches" for
> items in the list. And that makes a bit more of an invasive change, where
> each matches() would then loose a way to get to the "capabilities" entry,
> as they could be called with either the "match" in the top level or
> the one in the list.

Yes, that's true.  matches() could take a pointer to the cap struct
_and_ the relevant match entry, but I'm not sure it's worth it.  In any
case, my previous objection below doesn't make as much sense as I
thought.

> >>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 65a8e5cc600c..13e30c1b1e99 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
> >>  		return false;
> >>  	for (caps = cap_array; caps->matches; caps++)
> >>-		if (caps->capability == cap &&
> >>-		    caps->matches(caps, SCOPE_LOCAL_CPU))
> >>-			return true;
> >>+		if (caps->capability == cap)
> >>+			return caps->matches(caps, SCOPE_LOCAL_CPU);
> >
> >If we went for my capability { cap; match criteria or list; } approach,
> >would it still be necessary to iterate over the whole list here?
> 
> Sorry, I couldn't follow this. With this patch, we already stop scanning
> the list as soon as we find the first entry. It is upto "the entry" to run
> individual match criteria to decide.

Ah, I'm talking nonsense here.  Patch 6 iterates over the entire
capability list via the call to __this_cpu_has_cap() in
__verify_local_cpu_caps(), but this patch now changes the behaviour so
that this doesn't happen any more.

The only other users of this_cpu_has_cap() don't have the right cap
pointer already, so a scan over the whole list is required in those
cases -- and anyway, those look like fast paths (RAS exceptions).

[...]

Cheers
---Dave

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-08 12:01         ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 12:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 08, 2018 at 10:53:52AM +0000, Suzuki K Poulose wrote:
> On 07/02/18 10:39, Dave Martin wrote:
> >On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> >>Some capabilities have different criteria for detection and associated
> >>actions based on the matching criteria, even though they all share the
> >>same capability bit. So far we have used multiple entries with the same
> >>capability bit to handle this. This is prone to errors, as the
> >>cpu_enable is invoked for each entry, irrespective of whether the
> >>detection rule applies to the CPU or not. And also this complicates
> >>other helpers, e.g, __this_cpu_has_cap.
> >>
> >>This patch adds a wrapper entry to cover all the possible variations
> >>of a capability and ensures :
> >>  1) The capabilitiy is set when at least one of the entry detects
> >>  2) Action is only taken for the entries that detects.
> >
> >I guess this means that where we have a single cpu_enable() method
> >but complex match criteria that require multiple entries, then that
> >cpu_enable() method might get called multiple times on a given CPU.
> 
> A CPU executes cpu_enable() only for the "matching" entries in the list,
> unlike earlier. So as long as there is a single entry "matching" the given
> CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
> that a CPU cannot be matched by multiple entries.
> 
> >
> >Could be worth a comment if cpu_enable() methods must be robust
> >against this.

Could we say something like:

"Where a single capability has multiple entries, mutiple cpu_enable()
methods may be called if more than one entry matches.  Where this is
not desired, care should be taken to ensure that the entries are
mutually exclusive: for example, two entries for a single capability
that match on MIDR should be configured to match MIDR ranges that do
not overlap."

This is more verbose than I would like however.  Maybe there's a simpler
way to say it.

> >>This avoids explicit checks in the call backs. The only constraint
> >>here is that, all the entries should have the same "type".
> >>
> >>Cc: Dave Martin <dave.martin@arm.com>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>  arch/arm64/include/asm/cpufeature.h |  1 +
> >>  arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
> >>  arch/arm64/kernel/cpufeature.c      |  7 +++--
> >>  3 files changed, 50 insertions(+), 11 deletions(-)
> >>
> >>diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> >>index 462c35d1a38c..b73247c27f00 100644
> >>--- a/arch/arm64/include/asm/cpufeature.h
> >>+++ b/arch/arm64/include/asm/cpufeature.h
> >>@@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
> >>  			bool sign;
> >>  			unsigned long hwcap;
> >>  		};
> >>+		const struct arm64_cpu_capabilities *cap_list;
> >
> >Should desc, capability, def_scope and/or cpu_enable match for every cap
> >in such a group?
> 
> As mentioned above, the "type" field should match, which implies scope
> must match. The code ignores the scope, capability and desc of the individual
> entries in the list. They should be shared by the parent entry.
> 
> cpu_enable could be duplicated as long as a CPU is not matched by multiple
> entries.
> 
> >
> >I'd expected something maybe like this:
> >
> >struct arm64_cpu_capabilities {
> >	const char *desc;
> >	u16 capability;
> >	struct arm64_capability_match {
> >		bool (*matches)(const struct arm64_cpu_capabilities *, int);
> >		int (*cpu_enable)(void);
> >		union {
> >			struct { ... midr ... };
> >			struct { ... sysreg ... };
> >			const struct arm64_capability_match *list;
> >		};
> >>  	};
> >>  };
> 
> Yes, thats makes it more explicit. However, it makes the "matches()"
> complicated, as we have to change the prototype for matches to accept
> struct arm64_capability_match *, to point to the right "matches" for
> items in the list. And that makes a bit more of an invasive change, where
> each matches() would then loose a way to get to the "capabilities" entry,
> as they could be called with either the "match" in the top level or
> the one in the list.

Yes, that's true.  matches() could take a pointer to the cap struct
_and_ the relevant match entry, but I'm not sure it's worth it.  In any
case, my previous objection below doesn't make as much sense as I
thought.

> >>  		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
> >>diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >>index 65a8e5cc600c..13e30c1b1e99 100644
> >>--- a/arch/arm64/kernel/cpufeature.c
> >>+++ b/arch/arm64/kernel/cpufeature.c
> >>@@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
> >>  		return false;
> >>  	for (caps = cap_array; caps->matches; caps++)
> >>-		if (caps->capability == cap &&
> >>-		    caps->matches(caps, SCOPE_LOCAL_CPU))
> >>-			return true;
> >>+		if (caps->capability == cap)
> >>+			return caps->matches(caps, SCOPE_LOCAL_CPU);
> >
> >If we went for my capability { cap; match criteria or list; } approach,
> >would it still be necessary to iterate over the whole list here?
> 
> Sorry, I couldn't follow this. With this patch, we already stop scanning
> the list as soon as we find the first entry. It is upto "the entry" to run
> individual match criteria to decide.

Ah, I'm talking nonsense here.  Patch 6 iterates over the entire
capability list via the call to __this_cpu_has_cap() in
__verify_local_cpu_caps(), but this patch now changes the behaviour so
that this doesn't happen any more.

The only other users of this_cpu_has_cap() don't have the right cap
pointer already, so a scan over the whole list is required in those
cases -- and anyway, those look like fast paths (RAS exceptions).

[...]

Cheers
---Dave

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

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-01-31 18:28   ` Suzuki K Poulose
@ 2018-02-08 12:04     ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 12:04 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 Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> Some capabilities have different criteria for detection and associated
> actions based on the matching criteria, even though they all share the
> same capability bit. So far we have used multiple entries with the same
> capability bit to handle this. This is prone to errors, as the
> cpu_enable is invoked for each entry, irrespective of whether the
> detection rule applies to the CPU or not. And also this complicates
> other helpers, e.g, __this_cpu_has_cap.
> 
> This patch adds a wrapper entry to cover all the possible variations
> of a capability and ensures :
>  1) The capabilitiy is set when at least one of the entry detects
>  2) Action is only taken for the entries that detects.
> 
> This avoids explicit checks in the call backs. The only constraint
> here is that, all the entries should have the same "type".
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---

[...]

> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c

[...]

> @@ -1275,7 +1274,7 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>  		if (!(caps->type & scope_mask))
>  			continue;
>  
> -		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
> +		cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU);

One other minor thing: the original caps_list argument seems no longer
to be needed in this function after this change.

Can we rename the caps_list argument to "caps" and remove the local
variable of the same name?

Cheers
---Dave

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-08 12:04     ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 12:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> Some capabilities have different criteria for detection and associated
> actions based on the matching criteria, even though they all share the
> same capability bit. So far we have used multiple entries with the same
> capability bit to handle this. This is prone to errors, as the
> cpu_enable is invoked for each entry, irrespective of whether the
> detection rule applies to the CPU or not. And also this complicates
> other helpers, e.g, __this_cpu_has_cap.
> 
> This patch adds a wrapper entry to cover all the possible variations
> of a capability and ensures :
>  1) The capabilitiy is set when at least one of the entry detects
>  2) Action is only taken for the entries that detects.
> 
> This avoids explicit checks in the call backs. The only constraint
> here is that, all the entries should have the same "type".
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---

[...]

> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c

[...]

> @@ -1275,7 +1274,7 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>  		if (!(caps->type & scope_mask))
>  			continue;
>  
> -		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
> +		cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU);

One other minor thing: the original caps_list argument seems no longer
to be needed in this function after this change.

Can we rename the caps_list argument to "caps" and remove the local
variable of the same name?

Cheers
---Dave

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

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-02-08 12:04     ` Dave Martin
@ 2018-02-08 12:05       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 12: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 08/02/18 12:04, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
>> Some capabilities have different criteria for detection and associated
>> actions based on the matching criteria, even though they all share the
>> same capability bit. So far we have used multiple entries with the same
>> capability bit to handle this. This is prone to errors, as the
>> cpu_enable is invoked for each entry, irrespective of whether the
>> detection rule applies to the CPU or not. And also this complicates
>> other helpers, e.g, __this_cpu_has_cap.
>>
>> This patch adds a wrapper entry to cover all the possible variations
>> of a capability and ensures :
>>   1) The capabilitiy is set when at least one of the entry detects
>>   2) Action is only taken for the entries that detects.
>>
>> This avoids explicit checks in the call backs. The only constraint
>> here is that, all the entries should have the same "type".
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
> 
> [...]
> 
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> 
> [...]
> 
>> @@ -1275,7 +1274,7 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>>   		if (!(caps->type & scope_mask))
>>   			continue;
>>   
>> -		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
>> +		cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU);
> 
> One other minor thing: the original caps_list argument seems no longer
> to be needed in this function after this change.
> 
> Can we rename the caps_list argument to "caps" and remove the local
> variable of the same name?

Sure, will do.

Suzuki

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-08 12:05       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 12:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 12:04, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
>> Some capabilities have different criteria for detection and associated
>> actions based on the matching criteria, even though they all share the
>> same capability bit. So far we have used multiple entries with the same
>> capability bit to handle this. This is prone to errors, as the
>> cpu_enable is invoked for each entry, irrespective of whether the
>> detection rule applies to the CPU or not. And also this complicates
>> other helpers, e.g, __this_cpu_has_cap.
>>
>> This patch adds a wrapper entry to cover all the possible variations
>> of a capability and ensures :
>>   1) The capabilitiy is set when at least one of the entry detects
>>   2) Action is only taken for the entries that detects.
>>
>> This avoids explicit checks in the call backs. The only constraint
>> here is that, all the entries should have the same "type".
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
> 
> [...]
> 
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> 
> [...]
> 
>> @@ -1275,7 +1274,7 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>>   		if (!(caps->type & scope_mask))
>>   			continue;
>>   
>> -		cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
>> +		cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU);
> 
> One other minor thing: the original caps_list argument seems no longer
> to be needed in this function after this change.
> 
> Can we rename the caps_list argument to "caps" and remove the local
> variable of the same name?

Sure, will do.

Suzuki

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

* Re: [PATCH v2 08/20] arm64: capabilities: Group handling of features and errata
  2018-02-07 10:38     ` Dave Martin
@ 2018-02-08 12:10       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 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 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:55PM +0000, Suzuki K Poulose wrote:
>> So far we have had separate routes for triggering errata and feature
>> capability detection. 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 both
>> arm64_features and arm64_errata, in two phases for detection.
>>
>>   1) with SCOPE_LOCAL_CPU filter on each boot time enabled CPUs,
>>      via update_cpu_local_capabilities().
>>
>>   2) with SCOPE_SYSTEM filter only once after all boot time enabled
>>      CPUs are active, triggered from setup_cpu_features().
>>
>> A late CPU goes through both the tables for verification against
>> established capabilities, as before.
>>
>> We could ideally merge the two tables into one. But leave it as
>> it is for easy access to the list of particular type.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> I don't know if there's a way of splitting or refactoring this patch to
> make it easier to understand the changes, but I think I get what's going
> on here now.
> 
> So,
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> 

Thanks,

> (But if you can see a good way to split it, I'll be happy to take
> another look.)

I did try this out, patches follows.

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

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

On 07/02/18 10:38, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:27:55PM +0000, Suzuki K Poulose wrote:
>> So far we have had separate routes for triggering errata and feature
>> capability detection. 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 both
>> arm64_features and arm64_errata, in two phases for detection.
>>
>>   1) with SCOPE_LOCAL_CPU filter on each boot time enabled CPUs,
>>      via update_cpu_local_capabilities().
>>
>>   2) with SCOPE_SYSTEM filter only once after all boot time enabled
>>      CPUs are active, triggered from setup_cpu_features().
>>
>> A late CPU goes through both the tables for verification against
>> established capabilities, as before.
>>
>> We could ideally merge the two tables into one. But leave it as
>> it is for easy access to the list of particular type.
>>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> I don't know if there's a way of splitting or refactoring this patch to
> make it easier to understand the changes, but I think I get what's going
> on here now.
> 
> So,
> 
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> 

Thanks,

> (But if you can see a good way to split it, I'll be happy to take
> another look.)

I did try this out, patches follows.

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

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
  2018-02-08 12:10       ` Suzuki K Poulose
@ 2018-02-08 12:12         ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 12:12 UTC (permalink / raw)
  To: dave.martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair,
	Suzuki K Poulose

So far we have restricted the scopes for the capabilities
as follows :
 1) Errata workaround check are run all CPUs (i.e, always
    SCOPE_LOCAL_CPU)
 2) Arm64 features are run only once after the sanitised
    feature registers are available using the SCOPE_SYSTEM.

This prevents detecting cpu features that can be detected
on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
for errata workaround with SCOPE_SYSTEM.

This patch makes sure that we allow flexibility of having
any scope for a capability. So, we now run through both
arm64_features and arm64_errata in two phases for detection:

 a) with SCOPE_LOCAL_CPU filter on each boot time enabled
    CPUs.
 b) with SCOPE_SYSTEM filter only once after all boot time
    enabled CPUs are active.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 61d4c3cfb1cc..e1a56fa889a5 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -505,6 +505,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_features(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -554,6 +555,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 	 * initialised the cpu feature infrastructure.
 	 */
 	update_cpu_errata_workarounds();
+	update_cpu_local_features();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
 static void update_cpu_errata_workarounds(void)
 {
 	update_cpu_capabilities(arm64_errata,
-				ARM64_CPUCAP_SCOPE_ALL,
+				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
 				"enabling workaround for");
 }
 
-static void __init enable_errata_workarounds(void)
+static void update_cpu_local_features(void)
 {
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
+	update_cpu_capabilities(arm64_features,
+				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
+				"detected feature:");
 }
 
 /*
@@ -1430,23 +1434,34 @@ void check_local_cpu_capabilities(void)
 
 	/*
 	 * If we haven't finalised the system capabilities, this CPU gets
-	 * a chance to update the errata work arounds.
+	 * a chance to update the errata work arounds and local CPU features.
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised)
+	if (!sys_caps_initialised) {
 		update_cpu_errata_workarounds();
-	else
+		update_cpu_local_features();
+	} else {
 		verify_local_cpu_capabilities();
+	}
 }
 
 static void __init setup_feature_capabilities(void)
 {
 	update_cpu_capabilities(arm64_features,
-				ARM64_CPUCAP_SCOPE_ALL, "detected feature:");
+				ARM64_CPUCAP_SCOPE_SYSTEM,
+				"detected feature:");
 	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
 }
 
+static void __init setup_errata_workarounds(void)
+{
+	update_cpu_capabilities(arm64_errata,
+				ARM64_CPUCAP_SCOPE_SYSTEM,
+				"enabling workaround for");
+	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
+}
+
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
 EXPORT_SYMBOL(arm64_const_caps_ready);
 
@@ -1468,9 +1483,9 @@ void __init setup_cpu_features(void)
 	u32 cwg;
 	int cls;
 
-	/* Set the CPU feature capabilies */
+	/* Finalise the CPU capabilities */
 	setup_feature_capabilities();
-	enable_errata_workarounds();
+	setup_errata_workarounds();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
@ 2018-02-08 12:12         ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

So far we have restricted the scopes for the capabilities
as follows :
 1) Errata workaround check are run all CPUs (i.e, always
    SCOPE_LOCAL_CPU)
 2) Arm64 features are run only once after the sanitised
    feature registers are available using the SCOPE_SYSTEM.

This prevents detecting cpu features that can be detected
on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
for errata workaround with SCOPE_SYSTEM.

This patch makes sure that we allow flexibility of having
any scope for a capability. So, we now run through both
arm64_features and arm64_errata in two phases for detection:

 a) with SCOPE_LOCAL_CPU filter on each boot time enabled
    CPUs.
 b) with SCOPE_SYSTEM filter only once after all boot time
    enabled CPUs are active.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 61d4c3cfb1cc..e1a56fa889a5 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -505,6 +505,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_features(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -554,6 +555,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 	 * initialised the cpu feature infrastructure.
 	 */
 	update_cpu_errata_workarounds();
+	update_cpu_local_features();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
 static void update_cpu_errata_workarounds(void)
 {
 	update_cpu_capabilities(arm64_errata,
-				ARM64_CPUCAP_SCOPE_ALL,
+				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
 				"enabling workaround for");
 }
 
-static void __init enable_errata_workarounds(void)
+static void update_cpu_local_features(void)
 {
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
+	update_cpu_capabilities(arm64_features,
+				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
+				"detected feature:");
 }
 
 /*
@@ -1430,23 +1434,34 @@ void check_local_cpu_capabilities(void)
 
 	/*
 	 * If we haven't finalised the system capabilities, this CPU gets
-	 * a chance to update the errata work arounds.
+	 * a chance to update the errata work arounds and local CPU features.
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised)
+	if (!sys_caps_initialised) {
 		update_cpu_errata_workarounds();
-	else
+		update_cpu_local_features();
+	} else {
 		verify_local_cpu_capabilities();
+	}
 }
 
 static void __init setup_feature_capabilities(void)
 {
 	update_cpu_capabilities(arm64_features,
-				ARM64_CPUCAP_SCOPE_ALL, "detected feature:");
+				ARM64_CPUCAP_SCOPE_SYSTEM,
+				"detected feature:");
 	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
 }
 
+static void __init setup_errata_workarounds(void)
+{
+	update_cpu_capabilities(arm64_errata,
+				ARM64_CPUCAP_SCOPE_SYSTEM,
+				"enabling workaround for");
+	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
+}
+
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
 EXPORT_SYMBOL(arm64_const_caps_ready);
 
@@ -1468,9 +1483,9 @@ void __init setup_cpu_features(void)
 	u32 cwg;
 	int cls;
 
-	/* Set the CPU feature capabilies */
+	/* Finalise the CPU capabilities */
 	setup_feature_capabilities();
-	enable_errata_workarounds();
+	setup_errata_workarounds();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

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

We can now handle each capability entry independent of whether
it is a feature or an errata workaround. This patch consolidates
the handling of the capabilities, by grouping them, to streamline
the code flow.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 99 +++++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 49 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index e1a56fa889a5..31d1e02ed5be 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,8 +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_features(void);
+static void update_cpu_local_capabilities(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -554,8 +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_features();
+	update_cpu_local_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1223,8 +1221,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 scope_mask, const char *info)
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+				      u16 scope_mask, const char *info)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1238,6 +1236,15 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+/* Detect all capabilities which match the given scope_mask */
+static void update_cpu_capabilities(u16 scope_mask)
+{
+	__update_cpu_capabilities(arm64_features, scope_mask,
+				"detected feature:");
+	__update_cpu_capabilities(arm64_errata, scope_mask,
+				"enabling work around for");
+}
+
 static int __enable_cpu_capability(void *arg)
 {
 	const struct arm64_cpu_capabilities *cap = arg;
@@ -1251,7 +1258,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1330,6 +1337,13 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+/* Verify this CPU against all the capabilities that match the scope */
+static bool verify_local_cpu_caps(u16 scope_mask)
+{
+	return __verify_local_cpu_caps(arm64_features, scope_mask) &&
+	       __verify_local_cpu_caps(arm64_errata, scope_mask);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1352,12 +1366,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_SCOPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1376,28 +1384,29 @@ 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_SCOPE_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_SCOPE_LOCAL_CPU,
-				"enabling workaround for");
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
 }
 
-static void update_cpu_local_features(void)
+/* Enable all the capabilities matching the given scope mask */
+static void enable_cpu_capabilities(u16 scope_mask)
 {
-	update_cpu_capabilities(arm64_features,
-				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
-				"detected feature:");
+	__enable_cpu_capabilities(arm64_errata, scope_mask);
+	__enable_cpu_capabilities(arm64_features, scope_mask);
 }
 
 /*
@@ -1410,8 +1419,8 @@ static void update_cpu_local_features(void)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features();
+	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1438,28 +1447,21 @@ void check_local_cpu_capabilities(void)
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised) {
-		update_cpu_errata_workarounds();
-		update_cpu_local_features();
-	} else {
+	if (!sys_caps_initialised)
+		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_SCOPE_SYSTEM,
-				"detected feature:");
-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
-}
-
-static void __init setup_errata_workarounds(void)
-{
-	update_cpu_capabilities(arm64_errata,
-				ARM64_CPUCAP_SCOPE_SYSTEM,
-				"enabling workaround for");
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_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_SCOPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1484,8 +1486,7 @@ void __init setup_cpu_features(void)
 	int cls;
 
 	/* Finalise the CPU capabilities */
-	setup_feature_capabilities();
-	setup_errata_workarounds();
+	setup_system_capabilities();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

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

We can now handle each capability entry independent of whether
it is a feature or an errata workaround. This patch consolidates
the handling of the capabilities, by grouping them, to streamline
the code flow.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 99 +++++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 49 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index e1a56fa889a5..31d1e02ed5be 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,8 +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_features(void);
+static void update_cpu_local_capabilities(void);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -554,8 +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_features();
+	update_cpu_local_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1223,8 +1221,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 scope_mask, const char *info)
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
+				      u16 scope_mask, const char *info)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1238,6 +1236,15 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+/* Detect all capabilities which match the given scope_mask */
+static void update_cpu_capabilities(u16 scope_mask)
+{
+	__update_cpu_capabilities(arm64_features, scope_mask,
+				"detected feature:");
+	__update_cpu_capabilities(arm64_errata, scope_mask,
+				"enabling work around for");
+}
+
 static int __enable_cpu_capability(void *arg)
 {
 	const struct arm64_cpu_capabilities *cap = arg;
@@ -1251,7 +1258,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1330,6 +1337,13 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+/* Verify this CPU against all the capabilities that match the scope */
+static bool verify_local_cpu_caps(u16 scope_mask)
+{
+	return __verify_local_cpu_caps(arm64_features, scope_mask) &&
+	       __verify_local_cpu_caps(arm64_errata, scope_mask);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1352,12 +1366,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_SCOPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1376,28 +1384,29 @@ 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_SCOPE_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_SCOPE_LOCAL_CPU,
-				"enabling workaround for");
+	update_cpu_capabilities(ARM64_CPUCAP_SCOPE_SYSTEM);
 }
 
-static void update_cpu_local_features(void)
+/* Enable all the capabilities matching the given scope mask */
+static void enable_cpu_capabilities(u16 scope_mask)
 {
-	update_cpu_capabilities(arm64_features,
-				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
-				"detected feature:");
+	__enable_cpu_capabilities(arm64_errata, scope_mask);
+	__enable_cpu_capabilities(arm64_features, scope_mask);
 }
 
 /*
@@ -1410,8 +1419,8 @@ static void update_cpu_local_features(void)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features();
+	if (!verify_local_cpu_caps(ARM64_CPUCAP_SCOPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1438,28 +1447,21 @@ void check_local_cpu_capabilities(void)
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised) {
-		update_cpu_errata_workarounds();
-		update_cpu_local_features();
-	} else {
+	if (!sys_caps_initialised)
+		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_SCOPE_SYSTEM,
-				"detected feature:");
-	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
-}
-
-static void __init setup_errata_workarounds(void)
-{
-	update_cpu_capabilities(arm64_errata,
-				ARM64_CPUCAP_SCOPE_SYSTEM,
-				"enabling workaround for");
-	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_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_SCOPE_ALL);
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1484,8 +1486,7 @@ void __init setup_cpu_features(void)
 	int cls;
 
 	/* Finalise the CPU capabilities */
-	setup_feature_capabilities();
-	setup_errata_workarounds();
+	setup_system_capabilities();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

* Re: [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-02-07 10:39     ` Dave Martin
@ 2018-02-08 12:19       ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 12:19 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 07/02/18 10:39, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>> We defend against branch predictor training based exploits by
>> taking specific actions (based on the CPU model) to invalidate
>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>> ptr, which installs the specific actions for the CPU model.
>>
>> The core code can handle the following cases where:
>>   1) some CPUs doesn't need any work around
>>   2) a CPU can install the work around, when it is brought up,
>>      irrespective of how late that happens.

With the recent patches from Marc to expose this information to KVM
guests, it looks like allowing a late CPU to turn this on is not going
to be a good idea. We unconditionally set the capability even
when we don't need the mitigation. So I am not really sure if
we should go ahead with this patch. I am open to suggestions

Marc,

What do you think ?

>>
>> This concludes that it is safe to bring up a CPU which requires
>> bp hardening defense. However, with the current settings, we
>> reject a late CPU, if none of the active CPUs didn't need it.
> 
> Should this be "[...] reject a late CPU that needs the defense, if none
> of the active CPUs needed it." ?

Thats right. Will fix it.

> 
>>
>> This patch solves issue by changing the flags for the capability
>> to indicate that it is safe for a late CPU to turn up with the
>> capability. This is not sufficient to get things working, as
>> we cannot change the system wide state of the capability established
>> at the kernel boot. So, we "set" the capability unconditionally
>> and make sure that the call backs are only installed for those
>> CPUs which actually needs them. This is done by adding a dummy
>> entry at the end of the list of shared entries, which :
>>   a) Always returns true for matches, to ensure we turn this on.
>>   b) has an empty "cpu_enable" call back, so that we don't take
>>      any action on the CPUs which weren't matched with the real
>>      entries.
>>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>


>> +
>>   static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>>   	{
>>   		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
>> @@ -268,6 +274,17 @@ static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>>   		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
>>   		.cpu_enable = qcom_enable_link_stack_sanitization,
>>   	},
>> +	/*
>> +	 * Always enable the capability to make sure a late CPU can
>> +	 * safely use the BP hardening call backs. Since we use per-CPU
>> +	 * pointers for the call backs, the work around only affects the
>> +	 * CPUs which have some methods installed by any real matching entries
>> +	 * above. As such we don't have any specific cpu_enable() callback
>> +	 * for this entry, as it is just to make sure we always "detect" it.
>> +	 */
>> +	{
>> +		.matches = bp_hardening_always_on,
> 
> This function could simply be called "always_on", since it expresses
> something entirely generic and is static.

Sure, if we still go ahead with this.

> 
>> +	},
> 
> This feels like a bit of a hack: really there is no global on/off
> state for a cap like this: it's truly independent for each cpu.

Yea, I kind of didn't like it, but that does the job ;-).

> 
> OTOH, your code does achieve that, and the comment gives a good
> explanation.
> 
> The alternative would be to add a cap type flag to indicate that
> this cap is purely CPU-local, but it may not be worth it at this
> stage.

Agree. Thats going to make the code a bit more complex than it is already.

Cheers
Suzuki

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-02-08 12:19       ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/02/18 10:39, Dave Martin wrote:
> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>> We defend against branch predictor training based exploits by
>> taking specific actions (based on the CPU model) to invalidate
>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>> ptr, which installs the specific actions for the CPU model.
>>
>> The core code can handle the following cases where:
>>   1) some CPUs doesn't need any work around
>>   2) a CPU can install the work around, when it is brought up,
>>      irrespective of how late that happens.

With the recent patches from Marc to expose this information to KVM
guests, it looks like allowing a late CPU to turn this on is not going
to be a good idea. We unconditionally set the capability even
when we don't need the mitigation. So I am not really sure if
we should go ahead with this patch. I am open to suggestions

Marc,

What do you think ?

>>
>> This concludes that it is safe to bring up a CPU which requires
>> bp hardening defense. However, with the current settings, we
>> reject a late CPU, if none of the active CPUs didn't need it.
> 
> Should this be "[...] reject a late CPU that needs the defense, if none
> of the active CPUs needed it." ?

Thats right. Will fix it.

> 
>>
>> This patch solves issue by changing the flags for the capability
>> to indicate that it is safe for a late CPU to turn up with the
>> capability. This is not sufficient to get things working, as
>> we cannot change the system wide state of the capability established
>> at the kernel boot. So, we "set" the capability unconditionally
>> and make sure that the call backs are only installed for those
>> CPUs which actually needs them. This is done by adding a dummy
>> entry at the end of the list of shared entries, which :
>>   a) Always returns true for matches, to ensure we turn this on.
>>   b) has an empty "cpu_enable" call back, so that we don't take
>>      any action on the CPUs which weren't matched with the real
>>      entries.
>>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Dave Martin <dave.martin@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>


>> +
>>   static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>>   	{
>>   		CAP_MIDR_RANGE_LIST(arm64_bp_harden_psci_cpus),
>> @@ -268,6 +274,17 @@ static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
>>   		CAP_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
>>   		.cpu_enable = qcom_enable_link_stack_sanitization,
>>   	},
>> +	/*
>> +	 * Always enable the capability to make sure a late CPU can
>> +	 * safely use the BP hardening call backs. Since we use per-CPU
>> +	 * pointers for the call backs, the work around only affects the
>> +	 * CPUs which have some methods installed by any real matching entries
>> +	 * above. As such we don't have any specific cpu_enable() callback
>> +	 * for this entry, as it is just to make sure we always "detect" it.
>> +	 */
>> +	{
>> +		.matches = bp_hardening_always_on,
> 
> This function could simply be called "always_on", since it expresses
> something entirely generic and is static.

Sure, if we still go ahead with this.

> 
>> +	},
> 
> This feels like a bit of a hack: really there is no global on/off
> state for a cap like this: it's truly independent for each cpu.

Yea, I kind of didn't like it, but that does the job ;-).

> 
> OTOH, your code does achieve that, and the comment gives a good
> explanation.
> 
> The alternative would be to add a cap type flag to indicate that
> this cap is purely CPU-local, but it may not be worth it at this
> stage.

Agree. Thats going to make the code a bit more complex than it is already.

Cheers
Suzuki

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

* Re: [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-02-08 12:19       ` Suzuki K Poulose
@ 2018-02-08 12:26         ` Marc Zyngier
  -1 siblings, 0 replies; 156+ messages in thread
From: Marc Zyngier @ 2018-02-08 12:26 UTC (permalink / raw)
  To: Suzuki K Poulose, Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	catalin.marinas, will.deacon, linux-kernel, jnair

On 08/02/18 12:19, Suzuki K Poulose wrote:
> On 07/02/18 10:39, Dave Martin wrote:
>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>> We defend against branch predictor training based exploits by
>>> taking specific actions (based on the CPU model) to invalidate
>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>> ptr, which installs the specific actions for the CPU model.
>>>
>>> The core code can handle the following cases where:
>>>   1) some CPUs doesn't need any work around
>>>   2) a CPU can install the work around, when it is brought up,
>>>      irrespective of how late that happens.
> 
> With the recent patches from Marc to expose this information to KVM
> guests, it looks like allowing a late CPU to turn this on is not going
> to be a good idea. We unconditionally set the capability even
> when we don't need the mitigation. So I am not really sure if
> we should go ahead with this patch. I am open to suggestions
> 
> Marc,
> 
> What do you think ?

By the time we bring in that CPU that requires some level of mitigation,
we may be running a guest already, and we've told that guest that no
mitigation was required. If we bring in that CPU, we break that promise,
and the guest becomes vulnerable without knowing about it.

The same thing is valid for userspace once we expose the status of the
mitigation in /sys, just like x86 does. If we transition from not
vulnerable to vulnerable (or even mitigated), we have lied to userspace.

In either case, I don't think breaking this contract is acceptable.

Thanks,

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

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-02-08 12:26         ` Marc Zyngier
  0 siblings, 0 replies; 156+ messages in thread
From: Marc Zyngier @ 2018-02-08 12:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 12:19, Suzuki K Poulose wrote:
> On 07/02/18 10:39, Dave Martin wrote:
>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>> We defend against branch predictor training based exploits by
>>> taking specific actions (based on the CPU model) to invalidate
>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>> ptr, which installs the specific actions for the CPU model.
>>>
>>> The core code can handle the following cases where:
>>>   1) some CPUs doesn't need any work around
>>>   2) a CPU can install the work around, when it is brought up,
>>>      irrespective of how late that happens.
> 
> With the recent patches from Marc to expose this information to KVM
> guests, it looks like allowing a late CPU to turn this on is not going
> to be a good idea. We unconditionally set the capability even
> when we don't need the mitigation. So I am not really sure if
> we should go ahead with this patch. I am open to suggestions
> 
> Marc,
> 
> What do you think ?

By the time we bring in that CPU that requires some level of mitigation,
we may be running a guest already, and we've told that guest that no
mitigation was required. If we bring in that CPU, we break that promise,
and the guest becomes vulnerable without knowing about it.

The same thing is valid for userspace once we expose the status of the
mitigation in /sys, just like x86 does. If we transition from not
vulnerable to vulnerable (or even mitigated), we have lied to userspace.

In either case, I don't think breaking this contract is acceptable.

Thanks,

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

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

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-02-08 12:01         ` Dave Martin
@ 2018-02-08 12:32           ` Robin Murphy
  -1 siblings, 0 replies; 156+ messages in thread
From: Robin Murphy @ 2018-02-08 12:32 UTC (permalink / raw)
  To: Dave Martin, Suzuki K Poulose
  Cc: mark.rutland, ckadabi, ard.biesheuvel, marc.zyngier,
	catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On 08/02/18 12:01, Dave Martin wrote:
> On Thu, Feb 08, 2018 at 10:53:52AM +0000, Suzuki K Poulose wrote:
>> On 07/02/18 10:39, Dave Martin wrote:
>>> On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
>>>> Some capabilities have different criteria for detection and associated
>>>> actions based on the matching criteria, even though they all share the
>>>> same capability bit. So far we have used multiple entries with the same
>>>> capability bit to handle this. This is prone to errors, as the
>>>> cpu_enable is invoked for each entry, irrespective of whether the
>>>> detection rule applies to the CPU or not. And also this complicates
>>>> other helpers, e.g, __this_cpu_has_cap.
>>>>
>>>> This patch adds a wrapper entry to cover all the possible variations
>>>> of a capability and ensures :
>>>>   1) The capabilitiy is set when at least one of the entry detects
>>>>   2) Action is only taken for the entries that detects.
>>>
>>> I guess this means that where we have a single cpu_enable() method
>>> but complex match criteria that require multiple entries, then that
>>> cpu_enable() method might get called multiple times on a given CPU.
>>
>> A CPU executes cpu_enable() only for the "matching" entries in the list,
>> unlike earlier. So as long as there is a single entry "matching" the given
>> CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
>> that a CPU cannot be matched by multiple entries.
>>
>>>
>>> Could be worth a comment if cpu_enable() methods must be robust
>>> against this.
> 
> Could we say something like:
> 
> "Where a single capability has multiple entries, mutiple cpu_enable()
> methods may be called if more than one entry matches.  Where this is
> not desired, care should be taken to ensure that the entries are
> mutually exclusive: for example, two entries for a single capability
> that match on MIDR should be configured to match MIDR ranges that do
> not overlap."
> 
> This is more verbose than I would like however.  Maybe there's a simpler
> way to say it.

If we're not also talking about a capability having mutually exclusive 
enable methods (it doesn't seem so, but I'm not necessarily 100% clear), 
how about:

"If a cpu_enable() method is associated with multiple matches for a 
single capability, care should be taken that either the match criteria 
are mutually exclusive, or that the method is robust against being 
called multiple times."

?

Robin.

>>>> This avoids explicit checks in the call backs. The only constraint
>>>> here is that, all the entries should have the same "type".
>>>>
>>>> Cc: Dave Martin <dave.martin@arm.com>
>>>> Cc: Will Deacon <will.deacon@arm.com>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>>>   arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
>>>>   arch/arm64/kernel/cpufeature.c      |  7 +++--
>>>>   3 files changed, 50 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index 462c35d1a38c..b73247c27f00 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
>>>>   			bool sign;
>>>>   			unsigned long hwcap;
>>>>   		};
>>>> +		const struct arm64_cpu_capabilities *cap_list;
>>>
>>> Should desc, capability, def_scope and/or cpu_enable match for every cap
>>> in such a group?
>>
>> As mentioned above, the "type" field should match, which implies scope
>> must match. The code ignores the scope, capability and desc of the individual
>> entries in the list. They should be shared by the parent entry.
>>
>> cpu_enable could be duplicated as long as a CPU is not matched by multiple
>> entries.
>>
>>>
>>> I'd expected something maybe like this:
>>>
>>> struct arm64_cpu_capabilities {
>>> 	const char *desc;
>>> 	u16 capability;
>>> 	struct arm64_capability_match {
>>> 		bool (*matches)(const struct arm64_cpu_capabilities *, int);
>>> 		int (*cpu_enable)(void);
>>> 		union {
>>> 			struct { ... midr ... };
>>> 			struct { ... sysreg ... };
>>> 			const struct arm64_capability_match *list;
>>> 		};
>>>>   	};
>>>>   };
>>
>> Yes, thats makes it more explicit. However, it makes the "matches()"
>> complicated, as we have to change the prototype for matches to accept
>> struct arm64_capability_match *, to point to the right "matches" for
>> items in the list. And that makes a bit more of an invasive change, where
>> each matches() would then loose a way to get to the "capabilities" entry,
>> as they could be called with either the "match" in the top level or
>> the one in the list.
> 
> Yes, that's true.  matches() could take a pointer to the cap struct
> _and_ the relevant match entry, but I'm not sure it's worth it.  In any
> case, my previous objection below doesn't make as much sense as I
> thought.
> 
>>>>   		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>> index 65a8e5cc600c..13e30c1b1e99 100644
>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>> @@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>>>>   		return false;
>>>>   	for (caps = cap_array; caps->matches; caps++)
>>>> -		if (caps->capability == cap &&
>>>> -		    caps->matches(caps, SCOPE_LOCAL_CPU))
>>>> -			return true;
>>>> +		if (caps->capability == cap)
>>>> +			return caps->matches(caps, SCOPE_LOCAL_CPU);
>>>
>>> If we went for my capability { cap; match criteria or list; } approach,
>>> would it still be necessary to iterate over the whole list here?
>>
>> Sorry, I couldn't follow this. With this patch, we already stop scanning
>> the list as soon as we find the first entry. It is upto "the entry" to run
>> individual match criteria to decide.
> 
> Ah, I'm talking nonsense here.  Patch 6 iterates over the entire
> capability list via the call to __this_cpu_has_cap() in
> __verify_local_cpu_caps(), but this patch now changes the behaviour so
> that this doesn't happen any more.
> 
> The only other users of this_cpu_has_cap() don't have the right cap
> pointer already, so a scan over the whole list is required in those
> cases -- and anyway, those look like fast paths (RAS exceptions).
> 
> [...]
> 
> Cheers
> ---Dave
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-08 12:32           ` Robin Murphy
  0 siblings, 0 replies; 156+ messages in thread
From: Robin Murphy @ 2018-02-08 12:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 12:01, Dave Martin wrote:
> On Thu, Feb 08, 2018 at 10:53:52AM +0000, Suzuki K Poulose wrote:
>> On 07/02/18 10:39, Dave Martin wrote:
>>> On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
>>>> Some capabilities have different criteria for detection and associated
>>>> actions based on the matching criteria, even though they all share the
>>>> same capability bit. So far we have used multiple entries with the same
>>>> capability bit to handle this. This is prone to errors, as the
>>>> cpu_enable is invoked for each entry, irrespective of whether the
>>>> detection rule applies to the CPU or not. And also this complicates
>>>> other helpers, e.g, __this_cpu_has_cap.
>>>>
>>>> This patch adds a wrapper entry to cover all the possible variations
>>>> of a capability and ensures :
>>>>   1) The capabilitiy is set when at least one of the entry detects
>>>>   2) Action is only taken for the entries that detects.
>>>
>>> I guess this means that where we have a single cpu_enable() method
>>> but complex match criteria that require multiple entries, then that
>>> cpu_enable() method might get called multiple times on a given CPU.
>>
>> A CPU executes cpu_enable() only for the "matching" entries in the list,
>> unlike earlier. So as long as there is a single entry "matching" the given
>> CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
>> that a CPU cannot be matched by multiple entries.
>>
>>>
>>> Could be worth a comment if cpu_enable() methods must be robust
>>> against this.
> 
> Could we say something like:
> 
> "Where a single capability has multiple entries, mutiple cpu_enable()
> methods may be called if more than one entry matches.  Where this is
> not desired, care should be taken to ensure that the entries are
> mutually exclusive: for example, two entries for a single capability
> that match on MIDR should be configured to match MIDR ranges that do
> not overlap."
> 
> This is more verbose than I would like however.  Maybe there's a simpler
> way to say it.

If we're not also talking about a capability having mutually exclusive 
enable methods (it doesn't seem so, but I'm not necessarily 100% clear), 
how about:

"If a cpu_enable() method is associated with multiple matches for a 
single capability, care should be taken that either the match criteria 
are mutually exclusive, or that the method is robust against being 
called multiple times."

?

Robin.

>>>> This avoids explicit checks in the call backs. The only constraint
>>>> here is that, all the entries should have the same "type".
>>>>
>>>> Cc: Dave Martin <dave.martin@arm.com>
>>>> Cc: Will Deacon <will.deacon@arm.com>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> ---
>>>>   arch/arm64/include/asm/cpufeature.h |  1 +
>>>>   arch/arm64/kernel/cpu_errata.c      | 53 ++++++++++++++++++++++++++++++++-----
>>>>   arch/arm64/kernel/cpufeature.c      |  7 +++--
>>>>   3 files changed, 50 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>>> index 462c35d1a38c..b73247c27f00 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -290,6 +290,7 @@ struct arm64_cpu_capabilities {
>>>>   			bool sign;
>>>>   			unsigned long hwcap;
>>>>   		};
>>>> +		const struct arm64_cpu_capabilities *cap_list;
>>>
>>> Should desc, capability, def_scope and/or cpu_enable match for every cap
>>> in such a group?
>>
>> As mentioned above, the "type" field should match, which implies scope
>> must match. The code ignores the scope, capability and desc of the individual
>> entries in the list. They should be shared by the parent entry.
>>
>> cpu_enable could be duplicated as long as a CPU is not matched by multiple
>> entries.
>>
>>>
>>> I'd expected something maybe like this:
>>>
>>> struct arm64_cpu_capabilities {
>>> 	const char *desc;
>>> 	u16 capability;
>>> 	struct arm64_capability_match {
>>> 		bool (*matches)(const struct arm64_cpu_capabilities *, int);
>>> 		int (*cpu_enable)(void);
>>> 		union {
>>> 			struct { ... midr ... };
>>> 			struct { ... sysreg ... };
>>> 			const struct arm64_capability_match *list;
>>> 		};
>>>>   	};
>>>>   };
>>
>> Yes, thats makes it more explicit. However, it makes the "matches()"
>> complicated, as we have to change the prototype for matches to accept
>> struct arm64_capability_match *, to point to the right "matches" for
>> items in the list. And that makes a bit more of an invasive change, where
>> each matches() would then loose a way to get to the "capabilities" entry,
>> as they could be called with either the "match" in the top level or
>> the one in the list.
> 
> Yes, that's true.  matches() could take a pointer to the cap struct
> _and_ the relevant match entry, but I'm not sure it's worth it.  In any
> case, my previous objection below doesn't make as much sense as I
> thought.
> 
>>>>   		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>> index 65a8e5cc600c..13e30c1b1e99 100644
>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>> @@ -1181,9 +1181,8 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
>>>>   		return false;
>>>>   	for (caps = cap_array; caps->matches; caps++)
>>>> -		if (caps->capability == cap &&
>>>> -		    caps->matches(caps, SCOPE_LOCAL_CPU))
>>>> -			return true;
>>>> +		if (caps->capability == cap)
>>>> +			return caps->matches(caps, SCOPE_LOCAL_CPU);
>>>
>>> If we went for my capability { cap; match criteria or list; } approach,
>>> would it still be necessary to iterate over the whole list here?
>>
>> Sorry, I couldn't follow this. With this patch, we already stop scanning
>> the list as soon as we find the first entry. It is upto "the entry" to run
>> individual match criteria to decide.
> 
> Ah, I'm talking nonsense here.  Patch 6 iterates over the entire
> capability list via the call to __this_cpu_has_cap() in
> __verify_local_cpu_caps(), but this patch now changes the behaviour so
> that this doesn't happen any more.
> 
> The only other users of this_cpu_has_cap() don't have the right cap
> pointer already, so a scan over the whole list is required in those
> cases -- and anyway, those look like fast paths (RAS exceptions).
> 
> [...]
> 
> Cheers
> ---Dave
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
  2018-02-08 12:12         ` Suzuki K Poulose
@ 2018-02-08 16:10           ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 16:10 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, Feb 08, 2018 at 12:12:37PM +0000, Suzuki K Poulose wrote:
> So far we have restricted the scopes for the capabilities
> as follows :
>  1) Errata workaround check are run all CPUs (i.e, always
>     SCOPE_LOCAL_CPU)
>  2) Arm64 features are run only once after the sanitised
>     feature registers are available using the SCOPE_SYSTEM.
> 
> This prevents detecting cpu features that can be detected
> on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
> for errata workaround with SCOPE_SYSTEM.
> 
> This patch makes sure that we allow flexibility of having
> any scope for a capability. So, we now run through both
> arm64_features and arm64_errata in two phases for detection:
> 
>  a) with SCOPE_LOCAL_CPU filter on each boot time enabled
>     CPUs.
>  b) with SCOPE_SYSTEM filter only once after all boot time
>     enabled CPUs are active.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 33 ++++++++++++++++++++++++---------
>  1 file changed, 24 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 61d4c3cfb1cc..e1a56fa889a5 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -505,6 +505,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_features(void);
>  
>  void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  {
> @@ -554,6 +555,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  	 * initialised the cpu feature infrastructure.
>  	 */
>  	update_cpu_errata_workarounds();
> +	update_cpu_local_features();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
>  static void update_cpu_errata_workarounds(void)
>  {
>  	update_cpu_capabilities(arm64_errata,
> -				ARM64_CPUCAP_SCOPE_ALL,
> +				ARM64_CPUCAP_SCOPE_LOCAL_CPU,

In isolation, this looks strange because it seems to handle only a
subset of arm64_errata now.

I think I understand the change as follows:

 * all previously-existing errata workarounds SCOPE_LOCAL_CPU
   anyway, so the behavior here doesn't change for any existing
   caps;

 * the non SCOPE_SYSTEM workarounds (which this patch prepares for)
   are handled by the new setup_errata_workaround() path.

Similarly, the features handling is split into two: one mirroring
the current behaviour (for SCOPE_SYSTEM this time) and one handling
the rest, for supporting SCOPE_CPU_LOCAL features in subsequent
patches.

Does that sound right?

I'm not sure we need extra comments or documentation; I just want
to check that I've understood the patch correctly.

Cheers
---Dave

>  				"enabling workaround for");
>  }
>  
> -static void __init enable_errata_workarounds(void)
> +static void update_cpu_local_features(void)
>  {
> -	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
> +	update_cpu_capabilities(arm64_features,
> +				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> +				"detected feature:");
>  }
>  
>  /*
> @@ -1430,23 +1434,34 @@ void check_local_cpu_capabilities(void)
>  
>  	/*
>  	 * If we haven't finalised the system capabilities, this CPU gets
> -	 * a chance to update the errata work arounds.
> +	 * a chance to update the errata work arounds and local CPU features.
>  	 * Otherwise, this CPU should verify that it has all the system
>  	 * advertised capabilities.
>  	 */
> -	if (!sys_caps_initialised)
> +	if (!sys_caps_initialised) {
>  		update_cpu_errata_workarounds();
> -	else
> +		update_cpu_local_features();
> +	} else {
>  		verify_local_cpu_capabilities();
> +	}
>  }
>  
>  static void __init setup_feature_capabilities(void)
>  {
>  	update_cpu_capabilities(arm64_features,
> -				ARM64_CPUCAP_SCOPE_ALL, "detected feature:");
> +				ARM64_CPUCAP_SCOPE_SYSTEM,
> +				"detected feature:");
>  	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
>  }
>  
> +static void __init setup_errata_workarounds(void)
> +{
> +	update_cpu_capabilities(arm64_errata,
> +				ARM64_CPUCAP_SCOPE_SYSTEM,
> +				"enabling workaround for");
> +	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
> +}
> +
>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
>  EXPORT_SYMBOL(arm64_const_caps_ready);
>  
> @@ -1468,9 +1483,9 @@ void __init setup_cpu_features(void)
>  	u32 cwg;
>  	int cls;
>  
> -	/* Set the CPU feature capabilies */
> +	/* Finalise the CPU capabilities */
>  	setup_feature_capabilities();
> -	enable_errata_workarounds();
> +	setup_errata_workarounds();
>  	mark_const_caps_ready();
>  	setup_elf_hwcaps(arm64_elf_hwcaps);
>  
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
@ 2018-02-08 16:10           ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 16:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 08, 2018 at 12:12:37PM +0000, Suzuki K Poulose wrote:
> So far we have restricted the scopes for the capabilities
> as follows :
>  1) Errata workaround check are run all CPUs (i.e, always
>     SCOPE_LOCAL_CPU)
>  2) Arm64 features are run only once after the sanitised
>     feature registers are available using the SCOPE_SYSTEM.
> 
> This prevents detecting cpu features that can be detected
> on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
> for errata workaround with SCOPE_SYSTEM.
> 
> This patch makes sure that we allow flexibility of having
> any scope for a capability. So, we now run through both
> arm64_features and arm64_errata in two phases for detection:
> 
>  a) with SCOPE_LOCAL_CPU filter on each boot time enabled
>     CPUs.
>  b) with SCOPE_SYSTEM filter only once after all boot time
>     enabled CPUs are active.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 33 ++++++++++++++++++++++++---------
>  1 file changed, 24 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 61d4c3cfb1cc..e1a56fa889a5 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -505,6 +505,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_features(void);
>  
>  void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  {
> @@ -554,6 +555,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  	 * initialised the cpu feature infrastructure.
>  	 */
>  	update_cpu_errata_workarounds();
> +	update_cpu_local_features();
>  }
>  
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
>  static void update_cpu_errata_workarounds(void)
>  {
>  	update_cpu_capabilities(arm64_errata,
> -				ARM64_CPUCAP_SCOPE_ALL,
> +				ARM64_CPUCAP_SCOPE_LOCAL_CPU,

In isolation, this looks strange because it seems to handle only a
subset of arm64_errata now.

I think I understand the change as follows:

 * all previously-existing errata workarounds SCOPE_LOCAL_CPU
   anyway, so the behavior here doesn't change for any existing
   caps;

 * the non SCOPE_SYSTEM workarounds (which this patch prepares for)
   are handled by the new setup_errata_workaround() path.

Similarly, the features handling is split into two: one mirroring
the current behaviour (for SCOPE_SYSTEM this time) and one handling
the rest, for supporting SCOPE_CPU_LOCAL features in subsequent
patches.

Does that sound right?

I'm not sure we need extra comments or documentation; I just want
to check that I've understood the patch correctly.

Cheers
---Dave

>  				"enabling workaround for");
>  }
>  
> -static void __init enable_errata_workarounds(void)
> +static void update_cpu_local_features(void)
>  {
> -	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
> +	update_cpu_capabilities(arm64_features,
> +				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> +				"detected feature:");
>  }
>  
>  /*
> @@ -1430,23 +1434,34 @@ void check_local_cpu_capabilities(void)
>  
>  	/*
>  	 * If we haven't finalised the system capabilities, this CPU gets
> -	 * a chance to update the errata work arounds.
> +	 * a chance to update the errata work arounds and local CPU features.
>  	 * Otherwise, this CPU should verify that it has all the system
>  	 * advertised capabilities.
>  	 */
> -	if (!sys_caps_initialised)
> +	if (!sys_caps_initialised) {
>  		update_cpu_errata_workarounds();
> -	else
> +		update_cpu_local_features();
> +	} else {
>  		verify_local_cpu_capabilities();
> +	}
>  }
>  
>  static void __init setup_feature_capabilities(void)
>  {
>  	update_cpu_capabilities(arm64_features,
> -				ARM64_CPUCAP_SCOPE_ALL, "detected feature:");
> +				ARM64_CPUCAP_SCOPE_SYSTEM,
> +				"detected feature:");
>  	enable_cpu_capabilities(arm64_features, ARM64_CPUCAP_SCOPE_ALL);
>  }
>  
> +static void __init setup_errata_workarounds(void)
> +{
> +	update_cpu_capabilities(arm64_errata,
> +				ARM64_CPUCAP_SCOPE_SYSTEM,
> +				"enabling workaround for");
> +	enable_cpu_capabilities(arm64_errata, ARM64_CPUCAP_SCOPE_ALL);
> +}
> +
>  DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
>  EXPORT_SYMBOL(arm64_const_caps_ready);
>  
> @@ -1468,9 +1483,9 @@ void __init setup_cpu_features(void)
>  	u32 cwg;
>  	int cls;
>  
> -	/* Set the CPU feature capabilies */
> +	/* Finalise the CPU capabilities */
>  	setup_feature_capabilities();
> -	enable_errata_workarounds();
> +	setup_errata_workarounds();
>  	mark_const_caps_ready();
>  	setup_elf_hwcaps(arm64_elf_hwcaps);
>  
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> 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] 156+ messages in thread

* Re: [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
  2018-02-08 16:10           ` Dave Martin
@ 2018-02-08 16:31             ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 16:31 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 08/02/18 16:10, Dave Martin wrote:
> On Thu, Feb 08, 2018 at 12:12:37PM +0000, Suzuki K Poulose wrote:
>> So far we have restricted the scopes for the capabilities
>> as follows :
>>   1) Errata workaround check are run all CPUs (i.e, always
>>      SCOPE_LOCAL_CPU)
>>   2) Arm64 features are run only once after the sanitised
>>      feature registers are available using the SCOPE_SYSTEM.
>>
>> This prevents detecting cpu features that can be detected
>> on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
>> for errata workaround with SCOPE_SYSTEM.
>>
>> This patch makes sure that we allow flexibility of having
>> any scope for a capability. So, we now run through both
>> arm64_features and arm64_errata in two phases for detection:
>>
>>   a) with SCOPE_LOCAL_CPU filter on each boot time enabled
>>      CPUs.
>>   b) with SCOPE_SYSTEM filter only once after all boot time
>>      enabled CPUs are active.
>>


>>   
>>   static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
>> @@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
>>   static void update_cpu_errata_workarounds(void)
>>   {
>>   	update_cpu_capabilities(arm64_errata,
>> -				ARM64_CPUCAP_SCOPE_ALL,
>> +				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> 
> In isolation, this looks strange because it seems to handle only a
> subset of arm64_errata now.
> 
> I think I understand the change as follows:
> 
>   * all previously-existing errata workarounds SCOPE_LOCAL_CPU
>     anyway, so the behavior here doesn't change for any existing
>     caps;
> 
>   * the non SCOPE_SYSTEM workarounds (which this patch prepares for)
"the SCOPE_SYSTEM" workarounds..."

>     are handled by the new setup_errata_workaround() path.

> 
> Similarly, the features handling is split into two: one mirroring
> the current behaviour (for SCOPE_SYSTEM this time) and one handling> the rest, for supporting SCOPE_CPU_LOCAL features in subsequent
> patches.

Right. The changes here are :

New behavior:
   - Run SCOPE_LOCAL_CPU filter on arm64_features on all CPUs (newly added with
     this patch) via (newly added)update_cpu_local_features().

Split of existing behavior:
   - Run SCOPE_LOCAL_CPU(instead of the earlier SCOPE_ALL) on all CPUs in
     update_cpu_errata_workarounds()
   - Run SCOPE_SYSTEM filter on arm64_errata, once, via setup_errata_workarounds()

> 
> Does that sound right?
> 
> I'm not sure we need extra comments or documentation; I just want
> to check that I've understood the patch correctly.

So, would you prefer this split to the original patch ?

Cheers
Suzuki

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

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
@ 2018-02-08 16:31             ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 16:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 16:10, Dave Martin wrote:
> On Thu, Feb 08, 2018 at 12:12:37PM +0000, Suzuki K Poulose wrote:
>> So far we have restricted the scopes for the capabilities
>> as follows :
>>   1) Errata workaround check are run all CPUs (i.e, always
>>      SCOPE_LOCAL_CPU)
>>   2) Arm64 features are run only once after the sanitised
>>      feature registers are available using the SCOPE_SYSTEM.
>>
>> This prevents detecting cpu features that can be detected
>> on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
>> for errata workaround with SCOPE_SYSTEM.
>>
>> This patch makes sure that we allow flexibility of having
>> any scope for a capability. So, we now run through both
>> arm64_features and arm64_errata in two phases for detection:
>>
>>   a) with SCOPE_LOCAL_CPU filter on each boot time enabled
>>      CPUs.
>>   b) with SCOPE_SYSTEM filter only once after all boot time
>>      enabled CPUs are active.
>>


>>   
>>   static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
>> @@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
>>   static void update_cpu_errata_workarounds(void)
>>   {
>>   	update_cpu_capabilities(arm64_errata,
>> -				ARM64_CPUCAP_SCOPE_ALL,
>> +				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> 
> In isolation, this looks strange because it seems to handle only a
> subset of arm64_errata now.
> 
> I think I understand the change as follows:
> 
>   * all previously-existing errata workarounds SCOPE_LOCAL_CPU
>     anyway, so the behavior here doesn't change for any existing
>     caps;
> 
>   * the non SCOPE_SYSTEM workarounds (which this patch prepares for)
"the SCOPE_SYSTEM" workarounds..."

>     are handled by the new setup_errata_workaround() path.

> 
> Similarly, the features handling is split into two: one mirroring
> the current behaviour (for SCOPE_SYSTEM this time) and one handling> the rest, for supporting SCOPE_CPU_LOCAL features in subsequent
> patches.

Right. The changes here are :

New behavior:
   - Run SCOPE_LOCAL_CPU filter on arm64_features on all CPUs (newly added with
     this patch) via (newly added)update_cpu_local_features().

Split of existing behavior:
   - Run SCOPE_LOCAL_CPU(instead of the earlier SCOPE_ALL) on all CPUs in
     update_cpu_errata_workarounds()
   - Run SCOPE_SYSTEM filter on arm64_errata, once, via setup_errata_workarounds()

> 
> Does that sound right?
> 
> I'm not sure we need extra comments or documentation; I just want
> to check that I've understood the patch correctly.

So, would you prefer this split to the original patch ?

Cheers
Suzuki

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

* Re: [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-02-08 12:26         ` Marc Zyngier
@ 2018-02-08 16:58           ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 16:58 UTC (permalink / raw)
  To: Marc Zyngier, Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	catalin.marinas, will.deacon, linux-kernel, jnair

On 08/02/18 12:26, Marc Zyngier wrote:
> On 08/02/18 12:19, Suzuki K Poulose wrote:
>> On 07/02/18 10:39, Dave Martin wrote:
>>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>>> We defend against branch predictor training based exploits by
>>>> taking specific actions (based on the CPU model) to invalidate
>>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>>> ptr, which installs the specific actions for the CPU model.
>>>>
>>>> The core code can handle the following cases where:
>>>>    1) some CPUs doesn't need any work around
>>>>    2) a CPU can install the work around, when it is brought up,
>>>>       irrespective of how late that happens.
>>
>> With the recent patches from Marc to expose this information to KVM
>> guests, it looks like allowing a late CPU to turn this on is not going
>> to be a good idea. We unconditionally set the capability even
>> when we don't need the mitigation. So I am not really sure if
>> we should go ahead with this patch. I am open to suggestions
>>
>> Marc,
>>
>> What do you think ?
> 
> By the time we bring in that CPU that requires some level of mitigation,
> we may be running a guest already, and we've told that guest that no
> mitigation was required. If we bring in that CPU, we break that promise,
> and the guest becomes vulnerable without knowing about it.
> 
> The same thing is valid for userspace once we expose the status of the
> mitigation in /sys, just like x86 does. If we transition from not
> vulnerable to vulnerable (or even mitigated), we have lied to userspace.
> 
> In either case, I don't think breaking this contract is acceptable.

Thanks Marc, I have dropped this patch from the series.

Cheers
Suzuki

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-02-08 16:58           ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 16:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 12:26, Marc Zyngier wrote:
> On 08/02/18 12:19, Suzuki K Poulose wrote:
>> On 07/02/18 10:39, Dave Martin wrote:
>>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>>> We defend against branch predictor training based exploits by
>>>> taking specific actions (based on the CPU model) to invalidate
>>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>>> ptr, which installs the specific actions for the CPU model.
>>>>
>>>> The core code can handle the following cases where:
>>>>    1) some CPUs doesn't need any work around
>>>>    2) a CPU can install the work around, when it is brought up,
>>>>       irrespective of how late that happens.
>>
>> With the recent patches from Marc to expose this information to KVM
>> guests, it looks like allowing a late CPU to turn this on is not going
>> to be a good idea. We unconditionally set the capability even
>> when we don't need the mitigation. So I am not really sure if
>> we should go ahead with this patch. I am open to suggestions
>>
>> Marc,
>>
>> What do you think ?
> 
> By the time we bring in that CPU that requires some level of mitigation,
> we may be running a guest already, and we've told that guest that no
> mitigation was required. If we bring in that CPU, we break that promise,
> and the guest becomes vulnerable without knowing about it.
> 
> The same thing is valid for userspace once we expose the status of the
> mitigation in /sys, just like x86 does. If we transition from not
> vulnerable to vulnerable (or even mitigated), we have lied to userspace.
> 
> In either case, I don't think breaking this contract is acceptable.

Thanks Marc, I have dropped this patch from the series.

Cheers
Suzuki

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

* Re: [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
  2018-02-08 16:31             ` Suzuki K Poulose
@ 2018-02-08 17:32               ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 17:32 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, Feb 08, 2018 at 04:31:47PM +0000, Suzuki K Poulose wrote:
> On 08/02/18 16:10, Dave Martin wrote:
> >On Thu, Feb 08, 2018 at 12:12:37PM +0000, Suzuki K Poulose wrote:
> >>So far we have restricted the scopes for the capabilities
> >>as follows :
> >>  1) Errata workaround check are run all CPUs (i.e, always
> >>     SCOPE_LOCAL_CPU)
> >>  2) Arm64 features are run only once after the sanitised
> >>     feature registers are available using the SCOPE_SYSTEM.
> >>
> >>This prevents detecting cpu features that can be detected
> >>on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
> >>for errata workaround with SCOPE_SYSTEM.
> >>
> >>This patch makes sure that we allow flexibility of having
> >>any scope for a capability. So, we now run through both
> >>arm64_features and arm64_errata in two phases for detection:
> >>
> >>  a) with SCOPE_LOCAL_CPU filter on each boot time enabled
> >>     CPUs.
> >>  b) with SCOPE_SYSTEM filter only once after all boot time
> >>     enabled CPUs are active.
> >>
> 
> 
> >>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> >>@@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
> >>  static void update_cpu_errata_workarounds(void)
> >>  {
> >>  	update_cpu_capabilities(arm64_errata,
> >>-				ARM64_CPUCAP_SCOPE_ALL,
> >>+				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> >
> >In isolation, this looks strange because it seems to handle only a
> >subset of arm64_errata now.
> >
> >I think I understand the change as follows:
> >
> >  * all previously-existing errata workarounds SCOPE_LOCAL_CPU
> >    anyway, so the behavior here doesn't change for any existing
> >    caps;
> >
> >  * the non SCOPE_SYSTEM workarounds (which this patch prepares for)
> "the SCOPE_SYSTEM" workarounds..."
> 
> >    are handled by the new setup_errata_workaround() path.
> 
> >
> >Similarly, the features handling is split into two: one mirroring
> >the current behaviour (for SCOPE_SYSTEM this time) and one handling> the rest, for supporting SCOPE_CPU_LOCAL features in subsequent
> >patches.
> 
> Right. The changes here are :
> 
> New behavior:
>   - Run SCOPE_LOCAL_CPU filter on arm64_features on all CPUs (newly added with
>     this patch) via (newly added)update_cpu_local_features().
> 
> Split of existing behavior:
>   - Run SCOPE_LOCAL_CPU(instead of the earlier SCOPE_ALL) on all CPUs in
>     update_cpu_errata_workarounds()
>   - Run SCOPE_SYSTEM filter on arm64_errata, once, via setup_errata_workarounds()

OK, thanks for confirming.

[...]

> >I'm not sure we need extra comments or documentation; I just want
> >to check that I've understood the patch correctly.
> 
> So, would you prefer this split to the original patch ?

I think splitting out this patch (1/2) makes sense.


For the second part (2/2) of the split, I still find that hard to
review.  The commit message suggests trivially obvious refactoring
only, but I think there are three things going on:

 1) moving functions around (with the intention of merging them)
 2) merging functions together
 3) other miscellaneous bits of refactoring, and cleanups that become
    "obvious" after steps (1) and (2).

The refactoring is likely straightfoward, but the resulting diff is
not (at least, I struggle to read it).

Could you split the second part along the lines if (1)..(3) above?
I think that would make for much easier review.  (Sorry to be a pain!)

Also, the second patch leaves at least one function that does nothing
except call a second function that has no other caller.  It may do
no harm to remove and inline any such function.  (Falls under (3),
I guess.)

Cheers
---Dave

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

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
@ 2018-02-08 17:32               ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-08 17:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 08, 2018 at 04:31:47PM +0000, Suzuki K Poulose wrote:
> On 08/02/18 16:10, Dave Martin wrote:
> >On Thu, Feb 08, 2018 at 12:12:37PM +0000, Suzuki K Poulose wrote:
> >>So far we have restricted the scopes for the capabilities
> >>as follows :
> >>  1) Errata workaround check are run all CPUs (i.e, always
> >>     SCOPE_LOCAL_CPU)
> >>  2) Arm64 features are run only once after the sanitised
> >>     feature registers are available using the SCOPE_SYSTEM.
> >>
> >>This prevents detecting cpu features that can be detected
> >>on one or more CPUs with SCOPE_LOCAL_CPU (e.g KPTI). Similarly
> >>for errata workaround with SCOPE_SYSTEM.
> >>
> >>This patch makes sure that we allow flexibility of having
> >>any scope for a capability. So, we now run through both
> >>arm64_features and arm64_errata in two phases for detection:
> >>
> >>  a) with SCOPE_LOCAL_CPU filter on each boot time enabled
> >>     CPUs.
> >>  b) with SCOPE_SYSTEM filter only once after all boot time
> >>     enabled CPUs are active.
> >>
> 
> 
> >>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> >>@@ -1387,13 +1389,15 @@ static void verify_local_cpu_errata_workarounds(void)
> >>  static void update_cpu_errata_workarounds(void)
> >>  {
> >>  	update_cpu_capabilities(arm64_errata,
> >>-				ARM64_CPUCAP_SCOPE_ALL,
> >>+				ARM64_CPUCAP_SCOPE_LOCAL_CPU,
> >
> >In isolation, this looks strange because it seems to handle only a
> >subset of arm64_errata now.
> >
> >I think I understand the change as follows:
> >
> >  * all previously-existing errata workarounds SCOPE_LOCAL_CPU
> >    anyway, so the behavior here doesn't change for any existing
> >    caps;
> >
> >  * the non SCOPE_SYSTEM workarounds (which this patch prepares for)
> "the SCOPE_SYSTEM" workarounds..."
> 
> >    are handled by the new setup_errata_workaround() path.
> 
> >
> >Similarly, the features handling is split into two: one mirroring
> >the current behaviour (for SCOPE_SYSTEM this time) and one handling> the rest, for supporting SCOPE_CPU_LOCAL features in subsequent
> >patches.
> 
> Right. The changes here are :
> 
> New behavior:
>   - Run SCOPE_LOCAL_CPU filter on arm64_features on all CPUs (newly added with
>     this patch) via (newly added)update_cpu_local_features().
> 
> Split of existing behavior:
>   - Run SCOPE_LOCAL_CPU(instead of the earlier SCOPE_ALL) on all CPUs in
>     update_cpu_errata_workarounds()
>   - Run SCOPE_SYSTEM filter on arm64_errata, once, via setup_errata_workarounds()

OK, thanks for confirming.

[...]

> >I'm not sure we need extra comments or documentation; I just want
> >to check that I've understood the patch correctly.
> 
> So, would you prefer this split to the original patch ?

I think splitting out this patch (1/2) makes sense.


For the second part (2/2) of the split, I still find that hard to
review.  The commit message suggests trivially obvious refactoring
only, but I think there are three things going on:

 1) moving functions around (with the intention of merging them)
 2) merging functions together
 3) other miscellaneous bits of refactoring, and cleanups that become
    "obvious" after steps (1) and (2).

The refactoring is likely straightfoward, but the resulting diff is
not (at least, I struggle to read it).

Could you split the second part along the lines if (1)..(3) above?
I think that would make for much easier review.  (Sorry to be a pain!)

Also, the second patch leaves at least one function that does nothing
except call a second function that has no other caller.  It may do
no harm to remove and inline any such function.  (Falls under (3),
I guess.)

Cheers
---Dave

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

* Re: [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-02-08 16:58           ` Suzuki K Poulose
@ 2018-02-08 17:59             ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 17:59 UTC (permalink / raw)
  To: Marc Zyngier, Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	catalin.marinas, will.deacon, linux-kernel, jnair

On 08/02/18 16:58, Suzuki K Poulose wrote:
> On 08/02/18 12:26, Marc Zyngier wrote:
>> On 08/02/18 12:19, Suzuki K Poulose wrote:
>>> On 07/02/18 10:39, Dave Martin wrote:
>>>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>>>> We defend against branch predictor training based exploits by
>>>>> taking specific actions (based on the CPU model) to invalidate
>>>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>>>> ptr, which installs the specific actions for the CPU model.
>>>>>
>>>>> The core code can handle the following cases where:
>>>>>    1) some CPUs doesn't need any work around
>>>>>    2) a CPU can install the work around, when it is brought up,
>>>>>       irrespective of how late that happens.
>>>
>>> With the recent patches from Marc to expose this information to KVM
>>> guests, it looks like allowing a late CPU to turn this on is not going
>>> to be a good idea. We unconditionally set the capability even
>>> when we don't need the mitigation. So I am not really sure if
>>> we should go ahead with this patch. I am open to suggestions
>>>
>>> Marc,
>>>
>>> What do you think ?
>>
>> By the time we bring in that CPU that requires some level of mitigation,
>> we may be running a guest already, and we've told that guest that no
>> mitigation was required. If we bring in that CPU, we break that promise,
>> and the guest becomes vulnerable without knowing about it.
>>
>> The same thing is valid for userspace once we expose the status of the
>> mitigation in /sys, just like x86 does. If we transition from not
>> vulnerable to vulnerable (or even mitigated), we have lied to userspace.
>>
>> In either case, I don't think breaking this contract is acceptable.
> 
> Thanks Marc, I have dropped this patch from the series.

On a second thought, should we allow this if the KVM is not configured in ?

Cheers
Suzuki

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-02-08 17:59             ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 17:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 16:58, Suzuki K Poulose wrote:
> On 08/02/18 12:26, Marc Zyngier wrote:
>> On 08/02/18 12:19, Suzuki K Poulose wrote:
>>> On 07/02/18 10:39, Dave Martin wrote:
>>>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>>>> We defend against branch predictor training based exploits by
>>>>> taking specific actions (based on the CPU model) to invalidate
>>>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>>>> ptr, which installs the specific actions for the CPU model.
>>>>>
>>>>> The core code can handle the following cases where:
>>>>> ?? 1) some CPUs doesn't need any work around
>>>>> ?? 2) a CPU can install the work around, when it is brought up,
>>>>> ????? irrespective of how late that happens.
>>>
>>> With the recent patches from Marc to expose this information to KVM
>>> guests, it looks like allowing a late CPU to turn this on is not going
>>> to be a good idea. We unconditionally set the capability even
>>> when we don't need the mitigation. So I am not really sure if
>>> we should go ahead with this patch. I am open to suggestions
>>>
>>> Marc,
>>>
>>> What do you think ?
>>
>> By the time we bring in that CPU that requires some level of mitigation,
>> we may be running a guest already, and we've told that guest that no
>> mitigation was required. If we bring in that CPU, we break that promise,
>> and the guest becomes vulnerable without knowing about it.
>>
>> The same thing is valid for userspace once we expose the status of the
>> mitigation in /sys, just like x86 does. If we transition from not
>> vulnerable to vulnerable (or even mitigated), we have lied to userspace.
>>
>> In either case, I don't think breaking this contract is acceptable.
> 
> Thanks Marc, I have dropped this patch from the series.

On a second thought, should we allow this if the KVM is not configured in ?

Cheers
Suzuki

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

* Re: [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
  2018-02-08 17:59             ` Suzuki K Poulose
@ 2018-02-08 17:59               ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 17:59 UTC (permalink / raw)
  To: Marc Zyngier, Dave Martin
  Cc: linux-arm-kernel, mark.rutland, ckadabi, ard.biesheuvel,
	catalin.marinas, will.deacon, linux-kernel, jnair

On 08/02/18 17:59, Suzuki K Poulose wrote:
> On 08/02/18 16:58, Suzuki K Poulose wrote:
>> On 08/02/18 12:26, Marc Zyngier wrote:
>>> On 08/02/18 12:19, Suzuki K Poulose wrote:
>>>> On 07/02/18 10:39, Dave Martin wrote:
>>>>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>>>>> We defend against branch predictor training based exploits by
>>>>>> taking specific actions (based on the CPU model) to invalidate
>>>>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>>>>> ptr, which installs the specific actions for the CPU model.
>>>>>>
>>>>>> The core code can handle the following cases where:
>>>>>>    1) some CPUs doesn't need any work around
>>>>>>    2) a CPU can install the work around, when it is brought up,
>>>>>>       irrespective of how late that happens.
>>>>
>>>> With the recent patches from Marc to expose this information to KVM
>>>> guests, it looks like allowing a late CPU to turn this on is not going
>>>> to be a good idea. We unconditionally set the capability even
>>>> when we don't need the mitigation. So I am not really sure if
>>>> we should go ahead with this patch. I am open to suggestions
>>>>
>>>> Marc,
>>>>
>>>> What do you think ?
>>>
>>> By the time we bring in that CPU that requires some level of mitigation,
>>> we may be running a guest already, and we've told that guest that no
>>> mitigation was required. If we bring in that CPU, we break that promise,
>>> and the guest becomes vulnerable without knowing about it.
>>>
>>> The same thing is valid for userspace once we expose the status of the
>>> mitigation in /sys, just like x86 does. If we transition from not
>>> vulnerable to vulnerable (or even mitigated), we have lied to userspace.
>>>
>>> In either case, I don't think breaking this contract is acceptable.
>>
>> Thanks Marc, I have dropped this patch from the series.
> 
> On a second thought, should we allow this if the KVM is not configured in ?

Oops, no! Please ignore it. We are going to expose this to other userpsace anyway.
Sorry about the noise.

Suzuki

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

* [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around
@ 2018-02-08 17:59               ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-08 17:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/02/18 17:59, Suzuki K Poulose wrote:
> On 08/02/18 16:58, Suzuki K Poulose wrote:
>> On 08/02/18 12:26, Marc Zyngier wrote:
>>> On 08/02/18 12:19, Suzuki K Poulose wrote:
>>>> On 07/02/18 10:39, Dave Martin wrote:
>>>>> On Wed, Jan 31, 2018 at 06:28:04PM +0000, Suzuki K Poulose wrote:
>>>>>> We defend against branch predictor training based exploits by
>>>>>> taking specific actions (based on the CPU model) to invalidate
>>>>>> the Branch predictor buffer (BPB). This is implemented by per-CPU
>>>>>> ptr, which installs the specific actions for the CPU model.
>>>>>>
>>>>>> The core code can handle the following cases where:
>>>>>> ?? 1) some CPUs doesn't need any work around
>>>>>> ?? 2) a CPU can install the work around, when it is brought up,
>>>>>> ????? irrespective of how late that happens.
>>>>
>>>> With the recent patches from Marc to expose this information to KVM
>>>> guests, it looks like allowing a late CPU to turn this on is not going
>>>> to be a good idea. We unconditionally set the capability even
>>>> when we don't need the mitigation. So I am not really sure if
>>>> we should go ahead with this patch. I am open to suggestions
>>>>
>>>> Marc,
>>>>
>>>> What do you think ?
>>>
>>> By the time we bring in that CPU that requires some level of mitigation,
>>> we may be running a guest already, and we've told that guest that no
>>> mitigation was required. If we bring in that CPU, we break that promise,
>>> and the guest becomes vulnerable without knowing about it.
>>>
>>> The same thing is valid for userspace once we expose the status of the
>>> mitigation in /sys, just like x86 does. If we transition from not
>>> vulnerable to vulnerable (or even mitigated), we have lied to userspace.
>>>
>>> In either case, I don't think breaking this contract is acceptable.
>>
>> Thanks Marc, I have dropped this patch from the series.
> 
> On a second thought, should we allow this if the KVM is not configured in ?

Oops, no! Please ignore it. We are going to expose this to other userpsace anyway.
Sorry about the noise.

Suzuki

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

* Re: [PATCH v2 16/20] arm64: Handle shared capability entries
  2018-02-08 12:32           ` Robin Murphy
@ 2018-02-09 10:05             ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-09 10:05 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Suzuki K Poulose, mark.rutland, ckadabi, ard.biesheuvel,
	marc.zyngier, catalin.marinas, will.deacon, linux-kernel, jnair,
	linux-arm-kernel

On Thu, Feb 08, 2018 at 12:32:56PM +0000, Robin Murphy wrote:
> On 08/02/18 12:01, Dave Martin wrote:
> >On Thu, Feb 08, 2018 at 10:53:52AM +0000, Suzuki K Poulose wrote:
> >>On 07/02/18 10:39, Dave Martin wrote:
> >>>On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> >>>>Some capabilities have different criteria for detection and associated
> >>>>actions based on the matching criteria, even though they all share the
> >>>>same capability bit. So far we have used multiple entries with the same
> >>>>capability bit to handle this. This is prone to errors, as the
> >>>>cpu_enable is invoked for each entry, irrespective of whether the
> >>>>detection rule applies to the CPU or not. And also this complicates
> >>>>other helpers, e.g, __this_cpu_has_cap.
> >>>>
> >>>>This patch adds a wrapper entry to cover all the possible variations
> >>>>of a capability and ensures :
> >>>>  1) The capabilitiy is set when at least one of the entry detects
> >>>>  2) Action is only taken for the entries that detects.
> >>>
> >>>I guess this means that where we have a single cpu_enable() method
> >>>but complex match criteria that require multiple entries, then that
> >>>cpu_enable() method might get called multiple times on a given CPU.
> >>
> >>A CPU executes cpu_enable() only for the "matching" entries in the list,
> >>unlike earlier. So as long as there is a single entry "matching" the given
> >>CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
> >>that a CPU cannot be matched by multiple entries.
> >>
> >>>
> >>>Could be worth a comment if cpu_enable() methods must be robust
> >>>against this.
> >
> >Could we say something like:
> >
> >"Where a single capability has multiple entries, mutiple cpu_enable()
> >methods may be called if more than one entry matches.  Where this is
> >not desired, care should be taken to ensure that the entries are
> >mutually exclusive: for example, two entries for a single capability
> >that match on MIDR should be configured to match MIDR ranges that do
> >not overlap."
> >
> >This is more verbose than I would like however.  Maybe there's a simpler
> >way to say it.
> 
> If we're not also talking about a capability having mutually exclusive
> enable methods (it doesn't seem so, but I'm not necessarily 100% clear), how
> about:
> 
> "If a cpu_enable() method is associated with multiple matches for a single
> capability, care should be taken that either the match criteria are mutually
> exclusive, or that the method is robust against being called multiple
> times."

This is one reason why I wondered if we could pull cpu_enable() out of
the match criteria struct so that we don't duplicate it: in that case
there's no chance of multiple incompatible cpu_enable() methods.

But Suzuki is right that this would be a somewhat invasive change at
this point, and I think it's sufficient to warn about the possibility
of incompatible cpu_enable()s in a comment.

Otherwise, your text sounds good.

Cheers
---Dave

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

* [PATCH v2 16/20] arm64: Handle shared capability entries
@ 2018-02-09 10:05             ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-09 10:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 08, 2018 at 12:32:56PM +0000, Robin Murphy wrote:
> On 08/02/18 12:01, Dave Martin wrote:
> >On Thu, Feb 08, 2018 at 10:53:52AM +0000, Suzuki K Poulose wrote:
> >>On 07/02/18 10:39, Dave Martin wrote:
> >>>On Wed, Jan 31, 2018 at 06:28:03PM +0000, Suzuki K Poulose wrote:
> >>>>Some capabilities have different criteria for detection and associated
> >>>>actions based on the matching criteria, even though they all share the
> >>>>same capability bit. So far we have used multiple entries with the same
> >>>>capability bit to handle this. This is prone to errors, as the
> >>>>cpu_enable is invoked for each entry, irrespective of whether the
> >>>>detection rule applies to the CPU or not. And also this complicates
> >>>>other helpers, e.g, __this_cpu_has_cap.
> >>>>
> >>>>This patch adds a wrapper entry to cover all the possible variations
> >>>>of a capability and ensures :
> >>>>  1) The capabilitiy is set when at least one of the entry detects
> >>>>  2) Action is only taken for the entries that detects.
> >>>
> >>>I guess this means that where we have a single cpu_enable() method
> >>>but complex match criteria that require multiple entries, then that
> >>>cpu_enable() method might get called multiple times on a given CPU.
> >>
> >>A CPU executes cpu_enable() only for the "matching" entries in the list,
> >>unlike earlier. So as long as there is a single entry "matching" the given
> >>CPU, the cpu_enable() will not be duplicated. May be we *should* mandate
> >>that a CPU cannot be matched by multiple entries.
> >>
> >>>
> >>>Could be worth a comment if cpu_enable() methods must be robust
> >>>against this.
> >
> >Could we say something like:
> >
> >"Where a single capability has multiple entries, mutiple cpu_enable()
> >methods may be called if more than one entry matches.  Where this is
> >not desired, care should be taken to ensure that the entries are
> >mutually exclusive: for example, two entries for a single capability
> >that match on MIDR should be configured to match MIDR ranges that do
> >not overlap."
> >
> >This is more verbose than I would like however.  Maybe there's a simpler
> >way to say it.
> 
> If we're not also talking about a capability having mutually exclusive
> enable methods (it doesn't seem so, but I'm not necessarily 100% clear), how
> about:
> 
> "If a cpu_enable() method is associated with multiple matches for a single
> capability, care should be taken that either the match criteria are mutually
> exclusive, or that the method is robust against being called multiple
> times."

This is one reason why I wondered if we could pull cpu_enable() out of
the match criteria struct so that we don't duplicate it: in that case
there's no chance of multiple incompatible cpu_enable() methods.

But Suzuki is right that this would be a somewhat invasive change at
this point, and I think it's sufficient to warn about the possibility
of incompatible cpu_enable()s in a comment.

Otherwise, your text sounds good.

Cheers
---Dave

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

* Re: [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
  2018-02-08 17:32               ` Dave Martin
@ 2018-02-09 12:16                 ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: dave.martin
  Cc: mark.rutland, will.deacon, ard.biesheuvel, marc.zyngier,
	catalin.marinas, linux-arm-kernel, linux-kernel, jnair, ckadabi,
	Suzuki K Poulose

>>> I'm not sure we need extra comments or documentation; I just want
>>> to check that I've understood the patch correctly.
>>
>> So, would you prefer this split to the original patch ?
> 
> I think splitting out this patch (1/2) makes sense.
> 
> 
> For the second part (2/2) of the split, I still find that hard to
> review.  The commit message suggests trivially obvious refactoring
> only, but I think there are three things going on:
> 
>   1) moving functions around (with the intention of merging them)
>   2) merging functions together
>   3) other miscellaneous bits of refactoring, and cleanups that become
>      "obvious" after steps (1) and (2).
> 
> The refactoring is likely straightfoward, but the resulting diff is
> not (at least, I struggle to read it).
> 
> Could you split the second part along the lines if (1)..(3) above?
> I think that would make for much easier review.  (Sorry to be a pain!)
> 
> Also, the second patch leaves at least one function that does nothing
> except call a second function that has no other caller.  It may do
> no harm to remove and inline any such function.  (Falls under (3),
> I guess.)
> 

Here it goes...

Suzuki K Poulose (4):
  arm64: capabilities: Prepare for grouping features and errata work
    arounds
  arm64: capabilities: Split the processing of errata work arounds
  arm64: capabilities: Allow features based on local CPU scope
  arm64: capabilities: Group handling of features and errata workarounds

 arch/arm64/kernel/cpufeature.c | 91 ++++++++++++++++++++----------------------
 1 file changed, 43 insertions(+), 48 deletions(-)

-- 
2.14.3

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

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
@ 2018-02-09 12:16                 ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

>>> I'm not sure we need extra comments or documentation; I just want
>>> to check that I've understood the patch correctly.
>>
>> So, would you prefer this split to the original patch ?
> 
> I think splitting out this patch (1/2) makes sense.
> 
> 
> For the second part (2/2) of the split, I still find that hard to
> review.  The commit message suggests trivially obvious refactoring
> only, but I think there are three things going on:
> 
>   1) moving functions around (with the intention of merging them)
>   2) merging functions together
>   3) other miscellaneous bits of refactoring, and cleanups that become
>      "obvious" after steps (1) and (2).
> 
> The refactoring is likely straightfoward, but the resulting diff is
> not (at least, I struggle to read it).
> 
> Could you split the second part along the lines if (1)..(3) above?
> I think that would make for much easier review.  (Sorry to be a pain!)
> 
> Also, the second patch leaves at least one function that does nothing
> except call a second function that has no other caller.  It may do
> no harm to remove and inline any such function.  (Falls under (3),
> I guess.)
> 

Here it goes...

Suzuki K Poulose (4):
  arm64: capabilities: Prepare for grouping features and errata work
    arounds
  arm64: capabilities: Split the processing of errata work arounds
  arm64: capabilities: Allow features based on local CPU scope
  arm64: capabilities: Group handling of features and errata workarounds

 arch/arm64/kernel/cpufeature.c | 91 ++++++++++++++++++++----------------------
 1 file changed, 43 insertions(+), 48 deletions(-)

-- 
2.14.3

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

* [PATCH 1/4] arm64: capabilities: Prepare for grouping features and errata work arounds
  2018-02-09 12:16                 ` Suzuki K Poulose
@ 2018-02-09 12:16                   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: dave.martin
  Cc: mark.rutland, will.deacon, ard.biesheuvel, marc.zyngier,
	catalin.marinas, linux-arm-kernel, linux-kernel, jnair, ckadabi,
	Suzuki K Poulose

We are about to group the handling of all capabilities (features
and errata workarounds). This patch open codes the wrapper routines
to make it easier to merge the handling.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 60 +++++++++++++-----------------------------
 1 file changed, 19 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 3447821bec5a..9f52678a4df1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,7 +504,8 @@ 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_capabilities(const struct arm64_cpu_capabilities *caps,
+				    u16 scope_mask, const char *info);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -553,7 +554,8 @@ 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_capabilities(arm64_errata, SCOPE_ALL,
+				"enabling workaround for");
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1350,12 +1352,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, SCOPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1373,27 +1369,6 @@ static void verify_sve_features(void)
 	/* Add checks on other ZCR bits here if necessary */
 }
 
-/*
- * 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)
-{
-	if (!__verify_local_cpu_caps(arm64_errata, SCOPE_ALL))
-		cpu_die_early();
-}
-
-static void update_cpu_errata_workarounds(void)
-{
-	update_cpu_capabilities(arm64_errata, SCOPE_ALL,
-				"enabling workaround for");
-}
-
-static void __init enable_errata_workarounds(void)
-{
-	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
-}
 
 /*
  * Run through the enabled system capabilities and enable() it on this CPU.
@@ -1405,8 +1380,15 @@ static void __init enable_errata_workarounds(void)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features();
+	/*
+	 * 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.
+	 */
+	if (!__verify_local_cpu_caps(arm64_errata, SCOPE_ALL))
+		cpu_die_early();
+	if (!__verify_local_cpu_caps(arm64_features, SCOPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1434,18 +1416,12 @@ void check_local_cpu_capabilities(void)
 	 * advertised capabilities.
 	 */
 	if (!sys_caps_initialised)
-		update_cpu_errata_workarounds();
+		update_cpu_capabilities(arm64_errata, SCOPE_ALL,
+					"enabling workaround for");
 	else
 		verify_local_cpu_capabilities();
 }
 
-static void __init setup_feature_capabilities(void)
-{
-	update_cpu_capabilities(arm64_features, SCOPE_ALL,
-				"detected feature:");
-	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
-}
-
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
 EXPORT_SYMBOL(arm64_const_caps_ready);
 
@@ -1468,8 +1444,10 @@ void __init setup_cpu_features(void)
 	int cls;
 
 	/* Set the CPU feature capabilies */
-	setup_feature_capabilities();
-	enable_errata_workarounds();
+	update_cpu_capabilities(arm64_features, SCOPE_ALL,
+				"detected feature:");
+	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
+	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

* [PATCH 1/4] arm64: capabilities: Prepare for grouping features and errata work arounds
@ 2018-02-09 12:16                   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

We are about to group the handling of all capabilities (features
and errata workarounds). This patch open codes the wrapper routines
to make it easier to merge the handling.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 60 +++++++++++++-----------------------------
 1 file changed, 19 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 3447821bec5a..9f52678a4df1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,7 +504,8 @@ 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_capabilities(const struct arm64_cpu_capabilities *caps,
+				    u16 scope_mask, const char *info);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -553,7 +554,8 @@ 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_capabilities(arm64_errata, SCOPE_ALL,
+				"enabling workaround for");
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1350,12 +1352,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, SCOPE_ALL))
-		cpu_die_early();
-}
-
 static void verify_sve_features(void)
 {
 	u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
@@ -1373,27 +1369,6 @@ static void verify_sve_features(void)
 	/* Add checks on other ZCR bits here if necessary */
 }
 
-/*
- * 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)
-{
-	if (!__verify_local_cpu_caps(arm64_errata, SCOPE_ALL))
-		cpu_die_early();
-}
-
-static void update_cpu_errata_workarounds(void)
-{
-	update_cpu_capabilities(arm64_errata, SCOPE_ALL,
-				"enabling workaround for");
-}
-
-static void __init enable_errata_workarounds(void)
-{
-	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
-}
 
 /*
  * Run through the enabled system capabilities and enable() it on this CPU.
@@ -1405,8 +1380,15 @@ static void __init enable_errata_workarounds(void)
  */
 static void verify_local_cpu_capabilities(void)
 {
-	verify_local_cpu_errata_workarounds();
-	verify_local_cpu_features();
+	/*
+	 * 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.
+	 */
+	if (!__verify_local_cpu_caps(arm64_errata, SCOPE_ALL))
+		cpu_die_early();
+	if (!__verify_local_cpu_caps(arm64_features, SCOPE_ALL))
+		cpu_die_early();
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1434,18 +1416,12 @@ void check_local_cpu_capabilities(void)
 	 * advertised capabilities.
 	 */
 	if (!sys_caps_initialised)
-		update_cpu_errata_workarounds();
+		update_cpu_capabilities(arm64_errata, SCOPE_ALL,
+					"enabling workaround for");
 	else
 		verify_local_cpu_capabilities();
 }
 
-static void __init setup_feature_capabilities(void)
-{
-	update_cpu_capabilities(arm64_features, SCOPE_ALL,
-				"detected feature:");
-	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
-}
-
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
 EXPORT_SYMBOL(arm64_const_caps_ready);
 
@@ -1468,8 +1444,10 @@ void __init setup_cpu_features(void)
 	int cls;
 
 	/* Set the CPU feature capabilies */
-	setup_feature_capabilities();
-	enable_errata_workarounds();
+	update_cpu_capabilities(arm64_features, SCOPE_ALL,
+				"detected feature:");
+	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
+	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

* [PATCH 2/4] arm64: capabilities: Split the processing of errata work arounds
  2018-02-09 12:16                 ` Suzuki K Poulose
@ 2018-02-09 12:16                   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: dave.martin
  Cc: mark.rutland, will.deacon, ard.biesheuvel, marc.zyngier,
	catalin.marinas, linux-arm-kernel, linux-kernel, jnair, ckadabi,
	Suzuki K Poulose

Right now we run through the errata workarounds check on all boot
active CPUs, with SCOPE_ALL. This doesn't help with detecting the
errata's with a SYSTEM_SCOPE. While nobody uses it, let us clean
this up in preparation for merging capability handling.

So, we run the checks with SCOPE_LOCAL_CPU on all CPUs and SCOPE_SYSTEM
checks are run only once after all the boot time CPUs are active.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 9f52678a4df1..a6e124063e21 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -554,7 +554,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_capabilities(arm64_errata, SCOPE_ALL,
+	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 				"enabling workaround for");
 }
 
@@ -1416,7 +1416,7 @@ void check_local_cpu_capabilities(void)
 	 * advertised capabilities.
 	 */
 	if (!sys_caps_initialised)
-		update_cpu_capabilities(arm64_errata, SCOPE_ALL,
+		update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 					"enabling workaround for");
 	else
 		verify_local_cpu_capabilities();
@@ -1446,6 +1446,8 @@ void __init setup_cpu_features(void)
 	/* Set the CPU feature capabilies */
 	update_cpu_capabilities(arm64_features, SCOPE_ALL,
 				"detected feature:");
+	update_cpu_capabilities(arm64_errata, SCOPE_SYSTEM,
+				"enabling workaround for");
 	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
 	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
 	mark_const_caps_ready();
-- 
2.14.3

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

* [PATCH 2/4] arm64: capabilities: Split the processing of errata work arounds
@ 2018-02-09 12:16                   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

Right now we run through the errata workarounds check on all boot
active CPUs, with SCOPE_ALL. This doesn't help with detecting the
errata's with a SYSTEM_SCOPE. While nobody uses it, let us clean
this up in preparation for merging capability handling.

So, we run the checks with SCOPE_LOCAL_CPU on all CPUs and SCOPE_SYSTEM
checks are run only once after all the boot time CPUs are active.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 9f52678a4df1..a6e124063e21 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -554,7 +554,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_capabilities(arm64_errata, SCOPE_ALL,
+	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 				"enabling workaround for");
 }
 
@@ -1416,7 +1416,7 @@ void check_local_cpu_capabilities(void)
 	 * advertised capabilities.
 	 */
 	if (!sys_caps_initialised)
-		update_cpu_capabilities(arm64_errata, SCOPE_ALL,
+		update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 					"enabling workaround for");
 	else
 		verify_local_cpu_capabilities();
@@ -1446,6 +1446,8 @@ void __init setup_cpu_features(void)
 	/* Set the CPU feature capabilies */
 	update_cpu_capabilities(arm64_features, SCOPE_ALL,
 				"detected feature:");
+	update_cpu_capabilities(arm64_errata, SCOPE_SYSTEM,
+				"enabling workaround for");
 	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
 	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
 	mark_const_caps_ready();
-- 
2.14.3

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

* [PATCH 3/4] arm64: capabilities: Allow features based on local CPU scope
  2018-02-09 12:16                 ` Suzuki K Poulose
@ 2018-02-09 12:16                   ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: dave.martin
  Cc: mark.rutland, will.deacon, ard.biesheuvel, marc.zyngier,
	catalin.marinas, linux-arm-kernel, linux-kernel, jnair, ckadabi,
	Suzuki K Poulose

So far we have treated the feature capabilities as system wide
and this doesn't help with features that could be detected on
one or more CPUs (e.g, KPTI, Software prefetch). This patch
splits the feature detection to two phases :

 1) Local CPU features are checked on all boot time active CPUs.
 2) System wide features are checked only once after all CPUs are
    active.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index a6e124063e21..45bac0c4ae91 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -551,11 +551,13 @@ 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.
+	 * Run the errata work around and local feature checks on the
+	 * boot CPU, once we have initialised the cpu feature infrastructure.
 	 */
 	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 				"enabling workaround for");
+	update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
+				"detected feature:");
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1411,15 +1413,18 @@ void check_local_cpu_capabilities(void)
 
 	/*
 	 * If we haven't finalised the system capabilities, this CPU gets
-	 * a chance to update the errata work arounds.
+	 * a chance to update the errata work arounds and local features.
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised)
+	if (!sys_caps_initialised) {
 		update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 					"enabling workaround for");
-	else
+		update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
+					"detected feature:");
+	} else {
 		verify_local_cpu_capabilities();
+	}
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1444,7 +1449,7 @@ void __init setup_cpu_features(void)
 	int cls;
 
 	/* Set the CPU feature capabilies */
-	update_cpu_capabilities(arm64_features, SCOPE_ALL,
+	update_cpu_capabilities(arm64_features, SCOPE_SYSTEM,
 				"detected feature:");
 	update_cpu_capabilities(arm64_errata, SCOPE_SYSTEM,
 				"enabling workaround for");
-- 
2.14.3

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

* [PATCH 3/4] arm64: capabilities: Allow features based on local CPU scope
@ 2018-02-09 12:16                   ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

So far we have treated the feature capabilities as system wide
and this doesn't help with features that could be detected on
one or more CPUs (e.g, KPTI, Software prefetch). This patch
splits the feature detection to two phases :

 1) Local CPU features are checked on all boot time active CPUs.
 2) System wide features are checked only once after all CPUs are
    active.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index a6e124063e21..45bac0c4ae91 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -551,11 +551,13 @@ 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.
+	 * Run the errata work around and local feature checks on the
+	 * boot CPU, once we have initialised the cpu feature infrastructure.
 	 */
 	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 				"enabling workaround for");
+	update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
+				"detected feature:");
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1411,15 +1413,18 @@ void check_local_cpu_capabilities(void)
 
 	/*
 	 * If we haven't finalised the system capabilities, this CPU gets
-	 * a chance to update the errata work arounds.
+	 * a chance to update the errata work arounds and local features.
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised)
+	if (!sys_caps_initialised) {
 		update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
 					"enabling workaround for");
-	else
+		update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
+					"detected feature:");
+	} else {
 		verify_local_cpu_capabilities();
+	}
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1444,7 +1449,7 @@ void __init setup_cpu_features(void)
 	int cls;
 
 	/* Set the CPU feature capabilies */
-	update_cpu_capabilities(arm64_features, SCOPE_ALL,
+	update_cpu_capabilities(arm64_features, SCOPE_SYSTEM,
 				"detected feature:");
 	update_cpu_capabilities(arm64_errata, SCOPE_SYSTEM,
 				"enabling workaround for");
-- 
2.14.3

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

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

Now that the features and errata workarounds have the same
rules and flow, group the handling of the tables.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 72 ++++++++++++++++++++++++------------------
 1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 45bac0c4ae91..e97ec8d5fd89 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,8 +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_capabilities(const struct arm64_cpu_capabilities *caps,
-				    u16 scope_mask, const char *info);
+static void update_cpu_capabilities(u16 scope_mask);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -554,10 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 	 * Run the errata work around and local feature checks on the
 	 * boot CPU, once we have initialised the cpu feature infrastructure.
 	 */
-	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
-				"enabling workaround for");
-	update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
-				"detected feature:");
+	update_cpu_capabilities(SCOPE_LOCAL_CPU);
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1225,7 +1221,7 @@ 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,
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 				    u16 scope_mask, const char *info)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
@@ -1240,6 +1236,14 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+static void update_cpu_capabilities(u16 scope_mask)
+{
+	__update_cpu_capabilities(arm64_features, scope_mask,
+				  "detected feature:");
+	__update_cpu_capabilities(arm64_errata, scope_mask,
+				  "enabling workaround for");
+}
+
 static int __enable_cpu_capability(void *arg)
 {
 	const struct arm64_cpu_capabilities *cap = arg;
@@ -1253,7 +1257,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1277,6 +1281,12 @@ enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mas
 	}
 }
 
+static void __init enable_cpu_capabilities(u16 scope_mask)
+{
+	__enable_cpu_capabilities(arm64_features, scope_mask);
+	__enable_cpu_capabilities(arm64_errata, scope_mask);
+}
+
 /*
  * Run through the list of capabilities to check for conflicts.
  * If the system has already detected a capability, take necessary
@@ -1332,6 +1342,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+static bool verify_local_cpu_caps(u16 scope_mask)
+{
+	return __verify_local_cpu_caps(arm64_errata, scope_mask) &&
+	       __verify_local_cpu_caps(arm64_errata, scope_mask);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1371,7 +1387,6 @@ static void verify_sve_features(void)
 	/* Add checks on other ZCR bits here if necessary */
 }
 
-
 /*
  * 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.
@@ -1382,15 +1397,9 @@ static void verify_sve_features(void)
  */
 static void verify_local_cpu_capabilities(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.
-	 */
-	if (!__verify_local_cpu_caps(arm64_errata, SCOPE_ALL))
-		cpu_die_early();
-	if (!__verify_local_cpu_caps(arm64_features, SCOPE_ALL))
+	if (!verify_local_cpu_caps(SCOPE_ALL))
 		cpu_die_early();
+
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1417,14 +1426,10 @@ void check_local_cpu_capabilities(void)
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised) {
-		update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
-					"enabling workaround for");
-		update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
-					"detected feature:");
-	} else {
+	if (!sys_caps_initialised)
+		update_cpu_capabilities(SCOPE_LOCAL_CPU);
+	else
 		verify_local_cpu_capabilities();
-	}
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1443,18 +1448,23 @@ bool this_cpu_has_cap(unsigned int cap)
 		__this_cpu_has_cap(arm64_errata, cap));
 }
 
+static void __init setup_system_capabilities(void)
+{
+	/*
+	 * We have finalised the system-wide safe feature
+	 * registers, finalise the capabilities that depend
+	 * on it. Also enable all the available capabilities.
+	 */
+	update_cpu_capabilities(SCOPE_SYSTEM);
+	enable_cpu_capabilities(SCOPE_ALL);
+}
+
 void __init setup_cpu_features(void)
 {
 	u32 cwg;
 	int cls;
 
-	/* Set the CPU feature capabilies */
-	update_cpu_capabilities(arm64_features, SCOPE_SYSTEM,
-				"detected feature:");
-	update_cpu_capabilities(arm64_errata, SCOPE_SYSTEM,
-				"enabling workaround for");
-	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
-	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
+	setup_system_capabilities();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

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

Now that the features and errata workarounds have the same
rules and flow, group the handling of the tables.

Cc: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 72 ++++++++++++++++++++++++------------------
 1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 45bac0c4ae91..e97ec8d5fd89 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -504,8 +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_capabilities(const struct arm64_cpu_capabilities *caps,
-				    u16 scope_mask, const char *info);
+static void update_cpu_capabilities(u16 scope_mask);
 
 void __init init_cpu_features(struct cpuinfo_arm64 *info)
 {
@@ -554,10 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 	 * Run the errata work around and local feature checks on the
 	 * boot CPU, once we have initialised the cpu feature infrastructure.
 	 */
-	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
-				"enabling workaround for");
-	update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
-				"detected feature:");
+	update_cpu_capabilities(SCOPE_LOCAL_CPU);
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1225,7 +1221,7 @@ 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,
+static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 				    u16 scope_mask, const char *info)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
@@ -1240,6 +1236,14 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 	}
 }
 
+static void update_cpu_capabilities(u16 scope_mask)
+{
+	__update_cpu_capabilities(arm64_features, scope_mask,
+				  "detected feature:");
+	__update_cpu_capabilities(arm64_errata, scope_mask,
+				  "enabling workaround for");
+}
+
 static int __enable_cpu_capability(void *arg)
 {
 	const struct arm64_cpu_capabilities *cap = arg;
@@ -1253,7 +1257,7 @@ static int __enable_cpu_capability(void *arg)
  * CPUs
  */
 static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
+__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
 {
 	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
 	for (; caps->matches; caps++) {
@@ -1277,6 +1281,12 @@ enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mas
 	}
 }
 
+static void __init enable_cpu_capabilities(u16 scope_mask)
+{
+	__enable_cpu_capabilities(arm64_features, scope_mask);
+	__enable_cpu_capabilities(arm64_errata, scope_mask);
+}
+
 /*
  * Run through the list of capabilities to check for conflicts.
  * If the system has already detected a capability, take necessary
@@ -1332,6 +1342,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
 	return true;
 }
 
+static bool verify_local_cpu_caps(u16 scope_mask)
+{
+	return __verify_local_cpu_caps(arm64_errata, scope_mask) &&
+	       __verify_local_cpu_caps(arm64_errata, scope_mask);
+}
+
 /*
  * Check for CPU features that are used in early boot
  * based on the Boot CPU value.
@@ -1371,7 +1387,6 @@ static void verify_sve_features(void)
 	/* Add checks on other ZCR bits here if necessary */
 }
 
-
 /*
  * 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.
@@ -1382,15 +1397,9 @@ static void verify_sve_features(void)
  */
 static void verify_local_cpu_capabilities(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.
-	 */
-	if (!__verify_local_cpu_caps(arm64_errata, SCOPE_ALL))
-		cpu_die_early();
-	if (!__verify_local_cpu_caps(arm64_features, SCOPE_ALL))
+	if (!verify_local_cpu_caps(SCOPE_ALL))
 		cpu_die_early();
+
 	verify_local_elf_hwcaps(arm64_elf_hwcaps);
 
 	if (system_supports_32bit_el0())
@@ -1417,14 +1426,10 @@ void check_local_cpu_capabilities(void)
 	 * Otherwise, this CPU should verify that it has all the system
 	 * advertised capabilities.
 	 */
-	if (!sys_caps_initialised) {
-		update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
-					"enabling workaround for");
-		update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
-					"detected feature:");
-	} else {
+	if (!sys_caps_initialised)
+		update_cpu_capabilities(SCOPE_LOCAL_CPU);
+	else
 		verify_local_cpu_capabilities();
-	}
 }
 
 DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
@@ -1443,18 +1448,23 @@ bool this_cpu_has_cap(unsigned int cap)
 		__this_cpu_has_cap(arm64_errata, cap));
 }
 
+static void __init setup_system_capabilities(void)
+{
+	/*
+	 * We have finalised the system-wide safe feature
+	 * registers, finalise the capabilities that depend
+	 * on it. Also enable all the available capabilities.
+	 */
+	update_cpu_capabilities(SCOPE_SYSTEM);
+	enable_cpu_capabilities(SCOPE_ALL);
+}
+
 void __init setup_cpu_features(void)
 {
 	u32 cwg;
 	int cls;
 
-	/* Set the CPU feature capabilies */
-	update_cpu_capabilities(arm64_features, SCOPE_SYSTEM,
-				"detected feature:");
-	update_cpu_capabilities(arm64_errata, SCOPE_SYSTEM,
-				"enabling workaround for");
-	enable_cpu_capabilities(arm64_features, SCOPE_ALL);
-	enable_cpu_capabilities(arm64_errata, SCOPE_ALL);
+	setup_system_capabilities();
 	mark_const_caps_ready();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-- 
2.14.3

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

* Re: [PATCH 4/4] arm64: capabilities: Group handling of features and errata workarounds
  2018-02-09 12:16                   ` Suzuki K Poulose
@ 2018-02-09 12:19                     ` Suzuki K Poulose
  -1 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:19 UTC (permalink / raw)
  To: dave.martin
  Cc: mark.rutland, will.deacon, ard.biesheuvel, marc.zyngier,
	catalin.marinas, linux-arm-kernel, linux-kernel, jnair, ckadabi

On 09/02/18 12:16, Suzuki K Poulose wrote:
> Now that the features and errata workarounds have the same
> rules and flow, group the handling of the tables.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>   arch/arm64/kernel/cpufeature.c | 72 ++++++++++++++++++++++++------------------
>   1 file changed, 41 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 45bac0c4ae91..e97ec8d5fd89 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -504,8 +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_capabilities(const struct arm64_cpu_capabilities *caps,
> -				    u16 scope_mask, const char *info);
> +static void update_cpu_capabilities(u16 scope_mask);
>   
>   void __init init_cpu_features(struct cpuinfo_arm64 *info)
>   {
> @@ -554,10 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>   	 * Run the errata work around and local feature checks on the
>   	 * boot CPU, once we have initialised the cpu feature infrastructure.
>   	 */
> -	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
> -				"enabling workaround for");
> -	update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
> -				"detected feature:");
> +	update_cpu_capabilities(SCOPE_LOCAL_CPU);
>   }
>   
>   static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1225,7 +1221,7 @@ 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,
> +static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>   				    u16 scope_mask, const char *info)
>   {
>   	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
> @@ -1240,6 +1236,14 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>   	}
>   }
>   
> +static void update_cpu_capabilities(u16 scope_mask)
> +{
> +	__update_cpu_capabilities(arm64_features, scope_mask,
> +				  "detected feature:");
> +	__update_cpu_capabilities(arm64_errata, scope_mask,
> +				  "enabling workaround for");
> +}
> +
>   static int __enable_cpu_capability(void *arg)
>   {
>   	const struct arm64_cpu_capabilities *cap = arg;
> @@ -1253,7 +1257,7 @@ static int __enable_cpu_capability(void *arg)
>    * CPUs
>    */
>   static void __init
> -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
> +__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
>   {
>   	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>   	for (; caps->matches; caps++) {
> @@ -1277,6 +1281,12 @@ enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mas
>   	}
>   }
>   
> +static void __init enable_cpu_capabilities(u16 scope_mask)
> +{
> +	__enable_cpu_capabilities(arm64_features, scope_mask);
> +	__enable_cpu_capabilities(arm64_errata, scope_mask);
> +}
> +
>   /*
>    * Run through the list of capabilities to check for conflicts.
>    * If the system has already detected a capability, take necessary
> @@ -1332,6 +1342,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>   	return true;
>   }
>   
> +static bool verify_local_cpu_caps(u16 scope_mask)
> +{
> +	return __verify_local_cpu_caps(arm64_errata, scope_mask) &&


> +	       __verify_local_cpu_caps(arm64_errata, scope_mask);

Err.. this is arm64_features. Fixed up locally.

Suzuki

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

* [PATCH 4/4] arm64: capabilities: Group handling of features and errata workarounds
@ 2018-02-09 12:19                     ` Suzuki K Poulose
  0 siblings, 0 replies; 156+ messages in thread
From: Suzuki K Poulose @ 2018-02-09 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/02/18 12:16, Suzuki K Poulose wrote:
> Now that the features and errata workarounds have the same
> rules and flow, group the handling of the tables.
> 
> Cc: Dave Martin <dave.martin@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>   arch/arm64/kernel/cpufeature.c | 72 ++++++++++++++++++++++++------------------
>   1 file changed, 41 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 45bac0c4ae91..e97ec8d5fd89 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -504,8 +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_capabilities(const struct arm64_cpu_capabilities *caps,
> -				    u16 scope_mask, const char *info);
> +static void update_cpu_capabilities(u16 scope_mask);
>   
>   void __init init_cpu_features(struct cpuinfo_arm64 *info)
>   {
> @@ -554,10 +553,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>   	 * Run the errata work around and local feature checks on the
>   	 * boot CPU, once we have initialised the cpu feature infrastructure.
>   	 */
> -	update_cpu_capabilities(arm64_errata, SCOPE_LOCAL_CPU,
> -				"enabling workaround for");
> -	update_cpu_capabilities(arm64_features, SCOPE_LOCAL_CPU,
> -				"detected feature:");
> +	update_cpu_capabilities(SCOPE_LOCAL_CPU);
>   }
>   
>   static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> @@ -1225,7 +1221,7 @@ 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,
> +static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>   				    u16 scope_mask, const char *info)
>   {
>   	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
> @@ -1240,6 +1236,14 @@ static void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
>   	}
>   }
>   
> +static void update_cpu_capabilities(u16 scope_mask)
> +{
> +	__update_cpu_capabilities(arm64_features, scope_mask,
> +				  "detected feature:");
> +	__update_cpu_capabilities(arm64_errata, scope_mask,
> +				  "enabling workaround for");
> +}
> +
>   static int __enable_cpu_capability(void *arg)
>   {
>   	const struct arm64_cpu_capabilities *cap = arg;
> @@ -1253,7 +1257,7 @@ static int __enable_cpu_capability(void *arg)
>    * CPUs
>    */
>   static void __init
> -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
> +__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mask)
>   {
>   	scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
>   	for (; caps->matches; caps++) {
> @@ -1277,6 +1281,12 @@ enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps, u16 scope_mas
>   	}
>   }
>   
> +static void __init enable_cpu_capabilities(u16 scope_mask)
> +{
> +	__enable_cpu_capabilities(arm64_features, scope_mask);
> +	__enable_cpu_capabilities(arm64_errata, scope_mask);
> +}
> +
>   /*
>    * Run through the list of capabilities to check for conflicts.
>    * If the system has already detected a capability, take necessary
> @@ -1332,6 +1342,12 @@ static bool __verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_li
>   	return true;
>   }
>   
> +static bool verify_local_cpu_caps(u16 scope_mask)
> +{
> +	return __verify_local_cpu_caps(arm64_errata, scope_mask) &&


> +	       __verify_local_cpu_caps(arm64_errata, scope_mask);

Err.. this is arm64_features. Fixed up locally.

Suzuki

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

* Re: [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
  2018-02-09 12:16                 ` Suzuki K Poulose
@ 2018-02-09 14:21                   ` Dave Martin
  -1 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-09 14:21 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, Feb 09, 2018 at 12:16:01PM +0000, Suzuki K Poulose wrote:
> >>> I'm not sure we need extra comments or documentation; I just want
> >>> to check that I've understood the patch correctly.
> >>
> >> So, would you prefer this split to the original patch ?
> > 
> > I think splitting out this patch (1/2) makes sense.
> > 
> > 
> > For the second part (2/2) of the split, I still find that hard to
> > review.  The commit message suggests trivially obvious refactoring
> > only, but I think there are three things going on:
> > 
> >   1) moving functions around (with the intention of merging them)
> >   2) merging functions together
> >   3) other miscellaneous bits of refactoring, and cleanups that become
> >      "obvious" after steps (1) and (2).
> > 
> > The refactoring is likely straightfoward, but the resulting diff is
> > not (at least, I struggle to read it).
> > 
> > Could you split the second part along the lines if (1)..(3) above?
> > I think that would make for much easier review.  (Sorry to be a pain!)
> > 
> > Also, the second patch leaves at least one function that does nothing
> > except call a second function that has no other caller.  It may do
> > no harm to remove and inline any such function.  (Falls under (3),
> > I guess.)
> > 
> 
> Here it goes...
> 
> Suzuki K Poulose (4):
>   arm64: capabilities: Prepare for grouping features and errata work
>     arounds
>   arm64: capabilities: Split the processing of errata work arounds
>   arm64: capabilities: Allow features based on local CPU scope
>   arm64: capabilities: Group handling of features and errata workarounds

This is a lot easier to follow now, thanks.

The patches look OK to me, but I'll comment when you repost whole
series in its updated form, so I don't get confused about which
patches are live now...


Cheers
---Dave

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

* [PATCH 1/2] arm64: capabilities: Allow flexibility in scope
@ 2018-02-09 14:21                   ` Dave Martin
  0 siblings, 0 replies; 156+ messages in thread
From: Dave Martin @ 2018-02-09 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 09, 2018 at 12:16:01PM +0000, Suzuki K Poulose wrote:
> >>> I'm not sure we need extra comments or documentation; I just want
> >>> to check that I've understood the patch correctly.
> >>
> >> So, would you prefer this split to the original patch ?
> > 
> > I think splitting out this patch (1/2) makes sense.
> > 
> > 
> > For the second part (2/2) of the split, I still find that hard to
> > review.  The commit message suggests trivially obvious refactoring
> > only, but I think there are three things going on:
> > 
> >   1) moving functions around (with the intention of merging them)
> >   2) merging functions together
> >   3) other miscellaneous bits of refactoring, and cleanups that become
> >      "obvious" after steps (1) and (2).
> > 
> > The refactoring is likely straightfoward, but the resulting diff is
> > not (at least, I struggle to read it).
> > 
> > Could you split the second part along the lines if (1)..(3) above?
> > I think that would make for much easier review.  (Sorry to be a pain!)
> > 
> > Also, the second patch leaves at least one function that does nothing
> > except call a second function that has no other caller.  It may do
> > no harm to remove and inline any such function.  (Falls under (3),
> > I guess.)
> > 
> 
> Here it goes...
> 
> Suzuki K Poulose (4):
>   arm64: capabilities: Prepare for grouping features and errata work
>     arounds
>   arm64: capabilities: Split the processing of errata work arounds
>   arm64: capabilities: Allow features based on local CPU scope
>   arm64: capabilities: Group handling of features and errata workarounds

This is a lot easier to follow now, thanks.

The patches look OK to me, but I'll comment when you repost whole
series in its updated form, so I don't get confused about which
patches are live now...


Cheers
---Dave

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

end of thread, other threads:[~2018-02-09 14:21 UTC | newest]

Thread overview: 156+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-31 18:27 [PATCH v2 00/20] arm64: Rework cpu capabilities handling Suzuki K Poulose
2018-01-31 18:27 ` Suzuki K Poulose
2018-01-31 18:27 ` [PATCH v2 01/20] arm64: capabilities: Update prototype for enable call back Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:37   ` Dave Martin
2018-02-07 10:37     ` Dave Martin
2018-02-07 11:23   ` Robin Murphy
2018-02-07 11:23     ` Robin Murphy
2018-01-31 18:27 ` [PATCH v2 02/20] arm64: capabilities: Move errata work around check on boot CPU Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:37   ` Dave Martin
2018-02-07 10:37     ` Dave Martin
2018-02-07 14:47     ` Suzuki K Poulose
2018-02-07 14:47       ` Suzuki K Poulose
2018-01-31 18:27 ` [PATCH v2 03/20] arm64: capabilities: Move errata processing code Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:37   ` Dave Martin
2018-02-07 10:37     ` Dave Martin
2018-01-31 18:27 ` [PATCH v2 04/20] arm64: capabilities: Prepare for fine grained capabilities Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:37   ` Dave Martin
2018-02-07 10:37     ` Dave Martin
2018-02-07 15:16     ` Suzuki K Poulose
2018-02-07 15:16       ` Suzuki K Poulose
2018-02-07 15:39       ` Dave Martin
2018-02-07 15:39         ` Dave Martin
2018-01-31 18:27 ` [PATCH v2 05/20] arm64: capabilities: Add flags to handle the conflicts on late CPU Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-02-07 11:31     ` Robin Murphy
2018-02-07 11:31       ` Robin Murphy
2018-02-07 16:53       ` Suzuki K Poulose
2018-02-07 16:53         ` Suzuki K Poulose
2018-01-31 18:27 ` [PATCH v2 06/20] arm64: capabilities: Unify the verification Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-02-07 16:56     ` Suzuki K Poulose
2018-02-07 16:56       ` Suzuki K Poulose
2018-01-31 18:27 ` [PATCH v2 07/20] arm64: capabilities: Filter the entries based on a given mask Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-02-07 17:01     ` Suzuki K Poulose
2018-02-07 17:01       ` Suzuki K Poulose
2018-01-31 18:27 ` [PATCH v2 08/20] arm64: capabilities: Group handling of features and errata Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-02-08 12:10     ` Suzuki K Poulose
2018-02-08 12:10       ` Suzuki K Poulose
2018-02-08 12:12       ` [PATCH 1/2] arm64: capabilities: Allow flexibility in scope Suzuki K Poulose
2018-02-08 12:12         ` Suzuki K Poulose
2018-02-08 12:12         ` [PATCH 2/2] arm64: capabilities: Group handling of features and errata workarounds Suzuki K Poulose
2018-02-08 12:12           ` Suzuki K Poulose
2018-02-08 16:10         ` [PATCH 1/2] arm64: capabilities: Allow flexibility in scope Dave Martin
2018-02-08 16:10           ` Dave Martin
2018-02-08 16:31           ` Suzuki K Poulose
2018-02-08 16:31             ` Suzuki K Poulose
2018-02-08 17:32             ` Dave Martin
2018-02-08 17:32               ` Dave Martin
2018-02-09 12:16               ` Suzuki K Poulose
2018-02-09 12:16                 ` Suzuki K Poulose
2018-02-09 12:16                 ` [PATCH 1/4] arm64: capabilities: Prepare for grouping features and errata work arounds Suzuki K Poulose
2018-02-09 12:16                   ` Suzuki K Poulose
2018-02-09 12:16                 ` [PATCH 2/4] arm64: capabilities: Split the processing of " Suzuki K Poulose
2018-02-09 12:16                   ` Suzuki K Poulose
2018-02-09 12:16                 ` [PATCH 3/4] arm64: capabilities: Allow features based on local CPU scope Suzuki K Poulose
2018-02-09 12:16                   ` Suzuki K Poulose
2018-02-09 12:16                 ` [PATCH 4/4] arm64: capabilities: Group handling of features and errata workarounds Suzuki K Poulose
2018-02-09 12:16                   ` Suzuki K Poulose
2018-02-09 12:19                   ` Suzuki K Poulose
2018-02-09 12:19                     ` Suzuki K Poulose
2018-02-09 14:21                 ` [PATCH 1/2] arm64: capabilities: Allow flexibility in scope Dave Martin
2018-02-09 14:21                   ` Dave Martin
2018-01-31 18:27 ` [PATCH v2 09/20] arm64: capabilities: Introduce weak features based on local CPU Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-01-31 18:27 ` [PATCH v2 10/20] arm64: capabilities: Restrict KPTI detection to boot-time CPUs Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-02-07 18:15     ` Suzuki K Poulose
2018-02-07 18:15       ` Suzuki K Poulose
2018-02-08 11:05       ` Dave Martin
2018-02-08 11:05         ` Dave Martin
2018-01-31 18:27 ` [PATCH v2 11/20] arm64: capabilities: Add support for features enabled early Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:38   ` Dave Martin
2018-02-07 10:38     ` Dave Martin
2018-02-07 18:34     ` Suzuki K Poulose
2018-02-07 18:34       ` Suzuki K Poulose
2018-02-08 11:35       ` Dave Martin
2018-02-08 11:35         ` Dave Martin
2018-02-08 11:43         ` Suzuki K Poulose
2018-02-08 11:43           ` Suzuki K Poulose
2018-01-31 18:27 ` [PATCH v2 12/20] arm64: capabilities: Change scope of VHE to Boot CPU feature Suzuki K Poulose
2018-01-31 18:27   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-01-31 18:28 ` [PATCH v2 13/20] arm64: capabilities: Clean up midr range helpers Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-01-31 18:28 ` [PATCH v2 14/20] arm64: Add helpers for checking CPU MIDR against a range Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-01-31 18:28 ` [PATCH v2 15/20] arm64: capabilities: Add support for checks based on a list of MIDRs Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-01-31 18:28 ` [PATCH v2 16/20] arm64: Handle shared capability entries Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-02-08 10:53     ` Suzuki K Poulose
2018-02-08 10:53       ` Suzuki K Poulose
2018-02-08 12:01       ` Dave Martin
2018-02-08 12:01         ` Dave Martin
2018-02-08 12:32         ` Robin Murphy
2018-02-08 12:32           ` Robin Murphy
2018-02-09 10:05           ` Dave Martin
2018-02-09 10:05             ` Dave Martin
2018-02-08 12:04   ` Dave Martin
2018-02-08 12:04     ` Dave Martin
2018-02-08 12:05     ` Suzuki K Poulose
2018-02-08 12:05       ` Suzuki K Poulose
2018-01-31 18:28 ` [PATCH v2 17/20] arm64: bp hardening: Allow late CPUs to enable work around Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-02-08 12:19     ` Suzuki K Poulose
2018-02-08 12:19       ` Suzuki K Poulose
2018-02-08 12:26       ` Marc Zyngier
2018-02-08 12:26         ` Marc Zyngier
2018-02-08 16:58         ` Suzuki K Poulose
2018-02-08 16:58           ` Suzuki K Poulose
2018-02-08 17:59           ` Suzuki K Poulose
2018-02-08 17:59             ` Suzuki K Poulose
2018-02-08 17:59             ` Suzuki K Poulose
2018-02-08 17:59               ` Suzuki K Poulose
2018-01-31 18:28 ` [PATCH v2 18/20] arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35 Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:39   ` Dave Martin
2018-02-07 10:39     ` Dave Martin
2018-01-31 18:28 ` [PATCH v2 19/20] arm64: Delay enabling hardware DBM feature Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:40   ` Dave Martin
2018-02-07 10:40     ` Dave Martin
2018-01-31 18:28 ` [PATCH v2 20/20] arm64: Add work around for Arm Cortex-A55 Erratum 1024718 Suzuki K Poulose
2018-01-31 18:28   ` Suzuki K Poulose
2018-02-07 10:40   ` Dave Martin
2018-02-07 10:40     ` 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.