| 
									
										
										
										
											2005-11-09 13:04:06 +11:00
										 |  |  | #ifndef _ASM_POWERPC_CURRENT_H
 | 
					
						
							|  |  |  | #define _ASM_POWERPC_CURRENT_H
 | 
					
						
							| 
									
										
										
										
											2005-12-16 22:43:46 +01:00
										 |  |  | #ifdef __KERNEL__
 | 
					
						
							| 
									
										
										
										
											2005-11-09 13:04:06 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version | 
					
						
							|  |  |  |  * 2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct task_struct; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __powerpc64__
 | 
					
						
							| 
									
										
										
										
											2007-02-25 20:04:18 +01:00
										 |  |  | #include <linux/stddef.h>
 | 
					
						
							| 
									
										
										
										
											2005-11-09 13:04:06 +11:00
										 |  |  | #include <asm/paca.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												[POWERPC] Make current preempt-safe
Repeated -j20 kernel builds on a G5 Quad running an SMP PREEMPT kernel
would often collapse within a day, some exec failing with "Bad address".
In each case examined, load_elf_binary was doing a kernel_read, but
generic_file_aio_read's access_ok saw current->thread.fs.seg as USER_DS
instead of KERNEL_DS.
objdump of filemap.o shows gcc 4.1.0 emitting "mr r5,r13 ... ld r9,416(r5)"
here for get_paca()->__current, instead of the expected and much more usual
"ld r9,416(r13)"; I've seen other gcc4s do the same, but perhaps not gcc3s.
So, if the task is preempted and rescheduled on a different cpu in between
the mr and the ld, r5 will be looking at a different paca_struct from the
one it's now on, pick up the wrong __current, and perhaps the wrong seg.
Presumably much worse could happen elsewhere, though that split is rare.
Other architectures appear to be safe (x86_64's read_pda is more limiting
than get_paca), but ppc64 needs to force "current" into one instruction.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
											
										 
											2006-10-31 18:39:31 +00:00
										 |  |  | static inline struct task_struct *get_current(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct task_struct *task; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__asm__ __volatile__("ld %0,%1(13)" | 
					
						
							|  |  |  | 	: "=r" (task) | 
					
						
							|  |  |  | 	: "i" (offsetof(struct paca_struct, __current))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return task; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #define current	get_current()
 | 
					
						
							| 
									
										
										
										
											2005-11-09 13:04:06 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * We keep `current' in r2 for speed. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | register struct task_struct *current asm ("r2"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-16 22:43:46 +01:00
										 |  |  | #endif /* __KERNEL__ */
 | 
					
						
							| 
									
										
										
										
											2005-11-09 13:04:06 +11:00
										 |  |  | #endif /* _ASM_POWERPC_CURRENT_H */
 |