Commit 26584853 authored by Catalin Marinas's avatar Catalin Marinas

Add core support for ARMv6/v7 big-endian

Starting with ARMv6, the CPUs support the BE-8 variant of big-endian
(byte-invariant). This patch adds the core support:

- setting of the BE-8 mode via the CPSR.E register for both kernel and
  user threads
- big-endian page table walking
- REV used to rotate instructions read from memory during fault
  processing as they are still little-endian format
- Kconfig and Makefile support for BE-8. The --be8 option must be passed
  to the final linking stage to convert the instructions to
  little-endian
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent ee8c9571
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
# Copyright (C) 1995-2001 by Russell King # Copyright (C) 1995-2001 by Russell King
LDFLAGS_vmlinux :=-p --no-undefined -X LDFLAGS_vmlinux :=-p --no-undefined -X
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
LDFLAGS_vmlinux += --be8
endif
CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
GZFLAGS :=-9 GZFLAGS :=-9
......
...@@ -40,7 +40,7 @@ ifeq ($(CONFIG_PXA_SHARPSL),y) ...@@ -40,7 +40,7 @@ ifeq ($(CONFIG_PXA_SHARPSL),y)
OBJS += head-sharpsl.o OBJS += head-sharpsl.o
endif endif
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) ifeq ($(CONFIG_CPU_ENDIAN_BE32),y)
ifeq ($(CONFIG_CPU_CP15),y) ifeq ($(CONFIG_CPU_CP15),y)
OBJS += big-endian.o OBJS += big-endian.o
else else
...@@ -78,6 +78,9 @@ EXTRA_AFLAGS := -Wa,-march=all ...@@ -78,6 +78,9 @@ EXTRA_AFLAGS := -Wa,-march=all
# linker symbols. We only define initrd_phys and params_phys if the # linker symbols. We only define initrd_phys and params_phys if the
# machine class defined the corresponding makefile variable. # machine class defined the corresponding makefile variable.
LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
LDFLAGS_vmlinux += --be8
endif
ifneq ($(INITRD_PHYS),) ifneq ($(INITRD_PHYS),)
LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS) LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS)
endif endif
......
...@@ -438,6 +438,9 @@ __armv4_mmu_cache_on: ...@@ -438,6 +438,9 @@ __armv4_mmu_cache_on:
mrc p15, 0, r0, c1, c0, 0 @ read control reg mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x0030 orr r0, r0, #0x0030
#ifdef CONFIG_CPU_ENDIAN_BE8
orr r0, r0, #1 << 25 @ big-endian page tables
#endif
bl __common_mmu_cache_on bl __common_mmu_cache_on
mov r0, #0 mov r0, #0
mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
...@@ -455,6 +458,9 @@ __armv7_mmu_cache_on: ...@@ -455,6 +458,9 @@ __armv7_mmu_cache_on:
mrc p15, 0, r0, c1, c0, 0 @ read control reg mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x003c @ write buffer orr r0, r0, #0x003c @ write buffer
#ifdef CONFIG_CPU_ENDIAN_BE8
orr r0, r0, #1 << 25 @ big-endian page tables
#endif
orrne r0, r0, #1 @ MMU enabled orrne r0, r0, #1 @ MMU enabled
movne r1, #-1 movne r1, #-1
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
......
...@@ -71,6 +71,7 @@ struct thread_struct { ...@@ -71,6 +71,7 @@ struct thread_struct {
regs->ARM_cpsr = USR26_MODE; \ regs->ARM_cpsr = USR26_MODE; \
if (elf_hwcap & HWCAP_THUMB && pc & 1) \ if (elf_hwcap & HWCAP_THUMB && pc & 1) \
regs->ARM_cpsr |= PSR_T_BIT; \ regs->ARM_cpsr |= PSR_T_BIT; \
regs->ARM_cpsr |= PSR_ENDSTATE; \
regs->ARM_pc = pc & ~1; /* pc */ \ regs->ARM_pc = pc & ~1; /* pc */ \
regs->ARM_sp = sp; /* sp */ \ regs->ARM_sp = sp; /* sp */ \
regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#define PSR_F_BIT 0x00000040 #define PSR_F_BIT 0x00000040
#define PSR_I_BIT 0x00000080 #define PSR_I_BIT 0x00000080
#define PSR_A_BIT 0x00000100 #define PSR_A_BIT 0x00000100
#define PSR_E_BIT 0x00000200
#define PSR_J_BIT 0x01000000 #define PSR_J_BIT 0x01000000
#define PSR_Q_BIT 0x08000000 #define PSR_Q_BIT 0x08000000
#define PSR_V_BIT 0x10000000 #define PSR_V_BIT 0x10000000
...@@ -72,6 +73,15 @@ ...@@ -72,6 +73,15 @@
#define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ #define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
#define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */ #define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */
/*
* Default endianness state
*/
#ifdef CONFIG_CPU_ENDIAN_BE8
#define PSR_ENDSTATE PSR_E_BIT
#else
#define PSR_ENDSTATE 0
#endif
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/* /*
......
...@@ -482,6 +482,9 @@ __und_usr: ...@@ -482,6 +482,9 @@ __und_usr:
subeq r4, r2, #4 @ ARM instr at LR - 4 subeq r4, r2, #4 @ ARM instr at LR - 4
subne r4, r2, #2 @ Thumb instr at LR - 2 subne r4, r2, #2 @ Thumb instr at LR - 2
1: ldreqt r0, [r4] 1: ldreqt r0, [r4]
#ifdef CONFIG_CPU_ENDIAN_BE8
reveq r0, r0 @ little endian instruction
#endif
beq call_fpe beq call_fpe
@ Thumb instruction @ Thumb instruction
#if __LINUX_ARM_ARCH__ >= 7 #if __LINUX_ARM_ARCH__ >= 7
......
...@@ -210,6 +210,9 @@ ENTRY(vector_swi) ...@@ -210,6 +210,9 @@ ENTRY(vector_swi)
A710( teq ip, #0x0f000000 ) A710( teq ip, #0x0f000000 )
A710( bne .Larm710bug ) A710( bne .Larm710bug )
#endif #endif
#ifdef CONFIG_CPU_ENDIAN_BE8
rev r10, r10 @ little endian instruction
#endif
#elif defined(CONFIG_AEABI) #elif defined(CONFIG_AEABI)
......
...@@ -365,7 +365,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) ...@@ -365,7 +365,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
regs.ARM_r2 = (unsigned long)fn; regs.ARM_r2 = (unsigned long)fn;
regs.ARM_r3 = (unsigned long)do_exit; regs.ARM_r3 = (unsigned long)do_exit;
regs.ARM_pc = (unsigned long)kernel_thread_helper; regs.ARM_pc = (unsigned long)kernel_thread_helper;
regs.ARM_cpsr = SVC_MODE; regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE;
return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
} }
......
...@@ -639,6 +639,20 @@ config CPU_BIG_ENDIAN ...@@ -639,6 +639,20 @@ config CPU_BIG_ENDIAN
port must properly enable any big-endian related features port must properly enable any big-endian related features
of your chipset/board/processor. of your chipset/board/processor.
config CPU_ENDIAN_BE8
bool
depends on CPU_BIG_ENDIAN
default CPU_V6 || CPU_V7
help
Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors.
config CPU_ENDIAN_BE32
bool
depends on CPU_BIG_ENDIAN
default !CPU_ENDIAN_BE8
help
Support for the BE-32 (big-endian) mode on pre-ARMv6 processors.
config CPU_HIGH_VECTOR config CPU_HIGH_VECTOR
depends on !MMU && CPU_CP15 && !CPU_ARM740T depends on !MMU && CPU_CP15 && !CPU_ARM740T
bool "Select the High exception vector" bool "Select the High exception vector"
......
...@@ -37,6 +37,9 @@ ENTRY(v6_early_abort) ...@@ -37,6 +37,9 @@ ENTRY(v6_early_abort)
movne pc, lr movne pc, lr
do_thumb_abort do_thumb_abort
ldreq r3, [r2] @ read aborted ARM instruction ldreq r3, [r2] @ read aborted ARM instruction
#ifdef CONFIG_CPU_ENDIAN_BE8
reveq r3, r3
#endif
do_ldrd_abort do_ldrd_abort
tst r3, #1 << 20 @ L = 0 -> write tst r3, #1 << 20 @ L = 0 -> write
orreq r1, r1, #1 << 11 @ yes. orreq r1, r1, #1 << 11 @ yes.
......
...@@ -170,6 +170,9 @@ __v6_setup: ...@@ -170,6 +170,9 @@ __v6_setup:
#endif /* CONFIG_MMU */ #endif /* CONFIG_MMU */
adr r5, v6_crval adr r5, v6_crval
ldmia r5, {r5, r6} ldmia r5, {r5, r6}
#ifdef CONFIG_CPU_ENDIAN_BE8
orr r6, r6, #1 << 25 @ big-endian page tables
#endif
mrc p15, 0, r0, c1, c0, 0 @ read control register mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, r0, r5 @ clear bits them bic r0, r0, r5 @ clear bits them
orr r0, r0, r6 @ set them orr r0, r0, r6 @ set them
......
...@@ -253,6 +253,9 @@ __v7_setup: ...@@ -253,6 +253,9 @@ __v7_setup:
mcr p15, 0, r6, c10, c2, 1 @ write NMRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR
adr r5, v7_crval adr r5, v7_crval
ldmia r5, {r5, r6} ldmia r5, {r5, r6}
#ifdef CONFIG_CPU_ENDIAN_BE8
orr r6, r6, #1 << 25 @ big-endian page tables
#endif
mrc p15, 0, r0, c1, c0, 0 @ read control register mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, r0, r5 @ clear bits them bic r0, r0, r5 @ clear bits them
orr r0, r0, r6 @ set them orr r0, r0, r6 @ set them
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment