linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 0/3] Handle SETEND for AArch32 tasks
@ 2015-01-15 12:36 Suzuki K. Poulose
  2015-01-15 12:36 ` [PATCH 1/3] arm64: Track system support for mixed endian EL0 Suzuki K. Poulose
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-15 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: leo.yan, yexl, Will.Deacon, Catalin.Marinas, mark.rutland,
	linux-kernel, Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

This series add support for controlling the 'setend' instruction,
which is deprecated in ARMv8, using the legacy instruction emulation
framework, introduced by Punit Agrawal.


Changes since V1:
 - Added a patch to keep track of the mixed endian support and register
   the setend emulation only if all the active CPUs supports mixed endian.
 - Fail hotplug operation if the CPU doesn't support a feature
   required by insn_emulation.
 - Signal handler runs in native endian

Testing :

 $ cat setend_sig.c 
 #include <stdio.h>
 #include <signal.h>

 #define setend_be(a)	asm __volatile__ ( "setend be" ::: "memory" )
 #define setend_le(a)	asm __volatile__ ( "setend le" ::: "memory" )

 volatile int flag = 1;

 void sigint(int sig)
 {
	printf("in sighandler %d\n", sig);
	flag = 0;
	return;
 }

 main()
 {
	volatile int a = 0x0;

	(void)signal(SIGINT, sigint);
	printf("Press Ctrl+C to continue\n");
	setend_be();
	a ++;

	while (flag);

	setend_le();
	a ++;

	printf("a: 0x%x\n", a);
	return 0;
 }
 $ cat /proc/sys/abi/setend 
 1
 $ echo 1 > /sys/kernel/debug/tracing/events/emulation/instruction_emulation/enable 
 $ echo 1 > /sys/kernel/debug/tracing/tracing_on 
 $ ./setend_sig_a32 
 Press Ctrl+C to continue
 ^Cin sighandler 2
 a: 0x1000001
 $ cat /sys/kernel/debug/tracing/trace
 # tracer: nop
 #
 # entries-in-buffer/entries-written: 2/2   #P:2
 #
 #                              _-----=> irqs-off
 #                             / _----=> need-resched
 #                            | / _---=> hardirq/softirq
 #                            || / _--=> preempt-depth
 #                            ||| /     delay
 #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
 #              | |       |   ||||       |         |
   setend_sig_a32-1373  [000] ...1   491.554499: instruction_emulation: instr="setend be" addr=0x8460
   setend_sig_a32-1373  [000] ...1   492.833056: instruction_emulation: instr="setend le" addr=0x8488
 $ dmesg | tail
 [  491.554807] "setend_sig_a32" (1373) uses deprecated setend instruction at 0x8460
 [  492.833285] "setend_sig_a32" (1373) uses deprecated setend instruction at 0x8488
 $ echo 2 > /proc/sys/abi/setend
 $ ./setend_sig_t16 
 Press Ctrl+C to continue
 ^Cin sighandler 2
 a: 0x1000001
 $ dmesg | tail
 [  491.554807] "setend_sig_a32" (1373) uses deprecated setend instruction at 0x8460
 [  492.833285] "setend_sig_a32" (1373) uses deprecated setend instruction at 0x8488
 [  537.426216] Removed setend emulation handler
 [  537.426624] Enabled setend support

Suzuki K. Poulose (3):
  arm64: Track system support for mixed endian EL0
  arm64: Consolidate hotplug notifier for instruction emulation
  arm64:  Emulate SETEND for AArch32 tasks

 Documentation/arm64/legacy_instructions.txt |   13 ++
 arch/arm64/Kconfig                          |   10 ++
 arch/arm64/include/asm/cpufeature.h         |   13 ++
 arch/arm64/include/asm/ptrace.h             |    7 +
 arch/arm64/kernel/armv8_deprecated.c        |  195 ++++++++++++++++++++-------
 arch/arm64/kernel/cpuinfo.c                 |   22 +++
 arch/arm64/kernel/signal32.c                |    5 +-
 7 files changed, 214 insertions(+), 51 deletions(-)

-- 
1.7.9.5



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

* [PATCH 1/3] arm64: Track system support for mixed endian EL0
  2015-01-15 12:36 [PATCHv2 0/3] Handle SETEND for AArch32 tasks Suzuki K. Poulose
@ 2015-01-15 12:36 ` Suzuki K. Poulose
  2015-01-16 15:53   ` Will Deacon
  2015-01-15 12:36 ` [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation Suzuki K. Poulose
  2015-01-15 12:36 ` [PATCH 3/3] arm64: Emulate SETEND for AArch32 tasks Suzuki K. Poulose
  2 siblings, 1 reply; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-15 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: leo.yan, yexl, Will.Deacon, Catalin.Marinas, mark.rutland,
	linux-kernel, Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

This patch keeps track of the mixed endian EL0 support across
the system and provides helper functions to export it. The status
is a boolean indicating whether all the CPUs on the system supports
mixed endian at EL0.

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

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 07547cc..c7f68d1 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -26,6 +26,9 @@
 
 #define ARM64_NCAPS				2
 
+#define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
+#define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
+
 #ifndef __ASSEMBLY__
 
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
@@ -51,7 +54,14 @@ static inline void cpus_set_cap(unsigned int num)
 		__set_bit(num, cpu_hwcaps);
 }
 
+static inline bool id_aa64mmfr0_mixed_endian_el0(unsigned long mmfr0)
+{
+	return !!(mmfr0 & (ID_AA64MMFR0_EL1_BigEndEL0 | ID_AA64MMFR0_EL1_BigEnd));
+}
+
 void check_local_cpu_errata(void);
+bool system_supports_mixed_endian_el0(void);
+bool cpu_supports_mixed_endian_el0(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 07d435c..b6d1135 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -35,6 +35,7 @@
  */
 DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
 static struct cpuinfo_arm64 boot_cpu_data;
+static bool mixed_endian_el0 = true;
 
 static char *icache_policy_str[] = {
 	[ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
@@ -68,6 +69,26 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
 	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
 }
 
+bool cpu_supports_mixed_endian_el0(void)
+{
+	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
+}
+
+bool system_supports_mixed_endian_el0(void)
+{
+	return mixed_endian_el0;
+}
+
+static void update_mixed_endian_el0_support(struct cpuinfo_arm64 *info)
+{
+	mixed_endian_el0 &= id_aa64mmfr0_mixed_endian_el0(info->reg_id_aa64mmfr0);
+}
+
+static void update_cpu_features(struct cpuinfo_arm64 *info)
+{
+	update_mixed_endian_el0_support(info);
+}
+
 static int check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu)
 {
 	if ((boot & mask) == (cur & mask))
@@ -215,6 +236,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
 	cpuinfo_detect_icache_policy(info);
 
 	check_local_cpu_errata();
+	update_cpu_features(info);
 }
 
 void cpuinfo_store_cpu(void)
-- 
1.7.9.5



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

* [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation
  2015-01-15 12:36 [PATCHv2 0/3] Handle SETEND for AArch32 tasks Suzuki K. Poulose
  2015-01-15 12:36 ` [PATCH 1/3] arm64: Track system support for mixed endian EL0 Suzuki K. Poulose
@ 2015-01-15 12:36 ` Suzuki K. Poulose
  2015-01-16 16:07   ` Will Deacon
  2015-01-15 12:36 ` [PATCH 3/3] arm64: Emulate SETEND for AArch32 tasks Suzuki K. Poulose
  2 siblings, 1 reply; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-15 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: leo.yan, yexl, Will.Deacon, Catalin.Marinas, mark.rutland,
	linux-kernel, Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

As of now each insn_emulation has a cpu hotplug notifier that
enables/disables the CPU feature bit for the functionality. This
patch re-arranges the code, such that there is only one notifier
that runs through the list of registered emulation hooks and runs
their corresponding set_hw_mode.

We do nothing when a CPU is dying as we will set the appropriate bits
as it comes back online based on the state of the hooks.

Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
---
 Documentation/arm64/legacy_instructions.txt |    4 +
 arch/arm64/include/asm/cpufeature.h         |    2 +
 arch/arm64/kernel/armv8_deprecated.c        |  113 +++++++++++++++------------
 3 files changed, 69 insertions(+), 50 deletions(-)

diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
index a3b3da2..0a4dc26 100644
--- a/Documentation/arm64/legacy_instructions.txt
+++ b/Documentation/arm64/legacy_instructions.txt
@@ -27,6 +27,10 @@ behaviours and the corresponding values of the sysctl nodes -
   instructions. Using hardware execution generally provides better
   performance, but at the loss of ability to gather runtime statistics
   about the use of the deprecated instructions.
+  Note: Emulation of a deprecated instruction depends on the availability
+  of the feature on all the active CPUs. In case of CPU hotplug, if a new
+  CPU doesn't support a feature, it could result in the abortion of the
+  hotplug operation.
 
 The default mode depends on the status of the instruction in the
 architecture. Deprecated instructions should default to emulation
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index c7f68d1..a56b45f 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -29,6 +29,8 @@
 #define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
 #define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
 
+#define SCTLR_EL1_CP15BEN 	(1 << 5)
+
 #ifndef __ASSEMBLY__
 
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index c363671..be64218 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -19,6 +19,7 @@
 #include <asm/system_misc.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
+#include <asm/cpufeature.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
@@ -46,7 +47,7 @@ struct insn_emulation_ops {
 	const char		*name;
 	enum legacy_insn_status	status;
 	struct undef_hook	*hooks;
-	int			(*set_hw_mode)(bool enable);
+	int			(*set_hw_mode)(void *enable);
 };
 
 struct insn_emulation {
@@ -85,6 +86,40 @@ static void remove_emulation_hooks(struct insn_emulation_ops *ops)
 	pr_notice("Removed %s emulation handler\n", ops->name);
 }
 
+/* Run set_hw_mode(mode) on all active CPUs */
+static int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable)
+{
+	void (*set_hw_mode)(void *) = (void (*) (void *))insn->ops->set_hw_mode;
+	if (!set_hw_mode)
+		return -EINVAL;
+	on_each_cpu(set_hw_mode, (void *)enable, true);
+	return 0;
+}
+
+/*
+ * Run set_hw_mode for all insns on a starting CPU.
+ * Returns:
+ *  0 		- If all the hooks ran successfully.
+ * -EINVAL	- At least one hook is not supported by the CPU.
+ *		  abort the hotplug.
+ */
+static int run_all_insn_set_hw_mode(void)
+{
+	int rc = 0;
+	unsigned long flags;
+	struct insn_emulation *insn;
+
+	raw_spin_lock_irqsave(&insn_emulation_lock, flags);
+	list_for_each_entry(insn, &insn_emulation, node) {
+		bool hw_mode = (insn->current_mode == INSN_HW);
+		if (insn->ops->set_hw_mode &&
+			insn->ops->set_hw_mode((void*)hw_mode))
+			rc = -EINVAL;
+	}
+	raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
+	return rc;
+}
+
 static int update_insn_emulation_mode(struct insn_emulation *insn,
 				       enum insn_emulation_mode prev)
 {
@@ -97,10 +132,8 @@ static int update_insn_emulation_mode(struct insn_emulation *insn,
 		remove_emulation_hooks(insn->ops);
 		break;
 	case INSN_HW:
-		if (insn->ops->set_hw_mode) {
-			insn->ops->set_hw_mode(false);
+		if (!run_all_cpu_set_hw_mode(insn, false))
 			pr_notice("Disabled %s support\n", insn->ops->name);
-		}
 		break;
 	}
 
@@ -111,10 +144,9 @@ static int update_insn_emulation_mode(struct insn_emulation *insn,
 		register_emulation_hooks(insn->ops);
 		break;
 	case INSN_HW:
-		if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(true))
+		ret = run_all_cpu_set_hw_mode(insn, true);
+		if (!ret)
 			pr_notice("Enabled %s support\n", insn->ops->name);
-		else
-			ret = -EINVAL;
 		break;
 	}
 
@@ -133,6 +165,8 @@ static void register_insn_emulation(struct insn_emulation_ops *ops)
 	switch (ops->status) {
 	case INSN_DEPRECATED:
 		insn->current_mode = INSN_EMULATE;
+		/* Disable the HW mode if it was turned on at early boot time */
+		run_all_cpu_set_hw_mode(insn, false);
 		insn->max = INSN_HW;
 		break;
 	case INSN_OBSOLETE:
@@ -453,8 +487,6 @@ ret:
 	return 0;
 }
 
-#define SCTLR_EL1_CP15BEN (1 << 5)
-
 static inline void config_sctlr_el1(u32 clear, u32 set)
 {
 	u32 val;
@@ -465,48 +497,13 @@ static inline void config_sctlr_el1(u32 clear, u32 set)
 	asm volatile("msr sctlr_el1, %0" : : "r" (val));
 }
 
-static void enable_cp15_ben(void *info)
-{
-	config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
-}
-
-static void disable_cp15_ben(void *info)
+static int cp15_barrier_set_hw_mode(void *enable)
 {
-	config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
-}
-
-static int cpu_hotplug_notify(struct notifier_block *b,
-			      unsigned long action, void *hcpu)
-{
-	switch (action) {
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
-		enable_cp15_ben(NULL);
-		return NOTIFY_DONE;
-	case CPU_DYING:
-	case CPU_DYING_FROZEN:
-		disable_cp15_ben(NULL);
-		return NOTIFY_DONE;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block cpu_hotplug_notifier = {
-	.notifier_call = cpu_hotplug_notify,
-};
-
-static int cp15_barrier_set_hw_mode(bool enable)
-{
-	if (enable) {
-		register_cpu_notifier(&cpu_hotplug_notifier);
-		on_each_cpu(enable_cp15_ben, NULL, true);
-	} else {
-		unregister_cpu_notifier(&cpu_hotplug_notifier);
-		on_each_cpu(disable_cp15_ben, NULL, true);
-	}
-
-	return true;
+	if (enable)
+		config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
+	else
+		config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
+	return 0;
 }
 
 static struct undef_hook cp15_barrier_hooks[] = {
@@ -534,6 +531,21 @@ static struct insn_emulation_ops cp15_barrier_ops = {
 	.set_hw_mode = cp15_barrier_set_hw_mode,
 };
 
+static int insn_cpu_hotplug_notify(struct notifier_block *b,
+			      unsigned long action, void *hcpu)
+{
+	int rc = 0;
+	if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING)
+		rc = run_all_insn_set_hw_mode();
+
+	/* Abort the CPU hotplug if there is an incompatibility */
+	return notifier_from_errno(rc);
+}
+
+static struct notifier_block insn_cpu_hotplug_notifier = {
+	.notifier_call = insn_cpu_hotplug_notify,
+};
+
 /*
  * Invoked as late_initcall, since not needed before init spawned.
  */
@@ -545,6 +557,7 @@ static int __init armv8_deprecated_init(void)
 	if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
 		register_insn_emulation(&cp15_barrier_ops);
 
+	register_cpu_notifier(&insn_cpu_hotplug_notifier);
 	register_insn_emulation_sysctl(ctl_abi);
 
 	return 0;
-- 
1.7.9.5



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

* [PATCH 3/3] arm64:  Emulate SETEND for AArch32 tasks
  2015-01-15 12:36 [PATCHv2 0/3] Handle SETEND for AArch32 tasks Suzuki K. Poulose
  2015-01-15 12:36 ` [PATCH 1/3] arm64: Track system support for mixed endian EL0 Suzuki K. Poulose
  2015-01-15 12:36 ` [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation Suzuki K. Poulose
@ 2015-01-15 12:36 ` Suzuki K. Poulose
  2015-01-16 16:56   ` Mark Rutland
  2 siblings, 1 reply; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-15 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: leo.yan, yexl, Will.Deacon, Catalin.Marinas, mark.rutland,
	linux-kernel, Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

Emulate deprecated 'setend' instruction for AArch32 bit tasks.

	setend [le/be] - Sets the endianness of EL0

On systems with CPUs which support mixed endian at EL0, the hardware
support for the instruction can be enabled by setting the SCTLR_EL1.SED
bit. Like the other emulated instructions it is controlled by an entry in
/proc/sys/abi/. For more information see :
	Documentation/arm64/legacy_instructions.txt

The instruction is emulated by setting/clearing the SPSR_EL1.E bit, which
will be reflected in the PSTATE.E in AArch32 context.

This patch also restores the native endianness for the execution of signal
handlers, since the process could have changed the endianness.

Note: All CPUs on the system should support for mixed endian at EL0. Once the
handler is registered a CPU which doesn't support mixed endian, cannot be
hotplugged in.

Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
---
 Documentation/arm64/legacy_instructions.txt |    9 +++
 arch/arm64/Kconfig                          |   10 ++++
 arch/arm64/include/asm/cpufeature.h         |    1 +
 arch/arm64/include/asm/ptrace.h             |    7 +++
 arch/arm64/kernel/armv8_deprecated.c        |   82 +++++++++++++++++++++++++++
 arch/arm64/kernel/signal32.c                |    5 +-
 6 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
index 0a4dc26..92b7945 100644
--- a/Documentation/arm64/legacy_instructions.txt
+++ b/Documentation/arm64/legacy_instructions.txt
@@ -47,3 +47,12 @@ Default: Undef (0)
 Node: /proc/sys/abi/cp15_barrier
 Status: Deprecated
 Default: Emulate (1)
+
+* SETEND
+Node: /proc/sys/abi/setend
+Status: Deprecated
+Default: Emulate (1)*
+Note: All the cpus on the system should support mixed endian at EL0
+(ID_AA64MMFR0_EL1:BigEnd or BigEndEL0), for this feature to be enabled.
+Once this feature is registered, a CPU that doesn't support the feature
+cannot be hotplugged in.
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b1f9a20..c6d1fd9 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -540,6 +540,16 @@ config CP15_BARRIER_EMULATION
 
 	  If unsure, say Y
 
+config SETEND_EMULATION
+	bool "Emulate SETEND instruction"
+	help
+	  The SETEND instruction alters the data-endianness of the
+	  AArch32 EL0, and is deprecated in ARMv8.
+
+	  Say Y here to enable software emulation of the instruction
+	  for AArch32 userspace code.
+
+	  If unsure, say Y
 endif
 
 endmenu
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a56b45f..760bb20 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -30,6 +30,7 @@
 #define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
 
 #define SCTLR_EL1_CP15BEN 	(1 << 5)
+#define SCTLR_EL1_SED		(1 << 8)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 41ed9e1..d6dd9fd 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -58,6 +58,13 @@
 #define COMPAT_PSR_Z_BIT	0x40000000
 #define COMPAT_PSR_N_BIT	0x80000000
 #define COMPAT_PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define COMPAT_PSR_ENDSTATE	COMPAT_PSR_E_BIT
+#else
+#define COMPAT_PSR_ENDSTATE	0
+#endif
+
 /*
  * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
  * process is located in memory.
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index be64218..204c610 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -531,6 +531,84 @@ static struct insn_emulation_ops cp15_barrier_ops = {
 	.set_hw_mode = cp15_barrier_set_hw_mode,
 };
 
+static int setend_set_hw_mode(void *enable)
+{
+	if (!cpu_supports_mixed_endian_el0()) {
+		pr_warn_ratelimited("Missing mixed endian support at EL0,"
+					" Abort CPU hotplug...\n");
+		return -EINVAL;
+	}
+
+	if (enable)
+		config_sctlr_el1(SCTLR_EL1_SED, 0);
+	else
+		config_sctlr_el1(0, SCTLR_EL1_SED);
+	return 0;
+}
+
+static int compat_setend_handler(struct pt_regs *regs, u32 endian)
+{
+	char insn[16] = "setend _e";
+
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
+
+	if (endian) {
+		/* Big Endian */
+		insn[7] = 'b';
+		regs->pstate |= COMPAT_PSR_E_BIT;
+	} else {
+		/* Little Endian */
+		insn[7] = 'l';
+		regs->pstate &= ~COMPAT_PSR_E_BIT;
+	}
+
+	trace_instruction_emulation(insn, regs->pc);
+	pr_warn_ratelimited("\"%s\" (%ld) uses deprecated setend instruction at 0x%llx\n",
+			current->comm, (unsigned long)current->pid, regs->pc);
+
+	return 0;
+}
+
+static int a32_setend_handler(struct pt_regs *regs, u32 instr)
+{
+	int rc = compat_setend_handler(regs, (instr >> 9) & 1);
+	regs->pc += 4;
+	return rc;
+}
+
+static int t16_setend_handler(struct pt_regs *regs, u32 instr)
+{
+	int rc = compat_setend_handler(regs, (instr >> 3) & 1);
+	regs->pc += 2;
+	return rc;
+}
+
+static struct undef_hook setend_hooks[] = {
+	{
+		.instr_mask	= 0xfffffdff,
+		.instr_val	= 0xf1010000,
+		.pstate_mask	= COMPAT_PSR_MODE_MASK,
+		.pstate_val	= COMPAT_PSR_MODE_USR,
+		.fn		= a32_setend_handler,
+	},
+	{
+		/* Thumb mode */
+		.instr_mask	= 0x0000fff7,
+		.instr_val	= 0x0000b650,
+		.pstate_mask	= (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_MASK),
+		.pstate_val	= (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_USR),
+		.fn		= t16_setend_handler,
+	},
+	{}
+};
+
+static struct insn_emulation_ops setend_ops = {
+	.name = "setend",
+	.status = INSN_DEPRECATED,
+	.hooks = setend_hooks,
+	.set_hw_mode = setend_set_hw_mode,
+};
+
 static int insn_cpu_hotplug_notify(struct notifier_block *b,
 			      unsigned long action, void *hcpu)
 {
@@ -557,6 +635,10 @@ static int __init armv8_deprecated_init(void)
 	if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
 		register_insn_emulation(&cp15_barrier_ops);
 
+	if (IS_ENABLED(CONFIG_SETEND_EMULATION) &&
+			system_supports_mixed_endian_el0())
+		register_insn_emulation(&setend_ops);
+
 	register_cpu_notifier(&insn_cpu_hotplug_notifier);
 	register_insn_emulation_sysctl(ctl_abi);
 
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 5a1ba6e..aa763a5 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -440,7 +440,7 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 {
 	compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler);
 	compat_ulong_t retcode;
-	compat_ulong_t spsr = regs->pstate & ~PSR_f;
+	compat_ulong_t spsr = regs->pstate & ~(PSR_f | COMPAT_PSR_E_BIT);
 	int thumb;
 
 	/* Check if the handler is written for ARM or Thumb */
@@ -454,6 +454,9 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 	/* The IT state must be cleared for both ARM and Thumb-2 */
 	spsr &= ~COMPAT_PSR_IT_MASK;
 
+	/* Restore the original endianness */
+	spsr |= COMPAT_PSR_ENDSTATE;
+
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		retcode = ptr_to_compat(ka->sa.sa_restorer);
 	} else {
-- 
1.7.9.5



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

* Re: [PATCH 1/3] arm64: Track system support for mixed endian EL0
  2015-01-15 12:36 ` [PATCH 1/3] arm64: Track system support for mixed endian EL0 Suzuki K. Poulose
@ 2015-01-16 15:53   ` Will Deacon
  2015-01-16 16:15     ` Suzuki K. Poulose
  0 siblings, 1 reply; 14+ messages in thread
From: Will Deacon @ 2015-01-16 15:53 UTC (permalink / raw)
  To: Suzuki K. Poulose
  Cc: linux-arm-kernel, leo.yan, yexl, Catalin Marinas, Mark Rutland,
	linux-kernel

On Thu, Jan 15, 2015 at 12:36:04PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> 
> This patch keeps track of the mixed endian EL0 support across
> the system and provides helper functions to export it. The status
> is a boolean indicating whether all the CPUs on the system supports
> mixed endian at EL0.
> 
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |   10 ++++++++++
>  arch/arm64/kernel/cpuinfo.c         |   22 ++++++++++++++++++++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 07547cc..c7f68d1 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -26,6 +26,9 @@
>  
>  #define ARM64_NCAPS				2
>  
> +#define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
> +#define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)

I don't like the CaMeLcAsE. Also, perhaps these definitions should be
somewhere like cputype.h?

> +
>  #ifndef __ASSEMBLY__
>  
>  extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
> @@ -51,7 +54,14 @@ static inline void cpus_set_cap(unsigned int num)
>  		__set_bit(num, cpu_hwcaps);
>  }
>  
> +static inline bool id_aa64mmfr0_mixed_endian_el0(unsigned long mmfr0)
> +{
> +	return !!(mmfr0 & (ID_AA64MMFR0_EL1_BigEndEL0 | ID_AA64MMFR0_EL1_BigEnd));
> +}

These are 4-bit fields and I think you think you should be treating them
as such.

> +
>  void check_local_cpu_errata(void);
> +bool system_supports_mixed_endian_el0(void);
> +bool cpu_supports_mixed_endian_el0(void);
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 07d435c..b6d1135 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -35,6 +35,7 @@
>   */
>  DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
>  static struct cpuinfo_arm64 boot_cpu_data;
> +static bool mixed_endian_el0 = true;
>  
>  static char *icache_policy_str[] = {
>  	[ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
> @@ -68,6 +69,26 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
>  	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
>  }
>  
> +bool cpu_supports_mixed_endian_el0(void)
> +{
> +	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
> +}

Can we not just define a mask/value pair and have code do the MMFR0 access
inline? It also feels a bit over-engineered like this.

Will

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

* Re: [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation
  2015-01-15 12:36 ` [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation Suzuki K. Poulose
@ 2015-01-16 16:07   ` Will Deacon
  2015-01-16 16:32     ` Mark Rutland
  2015-01-16 16:47     ` Suzuki K. Poulose
  0 siblings, 2 replies; 14+ messages in thread
From: Will Deacon @ 2015-01-16 16:07 UTC (permalink / raw)
  To: Suzuki K. Poulose
  Cc: linux-arm-kernel, leo.yan, yexl, Catalin Marinas, Mark Rutland,
	linux-kernel

On Thu, Jan 15, 2015 at 12:36:05PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> 
> As of now each insn_emulation has a cpu hotplug notifier that
> enables/disables the CPU feature bit for the functionality. This
> patch re-arranges the code, such that there is only one notifier
> that runs through the list of registered emulation hooks and runs
> their corresponding set_hw_mode.
> 
> We do nothing when a CPU is dying as we will set the appropriate bits
> as it comes back online based on the state of the hooks.
> 
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> ---
>  Documentation/arm64/legacy_instructions.txt |    4 +
>  arch/arm64/include/asm/cpufeature.h         |    2 +
>  arch/arm64/kernel/armv8_deprecated.c        |  113 +++++++++++++++------------
>  3 files changed, 69 insertions(+), 50 deletions(-)
> 
> diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
> index a3b3da2..0a4dc26 100644
> --- a/Documentation/arm64/legacy_instructions.txt
> +++ b/Documentation/arm64/legacy_instructions.txt
> @@ -27,6 +27,10 @@ behaviours and the corresponding values of the sysctl nodes -
>    instructions. Using hardware execution generally provides better
>    performance, but at the loss of ability to gather runtime statistics
>    about the use of the deprecated instructions.
> +  Note: Emulation of a deprecated instruction depends on the availability
> +  of the feature on all the active CPUs. In case of CPU hotplug, if a new
> +  CPU doesn't support a feature, it could result in the abortion of the
> +  hotplug operation.

Is this true? We should be able to *emulate* the instruction anywhere,
it's the "hardware execution" setting that needs CPU support.

>  The default mode depends on the status of the instruction in the
>  architecture. Deprecated instructions should default to emulation
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index c7f68d1..a56b45f 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -29,6 +29,8 @@
>  #define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
>  #define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
>  
> +#define SCTLR_EL1_CP15BEN 	(1 << 5)
> +
>  #ifndef __ASSEMBLY__
>  
>  extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
> diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
> index c363671..be64218 100644
> --- a/arch/arm64/kernel/armv8_deprecated.c
> +++ b/arch/arm64/kernel/armv8_deprecated.c
> @@ -19,6 +19,7 @@
>  #include <asm/system_misc.h>
>  #include <asm/traps.h>
>  #include <asm/uaccess.h>
> +#include <asm/cpufeature.h>
>  
>  #define CREATE_TRACE_POINTS
>  #include "trace-events-emulation.h"
> @@ -46,7 +47,7 @@ struct insn_emulation_ops {
>  	const char		*name;
>  	enum legacy_insn_status	status;
>  	struct undef_hook	*hooks;
> -	int			(*set_hw_mode)(bool enable);
> +	int			(*set_hw_mode)(void *enable);

I think it would be cleaner to have a wrapper for the on_each_cpu
variant of this, otherwise we lose the type information altogether.

>  };
>  
>  struct insn_emulation {
> @@ -85,6 +86,40 @@ static void remove_emulation_hooks(struct insn_emulation_ops *ops)
>  	pr_notice("Removed %s emulation handler\n", ops->name);
>  }
>  
> +/* Run set_hw_mode(mode) on all active CPUs */
> +static int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable)
> +{
> +	void (*set_hw_mode)(void *) = (void (*) (void *))insn->ops->set_hw_mode;
> +	if (!set_hw_mode)
> +		return -EINVAL;
> +	on_each_cpu(set_hw_mode, (void *)enable, true);
> +	return 0;
> +}
> +
> +/*
> + * Run set_hw_mode for all insns on a starting CPU.
> + * Returns:
> + *  0 		- If all the hooks ran successfully.
> + * -EINVAL	- At least one hook is not supported by the CPU.
> + *		  abort the hotplug.
> + */
> +static int run_all_insn_set_hw_mode(void)
> +{
> +	int rc = 0;
> +	unsigned long flags;
> +	struct insn_emulation *insn;
> +
> +	raw_spin_lock_irqsave(&insn_emulation_lock, flags);
> +	list_for_each_entry(insn, &insn_emulation, node) {
> +		bool hw_mode = (insn->current_mode == INSN_HW);
> +		if (insn->ops->set_hw_mode &&
> +			insn->ops->set_hw_mode((void*)hw_mode))
> +			rc = -EINVAL;
> +	}
> +	raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
> +	return rc;
> +}
> +
>  static int update_insn_emulation_mode(struct insn_emulation *insn,
>  				       enum insn_emulation_mode prev)
>  {
> @@ -97,10 +132,8 @@ static int update_insn_emulation_mode(struct insn_emulation *insn,
>  		remove_emulation_hooks(insn->ops);
>  		break;
>  	case INSN_HW:
> -		if (insn->ops->set_hw_mode) {
> -			insn->ops->set_hw_mode(false);
> +		if (!run_all_cpu_set_hw_mode(insn, false))
>  			pr_notice("Disabled %s support\n", insn->ops->name);
> -		}
>  		break;
>  	}
>  
> @@ -111,10 +144,9 @@ static int update_insn_emulation_mode(struct insn_emulation *insn,
>  		register_emulation_hooks(insn->ops);
>  		break;
>  	case INSN_HW:
> -		if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(true))
> +		ret = run_all_cpu_set_hw_mode(insn, true);
> +		if (!ret)
>  			pr_notice("Enabled %s support\n", insn->ops->name);
> -		else
> -			ret = -EINVAL;
>  		break;
>  	}
>  
> @@ -133,6 +165,8 @@ static void register_insn_emulation(struct insn_emulation_ops *ops)
>  	switch (ops->status) {
>  	case INSN_DEPRECATED:
>  		insn->current_mode = INSN_EMULATE;
> +		/* Disable the HW mode if it was turned on at early boot time */
> +		run_all_cpu_set_hw_mode(insn, false);
>  		insn->max = INSN_HW;
>  		break;
>  	case INSN_OBSOLETE:
> @@ -453,8 +487,6 @@ ret:
>  	return 0;
>  }
>  
> -#define SCTLR_EL1_CP15BEN (1 << 5)
> -
>  static inline void config_sctlr_el1(u32 clear, u32 set)
>  {
>  	u32 val;
> @@ -465,48 +497,13 @@ static inline void config_sctlr_el1(u32 clear, u32 set)
>  	asm volatile("msr sctlr_el1, %0" : : "r" (val));
>  }
>  
> -static void enable_cp15_ben(void *info)
> -{
> -	config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
> -}
> -
> -static void disable_cp15_ben(void *info)
> +static int cp15_barrier_set_hw_mode(void *enable)
>  {
> -	config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
> -}
> -
> -static int cpu_hotplug_notify(struct notifier_block *b,
> -			      unsigned long action, void *hcpu)
> -{
> -	switch (action) {
> -	case CPU_STARTING:
> -	case CPU_STARTING_FROZEN:
> -		enable_cp15_ben(NULL);
> -		return NOTIFY_DONE;
> -	case CPU_DYING:
> -	case CPU_DYING_FROZEN:
> -		disable_cp15_ben(NULL);
> -		return NOTIFY_DONE;
> -	}
> -
> -	return NOTIFY_OK;
> -}
> -
> -static struct notifier_block cpu_hotplug_notifier = {
> -	.notifier_call = cpu_hotplug_notify,
> -};
> -
> -static int cp15_barrier_set_hw_mode(bool enable)
> -{
> -	if (enable) {
> -		register_cpu_notifier(&cpu_hotplug_notifier);
> -		on_each_cpu(enable_cp15_ben, NULL, true);
> -	} else {
> -		unregister_cpu_notifier(&cpu_hotplug_notifier);
> -		on_each_cpu(disable_cp15_ben, NULL, true);
> -	}
> -
> -	return true;
> +	if (enable)
> +		config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
> +	else
> +		config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
> +	return 0;
>  }
>  
>  static struct undef_hook cp15_barrier_hooks[] = {
> @@ -534,6 +531,21 @@ static struct insn_emulation_ops cp15_barrier_ops = {
>  	.set_hw_mode = cp15_barrier_set_hw_mode,
>  };
>  
> +static int insn_cpu_hotplug_notify(struct notifier_block *b,
> +			      unsigned long action, void *hcpu)
> +{
> +	int rc = 0;
> +	if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING)
> +		rc = run_all_insn_set_hw_mode();
> +
> +	/* Abort the CPU hotplug if there is an incompatibility */
> +	return notifier_from_errno(rc);

Could we restrict the emulation options instead and just disable hardware
support for the instruction?

Will

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

* Re: [PATCH 1/3] arm64: Track system support for mixed endian EL0
  2015-01-16 15:53   ` Will Deacon
@ 2015-01-16 16:15     ` Suzuki K. Poulose
  2015-01-19  9:41       ` Suzuki K. Poulose
  0 siblings, 1 reply; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-16 16:15 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-arm-kernel, leo.yan, yexl, Catalin Marinas, Mark Rutland,
	linux-kernel

On 16/01/15 15:53, Will Deacon wrote:
> On Thu, Jan 15, 2015 at 12:36:04PM +0000, Suzuki K. Poulose wrote:
>> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>>
>> This patch keeps track of the mixed endian EL0 support across
>> the system and provides helper functions to export it. The status
>> is a boolean indicating whether all the CPUs on the system supports
>> mixed endian at EL0.
>>
>> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |   10 ++++++++++
>>   arch/arm64/kernel/cpuinfo.c         |   22 ++++++++++++++++++++++
>>   2 files changed, 32 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 07547cc..c7f68d1 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -26,6 +26,9 @@
>>
>>   #define ARM64_NCAPS				2
>>
>> +#define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
>> +#define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
>
> I don't like the CaMeLcAsE. Also, perhaps these definitions should be
> somewhere like cputype.h?
Yeah, I tried to keep it aligned withe ARMv8 architecture definition of 
those bits. Will change it.
Things are a bit messy w.r.t the definitions. We have cpu.h, 
cpufeature.h and cputype.h. I could move it to cputype.h, where we 
already have MIDR_ defintions.

>
>> +
>>   #ifndef __ASSEMBLY__
>>
>>   extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
>> @@ -51,7 +54,14 @@ static inline void cpus_set_cap(unsigned int num)
>>   		__set_bit(num, cpu_hwcaps);
>>   }
>>
>> +static inline bool id_aa64mmfr0_mixed_endian_el0(unsigned long mmfr0)
>> +{
>> +	return !!(mmfr0 & (ID_AA64MMFR0_EL1_BigEndEL0 | ID_AA64MMFR0_EL1_BigEnd));
>> +}
>
> These are 4-bit fields and I think you think you should be treating them
> as such.
OK

>
>> +
>>   void check_local_cpu_errata(void);
>> +bool system_supports_mixed_endian_el0(void);
>> +bool cpu_supports_mixed_endian_el0(void);
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
>> index 07d435c..b6d1135 100644
>> --- a/arch/arm64/kernel/cpuinfo.c
>> +++ b/arch/arm64/kernel/cpuinfo.c
>> @@ -35,6 +35,7 @@
>>    */
>>   DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
>>   static struct cpuinfo_arm64 boot_cpu_data;
>> +static bool mixed_endian_el0 = true;
>>
>>   static char *icache_policy_str[] = {
>>   	[ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
>> @@ -68,6 +69,26 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
>>   	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
>>   }
>>
>> +bool cpu_supports_mixed_endian_el0(void)
>> +{
>> +	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
>> +}
>
> Can we not just define a mask/value pair and have code do the MMFR0 access
> inline? It also feels a bit over-engineered like this.
Sure, will change this.

Thanks
Suzuki
>
> Will
>



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

* Re: [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation
  2015-01-16 16:07   ` Will Deacon
@ 2015-01-16 16:32     ` Mark Rutland
  2015-01-16 16:44       ` Will Deacon
  2015-01-16 16:47     ` Suzuki K. Poulose
  1 sibling, 1 reply; 14+ messages in thread
From: Mark Rutland @ 2015-01-16 16:32 UTC (permalink / raw)
  To: Will Deacon
  Cc: Suzuki Poulose, linux-arm-kernel, leo.yan, yexl, Catalin Marinas,
	linux-kernel

On Fri, Jan 16, 2015 at 04:07:30PM +0000, Will Deacon wrote:
> On Thu, Jan 15, 2015 at 12:36:05PM +0000, Suzuki K. Poulose wrote:
> > From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> > 
> > As of now each insn_emulation has a cpu hotplug notifier that
> > enables/disables the CPU feature bit for the functionality. This
> > patch re-arranges the code, such that there is only one notifier
> > that runs through the list of registered emulation hooks and runs
> > their corresponding set_hw_mode.
> > 
> > We do nothing when a CPU is dying as we will set the appropriate bits
> > as it comes back online based on the state of the hooks.
> > 
> > Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > ---
> >  Documentation/arm64/legacy_instructions.txt |    4 +
> >  arch/arm64/include/asm/cpufeature.h         |    2 +
> >  arch/arm64/kernel/armv8_deprecated.c        |  113 +++++++++++++++------------
> >  3 files changed, 69 insertions(+), 50 deletions(-)
> > 
> > diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
> > index a3b3da2..0a4dc26 100644
> > --- a/Documentation/arm64/legacy_instructions.txt
> > +++ b/Documentation/arm64/legacy_instructions.txt
> > @@ -27,6 +27,10 @@ behaviours and the corresponding values of the sysctl nodes -
> >    instructions. Using hardware execution generally provides better
> >    performance, but at the loss of ability to gather runtime statistics
> >    about the use of the deprecated instructions.
> > +  Note: Emulation of a deprecated instruction depends on the availability
> > +  of the feature on all the active CPUs. In case of CPU hotplug, if a new
> > +  CPU doesn't support a feature, it could result in the abortion of the
> > +  hotplug operation.
> 
> Is this true? We should be able to *emulate* the instruction anywhere,
> it's the "hardware execution" setting that needs CPU support.

Not quite. In ARMv8 there are three possible cases for endianness
support:

(a) Mixed endian support at all levels
    ID_AA64MMFR0_EL1.BigEnd == 0b0001
    ID_AA64MMFR0_EL1.BigEnd0 == 0b0000 (RES0, invalid)

(b) Mixed endian support at EL0 only
    ID_AA64MMFR0_EL1.BigEnd == 0b0000
    ID_AA64MMFR0_EL1.BigEnd0 == 0b0001
    SCTLR_EL1.EE has a fixed value

(c) No mixed endian support at all
    ID_AA64MMFR0_EL1.BigEnd == 0b0000
    ID_AA64MMFR0_EL1.BigEnd0 == 0b0000
    SCTLR_EL1.{EE,E0E} have fixed values

We can emulate setend in cases (a) and (b), but not (c) unless we
trapped every single instruction that could access memory. I don't think
that's feasible.

Also fun in case (c) is that the kernel may not be able to run on all
CPUs (consider a BE kernel where some CPUs are fixed to LE at EL1).

I hope no-one builds a system where CPUs are mismatched w.r.t.
endianness support.

Thanks,
Mark.

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

* Re: [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation
  2015-01-16 16:32     ` Mark Rutland
@ 2015-01-16 16:44       ` Will Deacon
  2015-01-16 16:48         ` Mark Rutland
  0 siblings, 1 reply; 14+ messages in thread
From: Will Deacon @ 2015-01-16 16:44 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Suzuki Poulose, linux-arm-kernel, leo.yan, yexl, Catalin Marinas,
	linux-kernel

On Fri, Jan 16, 2015 at 04:32:54PM +0000, Mark Rutland wrote:
> On Fri, Jan 16, 2015 at 04:07:30PM +0000, Will Deacon wrote:
> > On Thu, Jan 15, 2015 at 12:36:05PM +0000, Suzuki K. Poulose wrote:
> > > From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> > > 
> > > As of now each insn_emulation has a cpu hotplug notifier that
> > > enables/disables the CPU feature bit for the functionality. This
> > > patch re-arranges the code, such that there is only one notifier
> > > that runs through the list of registered emulation hooks and runs
> > > their corresponding set_hw_mode.
> > > 
> > > We do nothing when a CPU is dying as we will set the appropriate bits
> > > as it comes back online based on the state of the hooks.
> > > 
> > > Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > ---
> > >  Documentation/arm64/legacy_instructions.txt |    4 +
> > >  arch/arm64/include/asm/cpufeature.h         |    2 +
> > >  arch/arm64/kernel/armv8_deprecated.c        |  113 +++++++++++++++------------
> > >  3 files changed, 69 insertions(+), 50 deletions(-)
> > > 
> > > diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
> > > index a3b3da2..0a4dc26 100644
> > > --- a/Documentation/arm64/legacy_instructions.txt
> > > +++ b/Documentation/arm64/legacy_instructions.txt
> > > @@ -27,6 +27,10 @@ behaviours and the corresponding values of the sysctl nodes -
> > >    instructions. Using hardware execution generally provides better
> > >    performance, but at the loss of ability to gather runtime statistics
> > >    about the use of the deprecated instructions.
> > > +  Note: Emulation of a deprecated instruction depends on the availability
> > > +  of the feature on all the active CPUs. In case of CPU hotplug, if a new
> > > +  CPU doesn't support a feature, it could result in the abortion of the
> > > +  hotplug operation.
> > 
> > Is this true? We should be able to *emulate* the instruction anywhere,
> > it's the "hardware execution" setting that needs CPU support.
> 
> Not quite. In ARMv8 there are three possible cases for endianness
> support:
> 
> (a) Mixed endian support at all levels
>     ID_AA64MMFR0_EL1.BigEnd == 0b0001
>     ID_AA64MMFR0_EL1.BigEnd0 == 0b0000 (RES0, invalid)
> 
> (b) Mixed endian support at EL0 only
>     ID_AA64MMFR0_EL1.BigEnd == 0b0000
>     ID_AA64MMFR0_EL1.BigEnd0 == 0b0001
>     SCTLR_EL1.EE has a fixed value
> 
> (c) No mixed endian support at all
>     ID_AA64MMFR0_EL1.BigEnd == 0b0000
>     ID_AA64MMFR0_EL1.BigEnd0 == 0b0000
>     SCTLR_EL1.{EE,E0E} have fixed values
> 
> We can emulate setend in cases (a) and (b), but not (c) unless we
> trapped every single instruction that could access memory. I don't think
> that's feasible.
> 
> Also fun in case (c) is that the kernel may not be able to run on all
> CPUs (consider a BE kernel where some CPUs are fixed to LE at EL1).
> 
> I hope no-one builds a system where CPUs are mismatched w.r.t.
> endianness support.

Agreed, the problem here is all down to the wording.
Documentation/arm64/legacy_instructions.txt isn't specific to SETEND
emulation and saying "Emulation of a deprecated instruction depends on the
availability of the feature on all the active CPUs." as a blanket statement
doesn't make a lot of sense in isolation. It's certainly not the case for
SWP and CP15 barriers, for example.

With SETEND, we have requirements on mixed-endian support for the emulation.
Fine, but let's not muddy the waters around the general CPU requirements
for deprecated instruction emulation.

Will

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

* Re: [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation
  2015-01-16 16:07   ` Will Deacon
  2015-01-16 16:32     ` Mark Rutland
@ 2015-01-16 16:47     ` Suzuki K. Poulose
  1 sibling, 0 replies; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-16 16:47 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-arm-kernel, leo.yan, yexl, Catalin Marinas, Mark Rutland,
	linux-kernel

On 16/01/15 16:07, Will Deacon wrote:
> On Thu, Jan 15, 2015 at 12:36:05PM +0000, Suzuki K. Poulose wrote:
>> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>>
>> As of now each insn_emulation has a cpu hotplug notifier that
>> enables/disables the CPU feature bit for the functionality. This
>> patch re-arranges the code, such that there is only one notifier
>> that runs through the list of registered emulation hooks and runs
>> their corresponding set_hw_mode.
>>
>> We do nothing when a CPU is dying as we will set the appropriate bits
>> as it comes back online based on the state of the hooks.
>>
>> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
>> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
>> ---
>>   Documentation/arm64/legacy_instructions.txt |    4 +
>>   arch/arm64/include/asm/cpufeature.h         |    2 +
>>   arch/arm64/kernel/armv8_deprecated.c        |  113 +++++++++++++++------------
>>   3 files changed, 69 insertions(+), 50 deletions(-)
>>
>> diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
>> index a3b3da2..0a4dc26 100644
>> --- a/Documentation/arm64/legacy_instructions.txt
>> +++ b/Documentation/arm64/legacy_instructions.txt
>> @@ -27,6 +27,10 @@ behaviours and the corresponding values of the sysctl nodes -
>>     instructions. Using hardware execution generally provides better
>>     performance, but at the loss of ability to gather runtime statistics
>>     about the use of the deprecated instructions.
>> +  Note: Emulation of a deprecated instruction depends on the availability
>> +  of the feature on all the active CPUs. In case of CPU hotplug, if a new
>> +  CPU doesn't support a feature, it could result in the abortion of the
>> +  hotplug operation.
>
> Is this true? We should be able to *emulate* the instruction anywhere,
> it's the "hardware execution" setting that needs CPU support.
Yes. Particularly for SETEND, if the CPU doesn't support mixed endian 
data access at EL0, we shouldn't emulate setend and cause unexpected 
results at EL0. So it is upto the hook to raise a flag if it can emulate 
without the hardware capability.

>
>>   The default mode depends on the status of the instruction in the
>>   architecture. Deprecated instructions should default to emulation
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index c7f68d1..a56b45f 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -29,6 +29,8 @@
>>   #define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
>>   #define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
>>
>> +#define SCTLR_EL1_CP15BEN 	(1 << 5)
>> +
>>   #ifndef __ASSEMBLY__
>>
>>   extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
>> diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
>> index c363671..be64218 100644
>> --- a/arch/arm64/kernel/armv8_deprecated.c
>> +++ b/arch/arm64/kernel/armv8_deprecated.c
>> @@ -19,6 +19,7 @@
>>   #include <asm/system_misc.h>
>>   #include <asm/traps.h>
>>   #include <asm/uaccess.h>
>> +#include <asm/cpufeature.h>
>>
>>   #define CREATE_TRACE_POINTS
>>   #include "trace-events-emulation.h"
>> @@ -46,7 +47,7 @@ struct insn_emulation_ops {
>>   	const char		*name;
>>   	enum legacy_insn_status	status;
>>   	struct undef_hook	*hooks;
>> -	int			(*set_hw_mode)(bool enable);
>> +	int			(*set_hw_mode)(void *enable);
>
> I think it would be cleaner to have a wrapper for the on_each_cpu
> variant of this, otherwise we lose the type information altogether.
>
OK.
>>   };
>>
>>   struct insn_emulation {
>> @@ -85,6 +86,40 @@ static void remove_emulation_hooks(struct insn_emulation_ops *ops)
>>   	pr_notice("Removed %s emulation handler\n", ops->name);
>>   }
>>

>>
>> +static int insn_cpu_hotplug_notify(struct notifier_block *b,
>> +			      unsigned long action, void *hcpu)
>> +{
>> +	int rc = 0;
>> +	if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING)
>> +		rc = run_all_insn_set_hw_mode();
>> +
>> +	/* Abort the CPU hotplug if there is an incompatibility */
>> +	return notifier_from_errno(rc);
>
> Could we restrict the emulation options instead and just disable hardware
> support for the instruction?

As explained earlier, each hook could decide if missing a feature could 
result in an abort.

Thanks
Suzuki



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

* Re: [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation
  2015-01-16 16:44       ` Will Deacon
@ 2015-01-16 16:48         ` Mark Rutland
  0 siblings, 0 replies; 14+ messages in thread
From: Mark Rutland @ 2015-01-16 16:48 UTC (permalink / raw)
  To: Will Deacon
  Cc: Suzuki Poulose, linux-arm-kernel, leo.yan, yexl, Catalin Marinas,
	linux-kernel

On Fri, Jan 16, 2015 at 04:44:34PM +0000, Will Deacon wrote:
> On Fri, Jan 16, 2015 at 04:32:54PM +0000, Mark Rutland wrote:
> > On Fri, Jan 16, 2015 at 04:07:30PM +0000, Will Deacon wrote:
> > > On Thu, Jan 15, 2015 at 12:36:05PM +0000, Suzuki K. Poulose wrote:
> > > > From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> > > > 
> > > > As of now each insn_emulation has a cpu hotplug notifier that
> > > > enables/disables the CPU feature bit for the functionality. This
> > > > patch re-arranges the code, such that there is only one notifier
> > > > that runs through the list of registered emulation hooks and runs
> > > > their corresponding set_hw_mode.
> > > > 
> > > > We do nothing when a CPU is dying as we will set the appropriate bits
> > > > as it comes back online based on the state of the hooks.
> > > > 
> > > > Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > > ---
> > > >  Documentation/arm64/legacy_instructions.txt |    4 +
> > > >  arch/arm64/include/asm/cpufeature.h         |    2 +
> > > >  arch/arm64/kernel/armv8_deprecated.c        |  113 +++++++++++++++------------
> > > >  3 files changed, 69 insertions(+), 50 deletions(-)
> > > > 
> > > > diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
> > > > index a3b3da2..0a4dc26 100644
> > > > --- a/Documentation/arm64/legacy_instructions.txt
> > > > +++ b/Documentation/arm64/legacy_instructions.txt
> > > > @@ -27,6 +27,10 @@ behaviours and the corresponding values of the sysctl nodes -
> > > >    instructions. Using hardware execution generally provides better
> > > >    performance, but at the loss of ability to gather runtime statistics
> > > >    about the use of the deprecated instructions.
> > > > +  Note: Emulation of a deprecated instruction depends on the availability
> > > > +  of the feature on all the active CPUs. In case of CPU hotplug, if a new
> > > > +  CPU doesn't support a feature, it could result in the abortion of the
> > > > +  hotplug operation.
> > > 
> > > Is this true? We should be able to *emulate* the instruction anywhere,
> > > it's the "hardware execution" setting that needs CPU support.
> > 
> > Not quite. In ARMv8 there are three possible cases for endianness
> > support:
> > 
> > (a) Mixed endian support at all levels
> >     ID_AA64MMFR0_EL1.BigEnd == 0b0001
> >     ID_AA64MMFR0_EL1.BigEnd0 == 0b0000 (RES0, invalid)
> > 
> > (b) Mixed endian support at EL0 only
> >     ID_AA64MMFR0_EL1.BigEnd == 0b0000
> >     ID_AA64MMFR0_EL1.BigEnd0 == 0b0001
> >     SCTLR_EL1.EE has a fixed value
> > 
> > (c) No mixed endian support at all
> >     ID_AA64MMFR0_EL1.BigEnd == 0b0000
> >     ID_AA64MMFR0_EL1.BigEnd0 == 0b0000
> >     SCTLR_EL1.{EE,E0E} have fixed values
> > 
> > We can emulate setend in cases (a) and (b), but not (c) unless we
> > trapped every single instruction that could access memory. I don't think
> > that's feasible.
> > 
> > Also fun in case (c) is that the kernel may not be able to run on all
> > CPUs (consider a BE kernel where some CPUs are fixed to LE at EL1).
> > 
> > I hope no-one builds a system where CPUs are mismatched w.r.t.
> > endianness support.
> 
> Agreed, the problem here is all down to the wording.
> Documentation/arm64/legacy_instructions.txt isn't specific to SETEND
> emulation and saying "Emulation of a deprecated instruction depends on the
> availability of the feature on all the active CPUs." as a blanket statement
> doesn't make a lot of sense in isolation. It's certainly not the case for
> SWP and CP15 barriers, for example.
> 
> With SETEND, we have requirements on mixed-endian support for the emulation.
> Fine, but let's not muddy the waters around the general CPU requirements
> for deprecated instruction emulation.

Sure. I was only contending the "We should be able to *emulate* the
instruction anywhere" part of your statement.

We should probably add _a_ note as part of the patch introducing SETEND
emulation, but not the one above, and we can drop it from this patch.

Mark.

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

* Re: [PATCH 3/3] arm64:  Emulate SETEND for AArch32 tasks
  2015-01-15 12:36 ` [PATCH 3/3] arm64: Emulate SETEND for AArch32 tasks Suzuki K. Poulose
@ 2015-01-16 16:56   ` Mark Rutland
  0 siblings, 0 replies; 14+ messages in thread
From: Mark Rutland @ 2015-01-16 16:56 UTC (permalink / raw)
  To: Suzuki K. Poulose
  Cc: linux-arm-kernel, leo.yan, yexl, Will Deacon, Catalin Marinas,
	linux-kernel

On Thu, Jan 15, 2015 at 12:36:06PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> 
> Emulate deprecated 'setend' instruction for AArch32 bit tasks.
> 
> 	setend [le/be] - Sets the endianness of EL0
> 
> On systems with CPUs which support mixed endian at EL0, the hardware
> support for the instruction can be enabled by setting the SCTLR_EL1.SED
> bit. Like the other emulated instructions it is controlled by an entry in
> /proc/sys/abi/. For more information see :
> 	Documentation/arm64/legacy_instructions.txt
> 
> The instruction is emulated by setting/clearing the SPSR_EL1.E bit, which
> will be reflected in the PSTATE.E in AArch32 context.
> 
> This patch also restores the native endianness for the execution of signal
> handlers, since the process could have changed the endianness.
> 
> Note: All CPUs on the system should support for mixed endian at EL0. Once the
> handler is registered a CPU which doesn't support mixed endian, cannot be
> hotplugged in.
> 
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> ---
>  Documentation/arm64/legacy_instructions.txt |    9 +++
>  arch/arm64/Kconfig                          |   10 ++++
>  arch/arm64/include/asm/cpufeature.h         |    1 +
>  arch/arm64/include/asm/ptrace.h             |    7 +++
>  arch/arm64/kernel/armv8_deprecated.c        |   82 +++++++++++++++++++++++++++
>  arch/arm64/kernel/signal32.c                |    5 +-
>  6 files changed, 113 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
> index 0a4dc26..92b7945 100644
> --- a/Documentation/arm64/legacy_instructions.txt
> +++ b/Documentation/arm64/legacy_instructions.txt
> @@ -47,3 +47,12 @@ Default: Undef (0)
>  Node: /proc/sys/abi/cp15_barrier
>  Status: Deprecated
>  Default: Emulate (1)
> +
> +* SETEND
> +Node: /proc/sys/abi/setend
> +Status: Deprecated
> +Default: Emulate (1)*
> +Note: All the cpus on the system should support mixed endian at EL0
> +(ID_AA64MMFR0_EL1:BigEnd or BigEndEL0), for this feature to be enabled.

This might read a little better as:

  Note: all CPUs in the system must have mixed-endian support at EL0 for
  this feature to be enabled.

That matches the ARM ARM wording for ID_AA64MMFR0_EL1. We shouldn't need
to mention the particular register fields here.

Also, we should probably add a note at the top like:

  Note: instruction emulation may not be possible in all cases. See
  below for further information.

Thanks,
Mark.

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

* Re: [PATCH 1/3] arm64: Track system support for mixed endian EL0
  2015-01-16 16:15     ` Suzuki K. Poulose
@ 2015-01-19  9:41       ` Suzuki K. Poulose
  0 siblings, 0 replies; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-19  9:41 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-arm-kernel, leo.yan, yexl, Catalin Marinas, Mark Rutland,
	linux-kernel

On 16/01/15 16:15, Suzuki K. Poulose wrote:
> On 16/01/15 15:53, Will Deacon wrote:
>> On Thu, Jan 15, 2015 at 12:36:04PM +0000, Suzuki K. Poulose wrote:
>>> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>>>
>>> This patch keeps track of the mixed endian EL0 support across
>>> the system and provides helper functions to export it. The status
>>> is a boolean indicating whether all the CPUs on the system supports
>>> mixed endian at EL0.
>>>
>>> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
>>> ---
>>>    arch/arm64/include/asm/cpufeature.h |   10 ++++++++++
>>>    arch/arm64/kernel/cpuinfo.c         |   22 ++++++++++++++++++++++
>>>    2 files changed, 32 insertions(+)
>>>
>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>>> index 07547cc..c7f68d1 100644
>>> --- a/arch/arm64/include/asm/cpufeature.h
>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>> @@ -26,6 +26,9 @@
>>>
>>>    #define ARM64_NCAPS				2
>>>
>>> +#define ID_AA64MMFR0_EL1_BigEndEL0	(0x1UL << 16)
>>> +#define ID_AA64MMFR0_EL1_BigEnd		(0x1UL << 8)
>>
>> I don't like the CaMeLcAsE. Also, perhaps these definitions should be
>> somewhere like cputype.h?
> Yeah, I tried to keep it aligned withe ARMv8 architecture definition of
> those bits. Will change it.
> Things are a bit messy w.r.t the definitions. We have cpu.h,
> cpufeature.h and cputype.h. I could move it to cputype.h, where we
> already have MIDR_ defintions.
>
>>
>>> +
>>>    #ifndef __ASSEMBLY__
>>>
>>>    extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
>>> @@ -51,7 +54,14 @@ static inline void cpus_set_cap(unsigned int num)
>>>    		__set_bit(num, cpu_hwcaps);
>>>    }
>>>
>>> +static inline bool id_aa64mmfr0_mixed_endian_el0(unsigned long mmfr0)
>>> +{
>>> +	return !!(mmfr0 & (ID_AA64MMFR0_EL1_BigEndEL0 | ID_AA64MMFR0_EL1_BigEnd));
>>> +}
>>
>> These are 4-bit fields and I think you think you should be treating them
>> as such.
> OK
>
>>
>>> +
>>>    void check_local_cpu_errata(void);
>>> +bool system_supports_mixed_endian_el0(void);
>>> +bool cpu_supports_mixed_endian_el0(void);
>>>
>>>    #endif /* __ASSEMBLY__ */
>>>
>>> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
>>> index 07d435c..b6d1135 100644
>>> --- a/arch/arm64/kernel/cpuinfo.c
>>> +++ b/arch/arm64/kernel/cpuinfo.c
>>> @@ -35,6 +35,7 @@
>>>     */
>>>    DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
>>>    static struct cpuinfo_arm64 boot_cpu_data;
>>> +static bool mixed_endian_el0 = true;
>>>
>>>    static char *icache_policy_str[] = {
>>>    	[ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
>>> @@ -68,6 +69,26 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
>>>    	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
>>>    }
>>>
>>> +bool cpu_supports_mixed_endian_el0(void)
>>> +{
>>> +	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
>>> +}
>>
>> Can we not just define a mask/value pair and have code do the MMFR0 access
>> inline? It also feels a bit over-engineered like this.
> Sure, will change this.

On a second thought, we need the id_aa64mmfr0_mixed_endian_el0() for 
another code path. For a new CPU detected at boot time via 
cpuinfo_store_cpu(), where we get the 'filled' cpuinfo_arm64 which 
already has the id_aa64mmfr0. So we do:

+
+static void update_mixed_endian_el0_support(struct cpuinfo_arm64 *info)
+{
+	mixed_endian_el0 &= id_aa64mmfr0_mixed_endian_el0(info->reg_id_aa64mmfr0);
+}

So, having a helper to extract the support from the id_aa64mmfr0 makes 
it a bit more ordered.

But yes, we could switch to mask/value pair.

Thanks
Suzuki
>
> Thanks
> Suzuki
>>
>> Will
>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>



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

* [PATCH 1/3] arm64: Track system support for mixed endian EL0
  2015-01-21 12:43 [PATCHv3 0/3] Handle " Suzuki K. Poulose
@ 2015-01-21 12:43 ` Suzuki K. Poulose
  0 siblings, 0 replies; 14+ messages in thread
From: Suzuki K. Poulose @ 2015-01-21 12:43 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: leo.yan, yexl, Will.Deacon, Catalin.Marinas, Mark.Rutland,
	linux-kernel, Suzuki K. Poulose, Will Deacon, Catalin Marinas

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

This patch keeps track of the mixed endian EL0 support across
the system and provides helper functions to export it. The status
is a boolean indicating whether all the CPUs on the system supports
mixed endian at EL0.

Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |    2 ++
 arch/arm64/include/asm/cputype.h    |   14 ++++++++++++++
 arch/arm64/kernel/cpuinfo.c         |   22 ++++++++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 07547cc..b6c16d5 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -52,6 +52,8 @@ static inline void cpus_set_cap(unsigned int num)
 }
 
 void check_local_cpu_errata(void);
+bool cpu_supports_mixed_endian_el0(void);
+bool system_supports_mixed_endian_el0(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 53d59b0..44e578d 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -73,6 +73,15 @@
 
 #define APM_CPU_PART_POTENZA	0x000
 
+#define ID_AA64MMFR0_BIGENDEL0_SHIFT	16
+#define ID_AA64MMFR0_BIGENDEL0_MASK	(0xf << ID_AA64MMFR0_BIGENDEL0_SHIFT)
+#define ID_AA64MMFR0_BIGENDEL0(mmfr0)	\
+	(((mmfr0) & ID_AA64MMFR0_BIGENDEL0_MASK) >> ID_AA64MMFR0_BIGENDEL0_SHIFT)
+#define ID_AA64MMFR0_BIGEND_SHIFT	8
+#define ID_AA64MMFR0_BIGEND_MASK	(0xf << ID_AA64MMFR0_BIGEND_SHIFT)
+#define ID_AA64MMFR0_BIGEND(mmfr0)	\
+	(((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -105,6 +114,11 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void)
 	return read_cpuid(CTR_EL0);
 }
 
+static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
+{
+	return (ID_AA64MMFR0_BIGEND(mmfr0) == 0x1) ||
+		(ID_AA64MMFR0_BIGENDEL0(mmfr0) == 0x1);
+}
 #endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 07d435c..b6d1135 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -35,6 +35,7 @@
  */
 DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
 static struct cpuinfo_arm64 boot_cpu_data;
+static bool mixed_endian_el0 = true;
 
 static char *icache_policy_str[] = {
 	[ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
@@ -68,6 +69,26 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
 	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
 }
 
+bool cpu_supports_mixed_endian_el0(void)
+{
+	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
+}
+
+bool system_supports_mixed_endian_el0(void)
+{
+	return mixed_endian_el0;
+}
+
+static void update_mixed_endian_el0_support(struct cpuinfo_arm64 *info)
+{
+	mixed_endian_el0 &= id_aa64mmfr0_mixed_endian_el0(info->reg_id_aa64mmfr0);
+}
+
+static void update_cpu_features(struct cpuinfo_arm64 *info)
+{
+	update_mixed_endian_el0_support(info);
+}
+
 static int check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu)
 {
 	if ((boot & mask) == (cur & mask))
@@ -215,6 +236,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
 	cpuinfo_detect_icache_policy(info);
 
 	check_local_cpu_errata();
+	update_cpu_features(info);
 }
 
 void cpuinfo_store_cpu(void)
-- 
1.7.9.5



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

end of thread, other threads:[~2015-01-21 12:44 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-15 12:36 [PATCHv2 0/3] Handle SETEND for AArch32 tasks Suzuki K. Poulose
2015-01-15 12:36 ` [PATCH 1/3] arm64: Track system support for mixed endian EL0 Suzuki K. Poulose
2015-01-16 15:53   ` Will Deacon
2015-01-16 16:15     ` Suzuki K. Poulose
2015-01-19  9:41       ` Suzuki K. Poulose
2015-01-15 12:36 ` [PATCH 2/3] arm64: Consolidate hotplug notifier for instruction emulation Suzuki K. Poulose
2015-01-16 16:07   ` Will Deacon
2015-01-16 16:32     ` Mark Rutland
2015-01-16 16:44       ` Will Deacon
2015-01-16 16:48         ` Mark Rutland
2015-01-16 16:47     ` Suzuki K. Poulose
2015-01-15 12:36 ` [PATCH 3/3] arm64: Emulate SETEND for AArch32 tasks Suzuki K. Poulose
2015-01-16 16:56   ` Mark Rutland
2015-01-21 12:43 [PATCHv3 0/3] Handle " Suzuki K. Poulose
2015-01-21 12:43 ` [PATCH 1/3] arm64: Track system support for mixed endian EL0 Suzuki K. Poulose

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).