diff options
Diffstat (limited to 'arch/frv')
34 files changed, 653 insertions, 350 deletions
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index ec85c0d6c6..60a617aff8 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig | |||
@@ -6,10 +6,6 @@ config FRV | |||
6 | bool | 6 | bool |
7 | default y | 7 | default y |
8 | 8 | ||
9 | config UID16 | ||
10 | bool | ||
11 | default y | ||
12 | |||
13 | config RWSEM_GENERIC_SPINLOCK | 9 | config RWSEM_GENERIC_SPINLOCK |
14 | bool | 10 | bool |
15 | default y | 11 | default y |
@@ -274,6 +270,11 @@ config GPREL_DATA_NONE | |||
274 | 270 | ||
275 | endchoice | 271 | endchoice |
276 | 272 | ||
273 | config FRV_ONCPU_SERIAL | ||
274 | bool "Use on-CPU serial ports" | ||
275 | select SERIAL_8250 | ||
276 | default y | ||
277 | |||
277 | config PCI | 278 | config PCI |
278 | bool "Use PCI" | 279 | bool "Use PCI" |
279 | depends on MB93090_MB00 | 280 | depends on MB93090_MB00 |
@@ -305,23 +306,7 @@ config RESERVE_DMA_COHERENT | |||
305 | 306 | ||
306 | source "drivers/pci/Kconfig" | 307 | source "drivers/pci/Kconfig" |
307 | 308 | ||
308 | config PCMCIA | 309 | source "drivers/pcmcia/Kconfig" |
309 | tristate "Use PCMCIA" | ||
310 | help | ||
311 | Say Y here if you want to attach PCMCIA- or PC-cards to your FR-V | ||
312 | board. These are credit-card size devices such as network cards, | ||
313 | modems or hard drives often used with laptops computers. There are | ||
314 | actually two varieties of these cards: the older 16 bit PCMCIA cards | ||
315 | and the newer 32 bit CardBus cards. If you want to use CardBus | ||
316 | cards, you need to say Y here and also to "CardBus support" below. | ||
317 | |||
318 | To use your PC-cards, you will need supporting software from David | ||
319 | Hinds pcmcia-cs package (see the file <file:Documentation/Changes> | ||
320 | for location). Please also read the PCMCIA-HOWTO, available from | ||
321 | <http://www.tldp.org/docs.html#howto>. | ||
322 | |||
323 | To compile this driver as modules, choose M here: the | ||
324 | modules will be called pcmcia_core and ds. | ||
325 | 310 | ||
326 | #config MATH_EMULATION | 311 | #config MATH_EMULATION |
327 | # bool "Math emulation support (EXPERIMENTAL)" | 312 | # bool "Math emulation support (EXPERIMENTAL)" |
diff --git a/arch/frv/Kconfig.debug b/arch/frv/Kconfig.debug index 0034b65499..211f01bc4c 100644 --- a/arch/frv/Kconfig.debug +++ b/arch/frv/Kconfig.debug | |||
@@ -2,32 +2,10 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | config EARLY_PRINTK | ||
6 | bool "Early printk" | ||
7 | depends on EMBEDDED && DEBUG_KERNEL | ||
8 | default n | ||
9 | help | ||
10 | Write kernel log output directly into the VGA buffer or to a serial | ||
11 | port. | ||
12 | |||
13 | This is useful for kernel debugging when your machine crashes very | ||
14 | early before the console code is initialized. For normal operation | ||
15 | it is not recommended because it looks ugly and doesn't cooperate | ||
16 | with klogd/syslogd or the X server. You should normally N here, | ||
17 | unless you want to debug such a crash. | ||
18 | |||
19 | config DEBUG_STACKOVERFLOW | 5 | config DEBUG_STACKOVERFLOW |
20 | bool "Check for stack overflows" | 6 | bool "Check for stack overflows" |
21 | depends on DEBUG_KERNEL | 7 | depends on DEBUG_KERNEL |
22 | 8 | ||
23 | config DEBUG_PAGEALLOC | ||
24 | bool "Page alloc debugging" | ||
25 | depends on DEBUG_KERNEL | ||
26 | help | ||
27 | Unmap pages from the kernel linear mapping after free_pages(). | ||
28 | This results in a large slowdown, but helps to find certain types | ||
29 | of memory corruptions. | ||
30 | |||
31 | config GDBSTUB | 9 | config GDBSTUB |
32 | bool "Remote GDB kernel debugging" | 10 | bool "Remote GDB kernel debugging" |
33 | depends on DEBUG_KERNEL | 11 | depends on DEBUG_KERNEL |
diff --git a/arch/frv/Makefile b/arch/frv/Makefile index 54046d2386..90c0fb8d9d 100644 --- a/arch/frv/Makefile +++ b/arch/frv/Makefile | |||
@@ -109,10 +109,10 @@ bootstrap: | |||
109 | $(Q)$(MAKEBOOT) bootstrap | 109 | $(Q)$(MAKEBOOT) bootstrap |
110 | 110 | ||
111 | archmrproper: | 111 | archmrproper: |
112 | $(Q)$(MAKE) -C arch/frv/boot mrproper | 112 | $(Q)$(MAKE) $(build)=arch/frv/boot mrproper |
113 | 113 | ||
114 | archclean: | 114 | archclean: |
115 | $(Q)$(MAKE) -C arch/frv/boot clean | 115 | $(Q)$(MAKE) $(build)=arch/frv/boot clean |
116 | 116 | ||
117 | archdep: scripts/mkdep symlinks | 117 | archdep: scripts/mkdep symlinks |
118 | $(Q)$(MAKE) -C arch/frv/boot dep | 118 | $(Q)$(MAKE) $(build)=arch/frv/boot dep |
diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index d75e0d7713..5dfc93fd94 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile | |||
@@ -57,10 +57,10 @@ initrd: | |||
57 | # installation | 57 | # installation |
58 | # | 58 | # |
59 | install: $(CONFIGURE) Image | 59 | install: $(CONFIGURE) Image |
60 | sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" | 60 | sh ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" |
61 | 61 | ||
62 | zinstall: $(CONFIGURE) zImage | 62 | zinstall: $(CONFIGURE) zImage |
63 | sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" | 63 | sh ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" |
64 | 64 | ||
65 | # | 65 | # |
66 | # miscellany | 66 | # miscellany |
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile index 981c2c7dec..5a827b349b 100644 --- a/arch/frv/kernel/Makefile +++ b/arch/frv/kernel/Makefile | |||
@@ -20,3 +20,5 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o | |||
20 | obj-$(CONFIG_PM) += pm.o cmode.o | 20 | obj-$(CONFIG_PM) += pm.o cmode.o |
21 | obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o | 21 | obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o |
22 | obj-$(CONFIG_SYSCTL) += sysctl.o | 22 | obj-$(CONFIG_SYSCTL) += sysctl.o |
23 | obj-$(CONFIG_FUTEX) += futex.o | ||
24 | obj-$(CONFIG_MODULES) += module.o | ||
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ad10ea5954..5f6548388b 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S | |||
@@ -1076,7 +1076,7 @@ __entry_work_notifysig: | |||
1076 | LEDS 0x6410 | 1076 | LEDS 0x6410 |
1077 | ori.p gr4,#0,gr8 | 1077 | ori.p gr4,#0,gr8 |
1078 | call do_notify_resume | 1078 | call do_notify_resume |
1079 | bra __entry_return_direct | 1079 | bra __entry_resume_userspace |
1080 | 1080 | ||
1081 | # perform syscall entry tracing | 1081 | # perform syscall entry tracing |
1082 | __syscall_trace_entry: | 1082 | __syscall_trace_entry: |
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index 1a76d52471..0f1c6cbc4f 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c | |||
@@ -16,17 +16,16 @@ | |||
16 | #include <asm/semaphore.h> | 16 | #include <asm/semaphore.h> |
17 | #include <asm/checksum.h> | 17 | #include <asm/checksum.h> |
18 | #include <asm/hardirq.h> | 18 | #include <asm/hardirq.h> |
19 | #include <asm/current.h> | 19 | #include <asm/cacheflush.h> |
20 | 20 | ||
21 | extern void dump_thread(struct pt_regs *, struct user *); | ||
22 | extern long __memcpy_user(void *dst, const void *src, size_t count); | 21 | extern long __memcpy_user(void *dst, const void *src, size_t count); |
22 | extern long __memset_user(void *dst, const void *src, size_t count); | ||
23 | 23 | ||
24 | /* platform dependent support */ | 24 | /* platform dependent support */ |
25 | 25 | ||
26 | EXPORT_SYMBOL(__ioremap); | 26 | EXPORT_SYMBOL(__ioremap); |
27 | EXPORT_SYMBOL(iounmap); | 27 | EXPORT_SYMBOL(iounmap); |
28 | 28 | ||
29 | EXPORT_SYMBOL(dump_thread); | ||
30 | EXPORT_SYMBOL(strnlen); | 29 | EXPORT_SYMBOL(strnlen); |
31 | EXPORT_SYMBOL(strrchr); | 30 | EXPORT_SYMBOL(strrchr); |
32 | EXPORT_SYMBOL(strstr); | 31 | EXPORT_SYMBOL(strstr); |
@@ -50,7 +49,11 @@ EXPORT_SYMBOL(disable_irq); | |||
50 | EXPORT_SYMBOL(__res_bus_clock_speed_HZ); | 49 | EXPORT_SYMBOL(__res_bus_clock_speed_HZ); |
51 | EXPORT_SYMBOL(__page_offset); | 50 | EXPORT_SYMBOL(__page_offset); |
52 | EXPORT_SYMBOL(__memcpy_user); | 51 | EXPORT_SYMBOL(__memcpy_user); |
53 | EXPORT_SYMBOL(flush_dcache_page); | 52 | EXPORT_SYMBOL(__memset_user); |
53 | EXPORT_SYMBOL(frv_dcache_writeback); | ||
54 | EXPORT_SYMBOL(frv_cache_invalidate); | ||
55 | EXPORT_SYMBOL(frv_icache_invalidate); | ||
56 | EXPORT_SYMBOL(frv_cache_wback_inv); | ||
54 | 57 | ||
55 | #ifndef CONFIG_MMU | 58 | #ifndef CONFIG_MMU |
56 | EXPORT_SYMBOL(memory_start); | 59 | EXPORT_SYMBOL(memory_start); |
@@ -72,6 +75,9 @@ EXPORT_SYMBOL(memcmp); | |||
72 | EXPORT_SYMBOL(memscan); | 75 | EXPORT_SYMBOL(memscan); |
73 | EXPORT_SYMBOL(memmove); | 76 | EXPORT_SYMBOL(memmove); |
74 | 77 | ||
78 | EXPORT_SYMBOL(__outsl_ns); | ||
79 | EXPORT_SYMBOL(__insl_ns); | ||
80 | |||
75 | EXPORT_SYMBOL(get_wchan); | 81 | EXPORT_SYMBOL(get_wchan); |
76 | 82 | ||
77 | #ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS | 83 | #ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS |
@@ -80,14 +86,13 @@ EXPORT_SYMBOL(atomic_test_and_OR_mask); | |||
80 | EXPORT_SYMBOL(atomic_test_and_XOR_mask); | 86 | EXPORT_SYMBOL(atomic_test_and_XOR_mask); |
81 | EXPORT_SYMBOL(atomic_add_return); | 87 | EXPORT_SYMBOL(atomic_add_return); |
82 | EXPORT_SYMBOL(atomic_sub_return); | 88 | EXPORT_SYMBOL(atomic_sub_return); |
83 | EXPORT_SYMBOL(__xchg_8); | ||
84 | EXPORT_SYMBOL(__xchg_16); | ||
85 | EXPORT_SYMBOL(__xchg_32); | 89 | EXPORT_SYMBOL(__xchg_32); |
86 | EXPORT_SYMBOL(__cmpxchg_8); | ||
87 | EXPORT_SYMBOL(__cmpxchg_16); | ||
88 | EXPORT_SYMBOL(__cmpxchg_32); | 90 | EXPORT_SYMBOL(__cmpxchg_32); |
89 | #endif | 91 | #endif |
90 | 92 | ||
93 | EXPORT_SYMBOL(__debug_bug_printk); | ||
94 | EXPORT_SYMBOL(__delay_loops_MHz); | ||
95 | |||
91 | /* | 96 | /* |
92 | * libgcc functions - functions that are used internally by the | 97 | * libgcc functions - functions that are used internally by the |
93 | * compiler... (prototypes are not correct though, but that | 98 | * compiler... (prototypes are not correct though, but that |
@@ -101,6 +106,8 @@ extern void __divdi3(void); | |||
101 | extern void __lshrdi3(void); | 106 | extern void __lshrdi3(void); |
102 | extern void __moddi3(void); | 107 | extern void __moddi3(void); |
103 | extern void __muldi3(void); | 108 | extern void __muldi3(void); |
109 | extern void __mulll(void); | ||
110 | extern void __umulll(void); | ||
104 | extern void __negdi2(void); | 111 | extern void __negdi2(void); |
105 | extern void __ucmpdi2(void); | 112 | extern void __ucmpdi2(void); |
106 | extern void __udivdi3(void); | 113 | extern void __udivdi3(void); |
@@ -116,8 +123,10 @@ EXPORT_SYMBOL(__ashrdi3); | |||
116 | EXPORT_SYMBOL(__lshrdi3); | 123 | EXPORT_SYMBOL(__lshrdi3); |
117 | //EXPORT_SYMBOL(__moddi3); | 124 | //EXPORT_SYMBOL(__moddi3); |
118 | EXPORT_SYMBOL(__muldi3); | 125 | EXPORT_SYMBOL(__muldi3); |
126 | EXPORT_SYMBOL(__mulll); | ||
127 | EXPORT_SYMBOL(__umulll); | ||
119 | EXPORT_SYMBOL(__negdi2); | 128 | EXPORT_SYMBOL(__negdi2); |
120 | //EXPORT_SYMBOL(__ucmpdi2); | 129 | EXPORT_SYMBOL(__ucmpdi2); |
121 | //EXPORT_SYMBOL(__udivdi3); | 130 | //EXPORT_SYMBOL(__udivdi3); |
122 | //EXPORT_SYMBOL(__udivmoddi4); | 131 | //EXPORT_SYMBOL(__udivmoddi4); |
123 | //EXPORT_SYMBOL(__umoddi3); | 132 | //EXPORT_SYMBOL(__umoddi3); |
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c new file mode 100644 index 0000000000..eae874a970 --- /dev/null +++ b/arch/frv/kernel/futex.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* futex.c: futex operations | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/futex.h> | ||
13 | #include <asm/futex.h> | ||
14 | #include <asm/errno.h> | ||
15 | #include <asm/uaccess.h> | ||
16 | |||
17 | /* | ||
18 | * the various futex operations; MMU fault checking is ignored under no-MMU | ||
19 | * conditions | ||
20 | */ | ||
21 | static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval) | ||
22 | { | ||
23 | int oldval, ret; | ||
24 | |||
25 | asm("0: \n" | ||
26 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
27 | " ckeq icc3,cc7 \n" | ||
28 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
29 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
30 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
31 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
32 | " beq icc3,#0,0b \n" | ||
33 | " setlos 0,%2 \n" | ||
34 | "3: \n" | ||
35 | ".subsection 2 \n" | ||
36 | "4: setlos %5,%2 \n" | ||
37 | " bra 3b \n" | ||
38 | ".previous \n" | ||
39 | ".section __ex_table,\"a\" \n" | ||
40 | " .balign 8 \n" | ||
41 | " .long 1b,4b \n" | ||
42 | " .long 2b,4b \n" | ||
43 | ".previous" | ||
44 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
45 | : "3"(oparg), "i"(-EFAULT) | ||
46 | : "memory", "cc7", "cc3", "icc3" | ||
47 | ); | ||
48 | |||
49 | *_oldval = oldval; | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval) | ||
54 | { | ||
55 | int oldval, ret; | ||
56 | |||
57 | asm("0: \n" | ||
58 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
59 | " ckeq icc3,cc7 \n" | ||
60 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
61 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
62 | " add %1,%3,%3 \n" | ||
63 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
64 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
65 | " beq icc3,#0,0b \n" | ||
66 | " setlos 0,%2 \n" | ||
67 | "3: \n" | ||
68 | ".subsection 2 \n" | ||
69 | "4: setlos %5,%2 \n" | ||
70 | " bra 3b \n" | ||
71 | ".previous \n" | ||
72 | ".section __ex_table,\"a\" \n" | ||
73 | " .balign 8 \n" | ||
74 | " .long 1b,4b \n" | ||
75 | " .long 2b,4b \n" | ||
76 | ".previous" | ||
77 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
78 | : "3"(oparg), "i"(-EFAULT) | ||
79 | : "memory", "cc7", "cc3", "icc3" | ||
80 | ); | ||
81 | |||
82 | *_oldval = oldval; | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval) | ||
87 | { | ||
88 | int oldval, ret; | ||
89 | |||
90 | asm("0: \n" | ||
91 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
92 | " ckeq icc3,cc7 \n" | ||
93 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
94 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
95 | " or %1,%3,%3 \n" | ||
96 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
97 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
98 | " beq icc3,#0,0b \n" | ||
99 | " setlos 0,%2 \n" | ||
100 | "3: \n" | ||
101 | ".subsection 2 \n" | ||
102 | "4: setlos %5,%2 \n" | ||
103 | " bra 3b \n" | ||
104 | ".previous \n" | ||
105 | ".section __ex_table,\"a\" \n" | ||
106 | " .balign 8 \n" | ||
107 | " .long 1b,4b \n" | ||
108 | " .long 2b,4b \n" | ||
109 | ".previous" | ||
110 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
111 | : "3"(oparg), "i"(-EFAULT) | ||
112 | : "memory", "cc7", "cc3", "icc3" | ||
113 | ); | ||
114 | |||
115 | *_oldval = oldval; | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval) | ||
120 | { | ||
121 | int oldval, ret; | ||
122 | |||
123 | asm("0: \n" | ||
124 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
125 | " ckeq icc3,cc7 \n" | ||
126 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
127 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
128 | " and %1,%3,%3 \n" | ||
129 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
130 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
131 | " beq icc3,#0,0b \n" | ||
132 | " setlos 0,%2 \n" | ||
133 | "3: \n" | ||
134 | ".subsection 2 \n" | ||
135 | "4: setlos %5,%2 \n" | ||
136 | " bra 3b \n" | ||
137 | ".previous \n" | ||
138 | ".section __ex_table,\"a\" \n" | ||
139 | " .balign 8 \n" | ||
140 | " .long 1b,4b \n" | ||
141 | " .long 2b,4b \n" | ||
142 | ".previous" | ||
143 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
144 | : "3"(oparg), "i"(-EFAULT) | ||
145 | : "memory", "cc7", "cc3", "icc3" | ||
146 | ); | ||
147 | |||
148 | *_oldval = oldval; | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval) | ||
153 | { | ||
154 | int oldval, ret; | ||
155 | |||
156 | asm("0: \n" | ||
157 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
158 | " ckeq icc3,cc7 \n" | ||
159 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
160 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
161 | " xor %1,%3,%3 \n" | ||
162 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
163 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
164 | " beq icc3,#0,0b \n" | ||
165 | " setlos 0,%2 \n" | ||
166 | "3: \n" | ||
167 | ".subsection 2 \n" | ||
168 | "4: setlos %5,%2 \n" | ||
169 | " bra 3b \n" | ||
170 | ".previous \n" | ||
171 | ".section __ex_table,\"a\" \n" | ||
172 | " .balign 8 \n" | ||
173 | " .long 1b,4b \n" | ||
174 | " .long 2b,4b \n" | ||
175 | ".previous" | ||
176 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
177 | : "3"(oparg), "i"(-EFAULT) | ||
178 | : "memory", "cc7", "cc3", "icc3" | ||
179 | ); | ||
180 | |||
181 | *_oldval = oldval; | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | /*****************************************************************************/ | ||
186 | /* | ||
187 | * do the futex operations | ||
188 | */ | ||
189 | int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | ||
190 | { | ||
191 | int op = (encoded_op >> 28) & 7; | ||
192 | int cmp = (encoded_op >> 24) & 15; | ||
193 | int oparg = (encoded_op << 8) >> 20; | ||
194 | int cmparg = (encoded_op << 20) >> 20; | ||
195 | int oldval = 0, ret; | ||
196 | |||
197 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
198 | oparg = 1 << oparg; | ||
199 | |||
200 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
201 | return -EFAULT; | ||
202 | |||
203 | inc_preempt_count(); | ||
204 | |||
205 | switch (op) { | ||
206 | case FUTEX_OP_SET: | ||
207 | ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval); | ||
208 | break; | ||
209 | case FUTEX_OP_ADD: | ||
210 | ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval); | ||
211 | break; | ||
212 | case FUTEX_OP_OR: | ||
213 | ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval); | ||
214 | break; | ||
215 | case FUTEX_OP_ANDN: | ||
216 | ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval); | ||
217 | break; | ||
218 | case FUTEX_OP_XOR: | ||
219 | ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval); | ||
220 | break; | ||
221 | default: | ||
222 | ret = -ENOSYS; | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | dec_preempt_count(); | ||
227 | |||
228 | if (!ret) { | ||
229 | switch (cmp) { | ||
230 | case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; | ||
231 | case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; | ||
232 | case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; | ||
233 | case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; | ||
234 | case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; | ||
235 | case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; | ||
236 | default: ret = -ENOSYS; break; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | return ret; | ||
241 | |||
242 | } /* end futex_atomic_op_inuser() */ | ||
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 8c524cdd27..59580c59c6 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/irq.h> | 32 | #include <linux/irq.h> |
33 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <linux/module.h> | ||
35 | 36 | ||
36 | #include <asm/atomic.h> | 37 | #include <asm/atomic.h> |
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
@@ -178,6 +179,8 @@ void disable_irq_nosync(unsigned int irq) | |||
178 | spin_unlock_irqrestore(&level->lock, flags); | 179 | spin_unlock_irqrestore(&level->lock, flags); |
179 | } | 180 | } |
180 | 181 | ||
182 | EXPORT_SYMBOL(disable_irq_nosync); | ||
183 | |||
181 | /** | 184 | /** |
182 | * disable_irq - disable an irq and wait for completion | 185 | * disable_irq - disable an irq and wait for completion |
183 | * @irq: Interrupt to disable | 186 | * @irq: Interrupt to disable |
@@ -204,6 +207,8 @@ void disable_irq(unsigned int irq) | |||
204 | #endif | 207 | #endif |
205 | } | 208 | } |
206 | 209 | ||
210 | EXPORT_SYMBOL(disable_irq); | ||
211 | |||
207 | /** | 212 | /** |
208 | * enable_irq - enable handling of an irq | 213 | * enable_irq - enable handling of an irq |
209 | * @irq: Interrupt to enable | 214 | * @irq: Interrupt to enable |
@@ -268,6 +273,8 @@ void enable_irq(unsigned int irq) | |||
268 | spin_unlock_irqrestore(&level->lock, flags); | 273 | spin_unlock_irqrestore(&level->lock, flags); |
269 | } | 274 | } |
270 | 275 | ||
276 | EXPORT_SYMBOL(enable_irq); | ||
277 | |||
271 | /*****************************************************************************/ | 278 | /*****************************************************************************/ |
272 | /* | 279 | /* |
273 | * handles all normal device IRQ's | 280 | * handles all normal device IRQ's |
@@ -425,6 +432,8 @@ int request_irq(unsigned int irq, | |||
425 | return retval; | 432 | return retval; |
426 | } | 433 | } |
427 | 434 | ||
435 | EXPORT_SYMBOL(request_irq); | ||
436 | |||
428 | /** | 437 | /** |
429 | * free_irq - free an interrupt | 438 | * free_irq - free an interrupt |
430 | * @irq: Interrupt line to free | 439 | * @irq: Interrupt line to free |
@@ -496,6 +505,8 @@ void free_irq(unsigned int irq, void *dev_id) | |||
496 | } | 505 | } |
497 | } | 506 | } |
498 | 507 | ||
508 | EXPORT_SYMBOL(free_irq); | ||
509 | |||
499 | /* | 510 | /* |
500 | * IRQ autodetection code.. | 511 | * IRQ autodetection code.. |
501 | * | 512 | * |
@@ -519,6 +530,8 @@ unsigned long probe_irq_on(void) | |||
519 | return 0; | 530 | return 0; |
520 | } | 531 | } |
521 | 532 | ||
533 | EXPORT_SYMBOL(probe_irq_on); | ||
534 | |||
522 | /* | 535 | /* |
523 | * Return a mask of triggered interrupts (this | 536 | * Return a mask of triggered interrupts (this |
524 | * can handle only legacy ISA interrupts). | 537 | * can handle only legacy ISA interrupts). |
@@ -542,6 +555,8 @@ unsigned int probe_irq_mask(unsigned long xmask) | |||
542 | return 0; | 555 | return 0; |
543 | } | 556 | } |
544 | 557 | ||
558 | EXPORT_SYMBOL(probe_irq_mask); | ||
559 | |||
545 | /* | 560 | /* |
546 | * Return the one interrupt that triggered (this can | 561 | * Return the one interrupt that triggered (this can |
547 | * handle any interrupt source). | 562 | * handle any interrupt source). |
@@ -571,6 +586,8 @@ int probe_irq_off(unsigned long xmask) | |||
571 | return -1; | 586 | return -1; |
572 | } | 587 | } |
573 | 588 | ||
589 | EXPORT_SYMBOL(probe_irq_off); | ||
590 | |||
574 | /* this was setup_x86_irq but it seems pretty generic */ | 591 | /* this was setup_x86_irq but it seems pretty generic */ |
575 | int setup_irq(unsigned int irq, struct irqaction *new) | 592 | int setup_irq(unsigned int irq, struct irqaction *new) |
576 | { | 593 | { |
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c new file mode 100644 index 0000000000..850d168f69 --- /dev/null +++ b/arch/frv/kernel/module.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* module.c: FRV specific module loading bits | ||
2 | * | ||
3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * - Derived from arch/i386/kernel/module.c, Copyright (C) 2001 Rusty Russell. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/moduleloader.h> | ||
13 | #include <linux/elf.h> | ||
14 | #include <linux/vmalloc.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/kernel.h> | ||
18 | |||
19 | #if 0 | ||
20 | #define DEBUGP printk | ||
21 | #else | ||
22 | #define DEBUGP(fmt...) | ||
23 | #endif | ||
24 | |||
25 | void *module_alloc(unsigned long size) | ||
26 | { | ||
27 | if (size == 0) | ||
28 | return NULL; | ||
29 | |||
30 | return vmalloc_exec(size); | ||
31 | } | ||
32 | |||
33 | |||
34 | /* Free memory returned from module_alloc */ | ||
35 | void module_free(struct module *mod, void *module_region) | ||
36 | { | ||
37 | vfree(module_region); | ||
38 | /* FIXME: If module_region == mod->init_region, trim exception | ||
39 | table entries. */ | ||
40 | } | ||
41 | |||
42 | /* We don't need anything special. */ | ||
43 | int module_frob_arch_sections(Elf_Ehdr *hdr, | ||
44 | Elf_Shdr *sechdrs, | ||
45 | char *secstrings, | ||
46 | struct module *mod) | ||
47 | { | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
52 | const char *strtab, | ||
53 | unsigned int symindex, | ||
54 | unsigned int relsec, | ||
55 | struct module *me) | ||
56 | { | ||
57 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); | ||
58 | return -ENOEXEC; | ||
59 | } | ||
60 | |||
61 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
62 | const char *strtab, | ||
63 | unsigned int symindex, | ||
64 | unsigned int relsec, | ||
65 | struct module *me) | ||
66 | { | ||
67 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); | ||
68 | return -ENOEXEC; | ||
69 | } | ||
70 | |||
71 | int module_finalize(const Elf_Ehdr *hdr, | ||
72 | const Elf_Shdr *sechdrs, | ||
73 | struct module *me) | ||
74 | { | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | void module_arch_cleanup(struct module *mod) | ||
79 | { | ||
80 | } | ||
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index 1a1e8a119c..f0b8fff3e7 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c | |||
@@ -13,7 +13,9 @@ | |||
13 | 13 | ||
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/module.h> | ||
16 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/pm_legacy.h> | ||
17 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
18 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
19 | #include <linux/sysctl.h> | 21 | #include <linux/sysctl.h> |
@@ -26,6 +28,7 @@ | |||
26 | #include "local.h" | 28 | #include "local.h" |
27 | 29 | ||
28 | void (*pm_power_off)(void); | 30 | void (*pm_power_off)(void); |
31 | EXPORT_SYMBOL(pm_power_off); | ||
29 | 32 | ||
30 | extern void frv_change_cmode(int); | 33 | extern void frv_change_cmode(int); |
31 | 34 | ||
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 54a452136f..0fff8a61ef 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c | |||
@@ -204,7 +204,7 @@ int copy_thread(int nr, unsigned long clone_flags, | |||
204 | 204 | ||
205 | regs0 = __kernel_frame0_ptr; | 205 | regs0 = __kernel_frame0_ptr; |
206 | childregs0 = (struct pt_regs *) | 206 | childregs0 = (struct pt_regs *) |
207 | ((unsigned long) p->thread_info + THREAD_SIZE - USER_CONTEXT_SIZE); | 207 | (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE); |
208 | childregs = childregs0; | 208 | childregs = childregs0; |
209 | 209 | ||
210 | /* set up the userspace frame (the only place that the USP is stored) */ | 210 | /* set up the userspace frame (the only place that the USP is stored) */ |
@@ -220,7 +220,7 @@ int copy_thread(int nr, unsigned long clone_flags, | |||
220 | *childregs = *regs; | 220 | *childregs = *regs; |
221 | childregs->sp = (unsigned long) childregs0; | 221 | childregs->sp = (unsigned long) childregs0; |
222 | childregs->next_frame = childregs0; | 222 | childregs->next_frame = childregs0; |
223 | childregs->gr15 = (unsigned long) p->thread_info; | 223 | childregs->gr15 = (unsigned long) task_thread_info(p); |
224 | childregs->gr29 = (unsigned long) p; | 224 | childregs->gr29 = (unsigned long) p; |
225 | } | 225 | } |
226 | 226 | ||
@@ -244,28 +244,6 @@ int copy_thread(int nr, unsigned long clone_flags, | |||
244 | } /* end copy_thread() */ | 244 | } /* end copy_thread() */ |
245 | 245 | ||
246 | /* | 246 | /* |
247 | * fill in the user structure for a core dump.. | ||
248 | */ | ||
249 | void dump_thread(struct pt_regs *regs, struct user *dump) | ||
250 | { | ||
251 | #if 0 | ||
252 | /* changed the size calculations - should hopefully work better. lbt */ | ||
253 | dump->magic = CMAGIC; | ||
254 | dump->start_code = 0; | ||
255 | dump->start_stack = user_stack(regs) & ~(PAGE_SIZE - 1); | ||
256 | dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; | ||
257 | dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; | ||
258 | dump->u_dsize -= dump->u_tsize; | ||
259 | dump->u_ssize = 0; | ||
260 | |||
261 | if (dump->start_stack < TASK_SIZE) | ||
262 | dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; | ||
263 | |||
264 | dump->regs = *(struct user_context *) regs; | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * sys_execve() executes a new program. | 247 | * sys_execve() executes a new program. |
270 | */ | 248 | */ |
271 | asmlinkage int sys_execve(char *name, char **argv, char **envp) | 249 | asmlinkage int sys_execve(char *name, char **argv, char **envp) |
diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c index 5cba9c1f2b..7971d680ae 100644 --- a/arch/frv/kernel/semaphore.c +++ b/arch/frv/kernel/semaphore.c | |||
@@ -20,7 +20,7 @@ struct sem_waiter { | |||
20 | struct task_struct *task; | 20 | struct task_struct *task; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | #if SEM_DEBUG | 23 | #if SEMAPHORE_DEBUG |
24 | void semtrace(struct semaphore *sem, const char *str) | 24 | void semtrace(struct semaphore *sem, const char *str) |
25 | { | 25 | { |
26 | if (sem->debug) | 26 | if (sem->debug) |
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 767ebb55bd..5908deae96 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c | |||
@@ -787,6 +787,7 @@ void __init setup_arch(char **cmdline_p) | |||
787 | #endif | 787 | #endif |
788 | 788 | ||
789 | /* register those serial ports that are available */ | 789 | /* register those serial ports that are available */ |
790 | #ifdef CONFIG_FRV_ONCPU_SERIAL | ||
790 | #ifndef CONFIG_GDBSTUB_UART0 | 791 | #ifndef CONFIG_GDBSTUB_UART0 |
791 | __reg(UART0_BASE + UART_IER * 8) = 0; | 792 | __reg(UART0_BASE + UART_IER * 8) = 0; |
792 | early_serial_setup(&__frv_uart0); | 793 | early_serial_setup(&__frv_uart0); |
@@ -795,6 +796,7 @@ void __init setup_arch(char **cmdline_p) | |||
795 | __reg(UART1_BASE + UART_IER * 8) = 0; | 796 | __reg(UART1_BASE + UART_IER * 8) = 0; |
796 | early_serial_setup(&__frv_uart1); | 797 | early_serial_setup(&__frv_uart1); |
797 | #endif | 798 | #endif |
799 | #endif | ||
798 | 800 | ||
799 | #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) | 801 | #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) |
800 | /* we need to initialize the Flashrom device here since we might | 802 | /* we need to initialize the Flashrom device here since we might |
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d4ccc0728d..679c1d5cc9 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -35,74 +35,22 @@ struct fdpic_func_descriptor { | |||
35 | unsigned long GOT; | 35 | unsigned long GOT; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
39 | |||
40 | /* | 38 | /* |
41 | * Atomically swap in the new signal mask, and wait for a signal. | 39 | * Atomically swap in the new signal mask, and wait for a signal. |
42 | */ | 40 | */ |
43 | asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 41 | asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
44 | { | 42 | { |
45 | sigset_t saveset; | ||
46 | |||
47 | mask &= _BLOCKABLE; | 43 | mask &= _BLOCKABLE; |
48 | spin_lock_irq(¤t->sighand->siglock); | 44 | spin_lock_irq(¤t->sighand->siglock); |
49 | saveset = current->blocked; | 45 | current->saved_sigmask = current->blocked; |
50 | siginitset(¤t->blocked, mask); | 46 | siginitset(¤t->blocked, mask); |
51 | recalc_sigpending(); | 47 | recalc_sigpending(); |
52 | spin_unlock_irq(¤t->sighand->siglock); | 48 | spin_unlock_irq(¤t->sighand->siglock); |
53 | 49 | ||
54 | __frame->gr8 = -EINTR; | 50 | current->state = TASK_INTERRUPTIBLE; |
55 | while (1) { | 51 | schedule(); |
56 | current->state = TASK_INTERRUPTIBLE; | 52 | set_thread_flag(TIF_RESTORE_SIGMASK); |
57 | schedule(); | 53 | return -ERESTARTNOHAND; |
58 | if (do_signal(__frame, &saveset)) | ||
59 | /* return the signal number as the return value of this function | ||
60 | * - this is an utterly evil hack. syscalls should not invoke do_signal() | ||
61 | * as entry.S sets regs->gr8 to the return value of the system call | ||
62 | * - we can't just use sigpending() as we'd have to discard SIG_IGN signals | ||
63 | * and call waitpid() if SIGCHLD needed discarding | ||
64 | * - this only works on the i386 because it passes arguments to the signal | ||
65 | * handler on the stack, and the return value in EAX is effectively | ||
66 | * discarded | ||
67 | */ | ||
68 | return __frame->gr8; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) | ||
73 | { | ||
74 | sigset_t saveset, newset; | ||
75 | |||
76 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
77 | if (sigsetsize != sizeof(sigset_t)) | ||
78 | return -EINVAL; | ||
79 | |||
80 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
81 | return -EFAULT; | ||
82 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
83 | |||
84 | spin_lock_irq(¤t->sighand->siglock); | ||
85 | saveset = current->blocked; | ||
86 | current->blocked = newset; | ||
87 | recalc_sigpending(); | ||
88 | spin_unlock_irq(¤t->sighand->siglock); | ||
89 | |||
90 | __frame->gr8 = -EINTR; | ||
91 | while (1) { | ||
92 | current->state = TASK_INTERRUPTIBLE; | ||
93 | schedule(); | ||
94 | if (do_signal(__frame, &saveset)) | ||
95 | /* return the signal number as the return value of this function | ||
96 | * - this is an utterly evil hack. syscalls should not invoke do_signal() | ||
97 | * as entry.S sets regs->gr8 to the return value of the system call | ||
98 | * - we can't just use sigpending() as we'd have to discard SIG_IGN signals | ||
99 | * and call waitpid() if SIGCHLD needed discarding | ||
100 | * - this only works on the i386 because it passes arguments to the signal | ||
101 | * handler on the stack, and the return value in EAX is effectively | ||
102 | * discarded | ||
103 | */ | ||
104 | return __frame->gr8; | ||
105 | } | ||
106 | } | 54 | } |
107 | 55 | ||
108 | asmlinkage int sys_sigaction(int sig, | 56 | asmlinkage int sys_sigaction(int sig, |
@@ -276,13 +224,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask) | |||
276 | * Determine which stack to use.. | 224 | * Determine which stack to use.. |
277 | */ | 225 | */ |
278 | static inline void __user *get_sigframe(struct k_sigaction *ka, | 226 | static inline void __user *get_sigframe(struct k_sigaction *ka, |
279 | struct pt_regs *regs, | ||
280 | size_t frame_size) | 227 | size_t frame_size) |
281 | { | 228 | { |
282 | unsigned long sp; | 229 | unsigned long sp; |
283 | 230 | ||
284 | /* Default to using normal stack */ | 231 | /* Default to using normal stack */ |
285 | sp = regs->sp; | 232 | sp = __frame->sp; |
286 | 233 | ||
287 | /* This is the X/Open sanctioned signal stack switching. */ | 234 | /* This is the X/Open sanctioned signal stack switching. */ |
288 | if (ka->sa.sa_flags & SA_ONSTACK) { | 235 | if (ka->sa.sa_flags & SA_ONSTACK) { |
@@ -291,18 +238,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, | |||
291 | } | 238 | } |
292 | 239 | ||
293 | return (void __user *) ((sp - frame_size) & ~7UL); | 240 | return (void __user *) ((sp - frame_size) & ~7UL); |
241 | |||
294 | } /* end get_sigframe() */ | 242 | } /* end get_sigframe() */ |
295 | 243 | ||
296 | /*****************************************************************************/ | 244 | /*****************************************************************************/ |
297 | /* | 245 | /* |
298 | * | 246 | * |
299 | */ | 247 | */ |
300 | static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) | 248 | static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) |
301 | { | 249 | { |
302 | struct sigframe __user *frame; | 250 | struct sigframe __user *frame; |
303 | int rsig; | 251 | int rsig; |
304 | 252 | ||
305 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 253 | frame = get_sigframe(ka, sizeof(*frame)); |
306 | 254 | ||
307 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 255 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
308 | goto give_sigsegv; | 256 | goto give_sigsegv; |
@@ -346,47 +294,51 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p | |||
346 | } | 294 | } |
347 | 295 | ||
348 | /* set up registers for signal handler */ | 296 | /* set up registers for signal handler */ |
349 | regs->sp = (unsigned long) frame; | 297 | __frame->sp = (unsigned long) frame; |
350 | regs->lr = (unsigned long) &frame->retcode; | 298 | __frame->lr = (unsigned long) &frame->retcode; |
351 | regs->gr8 = sig; | 299 | __frame->gr8 = sig; |
352 | 300 | ||
353 | if (get_personality & FDPIC_FUNCPTRS) { | 301 | if (get_personality & FDPIC_FUNCPTRS) { |
354 | struct fdpic_func_descriptor __user *funcptr = | 302 | struct fdpic_func_descriptor __user *funcptr = |
355 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; | 303 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; |
356 | __get_user(regs->pc, &funcptr->text); | 304 | __get_user(__frame->pc, &funcptr->text); |
357 | __get_user(regs->gr15, &funcptr->GOT); | 305 | __get_user(__frame->gr15, &funcptr->GOT); |
358 | } else { | 306 | } else { |
359 | regs->pc = (unsigned long) ka->sa.sa_handler; | 307 | __frame->pc = (unsigned long) ka->sa.sa_handler; |
360 | regs->gr15 = 0; | 308 | __frame->gr15 = 0; |
361 | } | 309 | } |
362 | 310 | ||
363 | set_fs(USER_DS); | 311 | set_fs(USER_DS); |
364 | 312 | ||
313 | /* the tracer may want to single-step inside the handler */ | ||
314 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
315 | ptrace_notify(SIGTRAP); | ||
316 | |||
365 | #if DEBUG_SIG | 317 | #if DEBUG_SIG |
366 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", | 318 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", |
367 | sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); | 319 | sig, current->comm, current->pid, frame, __frame->pc, |
320 | frame->pretcode); | ||
368 | #endif | 321 | #endif |
369 | 322 | ||
370 | return; | 323 | return 0; |
371 | 324 | ||
372 | give_sigsegv: | 325 | give_sigsegv: |
373 | if (sig == SIGSEGV) | ||
374 | ka->sa.sa_handler = SIG_DFL; | ||
375 | |||
376 | force_sig(SIGSEGV, current); | 326 | force_sig(SIGSEGV, current); |
327 | return -EFAULT; | ||
328 | |||
377 | } /* end setup_frame() */ | 329 | } /* end setup_frame() */ |
378 | 330 | ||
379 | /*****************************************************************************/ | 331 | /*****************************************************************************/ |
380 | /* | 332 | /* |
381 | * | 333 | * |
382 | */ | 334 | */ |
383 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 335 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
384 | sigset_t *set, struct pt_regs * regs) | 336 | sigset_t *set) |
385 | { | 337 | { |
386 | struct rt_sigframe __user *frame; | 338 | struct rt_sigframe __user *frame; |
387 | int rsig; | 339 | int rsig; |
388 | 340 | ||
389 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 341 | frame = get_sigframe(ka, sizeof(*frame)); |
390 | 342 | ||
391 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 343 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
392 | goto give_sigsegv; | 344 | goto give_sigsegv; |
@@ -409,7 +361,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
409 | if (__put_user(0, &frame->uc.uc_flags) || | 361 | if (__put_user(0, &frame->uc.uc_flags) || |
410 | __put_user(0, &frame->uc.uc_link) || | 362 | __put_user(0, &frame->uc.uc_link) || |
411 | __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || | 363 | __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || |
412 | __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) || | 364 | __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || |
413 | __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) | 365 | __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) |
414 | goto give_sigsegv; | 366 | goto give_sigsegv; |
415 | 367 | ||
@@ -440,34 +392,38 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
440 | } | 392 | } |
441 | 393 | ||
442 | /* Set up registers for signal handler */ | 394 | /* Set up registers for signal handler */ |
443 | regs->sp = (unsigned long) frame; | 395 | __frame->sp = (unsigned long) frame; |
444 | regs->lr = (unsigned long) &frame->retcode; | 396 | __frame->lr = (unsigned long) &frame->retcode; |
445 | regs->gr8 = sig; | 397 | __frame->gr8 = sig; |
446 | regs->gr9 = (unsigned long) &frame->info; | 398 | __frame->gr9 = (unsigned long) &frame->info; |
447 | 399 | ||
448 | if (get_personality & FDPIC_FUNCPTRS) { | 400 | if (get_personality & FDPIC_FUNCPTRS) { |
449 | struct fdpic_func_descriptor *funcptr = | 401 | struct fdpic_func_descriptor *funcptr = |
450 | (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; | 402 | (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; |
451 | __get_user(regs->pc, &funcptr->text); | 403 | __get_user(__frame->pc, &funcptr->text); |
452 | __get_user(regs->gr15, &funcptr->GOT); | 404 | __get_user(__frame->gr15, &funcptr->GOT); |
453 | } else { | 405 | } else { |
454 | regs->pc = (unsigned long) ka->sa.sa_handler; | 406 | __frame->pc = (unsigned long) ka->sa.sa_handler; |
455 | regs->gr15 = 0; | 407 | __frame->gr15 = 0; |
456 | } | 408 | } |
457 | 409 | ||
458 | set_fs(USER_DS); | 410 | set_fs(USER_DS); |
459 | 411 | ||
412 | /* the tracer may want to single-step inside the handler */ | ||
413 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
414 | ptrace_notify(SIGTRAP); | ||
415 | |||
460 | #if DEBUG_SIG | 416 | #if DEBUG_SIG |
461 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", | 417 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", |
462 | sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); | 418 | sig, current->comm, current->pid, frame, __frame->pc, |
419 | frame->pretcode); | ||
463 | #endif | 420 | #endif |
464 | 421 | ||
465 | return; | 422 | return 0; |
466 | 423 | ||
467 | give_sigsegv: | 424 | give_sigsegv: |
468 | if (sig == SIGSEGV) | ||
469 | ka->sa.sa_handler = SIG_DFL; | ||
470 | force_sig(SIGSEGV, current); | 425 | force_sig(SIGSEGV, current); |
426 | return -EFAULT; | ||
471 | 427 | ||
472 | } /* end setup_rt_frame() */ | 428 | } /* end setup_rt_frame() */ |
473 | 429 | ||
@@ -475,43 +431,51 @@ give_sigsegv: | |||
475 | /* | 431 | /* |
476 | * OK, we're invoking a handler | 432 | * OK, we're invoking a handler |
477 | */ | 433 | */ |
478 | static void handle_signal(unsigned long sig, siginfo_t *info, | 434 | static int handle_signal(unsigned long sig, siginfo_t *info, |
479 | struct k_sigaction *ka, sigset_t *oldset, | 435 | struct k_sigaction *ka, sigset_t *oldset) |
480 | struct pt_regs *regs) | ||
481 | { | 436 | { |
437 | int ret; | ||
438 | |||
482 | /* Are we from a system call? */ | 439 | /* Are we from a system call? */ |
483 | if (in_syscall(regs)) { | 440 | if (in_syscall(__frame)) { |
484 | /* If so, check system call restarting.. */ | 441 | /* If so, check system call restarting.. */ |
485 | switch (regs->gr8) { | 442 | switch (__frame->gr8) { |
486 | case -ERESTART_RESTARTBLOCK: | 443 | case -ERESTART_RESTARTBLOCK: |
487 | case -ERESTARTNOHAND: | 444 | case -ERESTARTNOHAND: |
488 | regs->gr8 = -EINTR; | 445 | __frame->gr8 = -EINTR; |
489 | break; | 446 | break; |
490 | 447 | ||
491 | case -ERESTARTSYS: | 448 | case -ERESTARTSYS: |
492 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 449 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
493 | regs->gr8 = -EINTR; | 450 | __frame->gr8 = -EINTR; |
494 | break; | 451 | break; |
495 | } | 452 | } |
453 | |||
496 | /* fallthrough */ | 454 | /* fallthrough */ |
497 | case -ERESTARTNOINTR: | 455 | case -ERESTARTNOINTR: |
498 | regs->gr8 = regs->orig_gr8; | 456 | __frame->gr8 = __frame->orig_gr8; |
499 | regs->pc -= 4; | 457 | __frame->pc -= 4; |
500 | } | 458 | } |
501 | } | 459 | } |
502 | 460 | ||
503 | /* Set up the stack frame */ | 461 | /* Set up the stack frame */ |
504 | if (ka->sa.sa_flags & SA_SIGINFO) | 462 | if (ka->sa.sa_flags & SA_SIGINFO) |
505 | setup_rt_frame(sig, ka, info, oldset, regs); | 463 | ret = setup_rt_frame(sig, ka, info, oldset); |
506 | else | 464 | else |
507 | setup_frame(sig, ka, oldset, regs); | 465 | ret = setup_frame(sig, ka, oldset); |
466 | |||
467 | if (ret == 0) { | ||
468 | spin_lock_irq(¤t->sighand->siglock); | ||
469 | sigorsets(¤t->blocked, ¤t->blocked, | ||
470 | &ka->sa.sa_mask); | ||
471 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
472 | sigaddset(¤t->blocked, sig); | ||
473 | recalc_sigpending(); | ||
474 | spin_unlock_irq(¤t->sighand->siglock); | ||
475 | } | ||
476 | |||
477 | return ret; | ||
508 | 478 | ||
509 | spin_lock_irq(¤t->sighand->siglock); | ||
510 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
511 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
512 | sigaddset(¤t->blocked, sig); | ||
513 | recalc_sigpending(); | ||
514 | spin_unlock_irq(¤t->sighand->siglock); | ||
515 | } /* end handle_signal() */ | 479 | } /* end handle_signal() */ |
516 | 480 | ||
517 | /*****************************************************************************/ | 481 | /*****************************************************************************/ |
@@ -520,10 +484,11 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
520 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 484 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
521 | * mistake. | 485 | * mistake. |
522 | */ | 486 | */ |
523 | int do_signal(struct pt_regs *regs, sigset_t *oldset) | 487 | static void do_signal(void) |
524 | { | 488 | { |
525 | struct k_sigaction ka; | 489 | struct k_sigaction ka; |
526 | siginfo_t info; | 490 | siginfo_t info; |
491 | sigset_t *oldset; | ||
527 | int signr; | 492 | int signr; |
528 | 493 | ||
529 | /* | 494 | /* |
@@ -532,45 +497,63 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
532 | * kernel mode. Just return without doing anything | 497 | * kernel mode. Just return without doing anything |
533 | * if so. | 498 | * if so. |
534 | */ | 499 | */ |
535 | if (!user_mode(regs)) | 500 | if (!user_mode(__frame)) |
536 | return 1; | 501 | return; |
537 | 502 | ||
538 | if (try_to_freeze()) | 503 | if (try_to_freeze()) |
539 | goto no_signal; | 504 | goto no_signal; |
540 | 505 | ||
541 | if (!oldset) | 506 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
507 | oldset = ¤t->saved_sigmask; | ||
508 | else | ||
542 | oldset = ¤t->blocked; | 509 | oldset = ¤t->blocked; |
543 | 510 | ||
544 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 511 | signr = get_signal_to_deliver(&info, &ka, __frame, NULL); |
545 | if (signr > 0) { | 512 | if (signr > 0) { |
546 | handle_signal(signr, &info, &ka, oldset, regs); | 513 | if (handle_signal(signr, &info, &ka, oldset) == 0) { |
547 | return 1; | 514 | /* a signal was successfully delivered; the saved |
515 | * sigmask will have been stored in the signal frame, | ||
516 | * and will be restored by sigreturn, so we can simply | ||
517 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
518 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
519 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
520 | } | ||
521 | |||
522 | return; | ||
548 | } | 523 | } |
549 | 524 | ||
550 | no_signal: | 525 | no_signal: |
551 | /* Did we come from a system call? */ | 526 | /* Did we come from a system call? */ |
552 | if (regs->syscallno >= 0) { | 527 | if (__frame->syscallno >= 0) { |
553 | /* Restart the system call - no handlers present */ | 528 | /* Restart the system call - no handlers present */ |
554 | if (regs->gr8 == -ERESTARTNOHAND || | 529 | switch (__frame->gr8) { |
555 | regs->gr8 == -ERESTARTSYS || | 530 | case -ERESTARTNOHAND: |
556 | regs->gr8 == -ERESTARTNOINTR) { | 531 | case -ERESTARTSYS: |
557 | regs->gr8 = regs->orig_gr8; | 532 | case -ERESTARTNOINTR: |
558 | regs->pc -= 4; | 533 | __frame->gr8 = __frame->orig_gr8; |
559 | } | 534 | __frame->pc -= 4; |
535 | break; | ||
560 | 536 | ||
561 | if (regs->gr8 == -ERESTART_RESTARTBLOCK){ | 537 | case -ERESTART_RESTARTBLOCK: |
562 | regs->gr8 = __NR_restart_syscall; | 538 | __frame->gr8 = __NR_restart_syscall; |
563 | regs->pc -= 4; | 539 | __frame->pc -= 4; |
540 | break; | ||
564 | } | 541 | } |
565 | } | 542 | } |
566 | 543 | ||
567 | return 0; | 544 | /* if there's no signal to deliver, we just put the saved sigmask |
545 | * back */ | ||
546 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
547 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
548 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
549 | } | ||
550 | |||
568 | } /* end do_signal() */ | 551 | } /* end do_signal() */ |
569 | 552 | ||
570 | /*****************************************************************************/ | 553 | /*****************************************************************************/ |
571 | /* | 554 | /* |
572 | * notification of userspace execution resumption | 555 | * notification of userspace execution resumption |
573 | * - triggered by current->work.notify_resume | 556 | * - triggered by the TIF_WORK_MASK flags |
574 | */ | 557 | */ |
575 | asmlinkage void do_notify_resume(__u32 thread_info_flags) | 558 | asmlinkage void do_notify_resume(__u32 thread_info_flags) |
576 | { | 559 | { |
@@ -579,7 +562,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) | |||
579 | clear_thread_flag(TIF_SINGLESTEP); | 562 | clear_thread_flag(TIF_SINGLESTEP); |
580 | 563 | ||
581 | /* deal with pending signal delivery */ | 564 | /* deal with pending signal delivery */ |
582 | if (thread_info_flags & _TIF_SIGPENDING) | 565 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) |
583 | do_signal(__frame, NULL); | 566 | do_signal(); |
584 | 567 | ||
585 | } /* end do_notify_resume() */ | 568 | } /* end do_notify_resume() */ |
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c index 2e9741227b..24cf85f89e 100644 --- a/arch/frv/kernel/time.c +++ b/arch/frv/kernel/time.c | |||
@@ -189,6 +189,8 @@ void do_gettimeofday(struct timeval *tv) | |||
189 | tv->tv_usec = usec; | 189 | tv->tv_usec = usec; |
190 | } | 190 | } |
191 | 191 | ||
192 | EXPORT_SYMBOL(do_gettimeofday); | ||
193 | |||
192 | int do_settimeofday(struct timespec *tv) | 194 | int do_settimeofday(struct timespec *tv) |
193 | { | 195 | { |
194 | time_t wtm_sec, sec = tv->tv_sec; | 196 | time_t wtm_sec, sec = tv->tv_sec; |
@@ -218,6 +220,7 @@ int do_settimeofday(struct timespec *tv) | |||
218 | clock_was_set(); | 220 | clock_was_set(); |
219 | return 0; | 221 | return 0; |
220 | } | 222 | } |
223 | |||
221 | EXPORT_SYMBOL(do_settimeofday); | 224 | EXPORT_SYMBOL(do_settimeofday); |
222 | 225 | ||
223 | /* | 226 | /* |
diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index 89073cae4b..9eb84b2e6a 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/linkage.h> | 20 | #include <linux/linkage.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/module.h> | ||
22 | 23 | ||
23 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
24 | #include <asm/fpu.h> | 25 | #include <asm/fpu.h> |
@@ -250,6 +251,8 @@ void dump_stack(void) | |||
250 | show_stack(NULL, NULL); | 251 | show_stack(NULL, NULL); |
251 | } | 252 | } |
252 | 253 | ||
254 | EXPORT_SYMBOL(dump_stack); | ||
255 | |||
253 | void show_stack(struct task_struct *task, unsigned long *sp) | 256 | void show_stack(struct task_struct *task, unsigned long *sp) |
254 | { | 257 | { |
255 | } | 258 | } |
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c index f3fd58a5bc..9b751c0f0e 100644 --- a/arch/frv/kernel/uaccess.c +++ b/arch/frv/kernel/uaccess.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/module.h> | ||
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
14 | 15 | ||
15 | /*****************************************************************************/ | 16 | /*****************************************************************************/ |
@@ -58,8 +59,11 @@ long strncpy_from_user(char *dst, const char *src, long count) | |||
58 | memset(p, 0, count); /* clear remainder of buffer [security] */ | 59 | memset(p, 0, count); /* clear remainder of buffer [security] */ |
59 | 60 | ||
60 | return err; | 61 | return err; |
62 | |||
61 | } /* end strncpy_from_user() */ | 63 | } /* end strncpy_from_user() */ |
62 | 64 | ||
65 | EXPORT_SYMBOL(strncpy_from_user); | ||
66 | |||
63 | /*****************************************************************************/ | 67 | /*****************************************************************************/ |
64 | /* | 68 | /* |
65 | * Return the size of a string (including the ending 0) | 69 | * Return the size of a string (including the ending 0) |
@@ -92,4 +96,7 @@ long strnlen_user(const char *src, long count) | |||
92 | } | 96 | } |
93 | 97 | ||
94 | return p - src + 1; /* return length including NUL */ | 98 | return p - src + 1; /* return length including NUL */ |
99 | |||
95 | } /* end strnlen_user() */ | 100 | } /* end strnlen_user() */ |
101 | |||
102 | EXPORT_SYMBOL(strnlen_user); | ||
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index fceafd2cc2..f474534ba7 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S | |||
@@ -112,6 +112,7 @@ SECTIONS | |||
112 | #endif | 112 | #endif |
113 | ) | 113 | ) |
114 | SCHED_TEXT | 114 | SCHED_TEXT |
115 | LOCK_TEXT | ||
115 | *(.fixup) | 116 | *(.fixup) |
116 | *(.gnu.warning) | 117 | *(.gnu.warning) |
117 | *(.exitcall.exit) | 118 | *(.exitcall.exit) |
diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile index 19be2626d5..08be305c9f 100644 --- a/arch/frv/lib/Makefile +++ b/arch/frv/lib/Makefile | |||
@@ -3,6 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y := \ | 5 | lib-y := \ |
6 | __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o \ | 6 | __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \ |
7 | checksum.o memcpy.o memset.o atomic-ops.o \ | 7 | checksum.o memcpy.o memset.o atomic-ops.o \ |
8 | outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o | 8 | outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o |
diff --git a/arch/frv/lib/__ucmpdi2.S b/arch/frv/lib/__ucmpdi2.S new file mode 100644 index 0000000000..d892f16ffa --- /dev/null +++ b/arch/frv/lib/__ucmpdi2.S | |||
@@ -0,0 +1,45 @@ | |||
1 | /* __ucmpdi2.S: 64-bit unsigned compare | ||
2 | * | ||
3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | |||
13 | .text | ||
14 | .p2align 4 | ||
15 | |||
16 | ############################################################################### | ||
17 | # | ||
18 | # int __ucmpdi2(unsigned long long a [GR8:GR9], | ||
19 | # unsigned long long b [GR10:GR11]) | ||
20 | # | ||
21 | # - returns 0, 1, or 2 as a <, =, > b respectively. | ||
22 | # | ||
23 | ############################################################################### | ||
24 | .globl __ucmpdi2 | ||
25 | .type __ucmpdi2,@function | ||
26 | __ucmpdi2: | ||
27 | or.p gr8,gr0,gr4 | ||
28 | subcc gr8,gr10,gr0,icc0 | ||
29 | setlos.p #0,gr8 | ||
30 | bclr icc0,#2 ; a.msw < b.msw | ||
31 | |||
32 | setlos.p #2,gr8 | ||
33 | bhilr icc0,#0 ; a.msw > b.msw | ||
34 | |||
35 | subcc.p gr9,gr11,gr0,icc1 | ||
36 | setlos #0,gr8 | ||
37 | setlos.p #2,gr9 | ||
38 | setlos #1,gr7 | ||
39 | cknc icc1,cc6 | ||
40 | cor.p gr9,gr0,gr8, cc6,#1 | ||
41 | cckls icc1,cc4, cc6,#1 | ||
42 | andcr cc6,cc4,cc4 | ||
43 | cor gr7,gr0,gr8, cc4,#1 | ||
44 | bralr | ||
45 | .size __ucmpdi2, .-__ucmpdi2 | ||
diff --git a/arch/frv/lib/atomic-ops.S b/arch/frv/lib/atomic-ops.S index b03d510a89..545cd325ac 100644 --- a/arch/frv/lib/atomic-ops.S +++ b/arch/frv/lib/atomic-ops.S | |||
@@ -129,48 +129,6 @@ atomic_sub_return: | |||
129 | 129 | ||
130 | ############################################################################### | 130 | ############################################################################### |
131 | # | 131 | # |
132 | # uint8_t __xchg_8(uint8_t i, uint8_t *v) | ||
133 | # | ||
134 | ############################################################################### | ||
135 | .globl __xchg_8 | ||
136 | .type __xchg_8,@function | ||
137 | __xchg_8: | ||
138 | or.p gr8,gr8,gr10 | ||
139 | 0: | ||
140 | orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ | ||
141 | ckeq icc3,cc7 | ||
142 | ldub.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */ | ||
143 | orcr cc7,cc7,cc3 /* set CC3 to true */ | ||
144 | cstb.p gr10,@(gr9,gr0) ,cc3,#1 | ||
145 | corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ | ||
146 | beq icc3,#0,0b | ||
147 | bralr | ||
148 | |||
149 | .size __xchg_8, .-__xchg_8 | ||
150 | |||
151 | ############################################################################### | ||
152 | # | ||
153 | # uint16_t __xchg_16(uint16_t i, uint16_t *v) | ||
154 | # | ||
155 | ############################################################################### | ||
156 | .globl __xchg_16 | ||
157 | .type __xchg_16,@function | ||
158 | __xchg_16: | ||
159 | or.p gr8,gr8,gr10 | ||
160 | 0: | ||
161 | orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ | ||
162 | ckeq icc3,cc7 | ||
163 | lduh.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */ | ||
164 | orcr cc7,cc7,cc3 /* set CC3 to true */ | ||
165 | csth.p gr10,@(gr9,gr0) ,cc3,#1 | ||
166 | corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ | ||
167 | beq icc3,#0,0b | ||
168 | bralr | ||
169 | |||
170 | .size __xchg_16, .-__xchg_16 | ||
171 | |||
172 | ############################################################################### | ||
173 | # | ||
174 | # uint32_t __xchg_32(uint32_t i, uint32_t *v) | 132 | # uint32_t __xchg_32(uint32_t i, uint32_t *v) |
175 | # | 133 | # |
176 | ############################################################################### | 134 | ############################################################################### |
@@ -192,56 +150,6 @@ __xchg_32: | |||
192 | 150 | ||
193 | ############################################################################### | 151 | ############################################################################### |
194 | # | 152 | # |
195 | # uint8_t __cmpxchg_8(uint8_t *v, uint8_t test, uint8_t new) | ||
196 | # | ||
197 | ############################################################################### | ||
198 | .globl __cmpxchg_8 | ||
199 | .type __cmpxchg_8,@function | ||
200 | __cmpxchg_8: | ||
201 | or.p gr8,gr8,gr11 | ||
202 | 0: | ||
203 | orcc gr0,gr0,gr0,icc3 | ||
204 | ckeq icc3,cc7 | ||
205 | ldub.p @(gr11,gr0),gr8 | ||
206 | orcr cc7,cc7,cc3 | ||
207 | sub gr8,gr9,gr7 | ||
208 | sllicc gr7,#24,gr0,icc0 | ||
209 | bne icc0,#0,1f | ||
210 | cstb.p gr10,@(gr11,gr0) ,cc3,#1 | ||
211 | corcc gr29,gr29,gr0 ,cc3,#1 | ||
212 | beq icc3,#0,0b | ||
213 | 1: | ||
214 | bralr | ||
215 | |||
216 | .size __cmpxchg_8, .-__cmpxchg_8 | ||
217 | |||
218 | ############################################################################### | ||
219 | # | ||
220 | # uint16_t __cmpxchg_16(uint16_t *v, uint16_t test, uint16_t new) | ||
221 | # | ||
222 | ############################################################################### | ||
223 | .globl __cmpxchg_16 | ||
224 | .type __cmpxchg_16,@function | ||
225 | __cmpxchg_16: | ||
226 | or.p gr8,gr8,gr11 | ||
227 | 0: | ||
228 | orcc gr0,gr0,gr0,icc3 | ||
229 | ckeq icc3,cc7 | ||
230 | lduh.p @(gr11,gr0),gr8 | ||
231 | orcr cc7,cc7,cc3 | ||
232 | sub gr8,gr9,gr7 | ||
233 | sllicc gr7,#16,gr0,icc0 | ||
234 | bne icc0,#0,1f | ||
235 | csth.p gr10,@(gr11,gr0) ,cc3,#1 | ||
236 | corcc gr29,gr29,gr0 ,cc3,#1 | ||
237 | beq icc3,#0,0b | ||
238 | 1: | ||
239 | bralr | ||
240 | |||
241 | .size __cmpxchg_16, .-__cmpxchg_16 | ||
242 | |||
243 | ############################################################################### | ||
244 | # | ||
245 | # uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new) | 153 | # uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new) |
246 | # | 154 | # |
247 | ############################################################################### | 155 | ############################################################################### |
diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c index 7bf5bd6cac..20e7dfc474 100644 --- a/arch/frv/lib/checksum.c +++ b/arch/frv/lib/checksum.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <net/checksum.h> | 34 | #include <net/checksum.h> |
35 | #include <asm/checksum.h> | 35 | #include <asm/checksum.h> |
36 | #include <linux/module.h> | ||
36 | 37 | ||
37 | static inline unsigned short from32to16(unsigned long x) | 38 | static inline unsigned short from32to16(unsigned long x) |
38 | { | 39 | { |
@@ -115,34 +116,52 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) | |||
115 | return result; | 116 | return result; |
116 | } | 117 | } |
117 | 118 | ||
119 | EXPORT_SYMBOL(csum_partial); | ||
120 | |||
118 | /* | 121 | /* |
119 | * this routine is used for miscellaneous IP-like checksums, mainly | 122 | * this routine is used for miscellaneous IP-like checksums, mainly |
120 | * in icmp.c | 123 | * in icmp.c |
121 | */ | 124 | */ |
122 | unsigned short ip_compute_csum(const unsigned char * buff, int len) | 125 | unsigned short ip_compute_csum(const unsigned char * buff, int len) |
123 | { | 126 | { |
124 | return ~do_csum(buff,len); | 127 | return ~do_csum(buff, len); |
125 | } | 128 | } |
126 | 129 | ||
130 | EXPORT_SYMBOL(ip_compute_csum); | ||
131 | |||
127 | /* | 132 | /* |
128 | * copy from fs while checksumming, otherwise like csum_partial | 133 | * copy from fs while checksumming, otherwise like csum_partial |
129 | */ | 134 | */ |
130 | |||
131 | unsigned int | 135 | unsigned int |
132 | csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err) | 136 | csum_partial_copy_from_user(const char __user *src, char *dst, |
137 | int len, int sum, int *csum_err) | ||
133 | { | 138 | { |
134 | if (csum_err) *csum_err = 0; | 139 | int rem; |
135 | memcpy(dst, src, len); | 140 | |
141 | if (csum_err) | ||
142 | *csum_err = 0; | ||
143 | |||
144 | rem = copy_from_user(dst, src, len); | ||
145 | if (rem != 0) { | ||
146 | if (csum_err) | ||
147 | *csum_err = -EFAULT; | ||
148 | memset(dst + len - rem, 0, rem); | ||
149 | len = rem; | ||
150 | } | ||
151 | |||
136 | return csum_partial(dst, len, sum); | 152 | return csum_partial(dst, len, sum); |
137 | } | 153 | } |
138 | 154 | ||
155 | EXPORT_SYMBOL(csum_partial_copy_from_user); | ||
156 | |||
139 | /* | 157 | /* |
140 | * copy from ds while checksumming, otherwise like csum_partial | 158 | * copy from ds while checksumming, otherwise like csum_partial |
141 | */ | 159 | */ |
142 | |||
143 | unsigned int | 160 | unsigned int |
144 | csum_partial_copy(const char *src, char *dst, int len, int sum) | 161 | csum_partial_copy(const char *src, char *dst, int len, int sum) |
145 | { | 162 | { |
146 | memcpy(dst, src, len); | 163 | memcpy(dst, src, len); |
147 | return csum_partial(dst, len, sum); | 164 | return csum_partial(dst, len, sum); |
148 | } | 165 | } |
166 | |||
167 | EXPORT_SYMBOL(csum_partial_copy); | ||
diff --git a/arch/frv/mb93090-mb00/Makefile b/arch/frv/mb93090-mb00/Makefile index 3faf0f8cf9..76595e8707 100644 --- a/arch/frv/mb93090-mb00/Makefile +++ b/arch/frv/mb93090-mb00/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | ifeq "$(CONFIG_PCI)" "y" | 5 | ifeq "$(CONFIG_PCI)" "y" |
6 | obj-y := pci-frv.o pci-irq.o pci-vdk.o | 6 | obj-y := pci-frv.o pci-irq.o pci-vdk.o pci-iomap.o |
7 | 7 | ||
8 | ifeq "$(CONFIG_MMU)" "y" | 8 | ifeq "$(CONFIG_MMU)" "y" |
9 | obj-y += pci-dma.o | 9 | obj-y += pci-dma.o |
diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c index 2082a9647f..4985466b1a 100644 --- a/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c | |||
@@ -83,6 +83,8 @@ void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_hand | |||
83 | return NULL; | 83 | return NULL; |
84 | } | 84 | } |
85 | 85 | ||
86 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
87 | |||
86 | void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) | 88 | void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) |
87 | { | 89 | { |
88 | struct dma_alloc_record *rec; | 90 | struct dma_alloc_record *rec; |
@@ -102,6 +104,8 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_ | |||
102 | BUG(); | 104 | BUG(); |
103 | } | 105 | } |
104 | 106 | ||
107 | EXPORT_SYMBOL(dma_free_coherent); | ||
108 | |||
105 | /* | 109 | /* |
106 | * Map a single buffer of the indicated size for DMA in streaming mode. | 110 | * Map a single buffer of the indicated size for DMA in streaming mode. |
107 | * The 32-bit bus address to use is returned. | 111 | * The 32-bit bus address to use is returned. |
@@ -120,6 +124,8 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
120 | return virt_to_bus(ptr); | 124 | return virt_to_bus(ptr); |
121 | } | 125 | } |
122 | 126 | ||
127 | EXPORT_SYMBOL(dma_map_single); | ||
128 | |||
123 | /* | 129 | /* |
124 | * Map a set of buffers described by scatterlist in streaming | 130 | * Map a set of buffers described by scatterlist in streaming |
125 | * mode for DMA. This is the scather-gather version of the | 131 | * mode for DMA. This is the scather-gather version of the |
@@ -150,3 +156,5 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
150 | 156 | ||
151 | return nents; | 157 | return nents; |
152 | } | 158 | } |
159 | |||
160 | EXPORT_SYMBOL(dma_map_sg); | ||
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c index 86fbdadc51..671ce1e843 100644 --- a/arch/frv/mb93090-mb00/pci-dma.c +++ b/arch/frv/mb93090-mb00/pci-dma.c | |||
@@ -28,11 +28,15 @@ void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_hand | |||
28 | return ret; | 28 | return ret; |
29 | } | 29 | } |
30 | 30 | ||
31 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
32 | |||
31 | void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) | 33 | void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) |
32 | { | 34 | { |
33 | consistent_free(vaddr); | 35 | consistent_free(vaddr); |
34 | } | 36 | } |
35 | 37 | ||
38 | EXPORT_SYMBOL(dma_free_coherent); | ||
39 | |||
36 | /* | 40 | /* |
37 | * Map a single buffer of the indicated size for DMA in streaming mode. | 41 | * Map a single buffer of the indicated size for DMA in streaming mode. |
38 | * The 32-bit bus address to use is returned. | 42 | * The 32-bit bus address to use is returned. |
@@ -51,6 +55,8 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
51 | return virt_to_bus(ptr); | 55 | return virt_to_bus(ptr); |
52 | } | 56 | } |
53 | 57 | ||
58 | EXPORT_SYMBOL(dma_map_single); | ||
59 | |||
54 | /* | 60 | /* |
55 | * Map a set of buffers described by scatterlist in streaming | 61 | * Map a set of buffers described by scatterlist in streaming |
56 | * mode for DMA. This is the scather-gather version of the | 62 | * mode for DMA. This is the scather-gather version of the |
@@ -96,6 +102,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
96 | return nents; | 102 | return nents; |
97 | } | 103 | } |
98 | 104 | ||
105 | EXPORT_SYMBOL(dma_map_sg); | ||
106 | |||
99 | dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, | 107 | dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, |
100 | size_t size, enum dma_data_direction direction) | 108 | size_t size, enum dma_data_direction direction) |
101 | { | 109 | { |
@@ -103,3 +111,5 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long off | |||
103 | flush_dcache_page(page); | 111 | flush_dcache_page(page); |
104 | return (dma_addr_t) page_to_phys(page) + offset; | 112 | return (dma_addr_t) page_to_phys(page) + offset; |
105 | } | 113 | } |
114 | |||
115 | EXPORT_SYMBOL(dma_map_page); | ||
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c index 83e5489cf0..0a26bf6f1c 100644 --- a/arch/frv/mb93090-mb00/pci-frv.c +++ b/arch/frv/mb93090-mb00/pci-frv.c | |||
@@ -142,9 +142,7 @@ static void __init pcibios_allocate_resources(int pass) | |||
142 | u16 command; | 142 | u16 command; |
143 | struct resource *r, *pr; | 143 | struct resource *r, *pr; |
144 | 144 | ||
145 | while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev), | 145 | for_each_pci_dev(dev) { |
146 | dev != NULL | ||
147 | ) { | ||
148 | pci_read_config_word(dev, PCI_COMMAND, &command); | 146 | pci_read_config_word(dev, PCI_COMMAND, &command); |
149 | for(idx = 0; idx < 6; idx++) { | 147 | for(idx = 0; idx < 6; idx++) { |
150 | r = &dev->resource[idx]; | 148 | r = &dev->resource[idx]; |
@@ -188,9 +186,7 @@ static void __init pcibios_assign_resources(void) | |||
188 | int idx; | 186 | int idx; |
189 | struct resource *r; | 187 | struct resource *r; |
190 | 188 | ||
191 | while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev), | 189 | for_each_pci_dev(dev) { |
192 | dev != NULL | ||
193 | ) { | ||
194 | int class = dev->class >> 8; | 190 | int class = dev->class >> 8; |
195 | 191 | ||
196 | /* Don't touch classless devices and host bridges */ | 192 | /* Don't touch classless devices and host bridges */ |
diff --git a/arch/frv/mb93090-mb00/pci-iomap.c b/arch/frv/mb93090-mb00/pci-iomap.c new file mode 100644 index 0000000000..068fa04bd5 --- /dev/null +++ b/arch/frv/mb93090-mb00/pci-iomap.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* pci-iomap.c: description | ||
2 | * | ||
3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/module.h> | ||
13 | |||
14 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
15 | { | ||
16 | unsigned long start = pci_resource_start(dev, bar); | ||
17 | unsigned long len = pci_resource_len(dev, bar); | ||
18 | unsigned long flags = pci_resource_flags(dev, bar); | ||
19 | |||
20 | if (!len || !start) | ||
21 | return NULL; | ||
22 | |||
23 | if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM)) | ||
24 | return (void __iomem *) start; | ||
25 | |||
26 | return NULL; | ||
27 | } | ||
28 | |||
29 | EXPORT_SYMBOL(pci_iomap); | ||
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c index af981bda01..c4a1144c98 100644 --- a/arch/frv/mb93090-mb00/pci-irq.c +++ b/arch/frv/mb93090-mb00/pci-irq.c | |||
@@ -48,9 +48,7 @@ void __init pcibios_fixup_irqs(void) | |||
48 | struct pci_dev *dev = NULL; | 48 | struct pci_dev *dev = NULL; |
49 | uint8_t line, pin; | 49 | uint8_t line, pin; |
50 | 50 | ||
51 | while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev), | 51 | for_each_pci_dev(dev) { |
52 | dev != NULL | ||
53 | ) { | ||
54 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | 52 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); |
55 | if (pin) { | 53 | if (pin) { |
56 | dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1]; | 54 | dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1]; |
@@ -60,7 +58,7 @@ void __init pcibios_fixup_irqs(void) | |||
60 | } | 58 | } |
61 | } | 59 | } |
62 | 60 | ||
63 | void __init pcibios_penalize_isa_irq(int irq, int active) | 61 | void __init pcibios_penalize_isa_irq(int irq) |
64 | { | 62 | { |
65 | } | 63 | } |
66 | 64 | ||
diff --git a/arch/frv/mm/cache-page.c b/arch/frv/mm/cache-page.c index 683b5e3443..0261cbe153 100644 --- a/arch/frv/mm/cache-page.c +++ b/arch/frv/mm/cache-page.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/highmem.h> | 13 | #include <linux/highmem.h> |
14 | #include <linux/module.h> | ||
14 | #include <asm/pgalloc.h> | 15 | #include <asm/pgalloc.h> |
15 | 16 | ||
16 | /*****************************************************************************/ | 17 | /*****************************************************************************/ |
@@ -38,6 +39,8 @@ void flush_dcache_page(struct page *page) | |||
38 | 39 | ||
39 | } /* end flush_dcache_page() */ | 40 | } /* end flush_dcache_page() */ |
40 | 41 | ||
42 | EXPORT_SYMBOL(flush_dcache_page); | ||
43 | |||
41 | /*****************************************************************************/ | 44 | /*****************************************************************************/ |
42 | /* | 45 | /* |
43 | * ICI takes a virtual address and the page may not currently have one | 46 | * ICI takes a virtual address and the page may not currently have one |
@@ -64,3 +67,5 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, | |||
64 | } | 67 | } |
65 | 68 | ||
66 | } /* end flush_icache_user_range() */ | 69 | } /* end flush_icache_user_range() */ |
70 | |||
71 | EXPORT_SYMBOL(flush_icache_user_range); | ||
diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c index 41be1128dc..caacf030ac 100644 --- a/arch/frv/mm/extable.c +++ b/arch/frv/mm/extable.c | |||
@@ -43,7 +43,7 @@ static inline unsigned long search_one_table(const struct exception_table_entry | |||
43 | */ | 43 | */ |
44 | unsigned long search_exception_table(unsigned long pc) | 44 | unsigned long search_exception_table(unsigned long pc) |
45 | { | 45 | { |
46 | unsigned long ret = 0; | 46 | const struct exception_table_entry *extab; |
47 | 47 | ||
48 | /* determine if the fault lay during a memcpy_user or a memset_user */ | 48 | /* determine if the fault lay during a memcpy_user or a memset_user */ |
49 | if (__frame->lr == (unsigned long) &__memset_user_error_lr && | 49 | if (__frame->lr == (unsigned long) &__memset_user_error_lr && |
@@ -55,9 +55,10 @@ unsigned long search_exception_table(unsigned long pc) | |||
55 | */ | 55 | */ |
56 | return (unsigned long) &__memset_user_error_handler; | 56 | return (unsigned long) &__memset_user_error_handler; |
57 | } | 57 | } |
58 | else if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && | 58 | |
59 | (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end | 59 | if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && |
60 | ) { | 60 | (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end |
61 | ) { | ||
61 | /* the fault occurred in a protected memset | 62 | /* the fault occurred in a protected memset |
62 | * - we search for the return address (in LR) instead of the program counter | 63 | * - we search for the return address (in LR) instead of the program counter |
63 | * - it was probably during a copy_to/from_user() | 64 | * - it was probably during a copy_to/from_user() |
@@ -65,27 +66,10 @@ unsigned long search_exception_table(unsigned long pc) | |||
65 | return (unsigned long) &__memcpy_user_error_handler; | 66 | return (unsigned long) &__memcpy_user_error_handler; |
66 | } | 67 | } |
67 | 68 | ||
68 | #ifndef CONFIG_MODULES | 69 | extab = search_exception_tables(pc); |
69 | /* there is only the kernel to search. */ | 70 | if (extab) |
70 | ret = search_one_table(__start___ex_table, __stop___ex_table - 1, pc); | 71 | return extab->fixup; |
71 | return ret; | ||
72 | |||
73 | #else | ||
74 | /* the kernel is the last "module" -- no need to treat it special */ | ||
75 | unsigned long flags; | ||
76 | struct module *mp; | ||
77 | 72 | ||
78 | spin_lock_irqsave(&modlist_lock, flags); | 73 | return 0; |
79 | |||
80 | for (mp = module_list; mp != NULL; mp = mp->next) { | ||
81 | if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) | ||
82 | continue; | ||
83 | ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, pc); | ||
84 | if (ret) | ||
85 | break; | ||
86 | } | ||
87 | 74 | ||
88 | spin_unlock_irqrestore(&modlist_lock, flags); | ||
89 | return ret; | ||
90 | #endif | ||
91 | } /* end search_exception_table() */ | 75 | } /* end search_exception_table() */ |
diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c index 7dc8fbf3af..7f77db7fab 100644 --- a/arch/frv/mm/highmem.c +++ b/arch/frv/mm/highmem.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | #include <linux/highmem.h> | 11 | #include <linux/highmem.h> |
12 | #include <linux/module.h> | ||
12 | 13 | ||
13 | void *kmap(struct page *page) | 14 | void *kmap(struct page *page) |
14 | { | 15 | { |
@@ -18,6 +19,8 @@ void *kmap(struct page *page) | |||
18 | return kmap_high(page); | 19 | return kmap_high(page); |
19 | } | 20 | } |
20 | 21 | ||
22 | EXPORT_SYMBOL(kmap); | ||
23 | |||
21 | void kunmap(struct page *page) | 24 | void kunmap(struct page *page) |
22 | { | 25 | { |
23 | if (in_interrupt()) | 26 | if (in_interrupt()) |
@@ -27,7 +30,12 @@ void kunmap(struct page *page) | |||
27 | kunmap_high(page); | 30 | kunmap_high(page); |
28 | } | 31 | } |
29 | 32 | ||
33 | EXPORT_SYMBOL(kunmap); | ||
34 | |||
30 | struct page *kmap_atomic_to_page(void *ptr) | 35 | struct page *kmap_atomic_to_page(void *ptr) |
31 | { | 36 | { |
32 | return virt_to_page(ptr); | 37 | return virt_to_page(ptr); |
33 | } | 38 | } |
39 | |||
40 | |||
41 | EXPORT_SYMBOL(kmap_atomic_to_page); | ||
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index 79433159b5..765088ea8a 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c | |||
@@ -108,7 +108,7 @@ void __init paging_init(void) | |||
108 | 108 | ||
109 | memset((void *) empty_zero_page, 0, PAGE_SIZE); | 109 | memset((void *) empty_zero_page, 0, PAGE_SIZE); |
110 | 110 | ||
111 | #if CONFIG_HIGHMEM | 111 | #ifdef CONFIG_HIGHMEM |
112 | if (num_physpages - num_mappedpages) { | 112 | if (num_physpages - num_mappedpages) { |
113 | pgd_t *pge; | 113 | pgd_t *pge; |
114 | pud_t *pue; | 114 | pud_t *pue; |
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c index 2c67dfe5a6..f76dd03ddd 100644 --- a/arch/frv/mm/pgalloc.c +++ b/arch/frv/mm/pgalloc.c | |||
@@ -85,7 +85,7 @@ static inline void pgd_list_add(pgd_t *pgd) | |||
85 | struct page *page = virt_to_page(pgd); | 85 | struct page *page = virt_to_page(pgd); |
86 | page->index = (unsigned long) pgd_list; | 86 | page->index = (unsigned long) pgd_list; |
87 | if (pgd_list) | 87 | if (pgd_list) |
88 | pgd_list->private = (unsigned long) &page->index; | 88 | set_page_private(pgd_list, (unsigned long) &page->index); |
89 | pgd_list = page; | 89 | pgd_list = page; |
90 | set_page_private(page, (unsigned long)&pgd_list); | 90 | set_page_private(page, (unsigned long)&pgd_list); |
91 | } | 91 | } |
@@ -94,10 +94,10 @@ static inline void pgd_list_del(pgd_t *pgd) | |||
94 | { | 94 | { |
95 | struct page *next, **pprev, *page = virt_to_page(pgd); | 95 | struct page *next, **pprev, *page = virt_to_page(pgd); |
96 | next = (struct page *) page->index; | 96 | next = (struct page *) page->index; |
97 | pprev = (struct page **)page_private(page); | 97 | pprev = (struct page **) page_private(page); |
98 | *pprev = next; | 98 | *pprev = next; |
99 | if (next) | 99 | if (next) |
100 | next->private = (unsigned long) pprev; | 100 | set_page_private(next, (unsigned long) pprev); |
101 | } | 101 | } |
102 | 102 | ||
103 | void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) | 103 | void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) |