aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
authorSuzuki K. Poulose <suzuki.poulose@arm.com>2015-01-21 07:43:11 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2015-01-23 12:11:44 -0500
commit2d888f48e056119495847a269a435d5c3d9df349 (patch)
treed63ed442721b6ce1305b46105982554d340a0702 /arch/arm64
parent736d474f0fafd1486f178570bc47660ee9dfdef8 (diff)
arm64: Emulate SETEND for AArch32 tasks
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 must have mixed endian support at EL0. Once the handler is registered, hotplugging a CPU which doesn't support mixed endian, could lead to unexpected results/behavior in applications. Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Punit Agrawal <punit.agrawal@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/Kconfig15
-rw-r--r--arch/arm64/include/asm/cputype.h1
-rw-r--r--arch/arm64/include/asm/ptrace.h7
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c80
-rw-r--r--arch/arm64/kernel/signal32.c5
5 files changed, 107 insertions, 1 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b1f9a20a3677..21a59bf37145 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -540,6 +540,21 @@ config CP15_BARRIER_EMULATION
540 540
541 If unsure, say Y 541 If unsure, say Y
542 542
543config SETEND_EMULATION
544 bool "Emulate SETEND instruction"
545 help
546 The SETEND instruction alters the data-endianness of the
547 AArch32 EL0, and is deprecated in ARMv8.
548
549 Say Y here to enable software emulation of the instruction
550 for AArch32 userspace code.
551
552 Note: All the cpus on the system must have mixed endian support at EL0
553 for this feature to be enabled. If a new CPU - which doesn't support mixed
554 endian - is hotplugged in after this feature has been enabled, there could
555 be unexpected results in the applications.
556
557 If unsure, say Y
543endif 558endif
544 559
545endmenu 560endmenu
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 68732e9a02fb..a84ec605bed8 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -82,6 +82,7 @@
82 (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT) 82 (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT)
83 83
84#define SCTLR_EL1_CP15BEN (0x1 << 5) 84#define SCTLR_EL1_CP15BEN (0x1 << 5)
85#define SCTLR_EL1_SED (0x1 << 8)
85 86
86#ifndef __ASSEMBLY__ 87#ifndef __ASSEMBLY__
87 88
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 41ed9e13795e..d6dd9fdbc3be 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -58,6 +58,13 @@
58#define COMPAT_PSR_Z_BIT 0x40000000 58#define COMPAT_PSR_Z_BIT 0x40000000
59#define COMPAT_PSR_N_BIT 0x80000000 59#define COMPAT_PSR_N_BIT 0x80000000
60#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ 60#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
61
62#ifdef CONFIG_CPU_BIG_ENDIAN
63#define COMPAT_PSR_ENDSTATE COMPAT_PSR_E_BIT
64#else
65#define COMPAT_PSR_ENDSTATE 0
66#endif
67
61/* 68/*
62 * These are 'magic' values for PTRACE_PEEKUSR that return info about where a 69 * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
63 * process is located in memory. 70 * process is located in memory.
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 68b955e1fd99..7922c2e710ca 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -548,6 +548,79 @@ static struct insn_emulation_ops cp15_barrier_ops = {
548 .set_hw_mode = cp15_barrier_set_hw_mode, 548 .set_hw_mode = cp15_barrier_set_hw_mode,
549}; 549};
550 550
551static int setend_set_hw_mode(bool enable)
552{
553 if (!cpu_supports_mixed_endian_el0())
554 return -EINVAL;
555
556 if (enable)
557 config_sctlr_el1(SCTLR_EL1_SED, 0);
558 else
559 config_sctlr_el1(0, SCTLR_EL1_SED);
560 return 0;
561}
562
563static int compat_setend_handler(struct pt_regs *regs, u32 big_endian)
564{
565 char *insn;
566
567 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
568
569 if (big_endian) {
570 insn = "setend be";
571 regs->pstate |= COMPAT_PSR_E_BIT;
572 } else {
573 insn = "setend le";
574 regs->pstate &= ~COMPAT_PSR_E_BIT;
575 }
576
577 trace_instruction_emulation(insn, regs->pc);
578 pr_warn_ratelimited("\"%s\" (%ld) uses deprecated setend instruction at 0x%llx\n",
579 current->comm, (unsigned long)current->pid, regs->pc);
580
581 return 0;
582}
583
584static int a32_setend_handler(struct pt_regs *regs, u32 instr)
585{
586 int rc = compat_setend_handler(regs, (instr >> 9) & 1);
587 regs->pc += 4;
588 return rc;
589}
590
591static int t16_setend_handler(struct pt_regs *regs, u32 instr)
592{
593 int rc = compat_setend_handler(regs, (instr >> 3) & 1);
594 regs->pc += 2;
595 return rc;
596}
597
598static struct undef_hook setend_hooks[] = {
599 {
600 .instr_mask = 0xfffffdff,
601 .instr_val = 0xf1010000,
602 .pstate_mask = COMPAT_PSR_MODE_MASK,
603 .pstate_val = COMPAT_PSR_MODE_USR,
604 .fn = a32_setend_handler,
605 },
606 {
607 /* Thumb mode */
608 .instr_mask = 0x0000fff7,
609 .instr_val = 0x0000b650,
610 .pstate_mask = (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_MASK),
611 .pstate_val = (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_USR),
612 .fn = t16_setend_handler,
613 },
614 {}
615};
616
617static struct insn_emulation_ops setend_ops = {
618 .name = "setend",
619 .status = INSN_DEPRECATED,
620 .hooks = setend_hooks,
621 .set_hw_mode = setend_set_hw_mode,
622};
623
551static int insn_cpu_hotplug_notify(struct notifier_block *b, 624static int insn_cpu_hotplug_notify(struct notifier_block *b,
552 unsigned long action, void *hcpu) 625 unsigned long action, void *hcpu)
553{ 626{
@@ -573,6 +646,13 @@ static int __init armv8_deprecated_init(void)
573 if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION)) 646 if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
574 register_insn_emulation(&cp15_barrier_ops); 647 register_insn_emulation(&cp15_barrier_ops);
575 648
649 if (IS_ENABLED(CONFIG_SETEND_EMULATION)) {
650 if(system_supports_mixed_endian_el0())
651 register_insn_emulation(&setend_ops);
652 else
653 pr_info("setend instruction emulation is not supported on the system");
654 }
655
576 register_cpu_notifier(&insn_cpu_hotplug_notifier); 656 register_cpu_notifier(&insn_cpu_hotplug_notifier);
577 register_insn_emulation_sysctl(ctl_abi); 657 register_insn_emulation_sysctl(ctl_abi);
578 658
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 192d900c058f..e299de396e9b 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,
440{ 440{
441 compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler); 441 compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler);
442 compat_ulong_t retcode; 442 compat_ulong_t retcode;
443 compat_ulong_t spsr = regs->pstate & ~PSR_f; 443 compat_ulong_t spsr = regs->pstate & ~(PSR_f | COMPAT_PSR_E_BIT);
444 int thumb; 444 int thumb;
445 445
446 /* Check if the handler is written for ARM or Thumb */ 446 /* 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,
454 /* The IT state must be cleared for both ARM and Thumb-2 */ 454 /* The IT state must be cleared for both ARM and Thumb-2 */
455 spsr &= ~COMPAT_PSR_IT_MASK; 455 spsr &= ~COMPAT_PSR_IT_MASK;
456 456
457 /* Restore the original endianness */
458 spsr |= COMPAT_PSR_ENDSTATE;
459
457 if (ka->sa.sa_flags & SA_RESTORER) { 460 if (ka->sa.sa_flags & SA_RESTORER) {
458 retcode = ptr_to_compat(ka->sa.sa_restorer); 461 retcode = ptr_to_compat(ka->sa.sa_restorer);
459 } else { 462 } else {