aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-05-30 09:00:18 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2009-05-30 09:00:18 -0400
commit26584853a44c58f3d6ac7360d697a2ddcd1a3efa (patch)
treea47156d781c6207d316746a056a81ca82b90d452
parentee8c9571191e588ede9a220ded807e33c4897d91 (diff)
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: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm/Makefile3
-rw-r--r--arch/arm/boot/compressed/Makefile5
-rw-r--r--arch/arm/boot/compressed/head.S6
-rw-r--r--arch/arm/include/asm/processor.h1
-rw-r--r--arch/arm/include/asm/ptrace.h10
-rw-r--r--arch/arm/kernel/entry-armv.S3
-rw-r--r--arch/arm/kernel/entry-common.S3
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/mm/Kconfig14
-rw-r--r--arch/arm/mm/abort-ev6.S3
-rw-r--r--arch/arm/mm/proc-v6.S3
-rw-r--r--arch/arm/mm/proc-v7.S3
12 files changed, 54 insertions, 2 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index e84729bf13d4..1167a4e8c7a8 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -11,6 +11,9 @@
11# Copyright (C) 1995-2001 by Russell King 11# Copyright (C) 1995-2001 by Russell King
12 12
13LDFLAGS_vmlinux :=-p --no-undefined -X 13LDFLAGS_vmlinux :=-p --no-undefined -X
14ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
15LDFLAGS_vmlinux += --be8
16endif
14CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) 17CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
15OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S 18OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
16GZFLAGS :=-9 19GZFLAGS :=-9
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index fbe5eef1f6c9..ce39dc540085 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -40,7 +40,7 @@ ifeq ($(CONFIG_PXA_SHARPSL),y)
40OBJS += head-sharpsl.o 40OBJS += head-sharpsl.o
41endif 41endif
42 42
43ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) 43ifeq ($(CONFIG_CPU_ENDIAN_BE32),y)
44ifeq ($(CONFIG_CPU_CP15),y) 44ifeq ($(CONFIG_CPU_CP15),y)
45OBJS += big-endian.o 45OBJS += big-endian.o
46else 46else
@@ -78,6 +78,9 @@ EXTRA_AFLAGS := -Wa,-march=all
78# linker symbols. We only define initrd_phys and params_phys if the 78# linker symbols. We only define initrd_phys and params_phys if the
79# machine class defined the corresponding makefile variable. 79# machine class defined the corresponding makefile variable.
80LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) 80LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
81ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
82LDFLAGS_vmlinux += --be8
83endif
81ifneq ($(INITRD_PHYS),) 84ifneq ($(INITRD_PHYS),)
82LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS) 85LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS)
83endif 86endif
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index b371fba1b954..01d49be3b2ca 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -438,6 +438,9 @@ __armv4_mmu_cache_on:
438 mrc p15, 0, r0, c1, c0, 0 @ read control reg 438 mrc p15, 0, r0, c1, c0, 0 @ read control reg
439 orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement 439 orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
440 orr r0, r0, #0x0030 440 orr r0, r0, #0x0030
441#ifdef CONFIG_CPU_ENDIAN_BE8
442 orr r0, r0, #1 << 25 @ big-endian page tables
443#endif
441 bl __common_mmu_cache_on 444 bl __common_mmu_cache_on
442 mov r0, #0 445 mov r0, #0
443 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 446 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
@@ -455,6 +458,9 @@ __armv7_mmu_cache_on:
455 mrc p15, 0, r0, c1, c0, 0 @ read control reg 458 mrc p15, 0, r0, c1, c0, 0 @ read control reg
456 orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement 459 orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
457 orr r0, r0, #0x003c @ write buffer 460 orr r0, r0, #0x003c @ write buffer
461#ifdef CONFIG_CPU_ENDIAN_BE8
462 orr r0, r0, #1 << 25 @ big-endian page tables
463#endif
458 orrne r0, r0, #1 @ MMU enabled 464 orrne r0, r0, #1 @ MMU enabled
459 movne r1, #-1 465 movne r1, #-1
460 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer 466 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 1845892260e7..6a89567ffc5b 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -71,6 +71,7 @@ struct thread_struct {
71 regs->ARM_cpsr = USR26_MODE; \ 71 regs->ARM_cpsr = USR26_MODE; \
72 if (elf_hwcap & HWCAP_THUMB && pc & 1) \ 72 if (elf_hwcap & HWCAP_THUMB && pc & 1) \
73 regs->ARM_cpsr |= PSR_T_BIT; \ 73 regs->ARM_cpsr |= PSR_T_BIT; \
74 regs->ARM_cpsr |= PSR_ENDSTATE; \
74 regs->ARM_pc = pc & ~1; /* pc */ \ 75 regs->ARM_pc = pc & ~1; /* pc */ \
75 regs->ARM_sp = sp; /* sp */ \ 76 regs->ARM_sp = sp; /* sp */ \
76 regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ 77 regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 4a4290f7b4a2..67b833c9b6b9 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -50,6 +50,7 @@
50#define PSR_F_BIT 0x00000040 50#define PSR_F_BIT 0x00000040
51#define PSR_I_BIT 0x00000080 51#define PSR_I_BIT 0x00000080
52#define PSR_A_BIT 0x00000100 52#define PSR_A_BIT 0x00000100
53#define PSR_E_BIT 0x00000200
53#define PSR_J_BIT 0x01000000 54#define PSR_J_BIT 0x01000000
54#define PSR_Q_BIT 0x08000000 55#define PSR_Q_BIT 0x08000000
55#define PSR_V_BIT 0x10000000 56#define PSR_V_BIT 0x10000000
@@ -72,6 +73,15 @@
72#define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ 73#define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
73#define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */ 74#define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */
74 75
76/*
77 * Default endianness state
78 */
79#ifdef CONFIG_CPU_ENDIAN_BE8
80#define PSR_ENDSTATE PSR_E_BIT
81#else
82#define PSR_ENDSTATE 0
83#endif
84
75#ifndef __ASSEMBLY__ 85#ifndef __ASSEMBLY__
76 86
77/* 87/*
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index d662a2f1fd85..9d7ce4377c5e 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -482,6 +482,9 @@ __und_usr:
482 subeq r4, r2, #4 @ ARM instr at LR - 4 482 subeq r4, r2, #4 @ ARM instr at LR - 4
483 subne r4, r2, #2 @ Thumb instr at LR - 2 483 subne r4, r2, #2 @ Thumb instr at LR - 2
4841: ldreqt r0, [r4] 4841: ldreqt r0, [r4]
485#ifdef CONFIG_CPU_ENDIAN_BE8
486 reveq r0, r0 @ little endian instruction
487#endif
485 beq call_fpe 488 beq call_fpe
486 @ Thumb instruction 489 @ Thumb instruction
487#if __LINUX_ARM_ARCH__ >= 7 490#if __LINUX_ARM_ARCH__ >= 7
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index b55cb0331809..366e5097a41a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -210,6 +210,9 @@ ENTRY(vector_swi)
210 A710( teq ip, #0x0f000000 ) 210 A710( teq ip, #0x0f000000 )
211 A710( bne .Larm710bug ) 211 A710( bne .Larm710bug )
212#endif 212#endif
213#ifdef CONFIG_CPU_ENDIAN_BE8
214 rev r10, r10 @ little endian instruction
215#endif
213 216
214#elif defined(CONFIG_AEABI) 217#elif defined(CONFIG_AEABI)
215 218
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index c3265a2e7cd4..1585423699ee 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -365,7 +365,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
365 regs.ARM_r2 = (unsigned long)fn; 365 regs.ARM_r2 = (unsigned long)fn;
366 regs.ARM_r3 = (unsigned long)do_exit; 366 regs.ARM_r3 = (unsigned long)do_exit;
367 regs.ARM_pc = (unsigned long)kernel_thread_helper; 367 regs.ARM_pc = (unsigned long)kernel_thread_helper;
368 regs.ARM_cpsr = SVC_MODE; 368 regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE;
369 369
370 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 370 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
371} 371}
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 76bbcde049b0..a25f34bd99da 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -639,6 +639,20 @@ config CPU_BIG_ENDIAN
639 port must properly enable any big-endian related features 639 port must properly enable any big-endian related features
640 of your chipset/board/processor. 640 of your chipset/board/processor.
641 641
642config CPU_ENDIAN_BE8
643 bool
644 depends on CPU_BIG_ENDIAN
645 default CPU_V6 || CPU_V7
646 help
647 Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors.
648
649config CPU_ENDIAN_BE32
650 bool
651 depends on CPU_BIG_ENDIAN
652 default !CPU_ENDIAN_BE8
653 help
654 Support for the BE-32 (big-endian) mode on pre-ARMv6 processors.
655
642config CPU_HIGH_VECTOR 656config CPU_HIGH_VECTOR
643 depends on !MMU && CPU_CP15 && !CPU_ARM740T 657 depends on !MMU && CPU_CP15 && !CPU_ARM740T
644 bool "Select the High exception vector" 658 bool "Select the High exception vector"
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index 6f7e70907e44..f332df7f0d37 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -37,6 +37,9 @@ ENTRY(v6_early_abort)
37 movne pc, lr 37 movne pc, lr
38 do_thumb_abort 38 do_thumb_abort
39 ldreq r3, [r2] @ read aborted ARM instruction 39 ldreq r3, [r2] @ read aborted ARM instruction
40#ifdef CONFIG_CPU_ENDIAN_BE8
41 reveq r3, r3
42#endif
40 do_ldrd_abort 43 do_ldrd_abort
41 tst r3, #1 << 20 @ L = 0 -> write 44 tst r3, #1 << 20 @ L = 0 -> write
42 orreq r1, r1, #1 << 11 @ yes. 45 orreq r1, r1, #1 << 11 @ yes.
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 087e239704df..524ddae92595 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -170,6 +170,9 @@ __v6_setup:
170#endif /* CONFIG_MMU */ 170#endif /* CONFIG_MMU */
171 adr r5, v6_crval 171 adr r5, v6_crval
172 ldmia r5, {r5, r6} 172 ldmia r5, {r5, r6}
173#ifdef CONFIG_CPU_ENDIAN_BE8
174 orr r6, r6, #1 << 25 @ big-endian page tables
175#endif
173 mrc p15, 0, r0, c1, c0, 0 @ read control register 176 mrc p15, 0, r0, c1, c0, 0 @ read control register
174 bic r0, r0, r5 @ clear bits them 177 bic r0, r0, r5 @ clear bits them
175 orr r0, r0, r6 @ set them 178 orr r0, r0, r6 @ set them
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 0a8ffd3c03fd..4f8486475a79 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -253,6 +253,9 @@ __v7_setup:
253 mcr p15, 0, r6, c10, c2, 1 @ write NMRR 253 mcr p15, 0, r6, c10, c2, 1 @ write NMRR
254 adr r5, v7_crval 254 adr r5, v7_crval
255 ldmia r5, {r5, r6} 255 ldmia r5, {r5, r6}
256#ifdef CONFIG_CPU_ENDIAN_BE8
257 orr r6, r6, #1 << 25 @ big-endian page tables
258#endif
256 mrc p15, 0, r0, c1, c0, 0 @ read control register 259 mrc p15, 0, r0, c1, c0, 0 @ read control register
257 bic r0, r0, r5 @ clear bits them 260 bic r0, r0, r5 @ clear bits them
258 orr r0, r0, r6 @ set them 261 orr r0, r0, r6 @ set them