diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2006-12-03 12:51:14 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-12-03 12:52:22 -0500 |
commit | afe4b25e7d9260d85fccb2d13c9933a987bdfc8a (patch) | |
tree | 9b603e52ef91531089b45e5860e89d91d2e01565 | |
parent | f5236225a3858b505221a59233af1f1158be9139 (diff) |
[ARM] 3881/4: xscale: clean up cp0/cp1 handling
XScale cores either have a DSP coprocessor (which contains a single
40 bit accumulator register), or an iWMMXt coprocessor (which contains
eight 64 bit registers.)
Because of the small amount of state in the DSP coprocessor, access to
the DSP coprocessor (CP0) is always enabled, and DSP context switching
is done unconditionally on every task switch. Access to the iWMMXt
coprocessor (CP0/CP1) is enabled only when an iWMMXt instruction is
first issued, and iWMMXt context switching is done lazily.
CONFIG_IWMMXT is supposed to mean 'the cpu we will be running on will
have iWMMXt support', but boards are supposed to select this config
symbol by hand, and at least one pxa27x board doesn't get this right,
so on that board, proc-xscale.S will incorrectly assume that we have a
DSP coprocessor, enable CP0 on boot, and we will then only save the
first iWMMXt register (wR0) on context switches, which is Bad.
This patch redefines CONFIG_IWMMXT as 'the cpu we will be running on
might have iWMMXt support, and we will enable iWMMXt context switching
if it does.' This means that with this patch, running a CONFIG_IWMMXT=n
kernel on an iWMMXt-capable CPU will no longer potentially corrupt iWMMXt
state over context switches, and running a CONFIG_IWMMXT=y kernel on a
non-iWMMXt capable CPU will still do DSP context save/restore.
These changes should make iWMMXt work on PXA3xx, and as a side effect,
enable proper acc0 save/restore on non-iWMMXt capable xsc3 cores such
as IOP13xx and IXP23xx (which will not have CONFIG_CPU_XSCALE defined),
as well as setting and using HWCAP_IWMMXT properly.
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Acked-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 9 | ||||
-rw-r--r-- | arch/arm/kernel/iwmmxt-notifier.c | 63 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/xscale-cp0.c | 179 | ||||
-rw-r--r-- | arch/arm/mach-pxa/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pm.c | 3 | ||||
-rw-r--r-- | arch/arm/mm/proc-xscale.S | 9 | ||||
-rw-r--r-- | include/asm-arm/elf.h | 48 |
10 files changed, 210 insertions, 124 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ce00c570459d..7be67ef4b84f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -374,6 +374,14 @@ config PLAT_IOP | |||
374 | 374 | ||
375 | source arch/arm/mm/Kconfig | 375 | source arch/arm/mm/Kconfig |
376 | 376 | ||
377 | config IWMMXT | ||
378 | bool "Enable iWMMXt support" | ||
379 | depends CPU_XSCALE || CPU_XSC3 | ||
380 | default y if PXA27x | ||
381 | help | ||
382 | Enable support for iWMMXt context switching at run time if | ||
383 | running on a CPU that supports it. | ||
384 | |||
377 | # bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER | 385 | # bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER |
378 | config XSCALE_PMU | 386 | config XSCALE_PMU |
379 | bool | 387 | bool |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 1320a0efca73..ab06a86e85d5 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -24,7 +24,9 @@ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | |||
24 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o | 24 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o |
25 | AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 | 25 | AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 |
26 | 26 | ||
27 | obj-$(CONFIG_IWMMXT) += iwmmxt.o iwmmxt-notifier.o | 27 | obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o |
28 | obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o | ||
29 | obj-$(CONFIG_IWMMXT) += iwmmxt.o | ||
28 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt | 30 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt |
29 | 31 | ||
30 | ifneq ($(CONFIG_ARCH_EBSA110),y) | 32 | ifneq ($(CONFIG_ARCH_EBSA110),y) |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index bd623b73445f..2db42b18f53f 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -589,10 +589,6 @@ ENTRY(__switch_to) | |||
589 | strex r5, r4, [ip] @ Clear exclusive monitor | 589 | strex r5, r4, [ip] @ Clear exclusive monitor |
590 | #endif | 590 | #endif |
591 | #endif | 591 | #endif |
592 | #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) | ||
593 | mra r4, r5, acc0 | ||
594 | stmia ip, {r4, r5} | ||
595 | #endif | ||
596 | #if defined(CONFIG_HAS_TLS_REG) | 592 | #if defined(CONFIG_HAS_TLS_REG) |
597 | mcr p15, 0, r3, c13, c0, 3 @ set TLS register | 593 | mcr p15, 0, r3, c13, c0, 3 @ set TLS register |
598 | #elif !defined(CONFIG_TLS_REG_EMUL) | 594 | #elif !defined(CONFIG_TLS_REG_EMUL) |
@@ -602,11 +598,6 @@ ENTRY(__switch_to) | |||
602 | #ifdef CONFIG_MMU | 598 | #ifdef CONFIG_MMU |
603 | mcr p15, 0, r6, c3, c0, 0 @ Set domain register | 599 | mcr p15, 0, r6, c3, c0, 0 @ Set domain register |
604 | #endif | 600 | #endif |
605 | #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) | ||
606 | add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra | ||
607 | ldmib r4, {r4, r5} | ||
608 | mar acc0, r4, r5 | ||
609 | #endif | ||
610 | mov r5, r0 | 601 | mov r5, r0 |
611 | add r4, r2, #TI_CPU_SAVE | 602 | add r4, r2, #TI_CPU_SAVE |
612 | ldr r0, =thread_notify_head | 603 | ldr r0, =thread_notify_head |
diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c deleted file mode 100644 index 0d1a1db40062..000000000000 --- a/arch/arm/kernel/iwmmxt-notifier.c +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/iwmmxt-notifier.c | ||
3 | * | ||
4 | * XScale iWMMXt (Concan) context switching and handling | ||
5 | * | ||
6 | * Initial code: | ||
7 | * Copyright (c) 2003, Intel Corporation | ||
8 | * | ||
9 | * Full lazy switching support, optimizations and more, by Nicolas Pitre | ||
10 | * Copyright (c) 2003-2004, MontaVista Software, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/signal.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <asm/thread_notify.h> | ||
24 | #include <asm/io.h> | ||
25 | |||
26 | static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) | ||
27 | { | ||
28 | struct thread_info *thread = t; | ||
29 | |||
30 | switch (cmd) { | ||
31 | case THREAD_NOTIFY_FLUSH: | ||
32 | /* | ||
33 | * flush_thread() zeroes thread->fpstate, so no need | ||
34 | * to do anything here. | ||
35 | * | ||
36 | * FALLTHROUGH: Ensure we don't try to overwrite our newly | ||
37 | * initialised state information on the first fault. | ||
38 | */ | ||
39 | |||
40 | case THREAD_NOTIFY_RELEASE: | ||
41 | iwmmxt_task_release(thread); | ||
42 | break; | ||
43 | |||
44 | case THREAD_NOTIFY_SWITCH: | ||
45 | iwmmxt_task_switch(thread); | ||
46 | break; | ||
47 | } | ||
48 | |||
49 | return NOTIFY_DONE; | ||
50 | } | ||
51 | |||
52 | static struct notifier_block iwmmxt_notifier_block = { | ||
53 | .notifier_call = iwmmxt_do, | ||
54 | }; | ||
55 | |||
56 | static int __init iwmmxt_init(void) | ||
57 | { | ||
58 | thread_register_notifier(&iwmmxt_notifier_block); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | late_initcall(iwmmxt_init); | ||
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 29efc9f82057..6f12d2686aaf 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -357,9 +357,6 @@ static void __init setup_processor(void) | |||
357 | #ifndef CONFIG_VFP | 357 | #ifndef CONFIG_VFP |
358 | elf_hwcap &= ~HWCAP_VFP; | 358 | elf_hwcap &= ~HWCAP_VFP; |
359 | #endif | 359 | #endif |
360 | #ifndef CONFIG_IWMMXT | ||
361 | elf_hwcap &= ~HWCAP_IWMMXT; | ||
362 | #endif | ||
363 | 360 | ||
364 | cpu_proc_init(); | 361 | cpu_proc_init(); |
365 | } | 362 | } |
diff --git a/arch/arm/kernel/xscale-cp0.c b/arch/arm/kernel/xscale-cp0.c new file mode 100644 index 000000000000..180000bfdc8f --- /dev/null +++ b/arch/arm/kernel/xscale-cp0.c | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/xscale-cp0.c | ||
3 | * | ||
4 | * XScale DSP and iWMMXt coprocessor context switching and handling | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/signal.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <asm/thread_notify.h> | ||
18 | #include <asm/io.h> | ||
19 | |||
20 | static inline void dsp_save_state(u32 *state) | ||
21 | { | ||
22 | __asm__ __volatile__ ( | ||
23 | "mrrc p0, 0, %0, %1, c0\n" | ||
24 | : "=r" (state[0]), "=r" (state[1])); | ||
25 | } | ||
26 | |||
27 | static inline void dsp_load_state(u32 *state) | ||
28 | { | ||
29 | __asm__ __volatile__ ( | ||
30 | "mcrr p0, 0, %0, %1, c0\n" | ||
31 | : : "r" (state[0]), "r" (state[1])); | ||
32 | } | ||
33 | |||
34 | static int dsp_do(struct notifier_block *self, unsigned long cmd, void *t) | ||
35 | { | ||
36 | struct thread_info *thread = t; | ||
37 | |||
38 | switch (cmd) { | ||
39 | case THREAD_NOTIFY_FLUSH: | ||
40 | thread->cpu_context.extra[0] = 0; | ||
41 | thread->cpu_context.extra[1] = 0; | ||
42 | break; | ||
43 | |||
44 | case THREAD_NOTIFY_SWITCH: | ||
45 | dsp_save_state(current_thread_info()->cpu_context.extra); | ||
46 | dsp_load_state(thread->cpu_context.extra); | ||
47 | break; | ||
48 | } | ||
49 | |||
50 | return NOTIFY_DONE; | ||
51 | } | ||
52 | |||
53 | static struct notifier_block dsp_notifier_block = { | ||
54 | .notifier_call = dsp_do, | ||
55 | }; | ||
56 | |||
57 | |||
58 | #ifdef CONFIG_IWMMXT | ||
59 | static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) | ||
60 | { | ||
61 | struct thread_info *thread = t; | ||
62 | |||
63 | switch (cmd) { | ||
64 | case THREAD_NOTIFY_FLUSH: | ||
65 | /* | ||
66 | * flush_thread() zeroes thread->fpstate, so no need | ||
67 | * to do anything here. | ||
68 | * | ||
69 | * FALLTHROUGH: Ensure we don't try to overwrite our newly | ||
70 | * initialised state information on the first fault. | ||
71 | */ | ||
72 | |||
73 | case THREAD_NOTIFY_RELEASE: | ||
74 | iwmmxt_task_release(thread); | ||
75 | break; | ||
76 | |||
77 | case THREAD_NOTIFY_SWITCH: | ||
78 | iwmmxt_task_switch(thread); | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | return NOTIFY_DONE; | ||
83 | } | ||
84 | |||
85 | static struct notifier_block iwmmxt_notifier_block = { | ||
86 | .notifier_call = iwmmxt_do, | ||
87 | }; | ||
88 | #endif | ||
89 | |||
90 | |||
91 | static u32 __init xscale_cp_access_read(void) | ||
92 | { | ||
93 | u32 value; | ||
94 | |||
95 | __asm__ __volatile__ ( | ||
96 | "mrc p15, 0, %0, c15, c1, 0\n\t" | ||
97 | : "=r" (value)); | ||
98 | |||
99 | return value; | ||
100 | } | ||
101 | |||
102 | static void __init xscale_cp_access_write(u32 value) | ||
103 | { | ||
104 | u32 temp; | ||
105 | |||
106 | __asm__ __volatile__ ( | ||
107 | "mcr p15, 0, %1, c15, c1, 0\n\t" | ||
108 | "mrc p15, 0, %0, c15, c1, 0\n\t" | ||
109 | "mov %0, %0\n\t" | ||
110 | "sub pc, pc, #4\n\t" | ||
111 | : "=r" (temp) : "r" (value)); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Detect whether we have a MAC coprocessor (40 bit register) or an | ||
116 | * iWMMXt coprocessor (64 bit registers) by loading 00000100:00000000 | ||
117 | * into a coprocessor register and reading it back, and checking | ||
118 | * whether the upper word survived intact. | ||
119 | */ | ||
120 | static int __init cpu_has_iwmmxt(void) | ||
121 | { | ||
122 | u32 lo; | ||
123 | u32 hi; | ||
124 | |||
125 | /* | ||
126 | * This sequence is interpreted by the DSP coprocessor as: | ||
127 | * mar acc0, %2, %3 | ||
128 | * mra %0, %1, acc0 | ||
129 | * | ||
130 | * And by the iWMMXt coprocessor as: | ||
131 | * tmcrr wR0, %2, %3 | ||
132 | * tmrrc %0, %1, wR0 | ||
133 | */ | ||
134 | __asm__ __volatile__ ( | ||
135 | "mcrr p0, 0, %2, %3, c0\n" | ||
136 | "mrrc p0, 0, %0, %1, c0\n" | ||
137 | : "=r" (lo), "=r" (hi) | ||
138 | : "r" (0), "r" (0x100)); | ||
139 | |||
140 | return !!hi; | ||
141 | } | ||
142 | |||
143 | |||
144 | /* | ||
145 | * If we detect that the CPU has iWMMXt (and CONFIG_IWMMXT=y), we | ||
146 | * disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy | ||
147 | * switch code handle iWMMXt context switching. If on the other | ||
148 | * hand the CPU has a DSP coprocessor, we keep access to CP0 enabled | ||
149 | * all the time, and save/restore acc0 on context switch in non-lazy | ||
150 | * fashion. | ||
151 | */ | ||
152 | static int __init xscale_cp0_init(void) | ||
153 | { | ||
154 | u32 cp_access; | ||
155 | |||
156 | cp_access = xscale_cp_access_read() & ~3; | ||
157 | xscale_cp_access_write(cp_access | 1); | ||
158 | |||
159 | if (cpu_has_iwmmxt()) { | ||
160 | #ifndef CONFIG_IWMMXT | ||
161 | printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor " | ||
162 | "detected, but kernel support is missing.\n"); | ||
163 | #else | ||
164 | printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n"); | ||
165 | elf_hwcap |= HWCAP_IWMMXT; | ||
166 | thread_register_notifier(&iwmmxt_notifier_block); | ||
167 | #endif | ||
168 | } else { | ||
169 | printk(KERN_INFO "XScale DSP coprocessor detected.\n"); | ||
170 | thread_register_notifier(&dsp_notifier_block); | ||
171 | cp_access |= 1; | ||
172 | } | ||
173 | |||
174 | xscale_cp_access_write(cp_access); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | late_initcall(xscale_cp0_init); | ||
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 03d07cae26c8..9e3d0bdcba07 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -13,12 +13,10 @@ config ARCH_LUBBOCK | |||
13 | config MACH_LOGICPD_PXA270 | 13 | config MACH_LOGICPD_PXA270 |
14 | bool "LogicPD PXA270 Card Engine Development Platform" | 14 | bool "LogicPD PXA270 Card Engine Development Platform" |
15 | select PXA27x | 15 | select PXA27x |
16 | select IWMMXT | ||
17 | 16 | ||
18 | config MACH_MAINSTONE | 17 | config MACH_MAINSTONE |
19 | bool "Intel HCDDBBVA0 Development Platform" | 18 | bool "Intel HCDDBBVA0 Development Platform" |
20 | select PXA27x | 19 | select PXA27x |
21 | select IWMMXT | ||
22 | 20 | ||
23 | config ARCH_PXA_IDP | 21 | config ARCH_PXA_IDP |
24 | bool "Accelent Xscale IDP" | 22 | bool "Accelent Xscale IDP" |
@@ -53,7 +51,6 @@ config PXA_SHARPSL_25x | |||
53 | config PXA_SHARPSL_27x | 51 | config PXA_SHARPSL_27x |
54 | bool "Sharp PXA270 models (SL-Cxx00)" | 52 | bool "Sharp PXA270 models (SL-Cxx00)" |
55 | select PXA27x | 53 | select PXA27x |
56 | select IWMMXT | ||
57 | 54 | ||
58 | endchoice | 55 | endchoice |
59 | 56 | ||
@@ -129,11 +126,6 @@ config PXA27x | |||
129 | help | 126 | help |
130 | Select code specific to PXA27x variants | 127 | Select code specific to PXA27x variants |
131 | 128 | ||
132 | config IWMMXT | ||
133 | bool | ||
134 | help | ||
135 | Enable support for iWMMXt | ||
136 | |||
137 | config PXA_SHARP_C7xx | 129 | config PXA_SHARP_C7xx |
138 | bool | 130 | bool |
139 | select PXA_SSP | 131 | select PXA_SSP |
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 2112c414f0e2..b4d8276d6050 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c | |||
@@ -83,7 +83,8 @@ int pxa_pm_enter(suspend_state_t state) | |||
83 | 83 | ||
84 | #ifdef CONFIG_IWMMXT | 84 | #ifdef CONFIG_IWMMXT |
85 | /* force any iWMMXt context to ram **/ | 85 | /* force any iWMMXt context to ram **/ |
86 | iwmmxt_task_disable(NULL); | 86 | if (elf_hwcap & HWCAP_IWMMXT) |
87 | iwmmxt_task_disable(NULL); | ||
87 | #endif | 88 | #endif |
88 | 89 | ||
89 | /* preserve current time */ | 90 | /* preserve current time */ |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 906e9de7f83e..cc1004b3e511 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S | |||
@@ -491,12 +491,7 @@ __xscale_setup: | |||
491 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB | 491 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB |
492 | mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer | 492 | mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer |
493 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs | 493 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs |
494 | #ifdef CONFIG_IWMMXT | 494 | mov r0, #1 << 6 @ cp6 for IOP3xx and Bulverde |
495 | mov r0, #0 @ initially disallow access to CP0/CP1 | ||
496 | #else | ||
497 | mov r0, #1 @ Allow access to CP0 | ||
498 | #endif | ||
499 | orr r0, r0, #1 << 6 @ cp6 for IOP3xx and Bulverde | ||
500 | orr r0, r0, #1 << 13 @ Its undefined whether this | 495 | orr r0, r0, #1 << 13 @ Its undefined whether this |
501 | mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes | 496 | mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes |
502 | 497 | ||
@@ -909,7 +904,7 @@ __pxa270_proc_info: | |||
909 | b __xscale_setup | 904 | b __xscale_setup |
910 | .long cpu_arch_name | 905 | .long cpu_arch_name |
911 | .long cpu_elf_name | 906 | .long cpu_elf_name |
912 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_IWMMXT | 907 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP |
913 | .long cpu_pxa270_name | 908 | .long cpu_pxa270_name |
914 | .long xscale_processor_functions | 909 | .long xscale_processor_functions |
915 | .long v4wbi_tlb_fns | 910 | .long v4wbi_tlb_fns |
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index f3929307a56b..642382d2c9f0 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h | |||
@@ -114,40 +114,24 @@ extern char elf_platform[]; | |||
114 | have no such handler. */ | 114 | have no such handler. */ |
115 | #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 | 115 | #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 |
116 | 116 | ||
117 | #ifndef CONFIG_IWMMXT | ||
118 | |||
119 | /* Old NetWinder binaries were compiled in such a way that the iBCS | ||
120 | heuristic always trips on them. Until these binaries become uncommon | ||
121 | enough not to care, don't trust the `ibcs' flag here. In any case | ||
122 | there is no other ELF system currently supported by iBCS. | ||
123 | @@ Could print a warning message to encourage users to upgrade. */ | ||
124 | #define SET_PERSONALITY(ex,ibcs2) \ | ||
125 | set_personality(((ex).e_flags & EF_ARM_APCS26 ? PER_LINUX : PER_LINUX_32BIT)) | ||
126 | |||
127 | #else | ||
128 | |||
129 | /* | 117 | /* |
130 | * All iWMMXt capable CPUs don't support 26-bit mode. Yet they can run | 118 | * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0 |
131 | * legacy binaries which used to contain FPA11 floating point instructions | 119 | * and CP1, we only enable access to the iWMMXt coprocessor if the |
132 | * that have always been emulated by the kernel. PFA11 and iWMMXt overlap | 120 | * binary is EABI or softfloat (and thus, guaranteed not to use |
133 | * on coprocessor 1 space though. We therefore must decide if given task | 121 | * FPA instructions.) |
134 | * is allowed to use CP 0 and 1 for iWMMXt, or if they should be blocked | ||
135 | * at all times for the prefetch exception handler to catch FPA11 opcodes | ||
136 | * and emulate them. The best indication to discriminate those two cases | ||
137 | * is the SOFT_FLOAT flag in the ELF header. | ||
138 | */ | 122 | */ |
139 | 123 | #define SET_PERSONALITY(ex, ibcs2) \ | |
140 | #define SET_PERSONALITY(ex,ibcs2) \ | 124 | do { \ |
141 | do { \ | 125 | if ((ex).e_flags & EF_ARM_APCS26) { \ |
142 | set_personality(PER_LINUX_32BIT); \ | 126 | set_personality(PER_LINUX); \ |
143 | if (((ex).e_flags & EF_ARM_EABI_MASK) || \ | 127 | } else { \ |
144 | ((ex).e_flags & EF_ARM_SOFT_FLOAT)) \ | 128 | set_personality(PER_LINUX_32BIT); \ |
145 | set_thread_flag(TIF_USING_IWMMXT); \ | 129 | if (elf_hwcap & HWCAP_IWMMXT && (ex).e_flags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) \ |
146 | else \ | 130 | set_thread_flag(TIF_USING_IWMMXT); \ |
147 | clear_thread_flag(TIF_USING_IWMMXT); \ | 131 | else \ |
148 | } while (0) | 132 | clear_thread_flag(TIF_USING_IWMMXT); \ |
149 | 133 | } \ | |
150 | #endif | 134 | } while (0) |
151 | 135 | ||
152 | #endif | 136 | #endif |
153 | 137 | ||