* [PATCH 01/14] Docs: arm64: booting: clarify boot requirements
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 02/14] arm64: big-endian: add big-endian support to top-level arch Makefile Matthew Leach
` (12 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Mark Rutland <mark.rutland@arm.com>
There are a few points in the arm64 booting document which are unclear
(such as the initial state of secondary CPUs), and/or have not been
documented (PSCI is a supported mechanism for booting secondary CPUs).
This patch amends the arm64 boot document to better express the
(existing) requirements, and to describe PSCI as a supported booting
mechanism.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Fu Wei <tekkamanninja@gmail.com>
---
Documentation/arm64/booting.txt | 45 +++++++++++++++++++++++++++------------
1 file changed, 31 insertions(+), 14 deletions(-)
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 98df4a0..a9691cc 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -115,9 +115,10 @@ Before jumping into the kernel, the following conditions must be met:
External caches (if present) must be configured and disabled.
- Architected timers
- CNTFRQ must be programmed with the timer frequency.
- If entering the kernel at EL1, CNTHCTL_EL2 must have EL1PCTEN (bit 0)
- set where available.
+ CNTFRQ must be programmed with the timer frequency and CNTVOFF must
+ be programmed with a consistent value on all CPUs. If entering the
+ kernel at EL1, CNTHCTL_EL2 must have EL1PCTEN (bit 0) set where
+ available.
- Coherency
All CPUs to be booted by the kernel must be part of the same coherency
@@ -130,30 +131,46 @@ Before jumping into the kernel, the following conditions must be met:
the kernel image will be entered must be initialised by software at a
higher exception level to prevent execution in an UNKNOWN state.
+The requirements described above for CPU mode, caches, MMUs, architected
+timers, coherency and system registers apply to all CPUs. All CPUs must
+enter the kernel in the same exception level.
+
The boot loader is expected to enter the kernel on each CPU in the
following manner:
- The primary CPU must jump directly to the first instruction of the
kernel image. The device tree blob passed by this CPU must contain
- for each CPU node:
-
- 1. An 'enable-method' property. Currently, the only supported value
- for this field is the string "spin-table".
-
- 2. A 'cpu-release-addr' property identifying a 64-bit,
- zero-initialised memory location.
+ an 'enable-method' property for each cpu node. The supported
+ enable-methods are described below.
It is expected that the bootloader will generate these device tree
properties and insert them into the blob prior to kernel entry.
-- Any secondary CPUs must spin outside of the kernel in a reserved area
- of memory (communicated to the kernel by a /memreserve/ region in the
+- CPUs with a "spin-table" enable-method must have a 'cpu-release-addr'
+ property in their cpu node. This property identifies a
+ naturally-aligned 64-bit zero-initalised memory location.
+
+ These CPUs should spin outside of the kernel in a reserved area of
+ memory (communicated to the kernel by a /memreserve/ region in the
device tree) polling their cpu-release-addr location, which must be
contained in the reserved region. A wfe instruction may be inserted
to reduce the overhead of the busy-loop and a sev will be issued by
the primary CPU. When a read of the location pointed to by the
- cpu-release-addr returns a non-zero value, the CPU must jump directly
- to this value.
+ cpu-release-addr returns a non-zero value, the CPU must jump to this
+ value. The value will be written as a single 64-bit little-endian
+ value, so CPUs must convert the read value to their native endianness
+ before jumping to it.
+
+- CPUs with a "psci" enable method should remain outside of
+ the kernel (i.e. outside of the regions of memory described to the
+ kernel in the memory node, or in a reserved area of memory described
+ to the kernel by a /memreserve/ region in the device tree). The
+ kernel will issue CPU_ON calls as described in ARM document number ARM
+ DEN 0022A ("Power State Coordination Interface System Software on ARM
+ processors") to bring CPUs into the kernel.
+
+ The device tree should contain a 'psci' node, as described in
+ Documentation/devicetree/bindings/arm/psci.txt.
- Secondary CPU general-purpose register settings
x0 = 0 (reserved for future use)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 02/14] arm64: big-endian: add big-endian support to top-level arch Makefile
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
2013-10-11 13:52 ` [PATCH 01/14] Docs: arm64: booting: clarify boot requirements Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 03/14] arm64: big-endian: fix byteorder include Matthew Leach
` (11 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
This patch adds big-endian support to the AArch64 top-level Makefile.
This currently just passes the relevant flags to the toolchain and is
predicated on a Kconfig option that will be introduced later on.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/Makefile | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index d90cf79..2fceb71 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -20,9 +20,15 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
KBUILD_DEFCONFIG := defconfig
KBUILD_CFLAGS += -mgeneral-regs-only
+ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
+KBUILD_CPPFLAGS += -mbig-endian
+AS += -EB
+LD += -EB
+else
KBUILD_CPPFLAGS += -mlittle-endian
AS += -EL
LD += -EL
+endif
comma = ,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 03/14] arm64: big-endian: fix byteorder include
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
2013-10-11 13:52 ` [PATCH 01/14] Docs: arm64: booting: clarify boot requirements Matthew Leach
2013-10-11 13:52 ` [PATCH 02/14] arm64: big-endian: add big-endian support to top-level arch Makefile Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 04/14] arm64: ELF: add support for big-endian executables Matthew Leach
` (10 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
For big-endian processors, we must include
linux/byteorder/big_endian.h to get the relevant definitions for
swabbing between CPU order and a defined endianness.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/uapi/asm/byteorder.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/include/uapi/asm/byteorder.h b/arch/arm64/include/uapi/asm/byteorder.h
index 2b92046..dc19e95 100644
--- a/arch/arm64/include/uapi/asm/byteorder.h
+++ b/arch/arm64/include/uapi/asm/byteorder.h
@@ -16,6 +16,10 @@
#ifndef __ASM_BYTEORDER_H
#define __ASM_BYTEORDER_H
+#ifdef __AARCH64EB__
+#include <linux/byteorder/big_endian.h>
+#else
#include <linux/byteorder/little_endian.h>
+#endif
#endif /* __ASM_BYTEORDER_H */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 04/14] arm64: ELF: add support for big-endian executables
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (2 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 03/14] arm64: big-endian: fix byteorder include Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 05/14] arm64: setup: report ELF_PLATFORM as the machine for utsname Matthew Leach
` (9 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
This patch adds support for the aarch64_be ELF format to the AArch64 ELF
loader.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/elf.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index e7fa87f..a3e4a55 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -90,11 +90,24 @@ typedef struct user_fpsimd_state elf_fpregset_t;
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS64
+#ifdef __AARCH64EB__
+#define ELF_DATA ELFDATA2MSB
+#else
#define ELF_DATA ELFDATA2LSB
+#endif
#define ELF_ARCH EM_AARCH64
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization. This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
#define ELF_PLATFORM_SIZE 16
+#ifdef __AARCH64EB__
+#define ELF_PLATFORM ("aarch64_be")
+#else
#define ELF_PLATFORM ("aarch64")
+#endif
/*
* This is used to ensure we don't load something for the wrong architecture.
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 05/14] arm64: setup: report ELF_PLATFORM as the machine for utsname
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (3 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 04/14] arm64: ELF: add support for big-endian executables Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 06/14] arm64: compat: add support for big-endian (BE8) AArch32 binaries Matthew Leach
` (8 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
uname -m reports the machine field from the current utsname, which should
reflect the endianness of the system.
This patch reports ELF_PLATFORM for the field, so that everything appears
consistent from userspace.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/kernel/setup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 055cfb8..df9ccb3 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -118,7 +118,7 @@ static void __init setup_processor(void)
printk("CPU: %s [%08x] revision %d\n",
cpu_name, read_cpuid_id(), read_cpuid_id() & 15);
- sprintf(init_utsname()->machine, "aarch64");
+ sprintf(init_utsname()->machine, ELF_PLATFORM);
elf_hwcap = 0;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 06/14] arm64: compat: add support for big-endian (BE8) AArch32 binaries
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (4 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 05/14] arm64: setup: report ELF_PLATFORM as the machine for utsname Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 14:36 ` Mark Rutland
2013-10-11 13:52 ` [PATCH 07/14] arm64: compat: correct register concatenation for syscall wrappers Matthew Leach
` (7 subsequent siblings)
13 siblings, 1 reply; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
This patch adds support for BE8 AArch32 tasks to the compat layer.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/compat.h | 14 ++++++++++++++
arch/arm64/include/asm/elf.h | 5 +++++
arch/arm64/include/asm/processor.h | 5 +++++
arch/arm64/include/asm/ptrace.h | 1 +
4 files changed, 25 insertions(+)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 899af80..93bd6b7 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -26,7 +26,11 @@
#include <linux/ptrace.h>
#define COMPAT_USER_HZ 100
+#ifdef __AARCH64EB__
+#define COMPAT_UTS_MACHINE "armv8b\0\0"
+#else
#define COMPAT_UTS_MACHINE "armv8l\0\0"
+#endif
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
@@ -73,13 +77,23 @@ struct compat_timeval {
};
struct compat_stat {
+#ifdef __AARCH64EB__
+ short st_dev;
+ short __pad1;
+#else
compat_dev_t st_dev;
+#endif
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_ushort_t st_nlink;
__compat_uid16_t st_uid;
__compat_gid16_t st_gid;
+#ifdef __AARCH64EB__
+ short st_rdev;
+ short __pad2;
+#else
compat_dev_t st_rdev;
+#endif
compat_off_t st_size;
compat_off_t st_blksize;
compat_off_t st_blocks;
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index a3e4a55..d42b82f 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -162,7 +162,12 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk
#ifdef CONFIG_COMPAT
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM ("v8b")
+#else
#define COMPAT_ELF_PLATFORM ("v8l")
+#endif
#define COMPAT_ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_32 / 3))
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index ab239b2..4ad8fec 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -107,6 +107,11 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
regs->pstate = COMPAT_PSR_MODE_USR;
if (pc & 1)
regs->pstate |= COMPAT_PSR_T_BIT;
+
+#ifdef __AARCH64EB__
+ regs->pstate |= COMPAT_PSR_E_BIT;
+#endif
+
regs->compat_sp = sp;
}
#endif
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0dacbbf..0e7fa49 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -42,6 +42,7 @@
#define COMPAT_PSR_MODE_UND 0x0000001b
#define COMPAT_PSR_MODE_SYS 0x0000001f
#define COMPAT_PSR_T_BIT 0x00000020
+#define COMPAT_PSR_E_BIT 0x00000200
#define COMPAT_PSR_F_BIT 0x00000040
#define COMPAT_PSR_I_BIT 0x00000080
#define COMPAT_PSR_A_BIT 0x00000100
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 06/14] arm64: compat: add support for big-endian (BE8) AArch32 binaries
2013-10-11 13:52 ` [PATCH 06/14] arm64: compat: add support for big-endian (BE8) AArch32 binaries Matthew Leach
@ 2013-10-11 14:36 ` Mark Rutland
0 siblings, 0 replies; 20+ messages in thread
From: Mark Rutland @ 2013-10-11 14:36 UTC (permalink / raw)
To: linux-arm-kernel
Hi Matt, Will,
On Fri, Oct 11, 2013 at 02:52:12PM +0100, Matthew Leach wrote:
> From: Will Deacon <will.deacon@arm.com>
>
> This patch adds support for BE8 AArch32 tasks to the compat layer.
>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
> arch/arm64/include/asm/compat.h | 14 ++++++++++++++
> arch/arm64/include/asm/elf.h | 5 +++++
> arch/arm64/include/asm/processor.h | 5 +++++
> arch/arm64/include/asm/ptrace.h | 1 +
> 4 files changed, 25 insertions(+)
>
> diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
> index 899af80..93bd6b7 100644
> --- a/arch/arm64/include/asm/compat.h
> +++ b/arch/arm64/include/asm/compat.h
> @@ -26,7 +26,11 @@
> #include <linux/ptrace.h>
>
> #define COMPAT_USER_HZ 100
> +#ifdef __AARCH64EB__
> +#define COMPAT_UTS_MACHINE "armv8b\0\0"
There's space damage here ^
> +#else
> #define COMPAT_UTS_MACHINE "armv8l\0\0"
> +#endif
>
> typedef u32 compat_size_t;
> typedef s32 compat_ssize_t;
> @@ -73,13 +77,23 @@ struct compat_timeval {
> };
>
> struct compat_stat {
> +#ifdef __AARCH64EB__
> + short st_dev;
> + short __pad1;
> +#else
> compat_dev_t st_dev;
> +#endif
I was going to ask why this was different across BE and LE, but I see it
matches arch/arm/include/uapi/asm/stat.h.
> diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> index a3e4a55..d42b82f 100644
> --- a/arch/arm64/include/asm/elf.h
> +++ b/arch/arm64/include/asm/elf.h
> @@ -162,7 +162,12 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
> #define arch_randomize_brk arch_randomize_brk
>
> #ifdef CONFIG_COMPAT
> +
> +#ifdef __AARCH64EB__
> +#define COMPAT_ELF_PLATFORM ("v8b")
Space damage here too ^
> +#else
> #define COMPAT_ELF_PLATFORM ("v8l")
> +#endif
>
> #define COMPAT_ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_32 / 3))
>
> diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
> index ab239b2..4ad8fec 100644
> --- a/arch/arm64/include/asm/processor.h
> +++ b/arch/arm64/include/asm/processor.h
> @@ -107,6 +107,11 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
> regs->pstate = COMPAT_PSR_MODE_USR;
> if (pc & 1)
> regs->pstate |= COMPAT_PSR_T_BIT;
> +
> +#ifdef __AARCH64EB__
> + regs->pstate |= COMPAT_PSR_E_BIT;
^ More space damage.
Cheers,
Mark.
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 07/14] arm64: compat: correct register concatenation for syscall wrappers
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (5 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 06/14] arm64: compat: add support for big-endian (BE8) AArch32 binaries Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 08/14] arm64: big-endian: don't treat code as data when copying sigret code Matthew Leach
` (6 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
The arm64 port contains wrappers for arm32 syscalls that pass 64-bit
values. These wrappers concatenate the two registers to hold a 64-bit
value in a single X register. On BE, however, the lower and higher
words are swapped.
Create a new assembler macro, regs_to_64, that when on BE systems
swaps the registers in the orr instruction.
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
---
arch/arm64/include/asm/assembler.h | 12 ++++++++++++
arch/arm64/kernel/sys32.S | 22 +++++++++++-----------
2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 5aceb83..381b935 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -115,3 +115,15 @@ lr .req x30 // link register
.align 7
b \label
.endm
+/*
+ * Define a macro that constructs a 64-bit value by concatenating two
+ * 32-bit registers. Note that on big endian systems the order of the
+ * registers is swapped.
+ */
+#ifndef CONFIG_CPU_BIG_ENDIAN
+ .macro regs_to_64, rd, lbits, hbits
+#else
+ .macro regs_to_64, rd, hbits, lbits
+#endif
+ orr \rd, \lbits, \hbits, lsl #32
+ .endm
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S
index a1b19ed..423a5b3 100644
--- a/arch/arm64/kernel/sys32.S
+++ b/arch/arm64/kernel/sys32.S
@@ -59,48 +59,48 @@ ENDPROC(compat_sys_fstatfs64_wrapper)
* extension.
*/
compat_sys_pread64_wrapper:
- orr x3, x4, x5, lsl #32
+ regs_to_64 x3, x4, x5
b sys_pread64
ENDPROC(compat_sys_pread64_wrapper)
compat_sys_pwrite64_wrapper:
- orr x3, x4, x5, lsl #32
+ regs_to_64 x3, x4, x5
b sys_pwrite64
ENDPROC(compat_sys_pwrite64_wrapper)
compat_sys_truncate64_wrapper:
- orr x1, x2, x3, lsl #32
+ regs_to_64 x1, x2, x3
b sys_truncate
ENDPROC(compat_sys_truncate64_wrapper)
compat_sys_ftruncate64_wrapper:
- orr x1, x2, x3, lsl #32
+ regs_to_64 x1, x2, x3
b sys_ftruncate
ENDPROC(compat_sys_ftruncate64_wrapper)
compat_sys_readahead_wrapper:
- orr x1, x2, x3, lsl #32
+ regs_to_64 x1, x2, x3
mov w2, w4
b sys_readahead
ENDPROC(compat_sys_readahead_wrapper)
compat_sys_fadvise64_64_wrapper:
mov w6, w1
- orr x1, x2, x3, lsl #32
- orr x2, x4, x5, lsl #32
+ regs_to_64 x1, x2, x3
+ regs_to_64 x2, x4, x5
mov w3, w6
b sys_fadvise64_64
ENDPROC(compat_sys_fadvise64_64_wrapper)
compat_sys_sync_file_range2_wrapper:
- orr x2, x2, x3, lsl #32
- orr x3, x4, x5, lsl #32
+ regs_to_64 x2, x2, x3
+ regs_to_64 x3, x4, x5
b sys_sync_file_range2
ENDPROC(compat_sys_sync_file_range2_wrapper)
compat_sys_fallocate_wrapper:
- orr x2, x2, x3, lsl #32
- orr x3, x4, x5, lsl #32
+ regs_to_64 x2, x2, x3
+ regs_to_64 x3, x4, x5
b sys_fallocate
ENDPROC(compat_sys_fallocate_wrapper)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 08/14] arm64: big-endian: don't treat code as data when copying sigret code
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (6 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 07/14] arm64: compat: correct register concatenation for syscall wrappers Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 09/14] arm64: asm: add CPU_LE & CPU_BE assembler helpers Matthew Leach
` (5 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
Currently the sigreturn compat code is copied to an offset in the
vectors table. When using a BE kernel this data will be stored in the
wrong endianess so when returning from a signal on a 32-bit BE system,
arbitrary code will be executed.
Instead of declaring the code inside a struct and copying that, use
the assembler's .byte directives to store the code in the correct
endianess regardless of platform endianess.
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
---
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/kuser32.S | 42 ++++++++++++++++++++++++++++++++++++++++++
arch/arm64/kernel/signal32.c | 28 ----------------------------
arch/arm64/kernel/vdso.c | 5 ++++-
4 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7b4b564..7d45ad7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -11,7 +11,7 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
sys.o stacktrace.o time.o traps.o io.o vdso.o \
hyp-stub.o psci.o
-arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
+arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
sys_compat.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o smp_psci.o
diff --git a/arch/arm64/kernel/kuser32.S b/arch/arm64/kernel/kuser32.S
index 8b69ecb..1e4905d 100644
--- a/arch/arm64/kernel/kuser32.S
+++ b/arch/arm64/kernel/kuser32.S
@@ -27,6 +27,9 @@
*
* See Documentation/arm/kernel_user_helpers.txt for formal definitions.
*/
+
+#include <asm/unistd32.h>
+
.align 5
.globl __kuser_helper_start
__kuser_helper_start:
@@ -75,3 +78,42 @@ __kuser_helper_version: // 0xffff0ffc
.word ((__kuser_helper_end - __kuser_helper_start) >> 5)
.globl __kuser_helper_end
__kuser_helper_end:
+
+/*
+ * AArch32 sigreturn code
+ *
+ * For ARM syscalls, the syscall number has to be loaded into r7.
+ * We do not support an OABI userspace.
+ *
+ * For Thumb syscalls, we also pass the syscall number via r7. We therefore
+ * need two 16-bit instructions.
+ */
+ .globl __aarch32_sigret_code_start
+__aarch32_sigret_code_start:
+
+ /*
+ * ARM Code
+ */
+ .byte __NR_compat_sigreturn, 0x70, 0xa0, 0xe3 // mov r7, #__NR_compat_sigreturn
+ .byte __NR_compat_sigreturn, 0x00, 0x00, 0xef // svc #__NR_compat_sigreturn
+
+ /*
+ * Thumb code
+ */
+ .byte __NR_compat_sigreturn, 0x27 // svc #__NR_compat_sigreturn
+ .byte __NR_compat_sigreturn, 0xdf // mov r7, #__NR_compat_sigreturn
+
+ /*
+ * ARM code
+ */
+ .byte __NR_compat_rt_sigreturn, 0x70, 0xa0, 0xe3 // mov r7, #__NR_compat_rt_sigreturn
+ .byte __NR_compat_rt_sigreturn, 0x00, 0x00, 0xef // svc #__NR_compat_rt_sigreturn
+
+ /*
+ * Thumb code
+ */
+ .byte __NR_compat_rt_sigreturn, 0x27 // svc #__NR_compat_rt_sigreturn
+ .byte __NR_compat_rt_sigreturn, 0xdf // mov r7, #__NR_compat_rt_sigreturn
+
+ .globl __aarch32_sigret_code_end
+__aarch32_sigret_code_end:
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index e393174..e8772c0 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -100,34 +100,6 @@ struct compat_rt_sigframe {
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-/*
- * For ARM syscalls, the syscall number has to be loaded into r7.
- * We do not support an OABI userspace.
- */
-#define MOV_R7_NR_SIGRETURN (0xe3a07000 | __NR_compat_sigreturn)
-#define SVC_SYS_SIGRETURN (0xef000000 | __NR_compat_sigreturn)
-#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | __NR_compat_rt_sigreturn)
-#define SVC_SYS_RT_SIGRETURN (0xef000000 | __NR_compat_rt_sigreturn)
-
-/*
- * For Thumb syscalls, we also pass the syscall number via r7. We therefore
- * need two 16-bit instructions.
- */
-#define SVC_THUMB_SIGRETURN (((0xdf00 | __NR_compat_sigreturn) << 16) | \
- 0x2700 | __NR_compat_sigreturn)
-#define SVC_THUMB_RT_SIGRETURN (((0xdf00 | __NR_compat_rt_sigreturn) << 16) | \
- 0x2700 | __NR_compat_rt_sigreturn)
-
-const compat_ulong_t aarch32_sigret_code[6] = {
- /*
- * AArch32 sigreturn code.
- * We don't construct an OABI SWI - instead we just set the imm24 field
- * to the EABI syscall number so that we create a sane disassembly.
- */
- MOV_R7_NR_SIGRETURN, SVC_SYS_SIGRETURN, SVC_THUMB_SIGRETURN,
- MOV_R7_NR_RT_SIGRETURN, SVC_SYS_RT_SIGRETURN, SVC_THUMB_RT_SIGRETURN,
-};
-
static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
{
compat_sigset_t cset;
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 6a389dc..65d40cf 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -58,7 +58,10 @@ static struct page *vectors_page[1];
static int alloc_vectors_page(void)
{
extern char __kuser_helper_start[], __kuser_helper_end[];
+ extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[];
+
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+ int sigret_sz = __aarch32_sigret_code_end - __aarch32_sigret_code_start;
unsigned long vpage;
vpage = get_zeroed_page(GFP_ATOMIC);
@@ -72,7 +75,7 @@ static int alloc_vectors_page(void)
/* sigreturn code */
memcpy((void *)vpage + AARCH32_KERN_SIGRET_CODE_OFFSET,
- aarch32_sigret_code, sizeof(aarch32_sigret_code));
+ __aarch32_sigret_code_start, sigret_sz);
flush_icache_range(vpage, vpage + PAGE_SIZE);
vectors_page[0] = virt_to_page(vpage);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 09/14] arm64: asm: add CPU_LE & CPU_BE assembler helpers
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (7 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 08/14] arm64: big-endian: don't treat code as data when copying sigret code Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 10/14] arm64: head: create a new function for setting the boot_cpu_mode flag Matthew Leach
` (4 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
Add CPU_LE and CPU_BE to select assembler code in little and big
endian configurations respectively.
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
---
arch/arm64/include/asm/assembler.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 381b935..fd3e392 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -115,6 +115,25 @@ lr .req x30 // link register
.align 7
b \label
.endm
+
+/*
+ * Select code when configured for BE.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define CPU_BE(code...) code
+#else
+#define CPU_BE(code...)
+#endif
+
+/*
+ * Select code when configured for LE.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define CPU_LE(code...)
+#else
+#define CPU_LE(code...) code
+#endif
+
/*
* Define a macro that constructs a 64-bit value by concatenating two
* 32-bit registers. Note that on big endian systems the order of the
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 10/14] arm64: head: create a new function for setting the boot_cpu_mode flag
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (8 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 09/14] arm64: asm: add CPU_LE & CPU_BE assembler helpers Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry Matthew Leach
` (3 subsequent siblings)
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
Currently, the code for setting the __cpu_boot_mode flag is munged in
with el2_setup. This makes things difficult on a BE bringup as a
memory access has to have occurred before el2_setup which is the place
that we'd like to set the endianess on the current EL.
Create a new function for setting __cpu_boot_mode and have el2_setup
return the mode the CPU. Also define a new constant in virt.h,
BOOT_CPU_MODE_EL1, for readability.
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
---
arch/arm64/include/asm/virt.h | 3 ++-
arch/arm64/kernel/head.S | 34 +++++++++++++++++++++++++---------
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 26e310c..130e2be 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -18,7 +18,8 @@
#ifndef __ASM__VIRT_H
#define __ASM__VIRT_H
-#define BOOT_CPU_MODE_EL2 (0x0e12b007)
+#define BOOT_CPU_MODE_EL1 (0xe11)
+#define BOOT_CPU_MODE_EL2 (0xe12)
#ifndef __ASSEMBLY__
#include <asm/cacheflush.h>
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 7090c12..b3fcdf4 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -123,8 +123,9 @@
ENTRY(stext)
mov x21, x0 // x21=FDT
+ bl el2_setup // Drop to EL1, w20=cpu_boot_mode
bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
- bl el2_setup // Drop to EL1
+ bl set_cpu_boot_mode_flag
mrs x22, midr_el1 // x22=cpuid
mov x0, x22
bl lookup_processor_type
@@ -150,21 +151,20 @@ ENDPROC(stext)
/*
* If we're fortunate enough to boot at EL2, ensure that the world is
* sane before dropping to EL1.
+ *
+ * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x20 if
+ * booted in EL1 or EL2 respectively.
*/
ENTRY(el2_setup)
mrs x0, CurrentEL
cmp x0, #PSR_MODE_EL2t
ccmp x0, #PSR_MODE_EL2h, #0x4, ne
- ldr x0, =__boot_cpu_mode // Compute __boot_cpu_mode
- add x0, x0, x28
b.eq 1f
- str wzr, [x0] // Remember we don't have EL2...
+ mov w20, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1
ret
/* Hyp configuration. */
-1: ldr w1, =BOOT_CPU_MODE_EL2
- str w1, [x0, #4] // This CPU has EL2
- mov x0, #(1 << 31) // 64-bit EL1
+1: mov x0, #(1 << 31) // 64-bit EL1
msr hcr_el2, x0
/* Generic timers. */
@@ -204,10 +204,25 @@ ENTRY(el2_setup)
PSR_MODE_EL1h)
msr spsr_el2, x0
msr elr_el2, lr
+ mov w20, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2
eret
ENDPROC(el2_setup)
/*
+ * Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
+ * in x20. See arch/arm64/include/asm/virt.h for more info.
+ */
+ENTRY(set_cpu_boot_mode_flag)
+ ldr x1, =__boot_cpu_mode // Compute __boot_cpu_mode
+ add x1, x1, x28
+ cmp w20, #BOOT_CPU_MODE_EL2
+ b.ne 1f
+ add x1, x1, #4
+1: str w20, [x1] // This CPU has booted in EL1
+ ret
+ENDPROC(set_cpu_boot_mode_flag)
+
+/*
* We need to find out the CPU boot mode long after boot, so we need to
* store it in a writable variable.
*
@@ -235,8 +250,9 @@ ENTRY(__boot_cpu_mode)
* cores are held until we're ready for them to initialise.
*/
ENTRY(secondary_holding_pen)
- bl __calc_phys_offset // x24=phys offset
- bl el2_setup // Drop to EL1
+ bl el2_setup // Drop to EL1, w20=cpu_boot_mode
+ bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+ bl set_cpu_boot_mode_flag
mrs x0, mpidr_el1
ldr x1, =MPIDR_HWID_BITMASK
and x0, x0, x1
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (9 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 10/14] arm64: head: create a new function for setting the boot_cpu_mode flag Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-15 18:46 ` Christopher Covington
2013-10-24 15:46 ` Catalin Marinas
2013-10-11 13:52 ` [PATCH 12/14] arm64: big-endian: write CPU holding pen address as LE Matthew Leach
` (2 subsequent siblings)
13 siblings, 2 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
The endianness of memory accesses at EL2 and EL1 are configured by
SCTLR_EL2.EE and SCTLR_EL1.EE respectively. When the kernel is booted,
the state of SCTLR_EL{2,1}.EE is unknown, and thus the kernel must
ensure that they are set before performing any memory accesses.
This patch ensures that SCTLR_EL{2,1} are configured appropriately at
boot for kernels of either endianness.
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
---
arch/arm64/kernel/head.S | 17 ++++++++++++++---
arch/arm64/mm/proc.S | 4 ++--
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index b3fcdf4..cd0ecb1 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -159,12 +159,22 @@ ENTRY(el2_setup)
mrs x0, CurrentEL
cmp x0, #PSR_MODE_EL2t
ccmp x0, #PSR_MODE_EL2h, #0x4, ne
- b.eq 1f
+ b.ne 1f
+ mrs x0, sctlr_el2
+CPU_BE( orr x0, x0, #(1 << 25) ) // Set the EE bit for EL2
+CPU_LE( bic x0, x0, #(1 << 25) ) // Clear the EE bit for EL2
+ msr sctlr_el2, x0
+ b 2f
+1: mrs x0, sctlr_el1
+CPU_BE( orr x0, x0, #(2 << 24) ) // Set the EE and E0E bits for EL1
+CPU_LE( bic x0, x0, #(2 << 24) ) // Clear the EE and E0E bits for EL1
+ msr sctlr_el1, x0
mov w20, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1
+ isb
ret
/* Hyp configuration. */
-1: mov x0, #(1 << 31) // 64-bit EL1
+2: mov x0, #(1 << 31) // 64-bit EL1
msr hcr_el2, x0
/* Generic timers. */
@@ -181,7 +191,8 @@ ENTRY(el2_setup)
/* sctlr_el1 */
mov x0, #0x0800 // Set/clear RES{1,0} bits
- movk x0, #0x30d0, lsl #16
+CPU_BE( movk x0, #0x33d0, lsl #16 ) // Set EE and E0E on BE systems
+CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems
msr sctlr_el1, x0
/* Coprocessor traps. */
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index b1b31bb..421b99f 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -162,9 +162,9 @@ ENDPROC(__cpu_setup)
* CE0 XWHW CZ ME TEEA S
* .... .IEE .... NEAI TE.I ..AD DEN0 ACAM
* 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved
- * .... .100 .... 01.1 11.1 ..01 0001 1101 < software settings
+ * .... .1.. .... 01.1 11.1 ..01 0001 1101 < software settings
*/
.type crval, #object
crval:
- .word 0x030802e2 // clear
+ .word 0x000802e2 // clear
.word 0x0405d11d // set
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry
2013-10-11 13:52 ` [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry Matthew Leach
@ 2013-10-15 18:46 ` Christopher Covington
2013-10-24 15:46 ` Catalin Marinas
1 sibling, 0 replies; 20+ messages in thread
From: Christopher Covington @ 2013-10-15 18:46 UTC (permalink / raw)
To: linux-arm-kernel
Hi Matthew,
On 10/11/2013 09:52 AM, Matthew Leach wrote:
> The endianness of memory accesses at EL2 and EL1 are configured by
> SCTLR_EL2.EE and SCTLR_EL1.EE respectively. When the kernel is booted,
> the state of SCTLR_EL{2,1}.EE is unknown, and thus the kernel must
> ensure that they are set before performing any memory accesses.
>
> This patch ensures that SCTLR_EL{2,1} are configured appropriately at
> boot for kernels of either endianness.
[...]
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -159,12 +159,22 @@ ENTRY(el2_setup)
> mrs x0, CurrentEL
> cmp x0, #PSR_MODE_EL2t
> ccmp x0, #PSR_MODE_EL2h, #0x4, ne
> - b.eq 1f
> + b.ne 1f
> + mrs x0, sctlr_el2
> +CPU_BE( orr x0, x0, #(1 << 25) ) // Set the EE bit for EL2
> +CPU_LE( bic x0, x0, #(1 << 25) ) // Clear the EE bit for EL2
> + msr sctlr_el2, x0
> + b 2f
> +1: mrs x0, sctlr_el1
> +CPU_BE( orr x0, x0, #(2 << 24) ) // Set the EE and E0E bits for EL1
> +CPU_LE( bic x0, x0, #(2 << 24) ) // Clear the EE and E0E bits for EL1
> + msr sctlr_el1, x0
> mov w20, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1
> + isb
Could you please comment on why this barrier is necessary?
> ret
>
> /* Hyp configuration. */
> -1: mov x0, #(1 << 31) // 64-bit EL1
> +2: mov x0, #(1 << 31) // 64-bit EL1
> msr hcr_el2, x0
>
> /* Generic timers. */
> @@ -181,7 +191,8 @@ ENTRY(el2_setup)
>
> /* sctlr_el1 */
> mov x0, #0x0800 // Set/clear RES{1,0} bits
> - movk x0, #0x30d0, lsl #16
> +CPU_BE( movk x0, #0x33d0, lsl #16 ) // Set EE and E0E on BE systems
> +CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems
Although the CPU_[BL]E macros make the ifdef'ery here and above prettier than
they would be otherwise, I wonder if making the set and clear operations and
this magic number macros instead could improve readability and fall more in
line with the "#ifdefs are ugly" guideline in Documentation/SubmittingPatches.
> msr sctlr_el1, x0
>
> /* Coprocessor traps. */
[...]
Thanks,
Christopher
--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by the Linux Foundation.
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry
2013-10-11 13:52 ` [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry Matthew Leach
2013-10-15 18:46 ` Christopher Covington
@ 2013-10-24 15:46 ` Catalin Marinas
1 sibling, 0 replies; 20+ messages in thread
From: Catalin Marinas @ 2013-10-24 15:46 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-10-11 at 14:52 +0100, Matthew Leach wrote:
> The endianness of memory accesses at EL2 and EL1 are configured by
> SCTLR_EL2.EE and SCTLR_EL1.EE respectively. When the kernel is booted,
> the state of SCTLR_EL{2,1}.EE is unknown, and thus the kernel must
> ensure that they are set before performing any memory accesses.
>
> This patch ensures that SCTLR_EL{2,1} are configured appropriately at
> boot for kernels of either endianness.
>
> Acked-by: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Matthew Leach <matthew.leach@arm.com>
> ---
> arch/arm64/kernel/head.S | 17 ++++++++++++++---
> arch/arm64/mm/proc.S | 4 ++--
> 2 files changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index b3fcdf4..cd0ecb1 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -159,12 +159,22 @@ ENTRY(el2_setup)
> mrs x0, CurrentEL
> cmp x0, #PSR_MODE_EL2t
> ccmp x0, #PSR_MODE_EL2h, #0x4, ne
> - b.eq 1f
> + b.ne 1f
> + mrs x0, sctlr_el2
> +CPU_BE( orr x0, x0, #(1 << 25) ) // Set the EE bit for EL2
> +CPU_LE( bic x0, x0, #(1 << 25) ) // Clear the EE bit for EL2
> + msr sctlr_el2, x0
> + b 2f
> +1: mrs x0, sctlr_el1
> +CPU_BE( orr x0, x0, #(2 << 24) ) // Set the EE and E0E bits for EL1
> +CPU_LE( bic x0, x0, #(2 << 24) ) // Clear the EE and E0E bits for EL1
Shouldn't this be (3 << 24)?
--
Catalin
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 12/14] arm64: big-endian: write CPU holding pen address as LE
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (10 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 11/14] arm64: big-endian: set correct endianess on kernel entry Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 13/14] arm64: kconfig: allow CPU_BIG_ENDIAN to be selected Matthew Leach
2013-10-11 13:52 ` [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data Matthew Leach
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
Currently when CPUs are brought online via a spin-table, the address
they should jump to is written to the cpu-release-addr in the kernel's
native endianness. As the kernel may switch endianness, secondaries
might read the value byte-reversed from what was intended, and they
would jump to the wrong address.
As the only current arm64 spin-table implementations are
little-endian, stricten up the arm64 spin-table definition such that
the value written to cpu-release-addr is _always_ little-endian
regardless of the endianness of any CPU. If a spinning CPU is
operating big-endian, it must byte-reverse the value before jumping to
handle this.
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
---
arch/arm64/kernel/smp_spin_table.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 7c35fa6..c0bc097 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -48,7 +48,16 @@ static int __init smp_spin_table_prepare_cpu(int cpu)
return -ENODEV;
release_addr = __va(cpu_release_addr[cpu]);
- release_addr[0] = (void *)__pa(secondary_holding_pen);
+
+ /*
+ * We write the release address as LE regardless of the native
+ * endianess of the kernel. Therefore, any boot-loaders that
+ * read this address need to convert this address to the
+ * boot-loader's endianess before jumping. This is mandated by
+ * the boot protocol.
+ */
+ release_addr[0] = (void *) cpu_to_le64(__pa(secondary_holding_pen));
+
__flush_dcache_area(release_addr, sizeof(release_addr[0]));
/*
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 13/14] arm64: kconfig: allow CPU_BIG_ENDIAN to be selected
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (11 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 12/14] arm64: big-endian: write CPU holding pen address as LE Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 13:52 ` [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data Matthew Leach
13 siblings, 0 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
This patch wires up CONFIG_CPU_BIG_ENDIAN for the AArch64 kernel
configuration.
Selecting this option builds a big-endian kernel which can boot into a
big-endian userspace.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/Kconfig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c044548..95d6cb9 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -138,6 +138,11 @@ config ARM64_64K_PAGES
look-up. AArch32 emulation is not available when this feature
is enabled.
+config CPU_BIG_ENDIAN
+ bool "Build big-endian kernel"
+ help
+ Say Y if you plan on running a kernel in big-endian mode.
+
config SMP
bool "Symmetric Multi-Processing"
select USE_GENERIC_SMP_HELPERS
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data
2013-10-11 13:52 [PATCH 00/14] AArch64 BE Support Matthew Leach
` (12 preceding siblings ...)
2013-10-11 13:52 ` [PATCH 13/14] arm64: kconfig: allow CPU_BIG_ENDIAN to be selected Matthew Leach
@ 2013-10-11 13:52 ` Matthew Leach
2013-10-11 20:41 ` Nicolas Pitre
2013-10-11 21:56 ` David Miller
13 siblings, 2 replies; 20+ messages in thread
From: Matthew Leach @ 2013-10-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Will Deacon <will.deacon@arm.com>
SMC_outw invokes an endian-aware I/O accessor, which may change the data
endianness before writing to the device. This is not suitable for data
transfers where the memory buffer is simply a string of bytes that does
not require any byte-swapping.
This patches fixes the smc91x SMC_PUSH_DATA macro so that it uses the
string I/O accessor for outputting the leading or trailing halfwords on
halfword-aligned buffers.
Cc: <netdev@vger.kernel.org>
Cc: Nicolas Pitre <nico@fluxnic.net>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/net/ethernet/smsc/smc91x.h | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 5730fe2..98eedb9 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -1124,8 +1124,7 @@ static const char * chip_ids[ 16 ] = {
void __iomem *__ioaddr = ioaddr; \
if (__len >= 2 && (unsigned long)__ptr & 2) { \
__len -= 2; \
- SMC_outw(*(u16 *)__ptr, ioaddr, \
- DATA_REG(lp)); \
+ SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
__ptr += 2; \
} \
if (SMC_CAN_USE_DATACS && lp->datacs) \
@@ -1133,8 +1132,7 @@ static const char * chip_ids[ 16 ] = {
SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
if (__len & 2) { \
__ptr += (__len & ~3); \
- SMC_outw(*((u16 *)__ptr), ioaddr, \
- DATA_REG(lp)); \
+ SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
} \
} else if (SMC_16BIT(lp)) \
SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1); \
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data
2013-10-11 13:52 ` [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data Matthew Leach
@ 2013-10-11 20:41 ` Nicolas Pitre
2013-10-11 21:56 ` David Miller
1 sibling, 0 replies; 20+ messages in thread
From: Nicolas Pitre @ 2013-10-11 20:41 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 11 Oct 2013, Matthew Leach wrote:
> From: Will Deacon <will.deacon@arm.com>
>
> SMC_outw invokes an endian-aware I/O accessor, which may change the data
> endianness before writing to the device. This is not suitable for data
> transfers where the memory buffer is simply a string of bytes that does
> not require any byte-swapping.
>
> This patches fixes the smc91x SMC_PUSH_DATA macro so that it uses the
> string I/O accessor for outputting the leading or trailing halfwords on
> halfword-aligned buffers.
Acked-by: Nicolas Pitre <nico@linaro.org>
>
> Cc: <netdev@vger.kernel.org>
> Cc: Nicolas Pitre <nico@fluxnic.net>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
> drivers/net/ethernet/smsc/smc91x.h | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
> index 5730fe2..98eedb9 100644
> --- a/drivers/net/ethernet/smsc/smc91x.h
> +++ b/drivers/net/ethernet/smsc/smc91x.h
> @@ -1124,8 +1124,7 @@ static const char * chip_ids[ 16 ] = {
> void __iomem *__ioaddr = ioaddr; \
> if (__len >= 2 && (unsigned long)__ptr & 2) { \
> __len -= 2; \
> - SMC_outw(*(u16 *)__ptr, ioaddr, \
> - DATA_REG(lp)); \
> + SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
> __ptr += 2; \
> } \
> if (SMC_CAN_USE_DATACS && lp->datacs) \
> @@ -1133,8 +1132,7 @@ static const char * chip_ids[ 16 ] = {
> SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
> if (__len & 2) { \
> __ptr += (__len & ~3); \
> - SMC_outw(*((u16 *)__ptr), ioaddr, \
> - DATA_REG(lp)); \
> + SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
> } \
> } else if (SMC_16BIT(lp)) \
> SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1); \
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data
2013-10-11 13:52 ` [PATCH 14/14] net: smc91x: dont't use SMC_outw for fixing up halfword-aligned data Matthew Leach
2013-10-11 20:41 ` Nicolas Pitre
@ 2013-10-11 21:56 ` David Miller
1 sibling, 0 replies; 20+ messages in thread
From: David Miller @ 2013-10-11 21:56 UTC (permalink / raw)
To: linux-arm-kernel
From: Matthew Leach <matthew.leach@arm.com>
Date: Fri, 11 Oct 2013 14:52:20 +0100
> From: Will Deacon <will.deacon@arm.com>
>
> SMC_outw invokes an endian-aware I/O accessor, which may change the data
> endianness before writing to the device. This is not suitable for data
> transfers where the memory buffer is simply a string of bytes that does
> not require any byte-swapping.
>
> This patches fixes the smc91x SMC_PUSH_DATA macro so that it uses the
> string I/O accessor for outputting the leading or trailing halfwords on
> halfword-aligned buffers.
>
> Cc: <netdev@vger.kernel.org>
> Cc: Nicolas Pitre <nico@fluxnic.net>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
Applied.
^ permalink raw reply [flat|nested] 20+ messages in thread