diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-05-30 09:00:18 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2009-05-30 09:00:18 -0400 |
commit | 26584853a44c58f3d6ac7360d697a2ddcd1a3efa (patch) | |
tree | a47156d781c6207d316746a056a81ca82b90d452 | |
parent | ee8c9571191e588ede9a220ded807e33c4897d91 (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/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 6 | ||||
-rw-r--r-- | arch/arm/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/ptrace.h | 10 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/Kconfig | 14 | ||||
-rw-r--r-- | arch/arm/mm/abort-ev6.S | 3 | ||||
-rw-r--r-- | arch/arm/mm/proc-v6.S | 3 | ||||
-rw-r--r-- | arch/arm/mm/proc-v7.S | 3 |
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 | ||
13 | LDFLAGS_vmlinux :=-p --no-undefined -X | 13 | LDFLAGS_vmlinux :=-p --no-undefined -X |
14 | ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) | ||
15 | LDFLAGS_vmlinux += --be8 | ||
16 | endif | ||
14 | CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) | 17 | CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) |
15 | OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S | 18 | OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S |
16 | GZFLAGS :=-9 | 19 | GZFLAGS :=-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) | |||
40 | OBJS += head-sharpsl.o | 40 | OBJS += head-sharpsl.o |
41 | endif | 41 | endif |
42 | 42 | ||
43 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) | 43 | ifeq ($(CONFIG_CPU_ENDIAN_BE32),y) |
44 | ifeq ($(CONFIG_CPU_CP15),y) | 44 | ifeq ($(CONFIG_CPU_CP15),y) |
45 | OBJS += big-endian.o | 45 | OBJS += big-endian.o |
46 | else | 46 | else |
@@ -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. |
80 | LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) | 80 | LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) |
81 | ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) | ||
82 | LDFLAGS_vmlinux += --be8 | ||
83 | endif | ||
81 | ifneq ($(INITRD_PHYS),) | 84 | ifneq ($(INITRD_PHYS),) |
82 | LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS) | 85 | LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS) |
83 | endif | 86 | endif |
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 |
484 | 1: ldreqt r0, [r4] | 484 | 1: 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, ®s, 0, NULL, NULL); | 370 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 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 | ||
642 | config 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 | |||
649 | config 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 | |||
642 | config CPU_HIGH_VECTOR | 656 | config 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 |