diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 00:13:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 00:13:26 -0500 |
commit | 5f32ed140dac726e880d292988ba20d16f545bda (patch) | |
tree | f08589f9489a05eb7a0b7f855ab96c57b0561cde /arch/parisc | |
parent | c68fea3464cbe4f3e1382f9f74a7c04cdbfb92ad (diff) | |
parent | 1dda59b4f3d03fa28d86f3ea235655f0f96aab3e (diff) |
Merge branch 'parisc-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc updates from Helge Deller.
The bulk of this is optimized page coping/clearing and cache flushing
(virtual caches are lovely) by John David Anglin.
* 'parisc-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: (31 commits)
arch/parisc/include/asm: use ARRAY_SIZE macro in mmzone.h
parisc: remove empty lines and unnecessary #ifdef coding in include/asm/signal.h
parisc: sendfile and sendfile64 syscall cleanups
parisc: switch to available compat_sched_rr_get_interval implementation
parisc: fix fallocate syscall
parisc: fix error return codes for rt_sigaction and rt_sigprocmask
parisc: convert msgrcv and msgsnd syscalls to use compat layer
parisc: correctly wire up mq_* functions for CONFIG_COMPAT case
parisc: fix personality on 32bit kernel
parisc: wire up process_vm_readv, process_vm_writev, kcmp and finit_module syscalls
parisc: led driver requires CONFIG_VM_EVENT_COUNTERS
parisc: remove unused compat_rt_sigframe.h header
parisc/mm/fault.c: Port OOM changes to do_page_fault
parisc: space register variables need to be in native length (unsigned long)
parisc: fix ptrace breakage
parisc: always detect multiple physical ranges
parisc: ensure that mmapped shared pages are aligned at SHMLBA addresses
parisc: disable preemption while flushing D- or I-caches through TMPALIAS region
parisc: remove IRQF_DISABLED
parisc: fixes and cleanups in page cache flushing (4/4)
...
Diffstat (limited to 'arch/parisc')
27 files changed, 697 insertions, 299 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index c600f39aa453..7f9b3c53f74a 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -160,6 +160,23 @@ config PREFETCH | |||
160 | def_bool y | 160 | def_bool y |
161 | depends on PA8X00 || PA7200 | 161 | depends on PA8X00 || PA7200 |
162 | 162 | ||
163 | config MLONGCALLS | ||
164 | bool "Enable the -mlong-calls compiler option for big kernels" | ||
165 | def_bool y if (!MODULES) | ||
166 | depends on PA8X00 | ||
167 | help | ||
168 | If you configure the kernel to include many drivers built-in instead | ||
169 | as modules, the kernel executable may become too big, so that the | ||
170 | linker will not be able to resolve some long branches and fails to link | ||
171 | your vmlinux kernel. In that case enabling this option will help you | ||
172 | to overcome this limit by using the -mlong-calls compiler option. | ||
173 | |||
174 | Usually you want to say N here, unless you e.g. want to build | ||
175 | a kernel which includes all necessary drivers built-in and which can | ||
176 | be used for TFTP booting without the need to have an initrd ramdisk. | ||
177 | |||
178 | Enabling this option will probably slow down your kernel. | ||
179 | |||
163 | config 64BIT | 180 | config 64BIT |
164 | bool "64-bit kernel" | 181 | bool "64-bit kernel" |
165 | depends on PA8X00 | 182 | depends on PA8X00 |
@@ -254,6 +271,10 @@ config COMPAT | |||
254 | def_bool y | 271 | def_bool y |
255 | depends on 64BIT | 272 | depends on 64BIT |
256 | 273 | ||
274 | config SYSVIPC_COMPAT | ||
275 | def_bool y | ||
276 | depends on COMPAT && SYSVIPC | ||
277 | |||
257 | config HPUX | 278 | config HPUX |
258 | bool "Support for HP-UX binaries" | 279 | bool "Support for HP-UX binaries" |
259 | depends on !64BIT | 280 | depends on !64BIT |
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 5707f1a62341..ed9a14ccd066 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile | |||
@@ -32,11 +32,6 @@ ifdef CONFIG_64BIT | |||
32 | UTS_MACHINE := parisc64 | 32 | UTS_MACHINE := parisc64 |
33 | CHECKFLAGS += -D__LP64__=1 -m64 | 33 | CHECKFLAGS += -D__LP64__=1 -m64 |
34 | WIDTH := 64 | 34 | WIDTH := 64 |
35 | |||
36 | # FIXME: if no default set, should really try to locate dynamically | ||
37 | ifeq ($(CROSS_COMPILE),) | ||
38 | CROSS_COMPILE := hppa64-linux-gnu- | ||
39 | endif | ||
40 | else # 32-bit | 35 | else # 32-bit |
41 | WIDTH := | 36 | WIDTH := |
42 | endif | 37 | endif |
@@ -44,6 +39,10 @@ endif | |||
44 | # attempt to help out folks who are cross-compiling | 39 | # attempt to help out folks who are cross-compiling |
45 | ifeq ($(NATIVE),1) | 40 | ifeq ($(NATIVE),1) |
46 | CROSS_COMPILE := hppa$(WIDTH)-linux- | 41 | CROSS_COMPILE := hppa$(WIDTH)-linux- |
42 | else | ||
43 | ifeq ($(CROSS_COMPILE),) | ||
44 | CROSS_COMPILE := hppa$(WIDTH)-linux-gnu- | ||
45 | endif | ||
47 | endif | 46 | endif |
48 | 47 | ||
49 | OBJCOPY_FLAGS =-O binary -R .note -R .comment -S | 48 | OBJCOPY_FLAGS =-O binary -R .note -R .comment -S |
@@ -65,6 +64,10 @@ ifndef CONFIG_FUNCTION_TRACER | |||
65 | cflags-y += -ffunction-sections | 64 | cflags-y += -ffunction-sections |
66 | endif | 65 | endif |
67 | 66 | ||
67 | # Use long jumps instead of long branches (needed if your linker fails to | ||
68 | # link a too big vmlinux executable) | ||
69 | cflags-$(CONFIG_MLONGCALLS) += -mlong-calls | ||
70 | |||
68 | # select which processor to optimise for | 71 | # select which processor to optimise for |
69 | cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100 | 72 | cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100 |
70 | cflags-$(CONFIG_PA7200) += -march=1.1 -mschedule=7200 | 73 | cflags-$(CONFIG_PA7200) += -march=1.1 -mschedule=7200 |
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index a0760b87fd4e..838b479a42c4 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c | |||
@@ -43,8 +43,7 @@ int hpux_execve(struct pt_regs *regs) | |||
43 | 43 | ||
44 | error = do_execve(filename->name, | 44 | error = do_execve(filename->name, |
45 | (const char __user *const __user *) regs->gr[25], | 45 | (const char __user *const __user *) regs->gr[25], |
46 | (const char __user *const __user *) regs->gr[24], | 46 | (const char __user *const __user *) regs->gr[24]); |
47 | regs); | ||
48 | 47 | ||
49 | putname(filename); | 48 | putname(filename); |
50 | 49 | ||
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index 9f21ab0c02e3..79f694f3ad9b 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h | |||
@@ -115,7 +115,9 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma | |||
115 | { | 115 | { |
116 | if (PageAnon(page)) { | 116 | if (PageAnon(page)) { |
117 | flush_tlb_page(vma, vmaddr); | 117 | flush_tlb_page(vma, vmaddr); |
118 | preempt_disable(); | ||
118 | flush_dcache_page_asm(page_to_phys(page), vmaddr); | 119 | flush_dcache_page_asm(page_to_phys(page), vmaddr); |
120 | preempt_enable(); | ||
119 | } | 121 | } |
120 | } | 122 | } |
121 | 123 | ||
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index db7a662691a8..94710cfc1ce8 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h | |||
@@ -28,6 +28,7 @@ typedef u16 compat_nlink_t; | |||
28 | typedef u16 compat_ipc_pid_t; | 28 | typedef u16 compat_ipc_pid_t; |
29 | typedef s32 compat_daddr_t; | 29 | typedef s32 compat_daddr_t; |
30 | typedef u32 compat_caddr_t; | 30 | typedef u32 compat_caddr_t; |
31 | typedef s32 compat_key_t; | ||
31 | typedef s32 compat_timer_t; | 32 | typedef s32 compat_timer_t; |
32 | 33 | ||
33 | typedef s32 compat_int_t; | 34 | typedef s32 compat_int_t; |
@@ -188,6 +189,66 @@ typedef struct compat_siginfo { | |||
188 | #define COMPAT_OFF_T_MAX 0x7fffffff | 189 | #define COMPAT_OFF_T_MAX 0x7fffffff |
189 | #define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL | 190 | #define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL |
190 | 191 | ||
192 | struct compat_ipc64_perm { | ||
193 | compat_key_t key; | ||
194 | __compat_uid_t uid; | ||
195 | __compat_gid_t gid; | ||
196 | __compat_uid_t cuid; | ||
197 | __compat_gid_t cgid; | ||
198 | unsigned short int __pad1; | ||
199 | compat_mode_t mode; | ||
200 | unsigned short int __pad2; | ||
201 | unsigned short int seq; | ||
202 | unsigned int __pad3; | ||
203 | unsigned long __unused1; /* yes they really are 64bit pads */ | ||
204 | unsigned long __unused2; | ||
205 | }; | ||
206 | |||
207 | struct compat_semid64_ds { | ||
208 | struct compat_ipc64_perm sem_perm; | ||
209 | compat_time_t sem_otime; | ||
210 | unsigned int __unused1; | ||
211 | compat_time_t sem_ctime; | ||
212 | unsigned int __unused2; | ||
213 | compat_ulong_t sem_nsems; | ||
214 | compat_ulong_t __unused3; | ||
215 | compat_ulong_t __unused4; | ||
216 | }; | ||
217 | |||
218 | struct compat_msqid64_ds { | ||
219 | struct compat_ipc64_perm msg_perm; | ||
220 | unsigned int __unused1; | ||
221 | compat_time_t msg_stime; | ||
222 | unsigned int __unused2; | ||
223 | compat_time_t msg_rtime; | ||
224 | unsigned int __unused3; | ||
225 | compat_time_t msg_ctime; | ||
226 | compat_ulong_t msg_cbytes; | ||
227 | compat_ulong_t msg_qnum; | ||
228 | compat_ulong_t msg_qbytes; | ||
229 | compat_pid_t msg_lspid; | ||
230 | compat_pid_t msg_lrpid; | ||
231 | compat_ulong_t __unused4; | ||
232 | compat_ulong_t __unused5; | ||
233 | }; | ||
234 | |||
235 | struct compat_shmid64_ds { | ||
236 | struct compat_ipc64_perm shm_perm; | ||
237 | unsigned int __unused1; | ||
238 | compat_time_t shm_atime; | ||
239 | unsigned int __unused2; | ||
240 | compat_time_t shm_dtime; | ||
241 | unsigned int __unused3; | ||
242 | compat_time_t shm_ctime; | ||
243 | unsigned int __unused4; | ||
244 | compat_size_t shm_segsz; | ||
245 | compat_pid_t shm_cpid; | ||
246 | compat_pid_t shm_lpid; | ||
247 | compat_ulong_t shm_nattch; | ||
248 | compat_ulong_t __unused5; | ||
249 | compat_ulong_t __unused6; | ||
250 | }; | ||
251 | |||
191 | /* | 252 | /* |
192 | * A pointer passed in from user mode. This should not | 253 | * A pointer passed in from user mode. This should not |
193 | * be used for syscall parameters, just declare them | 254 | * be used for syscall parameters, just declare them |
diff --git a/arch/parisc/include/asm/compat_rt_sigframe.h b/arch/parisc/include/asm/compat_rt_sigframe.h deleted file mode 100644 index b3f95a7f18b4..000000000000 --- a/arch/parisc/include/asm/compat_rt_sigframe.h +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | #include <linux/compat.h> | ||
2 | #include <linux/compat_siginfo.h> | ||
3 | #include <asm/compat_ucontext.h> | ||
4 | |||
5 | #ifndef _ASM_PARISC_COMPAT_RT_SIGFRAME_H | ||
6 | #define _ASM_PARISC_COMPAT_RT_SIGFRAME_H | ||
7 | |||
8 | /* In a deft move of uber-hackery, we decide to carry the top half of all | ||
9 | * 64-bit registers in a non-portable, non-ABI, hidden structure. | ||
10 | * Userspace can read the hidden structure if it *wants* but is never | ||
11 | * guaranteed to be in the same place. Infact the uc_sigmask from the | ||
12 | * ucontext_t structure may push the hidden register file downards | ||
13 | */ | ||
14 | struct compat_regfile { | ||
15 | /* Upper half of all the 64-bit registers that were truncated | ||
16 | on a copy to a 32-bit userspace */ | ||
17 | compat_int_t rf_gr[32]; | ||
18 | compat_int_t rf_iasq[2]; | ||
19 | compat_int_t rf_iaoq[2]; | ||
20 | compat_int_t rf_sar; | ||
21 | }; | ||
22 | |||
23 | #define COMPAT_SIGRETURN_TRAMP 4 | ||
24 | #define COMPAT_SIGRESTARTBLOCK_TRAMP 5 | ||
25 | #define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + COMPAT_SIGRESTARTBLOCK_TRAMP) | ||
26 | |||
27 | struct compat_rt_sigframe { | ||
28 | /* XXX: Must match trampoline size in arch/parisc/kernel/signal.c | ||
29 | Secondary to that it must protect the ERESTART_RESTARTBLOCK | ||
30 | trampoline we left on the stack (we were bad and didn't | ||
31 | change sp so we could run really fast.) */ | ||
32 | compat_uint_t tramp[COMPAT_TRAMP_SIZE]; | ||
33 | compat_siginfo_t info; | ||
34 | struct compat_ucontext uc; | ||
35 | /* Hidden location of truncated registers, *must* be last. */ | ||
36 | struct compat_regfile regs; | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * The 32-bit ABI wants at least 48 bytes for a function call frame: | ||
41 | * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of | ||
42 | * which Linux/parisc uses is sp-20 for the saved return pointer...) | ||
43 | * Then, the stack pointer must be rounded to a cache line (64 bytes). | ||
44 | */ | ||
45 | #define SIGFRAME32 64 | ||
46 | #define FUNCTIONCALLFRAME32 48 | ||
47 | #define PARISC_RT_SIGFRAME_SIZE32 \ | ||
48 | (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32) | ||
49 | |||
50 | #endif | ||
diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h index 19f6cb1a4a1c..ad2b50397894 100644 --- a/arch/parisc/include/asm/elf.h +++ b/arch/parisc/include/asm/elf.h | |||
@@ -247,7 +247,7 @@ typedef unsigned long elf_greg_t; | |||
247 | #define ELF_PLATFORM ("PARISC\0") | 247 | #define ELF_PLATFORM ("PARISC\0") |
248 | 248 | ||
249 | #define SET_PERSONALITY(ex) \ | 249 | #define SET_PERSONALITY(ex) \ |
250 | current->personality = PER_LINUX; \ | 250 | set_personality((current->personality & ~PER_MASK) | PER_LINUX); \ |
251 | current->thread.map_base = DEFAULT_MAP_BASE; \ | 251 | current->thread.map_base = DEFAULT_MAP_BASE; \ |
252 | current->thread.task_size = DEFAULT_TASK_SIZE \ | 252 | current->thread.task_size = DEFAULT_TASK_SIZE \ |
253 | 253 | ||
diff --git a/arch/parisc/include/asm/floppy.h b/arch/parisc/include/asm/floppy.h index 4ca69f558fae..f84ff12574b7 100644 --- a/arch/parisc/include/asm/floppy.h +++ b/arch/parisc/include/asm/floppy.h | |||
@@ -157,10 +157,10 @@ static int fd_request_irq(void) | |||
157 | { | 157 | { |
158 | if(can_use_virtual_dma) | 158 | if(can_use_virtual_dma) |
159 | return request_irq(FLOPPY_IRQ, floppy_hardint, | 159 | return request_irq(FLOPPY_IRQ, floppy_hardint, |
160 | IRQF_DISABLED, "floppy", NULL); | 160 | 0, "floppy", NULL); |
161 | else | 161 | else |
162 | return request_irq(FLOPPY_IRQ, floppy_interrupt, | 162 | return request_irq(FLOPPY_IRQ, floppy_interrupt, |
163 | IRQF_DISABLED, "floppy", NULL); | 163 | 0, "floppy", NULL); |
164 | } | 164 | } |
165 | 165 | ||
166 | static unsigned long dma_mem_alloc(unsigned long size) | 166 | static unsigned long dma_mem_alloc(unsigned long size) |
diff --git a/arch/parisc/include/asm/mmzone.h b/arch/parisc/include/asm/mmzone.h index e67eb9c3d1bf..0e625ab9aaec 100644 --- a/arch/parisc/include/asm/mmzone.h +++ b/arch/parisc/include/asm/mmzone.h | |||
@@ -1,9 +1,10 @@ | |||
1 | #ifndef _PARISC_MMZONE_H | 1 | #ifndef _PARISC_MMZONE_H |
2 | #define _PARISC_MMZONE_H | 2 | #define _PARISC_MMZONE_H |
3 | 3 | ||
4 | #define MAX_PHYSMEM_RANGES 8 /* Fix the size for now (current known max is 3) */ | ||
5 | |||
4 | #ifdef CONFIG_DISCONTIGMEM | 6 | #ifdef CONFIG_DISCONTIGMEM |
5 | 7 | ||
6 | #define MAX_PHYSMEM_RANGES 8 /* Fix the size for now (current known max is 3) */ | ||
7 | extern int npmem_ranges; | 8 | extern int npmem_ranges; |
8 | 9 | ||
9 | struct node_map_data { | 10 | struct node_map_data { |
@@ -44,7 +45,7 @@ static inline int pfn_to_nid(unsigned long pfn) | |||
44 | return 0; | 45 | return 0; |
45 | 46 | ||
46 | i = pfn >> PFNNID_SHIFT; | 47 | i = pfn >> PFNNID_SHIFT; |
47 | BUG_ON(i >= sizeof(pfnnid_map) / sizeof(pfnnid_map[0])); | 48 | BUG_ON(i >= ARRAY_SIZE(pfnnid_map)); |
48 | r = pfnnid_map[i]; | 49 | r = pfnnid_map[i]; |
49 | BUG_ON(r == 0xff); | 50 | BUG_ON(r == 0xff); |
50 | 51 | ||
@@ -60,7 +61,5 @@ static inline int pfn_valid(int pfn) | |||
60 | return 0; | 61 | return 0; |
61 | } | 62 | } |
62 | 63 | ||
63 | #else /* !CONFIG_DISCONTIGMEM */ | ||
64 | #define MAX_PHYSMEM_RANGES 1 | ||
65 | #endif | 64 | #endif |
66 | #endif /* _PARISC_MMZONE_H */ | 65 | #endif /* _PARISC_MMZONE_H */ |
diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h index 4e0e7dbf0f3f..b7adb2ac049c 100644 --- a/arch/parisc/include/asm/page.h +++ b/arch/parisc/include/asm/page.h | |||
@@ -21,15 +21,27 @@ | |||
21 | #include <asm/types.h> | 21 | #include <asm/types.h> |
22 | #include <asm/cache.h> | 22 | #include <asm/cache.h> |
23 | 23 | ||
24 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) | 24 | #define clear_page(page) clear_page_asm((void *)(page)) |
25 | #define copy_page(to,from) copy_user_page_asm((void *)(to), (void *)(from)) | 25 | #define copy_page(to, from) copy_page_asm((void *)(to), (void *)(from)) |
26 | 26 | ||
27 | struct page; | 27 | struct page; |
28 | 28 | ||
29 | void copy_user_page_asm(void *to, void *from); | 29 | void clear_page_asm(void *page); |
30 | void copy_page_asm(void *to, void *from); | ||
31 | void clear_user_page(void *vto, unsigned long vaddr, struct page *pg); | ||
30 | void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, | 32 | void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, |
31 | struct page *pg); | 33 | struct page *pg); |
32 | void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | 34 | |
35 | /* #define CONFIG_PARISC_TMPALIAS */ | ||
36 | |||
37 | #ifdef CONFIG_PARISC_TMPALIAS | ||
38 | void clear_user_highpage(struct page *page, unsigned long vaddr); | ||
39 | #define clear_user_highpage clear_user_highpage | ||
40 | struct vm_area_struct; | ||
41 | void copy_user_highpage(struct page *to, struct page *from, | ||
42 | unsigned long vaddr, struct vm_area_struct *vma); | ||
43 | #define __HAVE_ARCH_COPY_USER_HIGHPAGE | ||
44 | #endif | ||
33 | 45 | ||
34 | /* | 46 | /* |
35 | * These are used to make use of C type-checking.. | 47 | * These are used to make use of C type-checking.. |
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index ee99f2339356..7df49fad29f9 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
@@ -12,11 +12,10 @@ | |||
12 | 12 | ||
13 | #include <linux/bitops.h> | 13 | #include <linux/bitops.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/mm_types.h> | ||
15 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
16 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
17 | 18 | ||
18 | struct vm_area_struct; | ||
19 | |||
20 | /* | 19 | /* |
21 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel | 20 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel |
22 | * memory. For the return value to be meaningful, ADDR must be >= | 21 | * memory. For the return value to be meaningful, ADDR must be >= |
@@ -40,7 +39,14 @@ struct vm_area_struct; | |||
40 | do{ \ | 39 | do{ \ |
41 | *(pteptr) = (pteval); \ | 40 | *(pteptr) = (pteval); \ |
42 | } while(0) | 41 | } while(0) |
43 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) | 42 | |
43 | extern void purge_tlb_entries(struct mm_struct *, unsigned long); | ||
44 | |||
45 | #define set_pte_at(mm, addr, ptep, pteval) \ | ||
46 | do { \ | ||
47 | set_pte(ptep, pteval); \ | ||
48 | purge_tlb_entries(mm, addr); \ | ||
49 | } while (0) | ||
44 | 50 | ||
45 | #endif /* !__ASSEMBLY__ */ | 51 | #endif /* !__ASSEMBLY__ */ |
46 | 52 | ||
@@ -466,6 +472,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
466 | old = pte_val(*ptep); | 472 | old = pte_val(*ptep); |
467 | new = pte_val(pte_wrprotect(__pte (old))); | 473 | new = pte_val(pte_wrprotect(__pte (old))); |
468 | } while (cmpxchg((unsigned long *) ptep, old, new) != old); | 474 | } while (cmpxchg((unsigned long *) ptep, old, new) != old); |
475 | purge_tlb_entries(mm, addr); | ||
469 | #else | 476 | #else |
470 | pte_t old_pte = *ptep; | 477 | pte_t old_pte = *ptep; |
471 | set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); | 478 | set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); |
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h index 0fdb3c835952..b1a7c4c4a53a 100644 --- a/arch/parisc/include/asm/signal.h +++ b/arch/parisc/include/asm/signal.h | |||
@@ -3,16 +3,12 @@ | |||
3 | 3 | ||
4 | #include <uapi/asm/signal.h> | 4 | #include <uapi/asm/signal.h> |
5 | 5 | ||
6 | |||
7 | #define _NSIG 64 | 6 | #define _NSIG 64 |
8 | /* bits-per-word, where word apparently means 'long' not 'int' */ | 7 | /* bits-per-word, where word apparently means 'long' not 'int' */ |
9 | #define _NSIG_BPW BITS_PER_LONG | 8 | #define _NSIG_BPW BITS_PER_LONG |
10 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) | 9 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) |
11 | 10 | ||
12 | # ifndef __ASSEMBLY__ | 11 | # ifndef __ASSEMBLY__ |
13 | #ifdef CONFIG_64BIT | ||
14 | #else | ||
15 | #endif | ||
16 | 12 | ||
17 | /* Most things should be clean enough to redefine this at will, if care | 13 | /* Most things should be clean enough to redefine this at will, if care |
18 | is taken to make libc match. */ | 14 | is taken to make libc match. */ |
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 3043194547cd..74f801ebbe77 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h | |||
@@ -149,6 +149,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ | |||
149 | #define __ARCH_WANT_SYS_SIGNAL | 149 | #define __ARCH_WANT_SYS_SIGNAL |
150 | #define __ARCH_WANT_SYS_TIME | 150 | #define __ARCH_WANT_SYS_TIME |
151 | #define __ARCH_WANT_COMPAT_SYS_TIME | 151 | #define __ARCH_WANT_COMPAT_SYS_TIME |
152 | #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL | ||
152 | #define __ARCH_WANT_SYS_UTIME | 153 | #define __ARCH_WANT_SYS_UTIME |
153 | #define __ARCH_WANT_SYS_WAITPID | 154 | #define __ARCH_WANT_SYS_WAITPID |
154 | #define __ARCH_WANT_SYS_SOCKETCALL | 155 | #define __ARCH_WANT_SYS_SOCKETCALL |
@@ -166,6 +167,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ | |||
166 | #define __ARCH_WANT_SYS_FORK | 167 | #define __ARCH_WANT_SYS_FORK |
167 | #define __ARCH_WANT_SYS_VFORK | 168 | #define __ARCH_WANT_SYS_VFORK |
168 | #define __ARCH_WANT_SYS_CLONE | 169 | #define __ARCH_WANT_SYS_CLONE |
170 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE | ||
169 | 171 | ||
170 | #endif /* __ASSEMBLY__ */ | 172 | #endif /* __ASSEMBLY__ */ |
171 | 173 | ||
diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index e178f30f2ccc..2c8b9bde18eb 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h | |||
@@ -822,8 +822,12 @@ | |||
822 | #define __NR_syncfs (__NR_Linux + 327) | 822 | #define __NR_syncfs (__NR_Linux + 327) |
823 | #define __NR_setns (__NR_Linux + 328) | 823 | #define __NR_setns (__NR_Linux + 328) |
824 | #define __NR_sendmmsg (__NR_Linux + 329) | 824 | #define __NR_sendmmsg (__NR_Linux + 329) |
825 | #define __NR_process_vm_readv (__NR_Linux + 330) | ||
826 | #define __NR_process_vm_writev (__NR_Linux + 331) | ||
827 | #define __NR_kcmp (__NR_Linux + 332) | ||
828 | #define __NR_finit_module (__NR_Linux + 333) | ||
825 | 829 | ||
826 | #define __NR_Linux_syscalls (__NR_sendmmsg + 1) | 830 | #define __NR_Linux_syscalls (__NR_finit_module + 1) |
827 | 831 | ||
828 | 832 | ||
829 | #define __IGNORE_select /* newselect */ | 833 | #define __IGNORE_select /* newselect */ |
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 48e16dc20102..4b12890642eb 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
@@ -267,9 +267,11 @@ static inline void | |||
267 | __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, | 267 | __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, |
268 | unsigned long physaddr) | 268 | unsigned long physaddr) |
269 | { | 269 | { |
270 | preempt_disable(); | ||
270 | flush_dcache_page_asm(physaddr, vmaddr); | 271 | flush_dcache_page_asm(physaddr, vmaddr); |
271 | if (vma->vm_flags & VM_EXEC) | 272 | if (vma->vm_flags & VM_EXEC) |
272 | flush_icache_page_asm(physaddr, vmaddr); | 273 | flush_icache_page_asm(physaddr, vmaddr); |
274 | preempt_enable(); | ||
273 | } | 275 | } |
274 | 276 | ||
275 | void flush_dcache_page(struct page *page) | 277 | void flush_dcache_page(struct page *page) |
@@ -329,17 +331,6 @@ EXPORT_SYMBOL(flush_kernel_dcache_page_asm); | |||
329 | EXPORT_SYMBOL(flush_data_cache_local); | 331 | EXPORT_SYMBOL(flush_data_cache_local); |
330 | EXPORT_SYMBOL(flush_kernel_icache_range_asm); | 332 | EXPORT_SYMBOL(flush_kernel_icache_range_asm); |
331 | 333 | ||
332 | void clear_user_page_asm(void *page, unsigned long vaddr) | ||
333 | { | ||
334 | unsigned long flags; | ||
335 | /* This function is implemented in assembly in pacache.S */ | ||
336 | extern void __clear_user_page_asm(void *page, unsigned long vaddr); | ||
337 | |||
338 | purge_tlb_start(flags); | ||
339 | __clear_user_page_asm(page, vaddr); | ||
340 | purge_tlb_end(flags); | ||
341 | } | ||
342 | |||
343 | #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ | 334 | #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ |
344 | int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; | 335 | int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; |
345 | 336 | ||
@@ -373,20 +364,9 @@ void __init parisc_setup_cache_timing(void) | |||
373 | printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); | 364 | printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); |
374 | } | 365 | } |
375 | 366 | ||
376 | extern void purge_kernel_dcache_page(unsigned long); | 367 | extern void purge_kernel_dcache_page_asm(unsigned long); |
377 | extern void clear_user_page_asm(void *page, unsigned long vaddr); | 368 | extern void clear_user_page_asm(void *, unsigned long); |
378 | 369 | extern void copy_user_page_asm(void *, void *, unsigned long); | |
379 | void clear_user_page(void *page, unsigned long vaddr, struct page *pg) | ||
380 | { | ||
381 | unsigned long flags; | ||
382 | |||
383 | purge_kernel_dcache_page((unsigned long)page); | ||
384 | purge_tlb_start(flags); | ||
385 | pdtlb_kernel(page); | ||
386 | purge_tlb_end(flags); | ||
387 | clear_user_page_asm(page, vaddr); | ||
388 | } | ||
389 | EXPORT_SYMBOL(clear_user_page); | ||
390 | 370 | ||
391 | void flush_kernel_dcache_page_addr(void *addr) | 371 | void flush_kernel_dcache_page_addr(void *addr) |
392 | { | 372 | { |
@@ -399,11 +379,26 @@ void flush_kernel_dcache_page_addr(void *addr) | |||
399 | } | 379 | } |
400 | EXPORT_SYMBOL(flush_kernel_dcache_page_addr); | 380 | EXPORT_SYMBOL(flush_kernel_dcache_page_addr); |
401 | 381 | ||
382 | void clear_user_page(void *vto, unsigned long vaddr, struct page *page) | ||
383 | { | ||
384 | clear_page_asm(vto); | ||
385 | if (!parisc_requires_coherency()) | ||
386 | flush_kernel_dcache_page_asm(vto); | ||
387 | } | ||
388 | EXPORT_SYMBOL(clear_user_page); | ||
389 | |||
402 | void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, | 390 | void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, |
403 | struct page *pg) | 391 | struct page *pg) |
404 | { | 392 | { |
405 | /* no coherency needed (all in kmap/kunmap) */ | 393 | /* Copy using kernel mapping. No coherency is needed |
406 | copy_user_page_asm(vto, vfrom); | 394 | (all in kmap/kunmap) on machines that don't support |
395 | non-equivalent aliasing. However, the `from' page | ||
396 | needs to be flushed before it can be accessed through | ||
397 | the kernel mapping. */ | ||
398 | preempt_disable(); | ||
399 | flush_dcache_page_asm(__pa(vfrom), vaddr); | ||
400 | preempt_enable(); | ||
401 | copy_page_asm(vto, vfrom); | ||
407 | if (!parisc_requires_coherency()) | 402 | if (!parisc_requires_coherency()) |
408 | flush_kernel_dcache_page_asm(vto); | 403 | flush_kernel_dcache_page_asm(vto); |
409 | } | 404 | } |
@@ -419,6 +414,24 @@ void kunmap_parisc(void *addr) | |||
419 | EXPORT_SYMBOL(kunmap_parisc); | 414 | EXPORT_SYMBOL(kunmap_parisc); |
420 | #endif | 415 | #endif |
421 | 416 | ||
417 | void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | ||
418 | { | ||
419 | unsigned long flags; | ||
420 | |||
421 | /* Note: purge_tlb_entries can be called at startup with | ||
422 | no context. */ | ||
423 | |||
424 | /* Disable preemption while we play with %sr1. */ | ||
425 | preempt_disable(); | ||
426 | mtsp(mm->context, 1); | ||
427 | purge_tlb_start(flags); | ||
428 | pdtlb(addr); | ||
429 | pitlb(addr); | ||
430 | purge_tlb_end(flags); | ||
431 | preempt_enable(); | ||
432 | } | ||
433 | EXPORT_SYMBOL(purge_tlb_entries); | ||
434 | |||
422 | void __flush_tlb_range(unsigned long sid, unsigned long start, | 435 | void __flush_tlb_range(unsigned long sid, unsigned long start, |
423 | unsigned long end) | 436 | unsigned long end) |
424 | { | 437 | { |
@@ -458,8 +471,66 @@ void flush_cache_all(void) | |||
458 | on_each_cpu(cacheflush_h_tmp_function, NULL, 1); | 471 | on_each_cpu(cacheflush_h_tmp_function, NULL, 1); |
459 | } | 472 | } |
460 | 473 | ||
474 | static inline unsigned long mm_total_size(struct mm_struct *mm) | ||
475 | { | ||
476 | struct vm_area_struct *vma; | ||
477 | unsigned long usize = 0; | ||
478 | |||
479 | for (vma = mm->mmap; vma; vma = vma->vm_next) | ||
480 | usize += vma->vm_end - vma->vm_start; | ||
481 | return usize; | ||
482 | } | ||
483 | |||
484 | static inline pte_t *get_ptep(pgd_t *pgd, unsigned long addr) | ||
485 | { | ||
486 | pte_t *ptep = NULL; | ||
487 | |||
488 | if (!pgd_none(*pgd)) { | ||
489 | pud_t *pud = pud_offset(pgd, addr); | ||
490 | if (!pud_none(*pud)) { | ||
491 | pmd_t *pmd = pmd_offset(pud, addr); | ||
492 | if (!pmd_none(*pmd)) | ||
493 | ptep = pte_offset_map(pmd, addr); | ||
494 | } | ||
495 | } | ||
496 | return ptep; | ||
497 | } | ||
498 | |||
461 | void flush_cache_mm(struct mm_struct *mm) | 499 | void flush_cache_mm(struct mm_struct *mm) |
462 | { | 500 | { |
501 | /* Flushing the whole cache on each cpu takes forever on | ||
502 | rp3440, etc. So, avoid it if the mm isn't too big. */ | ||
503 | if (mm_total_size(mm) < parisc_cache_flush_threshold) { | ||
504 | struct vm_area_struct *vma; | ||
505 | |||
506 | if (mm->context == mfsp(3)) { | ||
507 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | ||
508 | flush_user_dcache_range_asm(vma->vm_start, | ||
509 | vma->vm_end); | ||
510 | if (vma->vm_flags & VM_EXEC) | ||
511 | flush_user_icache_range_asm( | ||
512 | vma->vm_start, vma->vm_end); | ||
513 | } | ||
514 | } else { | ||
515 | pgd_t *pgd = mm->pgd; | ||
516 | |||
517 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | ||
518 | unsigned long addr; | ||
519 | |||
520 | for (addr = vma->vm_start; addr < vma->vm_end; | ||
521 | addr += PAGE_SIZE) { | ||
522 | pte_t *ptep = get_ptep(pgd, addr); | ||
523 | if (ptep != NULL) { | ||
524 | pte_t pte = *ptep; | ||
525 | __flush_cache_page(vma, addr, | ||
526 | page_to_phys(pte_page(pte))); | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | return; | ||
532 | } | ||
533 | |||
463 | #ifdef CONFIG_SMP | 534 | #ifdef CONFIG_SMP |
464 | flush_cache_all(); | 535 | flush_cache_all(); |
465 | #else | 536 | #else |
@@ -485,20 +556,36 @@ flush_user_icache_range(unsigned long start, unsigned long end) | |||
485 | flush_instruction_cache(); | 556 | flush_instruction_cache(); |
486 | } | 557 | } |
487 | 558 | ||
488 | |||
489 | void flush_cache_range(struct vm_area_struct *vma, | 559 | void flush_cache_range(struct vm_area_struct *vma, |
490 | unsigned long start, unsigned long end) | 560 | unsigned long start, unsigned long end) |
491 | { | 561 | { |
492 | int sr3; | ||
493 | |||
494 | BUG_ON(!vma->vm_mm->context); | 562 | BUG_ON(!vma->vm_mm->context); |
495 | 563 | ||
496 | sr3 = mfsp(3); | 564 | if ((end - start) < parisc_cache_flush_threshold) { |
497 | if (vma->vm_mm->context == sr3) { | 565 | if (vma->vm_mm->context == mfsp(3)) { |
498 | flush_user_dcache_range(start,end); | 566 | flush_user_dcache_range_asm(start, end); |
499 | flush_user_icache_range(start,end); | 567 | if (vma->vm_flags & VM_EXEC) |
568 | flush_user_icache_range_asm(start, end); | ||
569 | } else { | ||
570 | unsigned long addr; | ||
571 | pgd_t *pgd = vma->vm_mm->pgd; | ||
572 | |||
573 | for (addr = start & PAGE_MASK; addr < end; | ||
574 | addr += PAGE_SIZE) { | ||
575 | pte_t *ptep = get_ptep(pgd, addr); | ||
576 | if (ptep != NULL) { | ||
577 | pte_t pte = *ptep; | ||
578 | flush_cache_page(vma, | ||
579 | addr, pte_pfn(pte)); | ||
580 | } | ||
581 | } | ||
582 | } | ||
500 | } else { | 583 | } else { |
584 | #ifdef CONFIG_SMP | ||
501 | flush_cache_all(); | 585 | flush_cache_all(); |
586 | #else | ||
587 | flush_cache_all_local(); | ||
588 | #endif | ||
502 | } | 589 | } |
503 | } | 590 | } |
504 | 591 | ||
@@ -511,3 +598,67 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long | |||
511 | __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); | 598 | __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); |
512 | 599 | ||
513 | } | 600 | } |
601 | |||
602 | #ifdef CONFIG_PARISC_TMPALIAS | ||
603 | |||
604 | void clear_user_highpage(struct page *page, unsigned long vaddr) | ||
605 | { | ||
606 | void *vto; | ||
607 | unsigned long flags; | ||
608 | |||
609 | /* Clear using TMPALIAS region. The page doesn't need to | ||
610 | be flushed but the kernel mapping needs to be purged. */ | ||
611 | |||
612 | vto = kmap_atomic(page, KM_USER0); | ||
613 | |||
614 | /* The PA-RISC 2.0 Architecture book states on page F-6: | ||
615 | "Before a write-capable translation is enabled, *all* | ||
616 | non-equivalently-aliased translations must be removed | ||
617 | from the page table and purged from the TLB. (Note | ||
618 | that the caches are not required to be flushed at this | ||
619 | time.) Before any non-equivalent aliased translation | ||
620 | is re-enabled, the virtual address range for the writeable | ||
621 | page (the entire page) must be flushed from the cache, | ||
622 | and the write-capable translation removed from the page | ||
623 | table and purged from the TLB." */ | ||
624 | |||
625 | purge_kernel_dcache_page_asm((unsigned long)vto); | ||
626 | purge_tlb_start(flags); | ||
627 | pdtlb_kernel(vto); | ||
628 | purge_tlb_end(flags); | ||
629 | preempt_disable(); | ||
630 | clear_user_page_asm(vto, vaddr); | ||
631 | preempt_enable(); | ||
632 | |||
633 | pagefault_enable(); /* kunmap_atomic(addr, KM_USER0); */ | ||
634 | } | ||
635 | |||
636 | void copy_user_highpage(struct page *to, struct page *from, | ||
637 | unsigned long vaddr, struct vm_area_struct *vma) | ||
638 | { | ||
639 | void *vfrom, *vto; | ||
640 | unsigned long flags; | ||
641 | |||
642 | /* Copy using TMPALIAS region. This has the advantage | ||
643 | that the `from' page doesn't need to be flushed. However, | ||
644 | the `to' page must be flushed in copy_user_page_asm since | ||
645 | it can be used to bring in executable code. */ | ||
646 | |||
647 | vfrom = kmap_atomic(from, KM_USER0); | ||
648 | vto = kmap_atomic(to, KM_USER1); | ||
649 | |||
650 | purge_kernel_dcache_page_asm((unsigned long)vto); | ||
651 | purge_tlb_start(flags); | ||
652 | pdtlb_kernel(vto); | ||
653 | pdtlb_kernel(vfrom); | ||
654 | purge_tlb_end(flags); | ||
655 | preempt_disable(); | ||
656 | copy_user_page_asm(vto, vfrom, vaddr); | ||
657 | flush_dcache_page_asm(__pa(vto), vaddr); | ||
658 | preempt_enable(); | ||
659 | |||
660 | pagefault_enable(); /* kunmap_atomic(addr, KM_USER1); */ | ||
661 | pagefault_enable(); /* kunmap_atomic(addr, KM_USER0); */ | ||
662 | } | ||
663 | |||
664 | #endif /* CONFIG_PARISC_TMPALIAS */ | ||
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index eb7850b46c25..7c9648919c91 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -483,7 +483,7 @@ | |||
483 | * B <-> _PAGE_DMB (memory break) | 483 | * B <-> _PAGE_DMB (memory break) |
484 | * | 484 | * |
485 | * Then incredible subtlety: The access rights are | 485 | * Then incredible subtlety: The access rights are |
486 | * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ | 486 | * _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE |
487 | * See 3-14 of the parisc 2.0 manual | 487 | * See 3-14 of the parisc 2.0 manual |
488 | * | 488 | * |
489 | * Finally, _PAGE_READ goes in the top bit of PL1 (so we | 489 | * Finally, _PAGE_READ goes in the top bit of PL1 (so we |
@@ -493,7 +493,7 @@ | |||
493 | 493 | ||
494 | /* PAGE_USER indicates the page can be read with user privileges, | 494 | /* PAGE_USER indicates the page can be read with user privileges, |
495 | * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1 | 495 | * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1 |
496 | * contains _PAGE_READ */ | 496 | * contains _PAGE_READ) */ |
497 | extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0 | 497 | extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0 |
498 | depdi 7,11,3,\prot | 498 | depdi 7,11,3,\prot |
499 | /* If we're a gateway page, drop PL2 back to zero for promotion | 499 | /* If we're a gateway page, drop PL2 back to zero for promotion |
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 08324aac3544..3295ef4a185d 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c | |||
@@ -186,12 +186,14 @@ pat_query_module(ulong pcell_loc, ulong mod_index) | |||
186 | 186 | ||
187 | if (status != PDC_OK) { | 187 | if (status != PDC_OK) { |
188 | /* no more cell modules or error */ | 188 | /* no more cell modules or error */ |
189 | kfree(pa_pdc_cell); | ||
189 | return status; | 190 | return status; |
190 | } | 191 | } |
191 | 192 | ||
192 | temp = pa_pdc_cell->cba; | 193 | temp = pa_pdc_cell->cba; |
193 | dev = alloc_pa_dev(PAT_GET_CBA(temp), &(pa_pdc_cell->mod_path)); | 194 | dev = alloc_pa_dev(PAT_GET_CBA(temp), &(pa_pdc_cell->mod_path)); |
194 | if (!dev) { | 195 | if (!dev) { |
196 | kfree(pa_pdc_cell); | ||
195 | return PDC_OK; | 197 | return PDC_OK; |
196 | } | 198 | } |
197 | 199 | ||
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 0299d63cd112..8094d3ed3b64 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c | |||
@@ -379,14 +379,14 @@ void do_cpu_irq_mask(struct pt_regs *regs) | |||
379 | static struct irqaction timer_action = { | 379 | static struct irqaction timer_action = { |
380 | .handler = timer_interrupt, | 380 | .handler = timer_interrupt, |
381 | .name = "timer", | 381 | .name = "timer", |
382 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU | IRQF_IRQPOLL, | 382 | .flags = IRQF_TIMER | IRQF_PERCPU | IRQF_IRQPOLL, |
383 | }; | 383 | }; |
384 | 384 | ||
385 | #ifdef CONFIG_SMP | 385 | #ifdef CONFIG_SMP |
386 | static struct irqaction ipi_action = { | 386 | static struct irqaction ipi_action = { |
387 | .handler = ipi_interrupt, | 387 | .handler = ipi_interrupt, |
388 | .name = "IPI", | 388 | .name = "IPI", |
389 | .flags = IRQF_DISABLED | IRQF_PERCPU, | 389 | .flags = IRQF_PERCPU, |
390 | }; | 390 | }; |
391 | #endif | 391 | #endif |
392 | 392 | ||
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 5d7218ad885c..312b48422a56 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S | |||
@@ -199,7 +199,6 @@ ENTRY(flush_instruction_cache_local) | |||
199 | .callinfo NO_CALLS | 199 | .callinfo NO_CALLS |
200 | .entry | 200 | .entry |
201 | 201 | ||
202 | mtsp %r0, %sr1 | ||
203 | load32 cache_info, %r1 | 202 | load32 cache_info, %r1 |
204 | 203 | ||
205 | /* Flush Instruction Cache */ | 204 | /* Flush Instruction Cache */ |
@@ -208,7 +207,8 @@ ENTRY(flush_instruction_cache_local) | |||
208 | LDREG ICACHE_STRIDE(%r1), %arg1 | 207 | LDREG ICACHE_STRIDE(%r1), %arg1 |
209 | LDREG ICACHE_COUNT(%r1), %arg2 | 208 | LDREG ICACHE_COUNT(%r1), %arg2 |
210 | LDREG ICACHE_LOOP(%r1), %arg3 | 209 | LDREG ICACHE_LOOP(%r1), %arg3 |
211 | rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/ | 210 | rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/ |
211 | mtsp %r0, %sr1 | ||
212 | addib,COND(=) -1, %arg3, fioneloop /* Preadjust and test */ | 212 | addib,COND(=) -1, %arg3, fioneloop /* Preadjust and test */ |
213 | movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */ | 213 | movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */ |
214 | 214 | ||
@@ -220,7 +220,33 @@ fimanyloop: /* Loop if LOOP >= 2 */ | |||
220 | addib,COND(<=),n -1, %arg2, fisync /* Outer loop decr */ | 220 | addib,COND(<=),n -1, %arg2, fisync /* Outer loop decr */ |
221 | 221 | ||
222 | fioneloop: /* Loop if LOOP = 1 */ | 222 | fioneloop: /* Loop if LOOP = 1 */ |
223 | addib,COND(>) -1, %arg2, fioneloop /* Outer loop count decr */ | 223 | /* Some implementations may flush with a single fice instruction */ |
224 | cmpib,COND(>>=),n 15, %arg2, fioneloop2 | ||
225 | |||
226 | fioneloop1: | ||
227 | fice,m %arg1(%sr1, %arg0) | ||
228 | fice,m %arg1(%sr1, %arg0) | ||
229 | fice,m %arg1(%sr1, %arg0) | ||
230 | fice,m %arg1(%sr1, %arg0) | ||
231 | fice,m %arg1(%sr1, %arg0) | ||
232 | fice,m %arg1(%sr1, %arg0) | ||
233 | fice,m %arg1(%sr1, %arg0) | ||
234 | fice,m %arg1(%sr1, %arg0) | ||
235 | fice,m %arg1(%sr1, %arg0) | ||
236 | fice,m %arg1(%sr1, %arg0) | ||
237 | fice,m %arg1(%sr1, %arg0) | ||
238 | fice,m %arg1(%sr1, %arg0) | ||
239 | fice,m %arg1(%sr1, %arg0) | ||
240 | fice,m %arg1(%sr1, %arg0) | ||
241 | fice,m %arg1(%sr1, %arg0) | ||
242 | addib,COND(>) -16, %arg2, fioneloop1 | ||
243 | fice,m %arg1(%sr1, %arg0) | ||
244 | |||
245 | /* Check if done */ | ||
246 | cmpb,COND(=),n %arg2, %r0, fisync /* Predict branch taken */ | ||
247 | |||
248 | fioneloop2: | ||
249 | addib,COND(>) -1, %arg2, fioneloop2 /* Outer loop count decr */ | ||
224 | fice,m %arg1(%sr1, %arg0) /* Fice for one loop */ | 250 | fice,m %arg1(%sr1, %arg0) /* Fice for one loop */ |
225 | 251 | ||
226 | fisync: | 252 | fisync: |
@@ -240,8 +266,7 @@ ENTRY(flush_data_cache_local) | |||
240 | .callinfo NO_CALLS | 266 | .callinfo NO_CALLS |
241 | .entry | 267 | .entry |
242 | 268 | ||
243 | mtsp %r0, %sr1 | 269 | load32 cache_info, %r1 |
244 | load32 cache_info, %r1 | ||
245 | 270 | ||
246 | /* Flush Data Cache */ | 271 | /* Flush Data Cache */ |
247 | 272 | ||
@@ -249,7 +274,8 @@ ENTRY(flush_data_cache_local) | |||
249 | LDREG DCACHE_STRIDE(%r1), %arg1 | 274 | LDREG DCACHE_STRIDE(%r1), %arg1 |
250 | LDREG DCACHE_COUNT(%r1), %arg2 | 275 | LDREG DCACHE_COUNT(%r1), %arg2 |
251 | LDREG DCACHE_LOOP(%r1), %arg3 | 276 | LDREG DCACHE_LOOP(%r1), %arg3 |
252 | rsm PSW_SM_I, %r22 | 277 | rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/ |
278 | mtsp %r0, %sr1 | ||
253 | addib,COND(=) -1, %arg3, fdoneloop /* Preadjust and test */ | 279 | addib,COND(=) -1, %arg3, fdoneloop /* Preadjust and test */ |
254 | movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */ | 280 | movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */ |
255 | 281 | ||
@@ -261,7 +287,33 @@ fdmanyloop: /* Loop if LOOP >= 2 */ | |||
261 | addib,COND(<=),n -1, %arg2, fdsync /* Outer loop decr */ | 287 | addib,COND(<=),n -1, %arg2, fdsync /* Outer loop decr */ |
262 | 288 | ||
263 | fdoneloop: /* Loop if LOOP = 1 */ | 289 | fdoneloop: /* Loop if LOOP = 1 */ |
264 | addib,COND(>) -1, %arg2, fdoneloop /* Outer loop count decr */ | 290 | /* Some implementations may flush with a single fdce instruction */ |
291 | cmpib,COND(>>=),n 15, %arg2, fdoneloop2 | ||
292 | |||
293 | fdoneloop1: | ||
294 | fdce,m %arg1(%sr1, %arg0) | ||
295 | fdce,m %arg1(%sr1, %arg0) | ||
296 | fdce,m %arg1(%sr1, %arg0) | ||
297 | fdce,m %arg1(%sr1, %arg0) | ||
298 | fdce,m %arg1(%sr1, %arg0) | ||
299 | fdce,m %arg1(%sr1, %arg0) | ||
300 | fdce,m %arg1(%sr1, %arg0) | ||
301 | fdce,m %arg1(%sr1, %arg0) | ||
302 | fdce,m %arg1(%sr1, %arg0) | ||
303 | fdce,m %arg1(%sr1, %arg0) | ||
304 | fdce,m %arg1(%sr1, %arg0) | ||
305 | fdce,m %arg1(%sr1, %arg0) | ||
306 | fdce,m %arg1(%sr1, %arg0) | ||
307 | fdce,m %arg1(%sr1, %arg0) | ||
308 | fdce,m %arg1(%sr1, %arg0) | ||
309 | addib,COND(>) -16, %arg2, fdoneloop1 | ||
310 | fdce,m %arg1(%sr1, %arg0) | ||
311 | |||
312 | /* Check if done */ | ||
313 | cmpb,COND(=),n %arg2, %r0, fdsync /* Predict branch taken */ | ||
314 | |||
315 | fdoneloop2: | ||
316 | addib,COND(>) -1, %arg2, fdoneloop2 /* Outer loop count decr */ | ||
265 | fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */ | 317 | fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */ |
266 | 318 | ||
267 | fdsync: | 319 | fdsync: |
@@ -277,7 +329,104 @@ ENDPROC(flush_data_cache_local) | |||
277 | 329 | ||
278 | .align 16 | 330 | .align 16 |
279 | 331 | ||
280 | ENTRY(copy_user_page_asm) | 332 | /* Macros to serialize TLB purge operations on SMP. */ |
333 | |||
334 | .macro tlb_lock la,flags,tmp | ||
335 | #ifdef CONFIG_SMP | ||
336 | ldil L%pa_tlb_lock,%r1 | ||
337 | ldo R%pa_tlb_lock(%r1),\la | ||
338 | rsm PSW_SM_I,\flags | ||
339 | 1: LDCW 0(\la),\tmp | ||
340 | cmpib,<>,n 0,\tmp,3f | ||
341 | 2: ldw 0(\la),\tmp | ||
342 | cmpb,<> %r0,\tmp,1b | ||
343 | nop | ||
344 | b,n 2b | ||
345 | 3: | ||
346 | #endif | ||
347 | .endm | ||
348 | |||
349 | .macro tlb_unlock la,flags,tmp | ||
350 | #ifdef CONFIG_SMP | ||
351 | ldi 1,\tmp | ||
352 | stw \tmp,0(\la) | ||
353 | mtsm \flags | ||
354 | #endif | ||
355 | .endm | ||
356 | |||
357 | /* Clear page using kernel mapping. */ | ||
358 | |||
359 | ENTRY(clear_page_asm) | ||
360 | .proc | ||
361 | .callinfo NO_CALLS | ||
362 | .entry | ||
363 | |||
364 | #ifdef CONFIG_64BIT | ||
365 | |||
366 | /* Unroll the loop. */ | ||
367 | ldi (PAGE_SIZE / 128), %r1 | ||
368 | |||
369 | 1: | ||
370 | std %r0, 0(%r26) | ||
371 | std %r0, 8(%r26) | ||
372 | std %r0, 16(%r26) | ||
373 | std %r0, 24(%r26) | ||
374 | std %r0, 32(%r26) | ||
375 | std %r0, 40(%r26) | ||
376 | std %r0, 48(%r26) | ||
377 | std %r0, 56(%r26) | ||
378 | std %r0, 64(%r26) | ||
379 | std %r0, 72(%r26) | ||
380 | std %r0, 80(%r26) | ||
381 | std %r0, 88(%r26) | ||
382 | std %r0, 96(%r26) | ||
383 | std %r0, 104(%r26) | ||
384 | std %r0, 112(%r26) | ||
385 | std %r0, 120(%r26) | ||
386 | |||
387 | /* Note reverse branch hint for addib is taken. */ | ||
388 | addib,COND(>),n -1, %r1, 1b | ||
389 | ldo 128(%r26), %r26 | ||
390 | |||
391 | #else | ||
392 | |||
393 | /* | ||
394 | * Note that until (if) we start saving the full 64-bit register | ||
395 | * values on interrupt, we can't use std on a 32 bit kernel. | ||
396 | */ | ||
397 | ldi (PAGE_SIZE / 64), %r1 | ||
398 | |||
399 | 1: | ||
400 | stw %r0, 0(%r26) | ||
401 | stw %r0, 4(%r26) | ||
402 | stw %r0, 8(%r26) | ||
403 | stw %r0, 12(%r26) | ||
404 | stw %r0, 16(%r26) | ||
405 | stw %r0, 20(%r26) | ||
406 | stw %r0, 24(%r26) | ||
407 | stw %r0, 28(%r26) | ||
408 | stw %r0, 32(%r26) | ||
409 | stw %r0, 36(%r26) | ||
410 | stw %r0, 40(%r26) | ||
411 | stw %r0, 44(%r26) | ||
412 | stw %r0, 48(%r26) | ||
413 | stw %r0, 52(%r26) | ||
414 | stw %r0, 56(%r26) | ||
415 | stw %r0, 60(%r26) | ||
416 | |||
417 | addib,COND(>),n -1, %r1, 1b | ||
418 | ldo 64(%r26), %r26 | ||
419 | #endif | ||
420 | bv %r0(%r2) | ||
421 | nop | ||
422 | .exit | ||
423 | |||
424 | .procend | ||
425 | ENDPROC(clear_page_asm) | ||
426 | |||
427 | /* Copy page using kernel mapping. */ | ||
428 | |||
429 | ENTRY(copy_page_asm) | ||
281 | .proc | 430 | .proc |
282 | .callinfo NO_CALLS | 431 | .callinfo NO_CALLS |
283 | .entry | 432 | .entry |
@@ -285,18 +434,14 @@ ENTRY(copy_user_page_asm) | |||
285 | #ifdef CONFIG_64BIT | 434 | #ifdef CONFIG_64BIT |
286 | /* PA8x00 CPUs can consume 2 loads or 1 store per cycle. | 435 | /* PA8x00 CPUs can consume 2 loads or 1 store per cycle. |
287 | * Unroll the loop by hand and arrange insn appropriately. | 436 | * Unroll the loop by hand and arrange insn appropriately. |
288 | * GCC probably can do this just as well. | 437 | * Prefetch doesn't improve performance on rp3440. |
438 | * GCC probably can do this just as well... | ||
289 | */ | 439 | */ |
290 | 440 | ||
291 | ldd 0(%r25), %r19 | ||
292 | ldi (PAGE_SIZE / 128), %r1 | 441 | ldi (PAGE_SIZE / 128), %r1 |
293 | 442 | ||
294 | ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */ | 443 | 1: ldd 0(%r25), %r19 |
295 | ldw 128(%r25), %r0 /* prefetch 2 */ | 444 | ldd 8(%r25), %r20 |
296 | |||
297 | 1: ldd 8(%r25), %r20 | ||
298 | ldw 192(%r25), %r0 /* prefetch 3 */ | ||
299 | ldw 256(%r25), %r0 /* prefetch 4 */ | ||
300 | 445 | ||
301 | ldd 16(%r25), %r21 | 446 | ldd 16(%r25), %r21 |
302 | ldd 24(%r25), %r22 | 447 | ldd 24(%r25), %r22 |
@@ -330,20 +475,16 @@ ENTRY(copy_user_page_asm) | |||
330 | 475 | ||
331 | ldd 112(%r25), %r21 | 476 | ldd 112(%r25), %r21 |
332 | ldd 120(%r25), %r22 | 477 | ldd 120(%r25), %r22 |
478 | ldo 128(%r25), %r25 | ||
333 | std %r19, 96(%r26) | 479 | std %r19, 96(%r26) |
334 | std %r20, 104(%r26) | 480 | std %r20, 104(%r26) |
335 | 481 | ||
336 | ldo 128(%r25), %r25 | ||
337 | std %r21, 112(%r26) | 482 | std %r21, 112(%r26) |
338 | std %r22, 120(%r26) | 483 | std %r22, 120(%r26) |
339 | ldo 128(%r26), %r26 | ||
340 | 484 | ||
341 | /* conditional branches nullify on forward taken branch, and on | 485 | /* Note reverse branch hint for addib is taken. */ |
342 | * non-taken backward branch. Note that .+4 is a backwards branch. | 486 | addib,COND(>),n -1, %r1, 1b |
343 | * The ldd should only get executed if the branch is taken. | 487 | ldo 128(%r26), %r26 |
344 | */ | ||
345 | addib,COND(>),n -1, %r1, 1b /* bundle 10 */ | ||
346 | ldd 0(%r25), %r19 /* start next loads */ | ||
347 | 488 | ||
348 | #else | 489 | #else |
349 | 490 | ||
@@ -399,7 +540,7 @@ ENTRY(copy_user_page_asm) | |||
399 | .exit | 540 | .exit |
400 | 541 | ||
401 | .procend | 542 | .procend |
402 | ENDPROC(copy_user_page_asm) | 543 | ENDPROC(copy_page_asm) |
403 | 544 | ||
404 | /* | 545 | /* |
405 | * NOTE: Code in clear_user_page has a hard coded dependency on the | 546 | * NOTE: Code in clear_user_page has a hard coded dependency on the |
@@ -422,8 +563,6 @@ ENDPROC(copy_user_page_asm) | |||
422 | * %r23 physical page (shifted for tlb insert) of "from" translation | 563 | * %r23 physical page (shifted for tlb insert) of "from" translation |
423 | */ | 564 | */ |
424 | 565 | ||
425 | #if 0 | ||
426 | |||
427 | /* | 566 | /* |
428 | * We can't do this since copy_user_page is used to bring in | 567 | * We can't do this since copy_user_page is used to bring in |
429 | * file data that might have instructions. Since the data would | 568 | * file data that might have instructions. Since the data would |
@@ -435,6 +574,7 @@ ENDPROC(copy_user_page_asm) | |||
435 | * use it if more information is passed into copy_user_page(). | 574 | * use it if more information is passed into copy_user_page(). |
436 | * Have to do some measurements to see if it is worthwhile to | 575 | * Have to do some measurements to see if it is worthwhile to |
437 | * lobby for such a change. | 576 | * lobby for such a change. |
577 | * | ||
438 | */ | 578 | */ |
439 | 579 | ||
440 | ENTRY(copy_user_page_asm) | 580 | ENTRY(copy_user_page_asm) |
@@ -442,16 +582,21 @@ ENTRY(copy_user_page_asm) | |||
442 | .callinfo NO_CALLS | 582 | .callinfo NO_CALLS |
443 | .entry | 583 | .entry |
444 | 584 | ||
585 | /* Convert virtual `to' and `from' addresses to physical addresses. | ||
586 | Move `from' physical address to non shadowed register. */ | ||
445 | ldil L%(__PAGE_OFFSET), %r1 | 587 | ldil L%(__PAGE_OFFSET), %r1 |
446 | sub %r26, %r1, %r26 | 588 | sub %r26, %r1, %r26 |
447 | sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */ | 589 | sub %r25, %r1, %r23 |
448 | 590 | ||
449 | ldil L%(TMPALIAS_MAP_START), %r28 | 591 | ldil L%(TMPALIAS_MAP_START), %r28 |
450 | /* FIXME for different page sizes != 4k */ | 592 | /* FIXME for different page sizes != 4k */ |
451 | #ifdef CONFIG_64BIT | 593 | #ifdef CONFIG_64BIT |
452 | extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */ | 594 | #if (TMPALIAS_MAP_START >= 0x80000000) |
453 | extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */ | 595 | depdi 0, 31,32, %r28 /* clear any sign extension */ |
454 | depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */ | 596 | #endif |
597 | extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */ | ||
598 | extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */ | ||
599 | depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */ | ||
455 | depdi 0, 63,12, %r28 /* Clear any offset bits */ | 600 | depdi 0, 63,12, %r28 /* Clear any offset bits */ |
456 | copy %r28, %r29 | 601 | copy %r28, %r29 |
457 | depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */ | 602 | depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */ |
@@ -466,10 +611,76 @@ ENTRY(copy_user_page_asm) | |||
466 | 611 | ||
467 | /* Purge any old translations */ | 612 | /* Purge any old translations */ |
468 | 613 | ||
614 | #ifdef CONFIG_PA20 | ||
615 | pdtlb,l 0(%r28) | ||
616 | pdtlb,l 0(%r29) | ||
617 | #else | ||
618 | tlb_lock %r20,%r21,%r22 | ||
469 | pdtlb 0(%r28) | 619 | pdtlb 0(%r28) |
470 | pdtlb 0(%r29) | 620 | pdtlb 0(%r29) |
621 | tlb_unlock %r20,%r21,%r22 | ||
622 | #endif | ||
623 | |||
624 | #ifdef CONFIG_64BIT | ||
625 | /* PA8x00 CPUs can consume 2 loads or 1 store per cycle. | ||
626 | * Unroll the loop by hand and arrange insn appropriately. | ||
627 | * GCC probably can do this just as well. | ||
628 | */ | ||
471 | 629 | ||
472 | ldi 64, %r1 | 630 | ldd 0(%r29), %r19 |
631 | ldi (PAGE_SIZE / 128), %r1 | ||
632 | |||
633 | 1: ldd 8(%r29), %r20 | ||
634 | |||
635 | ldd 16(%r29), %r21 | ||
636 | ldd 24(%r29), %r22 | ||
637 | std %r19, 0(%r28) | ||
638 | std %r20, 8(%r28) | ||
639 | |||
640 | ldd 32(%r29), %r19 | ||
641 | ldd 40(%r29), %r20 | ||
642 | std %r21, 16(%r28) | ||
643 | std %r22, 24(%r28) | ||
644 | |||
645 | ldd 48(%r29), %r21 | ||
646 | ldd 56(%r29), %r22 | ||
647 | std %r19, 32(%r28) | ||
648 | std %r20, 40(%r28) | ||
649 | |||
650 | ldd 64(%r29), %r19 | ||
651 | ldd 72(%r29), %r20 | ||
652 | std %r21, 48(%r28) | ||
653 | std %r22, 56(%r28) | ||
654 | |||
655 | ldd 80(%r29), %r21 | ||
656 | ldd 88(%r29), %r22 | ||
657 | std %r19, 64(%r28) | ||
658 | std %r20, 72(%r28) | ||
659 | |||
660 | ldd 96(%r29), %r19 | ||
661 | ldd 104(%r29), %r20 | ||
662 | std %r21, 80(%r28) | ||
663 | std %r22, 88(%r28) | ||
664 | |||
665 | ldd 112(%r29), %r21 | ||
666 | ldd 120(%r29), %r22 | ||
667 | std %r19, 96(%r28) | ||
668 | std %r20, 104(%r28) | ||
669 | |||
670 | ldo 128(%r29), %r29 | ||
671 | std %r21, 112(%r28) | ||
672 | std %r22, 120(%r28) | ||
673 | ldo 128(%r28), %r28 | ||
674 | |||
675 | /* conditional branches nullify on forward taken branch, and on | ||
676 | * non-taken backward branch. Note that .+4 is a backwards branch. | ||
677 | * The ldd should only get executed if the branch is taken. | ||
678 | */ | ||
679 | addib,COND(>),n -1, %r1, 1b /* bundle 10 */ | ||
680 | ldd 0(%r29), %r19 /* start next loads */ | ||
681 | |||
682 | #else | ||
683 | ldi (PAGE_SIZE / 64), %r1 | ||
473 | 684 | ||
474 | /* | 685 | /* |
475 | * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw | 686 | * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw |
@@ -480,9 +691,7 @@ ENTRY(copy_user_page_asm) | |||
480 | * use ldd/std on a 32 bit kernel. | 691 | * use ldd/std on a 32 bit kernel. |
481 | */ | 692 | */ |
482 | 693 | ||
483 | 694 | 1: ldw 0(%r29), %r19 | |
484 | 1: | ||
485 | ldw 0(%r29), %r19 | ||
486 | ldw 4(%r29), %r20 | 695 | ldw 4(%r29), %r20 |
487 | ldw 8(%r29), %r21 | 696 | ldw 8(%r29), %r21 |
488 | ldw 12(%r29), %r22 | 697 | ldw 12(%r29), %r22 |
@@ -515,8 +724,10 @@ ENTRY(copy_user_page_asm) | |||
515 | stw %r21, 56(%r28) | 724 | stw %r21, 56(%r28) |
516 | stw %r22, 60(%r28) | 725 | stw %r22, 60(%r28) |
517 | ldo 64(%r28), %r28 | 726 | ldo 64(%r28), %r28 |
727 | |||
518 | addib,COND(>) -1, %r1,1b | 728 | addib,COND(>) -1, %r1,1b |
519 | ldo 64(%r29), %r29 | 729 | ldo 64(%r29), %r29 |
730 | #endif | ||
520 | 731 | ||
521 | bv %r0(%r2) | 732 | bv %r0(%r2) |
522 | nop | 733 | nop |
@@ -524,9 +735,8 @@ ENTRY(copy_user_page_asm) | |||
524 | 735 | ||
525 | .procend | 736 | .procend |
526 | ENDPROC(copy_user_page_asm) | 737 | ENDPROC(copy_user_page_asm) |
527 | #endif | ||
528 | 738 | ||
529 | ENTRY(__clear_user_page_asm) | 739 | ENTRY(clear_user_page_asm) |
530 | .proc | 740 | .proc |
531 | .callinfo NO_CALLS | 741 | .callinfo NO_CALLS |
532 | .entry | 742 | .entry |
@@ -550,7 +760,13 @@ ENTRY(__clear_user_page_asm) | |||
550 | 760 | ||
551 | /* Purge any old translation */ | 761 | /* Purge any old translation */ |
552 | 762 | ||
763 | #ifdef CONFIG_PA20 | ||
764 | pdtlb,l 0(%r28) | ||
765 | #else | ||
766 | tlb_lock %r20,%r21,%r22 | ||
553 | pdtlb 0(%r28) | 767 | pdtlb 0(%r28) |
768 | tlb_unlock %r20,%r21,%r22 | ||
769 | #endif | ||
554 | 770 | ||
555 | #ifdef CONFIG_64BIT | 771 | #ifdef CONFIG_64BIT |
556 | ldi (PAGE_SIZE / 128), %r1 | 772 | ldi (PAGE_SIZE / 128), %r1 |
@@ -580,8 +796,7 @@ ENTRY(__clear_user_page_asm) | |||
580 | #else /* ! CONFIG_64BIT */ | 796 | #else /* ! CONFIG_64BIT */ |
581 | ldi (PAGE_SIZE / 64), %r1 | 797 | ldi (PAGE_SIZE / 64), %r1 |
582 | 798 | ||
583 | 1: | 799 | 1: stw %r0, 0(%r28) |
584 | stw %r0, 0(%r28) | ||
585 | stw %r0, 4(%r28) | 800 | stw %r0, 4(%r28) |
586 | stw %r0, 8(%r28) | 801 | stw %r0, 8(%r28) |
587 | stw %r0, 12(%r28) | 802 | stw %r0, 12(%r28) |
@@ -606,7 +821,7 @@ ENTRY(__clear_user_page_asm) | |||
606 | .exit | 821 | .exit |
607 | 822 | ||
608 | .procend | 823 | .procend |
609 | ENDPROC(__clear_user_page_asm) | 824 | ENDPROC(clear_user_page_asm) |
610 | 825 | ||
611 | ENTRY(flush_dcache_page_asm) | 826 | ENTRY(flush_dcache_page_asm) |
612 | .proc | 827 | .proc |
@@ -630,7 +845,13 @@ ENTRY(flush_dcache_page_asm) | |||
630 | 845 | ||
631 | /* Purge any old translation */ | 846 | /* Purge any old translation */ |
632 | 847 | ||
848 | #ifdef CONFIG_PA20 | ||
849 | pdtlb,l 0(%r28) | ||
850 | #else | ||
851 | tlb_lock %r20,%r21,%r22 | ||
633 | pdtlb 0(%r28) | 852 | pdtlb 0(%r28) |
853 | tlb_unlock %r20,%r21,%r22 | ||
854 | #endif | ||
634 | 855 | ||
635 | ldil L%dcache_stride, %r1 | 856 | ldil L%dcache_stride, %r1 |
636 | ldw R%dcache_stride(%r1), %r1 | 857 | ldw R%dcache_stride(%r1), %r1 |
@@ -663,8 +884,17 @@ ENTRY(flush_dcache_page_asm) | |||
663 | fdc,m %r1(%r28) | 884 | fdc,m %r1(%r28) |
664 | 885 | ||
665 | sync | 886 | sync |
887 | |||
888 | #ifdef CONFIG_PA20 | ||
889 | pdtlb,l 0(%r25) | ||
890 | #else | ||
891 | tlb_lock %r20,%r21,%r22 | ||
892 | pdtlb 0(%r25) | ||
893 | tlb_unlock %r20,%r21,%r22 | ||
894 | #endif | ||
895 | |||
666 | bv %r0(%r2) | 896 | bv %r0(%r2) |
667 | pdtlb (%r25) | 897 | nop |
668 | .exit | 898 | .exit |
669 | 899 | ||
670 | .procend | 900 | .procend |
@@ -692,7 +922,13 @@ ENTRY(flush_icache_page_asm) | |||
692 | 922 | ||
693 | /* Purge any old translation */ | 923 | /* Purge any old translation */ |
694 | 924 | ||
695 | pitlb (%sr4,%r28) | 925 | #ifdef CONFIG_PA20 |
926 | pitlb,l %r0(%sr4,%r28) | ||
927 | #else | ||
928 | tlb_lock %r20,%r21,%r22 | ||
929 | pitlb (%sr4,%r28) | ||
930 | tlb_unlock %r20,%r21,%r22 | ||
931 | #endif | ||
696 | 932 | ||
697 | ldil L%icache_stride, %r1 | 933 | ldil L%icache_stride, %r1 |
698 | ldw R%icache_stride(%r1), %r1 | 934 | ldw R%icache_stride(%r1), %r1 |
@@ -727,8 +963,17 @@ ENTRY(flush_icache_page_asm) | |||
727 | fic,m %r1(%sr4,%r28) | 963 | fic,m %r1(%sr4,%r28) |
728 | 964 | ||
729 | sync | 965 | sync |
966 | |||
967 | #ifdef CONFIG_PA20 | ||
968 | pitlb,l %r0(%sr4,%r25) | ||
969 | #else | ||
970 | tlb_lock %r20,%r21,%r22 | ||
971 | pitlb (%sr4,%r25) | ||
972 | tlb_unlock %r20,%r21,%r22 | ||
973 | #endif | ||
974 | |||
730 | bv %r0(%r2) | 975 | bv %r0(%r2) |
731 | pitlb (%sr4,%r25) | 976 | nop |
732 | .exit | 977 | .exit |
733 | 978 | ||
734 | .procend | 979 | .procend |
@@ -777,7 +1022,7 @@ ENTRY(flush_kernel_dcache_page_asm) | |||
777 | .procend | 1022 | .procend |
778 | ENDPROC(flush_kernel_dcache_page_asm) | 1023 | ENDPROC(flush_kernel_dcache_page_asm) |
779 | 1024 | ||
780 | ENTRY(purge_kernel_dcache_page) | 1025 | ENTRY(purge_kernel_dcache_page_asm) |
781 | .proc | 1026 | .proc |
782 | .callinfo NO_CALLS | 1027 | .callinfo NO_CALLS |
783 | .entry | 1028 | .entry |
@@ -817,7 +1062,7 @@ ENTRY(purge_kernel_dcache_page) | |||
817 | .exit | 1062 | .exit |
818 | 1063 | ||
819 | .procend | 1064 | .procend |
820 | ENDPROC(purge_kernel_dcache_page) | 1065 | ENDPROC(purge_kernel_dcache_page_asm) |
821 | 1066 | ||
822 | ENTRY(flush_user_dcache_range_asm) | 1067 | ENTRY(flush_user_dcache_range_asm) |
823 | .proc | 1068 | .proc |
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index ceec85de6290..6795dc6c995f 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c | |||
@@ -157,5 +157,6 @@ extern void _mcount(void); | |||
157 | EXPORT_SYMBOL(_mcount); | 157 | EXPORT_SYMBOL(_mcount); |
158 | #endif | 158 | #endif |
159 | 159 | ||
160 | /* from pacache.S -- needed for copy_page */ | 160 | /* from pacache.S -- needed for clear/copy_page */ |
161 | EXPORT_SYMBOL(copy_user_page_asm); | 161 | EXPORT_SYMBOL(clear_page_asm); |
162 | EXPORT_SYMBOL(copy_page_asm); | ||
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index fd051705a407..52c85b2f502e 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -312,7 +312,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
312 | #if DEBUG_SIG | 312 | #if DEBUG_SIG |
313 | /* Assert that we're flushing in the correct space... */ | 313 | /* Assert that we're flushing in the correct space... */ |
314 | { | 314 | { |
315 | int sid; | 315 | unsigned long sid; |
316 | asm ("mfsp %%sr3,%0" : "=r" (sid)); | 316 | asm ("mfsp %%sr3,%0" : "=r" (sid)); |
317 | DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n", | 317 | DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n", |
318 | sid, frame->tramp); | 318 | sid, frame->tramp); |
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 5dede04f2f3e..2ddcabb616ce 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c | |||
@@ -65,7 +65,7 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) | |||
65 | { | 65 | { |
66 | compat_sigset_t s; | 66 | compat_sigset_t s; |
67 | 67 | ||
68 | if (sz != sizeof *set) | 68 | if (sz != sizeof(compat_sigset_t)) |
69 | return -EINVAL; | 69 | return -EINVAL; |
70 | sigset_64to32(&s, set); | 70 | sigset_64to32(&s, set); |
71 | 71 | ||
@@ -78,7 +78,7 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) | |||
78 | compat_sigset_t s; | 78 | compat_sigset_t s; |
79 | int r; | 79 | int r; |
80 | 80 | ||
81 | if (sz != sizeof *set) | 81 | if (sz != sizeof(compat_sigset_t)) |
82 | return -EINVAL; | 82 | return -EINVAL; |
83 | 83 | ||
84 | if ((r = copy_from_user(&s, up, sz)) == 0) { | 84 | if ((r = copy_from_user(&s, up, sz)) == 0) { |
@@ -94,8 +94,11 @@ int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t _ | |||
94 | sigset_t old_set, new_set; | 94 | sigset_t old_set, new_set; |
95 | int ret; | 95 | int ret; |
96 | 96 | ||
97 | if (set && get_sigset32(set, &new_set, sigsetsize)) | 97 | if (set) { |
98 | return -EFAULT; | 98 | ret = get_sigset32(set, &new_set, sigsetsize); |
99 | if (ret) | ||
100 | return ret; | ||
101 | } | ||
99 | 102 | ||
100 | KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL, | 103 | KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL, |
101 | oset ? (sigset_t __user *)&old_set : NULL, sigsetsize); | 104 | oset ? (sigset_t __user *)&old_set : NULL, sigsetsize); |
@@ -128,6 +131,10 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigacti | |||
128 | struct k_sigaction new_sa, old_sa; | 131 | struct k_sigaction new_sa, old_sa; |
129 | int ret = -EINVAL; | 132 | int ret = -EINVAL; |
130 | 133 | ||
134 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
135 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
136 | return -EINVAL; | ||
137 | |||
131 | if (act) { | 138 | if (act) { |
132 | if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa)) | 139 | if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa)) |
133 | return -EFAULT; | 140 | return -EFAULT; |
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index f76c10863c62..54d619d4cac6 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c | |||
@@ -94,11 +94,12 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, | |||
94 | { | 94 | { |
95 | if (len > TASK_SIZE) | 95 | if (len > TASK_SIZE) |
96 | return -ENOMEM; | 96 | return -ENOMEM; |
97 | /* Might want to check for cache aliasing issues for MAP_FIXED case | 97 | if (flags & MAP_FIXED) { |
98 | * like ARM or MIPS ??? --BenH. | 98 | if ((flags & MAP_SHARED) && |
99 | */ | 99 | (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) |
100 | if (flags & MAP_FIXED) | 100 | return -EINVAL; |
101 | return addr; | 101 | return addr; |
102 | } | ||
102 | if (!addr) | 103 | if (!addr) |
103 | addr = TASK_UNMAPPED_BASE; | 104 | addr = TASK_UNMAPPED_BASE; |
104 | 105 | ||
@@ -212,6 +213,13 @@ asmlinkage long parisc_sync_file_range(int fd, | |||
212 | (loff_t)hi_nbytes << 32 | lo_nbytes, flags); | 213 | (loff_t)hi_nbytes << 32 | lo_nbytes, flags); |
213 | } | 214 | } |
214 | 215 | ||
216 | asmlinkage long parisc_fallocate(int fd, int mode, u32 offhi, u32 offlo, | ||
217 | u32 lenhi, u32 lenlo) | ||
218 | { | ||
219 | return sys_fallocate(fd, mode, ((u64)offhi << 32) | offlo, | ||
220 | ((u64)lenhi << 32) | lenlo); | ||
221 | } | ||
222 | |||
215 | asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag) | 223 | asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag) |
216 | { | 224 | { |
217 | return -ENOMEM; | 225 | return -ENOMEM; |
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 9cfdaa19ab63..eca69bb8ef5f 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/smp.h> | 22 | #include <linux/smp.h> |
23 | #include <linux/sem.h> | 23 | #include <linux/sem.h> |
24 | #include <linux/msg.h> | ||
25 | #include <linux/shm.h> | 24 | #include <linux/shm.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
@@ -61,111 +60,23 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, | |||
61 | return -ENOSYS; | 60 | return -ENOSYS; |
62 | } | 61 | } |
63 | 62 | ||
64 | asmlinkage long sys32_sched_rr_get_interval(pid_t pid, | 63 | /* Note: it is necessary to treat out_fd and in_fd as unsigned ints, with the |
65 | struct compat_timespec __user *interval) | 64 | * corresponding cast to a signed int to insure that the proper conversion |
66 | { | 65 | * (sign extension) between the register representation of a signed int (msr in |
67 | struct timespec t; | 66 | * 32-bit mode) and the register representation of a signed int (msr in 64-bit |
68 | int ret; | 67 | * mode) is performed. |
69 | 68 | */ | |
70 | KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t); | 69 | asmlinkage long sys32_sendfile(u32 out_fd, u32 in_fd, |
71 | if (put_compat_timespec(&t, interval)) | 70 | compat_off_t __user *offset, compat_size_t count) |
72 | return -EFAULT; | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | struct msgbuf32 { | ||
77 | int mtype; | ||
78 | char mtext[1]; | ||
79 | }; | ||
80 | |||
81 | asmlinkage long sys32_msgsnd(int msqid, | ||
82 | struct msgbuf32 __user *umsgp32, | ||
83 | size_t msgsz, int msgflg) | ||
84 | { | ||
85 | struct msgbuf *mb; | ||
86 | struct msgbuf32 mb32; | ||
87 | int err; | ||
88 | |||
89 | if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | err = get_user(mb32.mtype, &umsgp32->mtype); | ||
93 | mb->mtype = mb32.mtype; | ||
94 | err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz); | ||
95 | |||
96 | if (err) | ||
97 | err = -EFAULT; | ||
98 | else | ||
99 | KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg); | ||
100 | |||
101 | kfree(mb); | ||
102 | return err; | ||
103 | } | ||
104 | |||
105 | asmlinkage long sys32_msgrcv(int msqid, | ||
106 | struct msgbuf32 __user *umsgp32, | ||
107 | size_t msgsz, long msgtyp, int msgflg) | ||
108 | { | ||
109 | struct msgbuf *mb; | ||
110 | struct msgbuf32 mb32; | ||
111 | int err, len; | ||
112 | |||
113 | if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg); | ||
117 | |||
118 | if (err >= 0) { | ||
119 | len = err; | ||
120 | mb32.mtype = mb->mtype; | ||
121 | err = put_user(mb32.mtype, &umsgp32->mtype); | ||
122 | err |= copy_to_user(&umsgp32->mtext, mb->mtext, len); | ||
123 | if (err) | ||
124 | err = -EFAULT; | ||
125 | else | ||
126 | err = len; | ||
127 | } | ||
128 | |||
129 | kfree(mb); | ||
130 | return err; | ||
131 | } | ||
132 | |||
133 | asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count) | ||
134 | { | 71 | { |
135 | mm_segment_t old_fs = get_fs(); | 72 | return compat_sys_sendfile((int)out_fd, (int)in_fd, offset, count); |
136 | int ret; | ||
137 | off_t of; | ||
138 | |||
139 | if (offset && get_user(of, offset)) | ||
140 | return -EFAULT; | ||
141 | |||
142 | set_fs(KERNEL_DS); | ||
143 | ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); | ||
144 | set_fs(old_fs); | ||
145 | |||
146 | if (offset && put_user(of, offset)) | ||
147 | return -EFAULT; | ||
148 | |||
149 | return ret; | ||
150 | } | 73 | } |
151 | 74 | ||
152 | asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count) | 75 | asmlinkage long sys32_sendfile64(u32 out_fd, u32 in_fd, |
76 | compat_loff_t __user *offset, compat_size_t count) | ||
153 | { | 77 | { |
154 | mm_segment_t old_fs = get_fs(); | 78 | return sys_sendfile64((int)out_fd, (int)in_fd, |
155 | int ret; | 79 | (loff_t __user *)offset, count); |
156 | loff_t lof; | ||
157 | |||
158 | if (offset && get_user(lof, offset)) | ||
159 | return -EFAULT; | ||
160 | |||
161 | set_fs(KERNEL_DS); | ||
162 | ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count); | ||
163 | set_fs(old_fs); | ||
164 | |||
165 | if (offset && put_user(lof, offset)) | ||
166 | return -EFAULT; | ||
167 | |||
168 | return ret; | ||
169 | } | 80 | } |
170 | 81 | ||
171 | 82 | ||
@@ -200,13 +111,6 @@ long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf, | |||
200 | buf, len); | 111 | buf, len); |
201 | } | 112 | } |
202 | 113 | ||
203 | asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo, | ||
204 | u32 lenhi, u32 lenlo) | ||
205 | { | ||
206 | return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo, | ||
207 | ((loff_t)lenhi << 32) | lenlo); | ||
208 | } | ||
209 | |||
210 | asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi, | 114 | asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi, |
211 | u32 mask_lo, int fd, | 115 | u32 mask_lo, int fd, |
212 | const char __user *pathname) | 116 | const char __user *pathname) |
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 86742df0b194..5e055240f00b 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S | |||
@@ -309,10 +309,13 @@ tracesys_next: | |||
309 | LDREG TASK_PT_GR25(%r1), %r25 | 309 | LDREG TASK_PT_GR25(%r1), %r25 |
310 | LDREG TASK_PT_GR24(%r1), %r24 | 310 | LDREG TASK_PT_GR24(%r1), %r24 |
311 | LDREG TASK_PT_GR23(%r1), %r23 | 311 | LDREG TASK_PT_GR23(%r1), %r23 |
312 | #ifdef CONFIG_64BIT | ||
313 | LDREG TASK_PT_GR22(%r1), %r22 | 312 | LDREG TASK_PT_GR22(%r1), %r22 |
314 | LDREG TASK_PT_GR21(%r1), %r21 | 313 | LDREG TASK_PT_GR21(%r1), %r21 |
314 | #ifdef CONFIG_64BIT | ||
315 | ldo -16(%r30),%r29 /* Reference param save area */ | 315 | ldo -16(%r30),%r29 /* Reference param save area */ |
316 | #else | ||
317 | stw %r22, -52(%r30) /* 5th argument */ | ||
318 | stw %r21, -56(%r30) /* 6th argument */ | ||
316 | #endif | 319 | #endif |
317 | 320 | ||
318 | comiclr,>>= __NR_Linux_syscalls, %r20, %r0 | 321 | comiclr,>>= __NR_Linux_syscalls, %r20, %r0 |
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 54d950b067b7..129fd472c471 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S | |||
@@ -247,10 +247,7 @@ | |||
247 | ENTRY_SAME(sched_yield) | 247 | ENTRY_SAME(sched_yield) |
248 | ENTRY_SAME(sched_get_priority_max) | 248 | ENTRY_SAME(sched_get_priority_max) |
249 | ENTRY_SAME(sched_get_priority_min) /* 160 */ | 249 | ENTRY_SAME(sched_get_priority_min) /* 160 */ |
250 | /* These 2 would've worked if someone had defined struct timespec | 250 | ENTRY_COMP(sched_rr_get_interval) |
251 | * carefully, like timeval for example (which is about the same). | ||
252 | * Unfortunately it contains a long :-( */ | ||
253 | ENTRY_DIFF(sched_rr_get_interval) | ||
254 | ENTRY_COMP(nanosleep) | 251 | ENTRY_COMP(nanosleep) |
255 | ENTRY_SAME(mremap) | 252 | ENTRY_SAME(mremap) |
256 | ENTRY_SAME(setresuid) | 253 | ENTRY_SAME(setresuid) |
@@ -286,8 +283,8 @@ | |||
286 | ENTRY_SAME(semop) /* 185 */ | 283 | ENTRY_SAME(semop) /* 185 */ |
287 | ENTRY_SAME(semget) | 284 | ENTRY_SAME(semget) |
288 | ENTRY_DIFF(semctl) | 285 | ENTRY_DIFF(semctl) |
289 | ENTRY_DIFF(msgsnd) | 286 | ENTRY_COMP(msgsnd) |
290 | ENTRY_DIFF(msgrcv) | 287 | ENTRY_COMP(msgrcv) |
291 | ENTRY_SAME(msgget) /* 190 */ | 288 | ENTRY_SAME(msgget) /* 190 */ |
292 | ENTRY_SAME(msgctl) | 289 | ENTRY_SAME(msgctl) |
293 | ENTRY_SAME(shmat) | 290 | ENTRY_SAME(shmat) |
@@ -307,7 +304,7 @@ | |||
307 | ENTRY_SAME(gettid) | 304 | ENTRY_SAME(gettid) |
308 | ENTRY_OURS(readahead) | 305 | ENTRY_OURS(readahead) |
309 | ENTRY_SAME(tkill) | 306 | ENTRY_SAME(tkill) |
310 | ENTRY_SAME(sendfile64) | 307 | ENTRY_DIFF(sendfile64) |
311 | ENTRY_COMP(futex) /* 210 */ | 308 | ENTRY_COMP(futex) /* 210 */ |
312 | ENTRY_COMP(sched_setaffinity) | 309 | ENTRY_COMP(sched_setaffinity) |
313 | ENTRY_COMP(sched_getaffinity) | 310 | ENTRY_COMP(sched_getaffinity) |
@@ -327,12 +324,12 @@ | |||
327 | ENTRY_SAME(epoll_wait) | 324 | ENTRY_SAME(epoll_wait) |
328 | ENTRY_SAME(remap_file_pages) | 325 | ENTRY_SAME(remap_file_pages) |
329 | ENTRY_SAME(semtimedop) | 326 | ENTRY_SAME(semtimedop) |
330 | ENTRY_SAME(mq_open) | 327 | ENTRY_COMP(mq_open) |
331 | ENTRY_SAME(mq_unlink) /* 230 */ | 328 | ENTRY_SAME(mq_unlink) /* 230 */ |
332 | ENTRY_SAME(mq_timedsend) | 329 | ENTRY_COMP(mq_timedsend) |
333 | ENTRY_SAME(mq_timedreceive) | 330 | ENTRY_COMP(mq_timedreceive) |
334 | ENTRY_SAME(mq_notify) | 331 | ENTRY_COMP(mq_notify) |
335 | ENTRY_SAME(mq_getsetattr) | 332 | ENTRY_COMP(mq_getsetattr) |
336 | ENTRY_COMP(waitid) /* 235 */ | 333 | ENTRY_COMP(waitid) /* 235 */ |
337 | ENTRY_OURS(fadvise64_64) | 334 | ENTRY_OURS(fadvise64_64) |
338 | ENTRY_SAME(set_tid_address) | 335 | ENTRY_SAME(set_tid_address) |
@@ -403,7 +400,7 @@ | |||
403 | ENTRY_COMP(signalfd) | 400 | ENTRY_COMP(signalfd) |
404 | ENTRY_SAME(ni_syscall) /* was timerfd */ | 401 | ENTRY_SAME(ni_syscall) /* was timerfd */ |
405 | ENTRY_SAME(eventfd) | 402 | ENTRY_SAME(eventfd) |
406 | ENTRY_COMP(fallocate) /* 305 */ | 403 | ENTRY_OURS(fallocate) /* 305 */ |
407 | ENTRY_SAME(timerfd_create) | 404 | ENTRY_SAME(timerfd_create) |
408 | ENTRY_COMP(timerfd_settime) | 405 | ENTRY_COMP(timerfd_settime) |
409 | ENTRY_COMP(timerfd_gettime) | 406 | ENTRY_COMP(timerfd_gettime) |
@@ -428,6 +425,10 @@ | |||
428 | ENTRY_SAME(syncfs) | 425 | ENTRY_SAME(syncfs) |
429 | ENTRY_SAME(setns) | 426 | ENTRY_SAME(setns) |
430 | ENTRY_COMP(sendmmsg) | 427 | ENTRY_COMP(sendmmsg) |
428 | ENTRY_COMP(process_vm_readv) /* 330 */ | ||
429 | ENTRY_COMP(process_vm_writev) | ||
430 | ENTRY_SAME(kcmp) | ||
431 | ENTRY_SAME(finit_module) | ||
431 | 432 | ||
432 | /* Nothing yet */ | 433 | /* Nothing yet */ |
433 | 434 | ||
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 18162ce4261e..f247a3480e8e 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c | |||
@@ -175,10 +175,12 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, | |||
175 | struct mm_struct *mm = tsk->mm; | 175 | struct mm_struct *mm = tsk->mm; |
176 | unsigned long acc_type; | 176 | unsigned long acc_type; |
177 | int fault; | 177 | int fault; |
178 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | ||
178 | 179 | ||
179 | if (in_atomic() || !mm) | 180 | if (in_atomic() || !mm) |
180 | goto no_context; | 181 | goto no_context; |
181 | 182 | ||
183 | retry: | ||
182 | down_read(&mm->mmap_sem); | 184 | down_read(&mm->mmap_sem); |
183 | vma = find_vma_prev(mm, address, &prev_vma); | 185 | vma = find_vma_prev(mm, address, &prev_vma); |
184 | if (!vma || address < vma->vm_start) | 186 | if (!vma || address < vma->vm_start) |
@@ -201,7 +203,12 @@ good_area: | |||
201 | * fault. | 203 | * fault. |
202 | */ | 204 | */ |
203 | 205 | ||
204 | fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0); | 206 | fault = handle_mm_fault(mm, vma, address, |
207 | flags | ((acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0)); | ||
208 | |||
209 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
210 | return; | ||
211 | |||
205 | if (unlikely(fault & VM_FAULT_ERROR)) { | 212 | if (unlikely(fault & VM_FAULT_ERROR)) { |
206 | /* | 213 | /* |
207 | * We hit a shared mapping outside of the file, or some | 214 | * We hit a shared mapping outside of the file, or some |
@@ -214,10 +221,23 @@ good_area: | |||
214 | goto bad_area; | 221 | goto bad_area; |
215 | BUG(); | 222 | BUG(); |
216 | } | 223 | } |
217 | if (fault & VM_FAULT_MAJOR) | 224 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
218 | current->maj_flt++; | 225 | if (fault & VM_FAULT_MAJOR) |
219 | else | 226 | current->maj_flt++; |
220 | current->min_flt++; | 227 | else |
228 | current->min_flt++; | ||
229 | if (fault & VM_FAULT_RETRY) { | ||
230 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
231 | |||
232 | /* | ||
233 | * No need to up_read(&mm->mmap_sem) as we would | ||
234 | * have already released it in __lock_page_or_retry | ||
235 | * in mm/filemap.c. | ||
236 | */ | ||
237 | |||
238 | goto retry; | ||
239 | } | ||
240 | } | ||
221 | up_read(&mm->mmap_sem); | 241 | up_read(&mm->mmap_sem); |
222 | return; | 242 | return; |
223 | 243 | ||