diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-16 22:28:43 -0500 | 
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-16 22:28:43 -0500 | 
| commit | 2bf81c8af92dd53890557c5d87875842d573a3e9 (patch) | |
| tree | 83e7e3539599b091ac69557658c06c0a39cfa60e /arch | |
| parent | 9526d9bc23f362035cfabf044aa90f4ed1787955 (diff) | |
| parent | 5f6c4ab6ee781c9aace7c8548ad9bd87f5678df7 (diff) | |
| download | linux-2bf81c8af92dd53890557c5d87875842d573a3e9.tar.bz2 | |
Merge branch 'arch-microblaze' into no-rebases
Diffstat (limited to 'arch')
50 files changed, 288 insertions, 214 deletions
| diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 35c1ed89b936..42f042ee4ada 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);  static inline void __raw_writew(u16 val, volatile void __iomem *addr)  {  	asm volatile("strh %1, %0" -		     : "+Qo" (*(volatile u16 __force *)addr) +		     : "+Q" (*(volatile u16 __force *)addr)  		     : "r" (val));  } @@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)  {  	u16 val;  	asm volatile("ldrh %1, %0" -		     : "+Qo" (*(volatile u16 __force *)addr), +		     : "+Q" (*(volatile u16 __force *)addr),  		       "=r" (val));  	return val;  } diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index 05b8e82ec9f5..e3f757263438 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h @@ -10,7 +10,5 @@  extern void sched_clock_postinit(void);  extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); -extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, -		unsigned long rate);  #endif diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 6a6f1e485f41..301c1db3e99b 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -27,9 +27,9 @@  #if __LINUX_ARM_ARCH__ <= 6  	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs  	ldr	\tmp, [\tmp, #0] -	tst	\tmp, #HWCAP_VFPv3D16 -	ldceql	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31} -	addne	\base, \base, #32*4		    @ step over unused register space +	tst	\tmp, #HWCAP_VFPD32 +	ldcnel	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31} +	addeq	\base, \base, #32*4		    @ step over unused register space  #else  	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0  	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field @@ -51,9 +51,9 @@  #if __LINUX_ARM_ARCH__ <= 6  	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs  	ldr	\tmp, [\tmp, #0] -	tst	\tmp, #HWCAP_VFPv3D16 -	stceql	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31} -	addne	\base, \base, #32*4		    @ step over unused register space +	tst	\tmp, #HWCAP_VFPD32 +	stcnel	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31} +	addeq	\base, \base, #32*4		    @ step over unused register space  #else  	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0  	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h index f254f6503cce..3688fd15a32d 100644 --- a/arch/arm/include/uapi/asm/hwcap.h +++ b/arch/arm/include/uapi/asm/hwcap.h @@ -18,11 +18,12 @@  #define HWCAP_THUMBEE	(1 << 11)  #define HWCAP_NEON	(1 << 12)  #define HWCAP_VFPv3	(1 << 13) -#define HWCAP_VFPv3D16	(1 << 14) +#define HWCAP_VFPv3D16	(1 << 14)	/* also set for VFPv4-D16 */  #define HWCAP_TLS	(1 << 15)  #define HWCAP_VFPv4	(1 << 16)  #define HWCAP_IDIVA	(1 << 17)  #define HWCAP_IDIVT	(1 << 18) +#define HWCAP_VFPD32	(1 << 19)	/* set if VFP has 32 regs (not 16) */  #define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT) diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index e21bac20d90d..fc6692e2b603 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)  	update_sched_clock();  } -void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, -		unsigned long rate) -{ -	setup_sched_clock(read, bits, rate); -	cd.needs_suspend = true; -} -  void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)  {  	unsigned long r, w; @@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)  static int sched_clock_suspend(void)  {  	sched_clock_poll(sched_clock_timer.data); -	if (cd.needs_suspend) -		cd.suspended = true; +	cd.suspended = true;  	return 0;  }  static void sched_clock_resume(void)  { -	if (cd.needs_suspend) { -		cd.epoch_cyc = read_sched_clock(); -		cd.epoch_cyc_copy = cd.epoch_cyc; -		cd.suspended = false; -	} +	cd.epoch_cyc = read_sched_clock(); +	cd.epoch_cyc_copy = cd.epoch_cyc; +	cd.suspended = false;  }  static struct syscore_ops sched_clock_ops = { diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 023f443784ec..b820edaf3184 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,  static int  do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  { -	union offset_union offset; +	union offset_union uninitialized_var(offset);  	unsigned long instr = 0, instrptr;  	int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);  	unsigned int type; diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index c834b32af275..3b44e0dd0a93 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -701,11 +701,14 @@ static int __init vfp_init(void)  			elf_hwcap |= HWCAP_VFPv3;  			/* -			 * Check for VFPv3 D16. CPUs in this configuration -			 * only have 16 x 64bit registers. +			 * Check for VFPv3 D16 and VFPv4 D16.  CPUs in +			 * this configuration only have 16 x 64bit +			 * registers.  			 */  			if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) -				elf_hwcap |= HWCAP_VFPv3D16; +				elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ +			else +				elf_hwcap |= HWCAP_VFPD32;  		}  #endif  		/* diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 59bcb96ac369..f57609275449 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)  	*pages = NULL;  }  EXPORT_SYMBOL_GPL(free_xenballooned_pages); + +/* In the hypervisor.S file. */ +EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version); +EXPORT_SYMBOL_GPL(HYPERVISOR_console_io); +EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); +EXPORT_SYMBOL_GPL(privcmd_call); diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 138fc9cfd783..20b688c81956 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1,6 +1,7 @@  config ARM64  	def_bool y  	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE +	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION  	select GENERIC_CLOCKEVENTS  	select GENERIC_HARDIRQS_NO_DEPRECATED  	select GENERIC_IOMAP diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 42471d07d972..ab239b2c456f 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -43,6 +43,8 @@  #else  #define STACK_TOP		STACK_TOP_MAX  #endif /* CONFIG_COMPAT */ + +#define ARCH_LOW_ADDRESS_LIMIT	PHYS_MASK  #endif /* __KERNEL__ */  struct debug_info { diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index b40dc6b69848..43064a8bd99e 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -14,7 +14,6 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #ifdef CONFIG_COMPAT -#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION  #define __ARCH_WANT_COMPAT_STAT64  #define __ARCH_WANT_SYS_GETHOSTNAME  #define __ARCH_WANT_SYS_PAUSE diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 226b6bf6e9c2..538300f2273d 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -211,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)  	 * before we continue.  	 */  	set_cpu_online(cpu, true); -	while (!cpu_active(cpu)) -		cpu_relax(); +	complete(&cpu_running);  	/*  	 * OK, it's off to the idle thread for us diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index efbf7df05d3f..4cd28931dba9 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)  #ifdef CONFIG_ZONE_DMA32  	/* 4GB maximum for 32-bit only capable devices */  	max_dma32 = min(max, MAX_DMA32_PFN); -	zone_size[ZONE_DMA32] = max_dma32 - min; +	zone_size[ZONE_DMA32] = max(min, max_dma32) - min;  #endif  	zone_size[ZONE_NORMAL] = max - max_dma32; diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h index c6350283649d..05887a1d80e5 100644 --- a/arch/h8300/include/asm/cache.h +++ b/arch/h8300/include/asm/cache.h @@ -2,7 +2,8 @@  #define __ARCH_H8300_CACHE_H  /* bytes per L1 cache line */ -#define        L1_CACHE_BYTES  4 +#define        L1_CACHE_SHIFT  2 +#define        L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)  /* m68k-elf-gcc  2.95.2 doesn't like these */ diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 4cba7439f9de..198abf6d41c4 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -26,6 +26,8 @@ config MICROBLAZE  	select GENERIC_ATOMIC64  	select GENERIC_CLOCKEVENTS  	select MODULES_USE_ELF_RELA +	select GENERIC_KERNEL_THREAD +	select GENERIC_KERNEL_EXECVE  config SWAP  	def_bool n diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index af2bb9652392..0759153e8117 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -31,6 +31,7 @@ extern const struct seq_operations cpuinfo_op;  void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);  extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void);  # endif /* __ASSEMBLY__ */ @@ -78,11 +79,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t);  extern unsigned long get_wchan(struct task_struct *p); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); -  # define KSTK_EIP(tsk)	(0)  # define KSTK_ESP(tsk)	(0) @@ -131,8 +127,6 @@ extern inline void release_thread(struct task_struct *dead_task)  {  } -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); -  /* Free current thread data structures etc.  */  static inline void exit_thread(void)  { diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 6985e6e9d826..ea7442834294 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -422,6 +422,7 @@  #define __ARCH_WANT_SYS_SIGPROCMASK  #define __ARCH_WANT_SYS_RT_SIGACTION  #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE  /*   * "Conditional" syscalls diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 75c3ea1f48a1..673a49c04a02 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -474,6 +474,14 @@ ENTRY(ret_from_fork)  	brid	ret_to_user  	nop +ENTRY(ret_from_kernel_thread) +	brlid	r15, schedule_tail +	addk	r5, r0, r3 +	brald	r15, r20 +	addk	r5, r0, r19 +	brid	ret_to_user +	addk	r3, r0, r0 +  work_pending:  	enable_irq @@ -559,10 +567,6 @@ sys_clone:  	brid	microblaze_clone  	addk	r7, r1, r0 -sys_execve: -	brid	microblaze_execve -	addk	r8, r1, r0 -  sys_rt_sigreturn_wrapper:  	brid	sys_rt_sigreturn  	addk	r5, r1, r0 diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 03f7b8ce6b6b..10f360ed82b4 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -293,24 +293,6 @@ C_ENTRY(_user_exception):  	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */  	addi	r14, r14, 4	/* return address is 4 byte after call */ -	mfs	r1, rmsr -	nop -	andi	r1, r1, MSR_UMS -	bnei	r1, 1f - -/* Kernel-mode state save - kernel execve */ -	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ -	tophys(r1,r1); - -	addik	r1, r1, -PT_SIZE; /* Make room on the stack. */ -	SAVE_REGS - -	swi	r1, r1, PT_MODE; /* pt_regs -> kernel mode */ -	brid	2f; -	nop;				/* Fill delay slot */ - -/* User-mode state save.  */ -1:  	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */  	tophys(r1,r1);  	lwi	r1, r1, TS_THREAD_INFO;	/* get stack from task_struct */ @@ -479,11 +461,20 @@ C_ENTRY(sys_fork_wrapper):     saved context).  */  C_ENTRY(ret_from_fork):  	bralid	r15, schedule_tail; /* ...which is schedule_tail's arg */ -	add	r3, r5, r0;	/* switch_thread returns the prev task */ +	add	r5, r3, r0;	/* switch_thread returns the prev task */  				/* ( in the delay slot ) */  	brid	ret_from_trap;	/* Do normal trap return */  	add	r3, r0, r0;	/* Child's fork call should return 0. */ +C_ENTRY(ret_from_kernel_thread): +	bralid	r15, schedule_tail; /* ...which is schedule_tail's arg */ +	add	r5, r3, r0;	/* switch_thread returns the prev task */ +				/* ( in the delay slot ) */ +	brald	r15, r20	/* fn was left in r20 */ +	addk	r5, r0, r19	/* ... and argument - in r19 */ +	brid	ret_from_trap +	add	r3, r0, r0 +  C_ENTRY(sys_vfork):  	brid	microblaze_vfork	/* Do real work (tail-call) */  	addik	r5, r1, 0 @@ -498,10 +489,6 @@ C_ENTRY(sys_clone):  	brid	do_fork		/* Do real work (tail-call) */  	add     r8, r0, r0;             /* Arg 3: (unused) */ -C_ENTRY(sys_execve): -	brid	microblaze_execve;	/* Do real work (tail-call).*/ -	addik	r8, r1, 0;		/* add user context as 4th arg */ -  C_ENTRY(sys_rt_sigreturn_wrapper):  	brid	sys_rt_sigreturn	/* Do real work */  	addik	r5, r1, 0;		/* add user context as 1st arg */ diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 1944e00f07e1..29768c3dc358 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -119,46 +119,38 @@ void flush_thread(void)  }  int copy_thread(unsigned long clone_flags, unsigned long usp, -		unsigned long unused, +		unsigned long arg,  		struct task_struct *p, struct pt_regs *regs)  {  	struct pt_regs *childregs = task_pt_regs(p);  	struct thread_info *ti = task_thread_info(p); +	if (unlikely(p->flags & PF_KTHREAD)) { +		/* if we're creating a new kernel thread then just zeroing all +		 * the registers. That's OK for a brand new thread.*/ +		memset(childregs, 0, sizeof(struct pt_regs)); +		memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); +		ti->cpu_context.r1  = (unsigned long)childregs; +		ti->cpu_context.r20 = (unsigned long)usp; /* fn */ +		ti->cpu_context.r19 = (unsigned long)arg; +		childregs->pt_mode = 1; +		local_save_flags(childregs->msr); +#ifdef CONFIG_MMU +		ti->cpu_context.msr = childregs->msr & ~MSR_IE; +#endif +		ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8; +		return 0; +	}  	*childregs = *regs; -	if (user_mode(regs)) -		childregs->r1 = usp; -	else -		childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; +	childregs->r1 = usp; -#ifndef CONFIG_MMU  	memset(&ti->cpu_context, 0, sizeof(struct cpu_context));  	ti->cpu_context.r1 = (unsigned long)childregs; +#ifndef CONFIG_MMU  	ti->cpu_context.msr = (unsigned long)childregs->msr;  #else +	childregs->msr |= MSR_UMS; -	/* if creating a kernel thread then update the current reg (we don't -	 * want to use the parent's value when restoring by POP_STATE) */ -	if (kernel_mode(regs)) -		/* save new current on stack to use POP_STATE */ -		childregs->CURRENT_TASK = (unsigned long)p; -	/* if returning to user then use the parent's value of this register */ - -	/* if we're creating a new kernel thread then just zeroing all -	 * the registers. That's OK for a brand new thread.*/ -	/* Pls. note that some of them will be restored in POP_STATE */ -	if (kernel_mode(regs)) -		memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); -	/* if this thread is created for fork/vfork/clone, then we want to -	 * restore all the parent's context */ -	/* in addition to the registers which will be restored by POP_STATE */ -	else { -		ti->cpu_context = *(struct cpu_context *)regs; -		childregs->msr |= MSR_UMS; -	} - -	/* FIXME STATE_SAVE_PT_OFFSET; */ -	ti->cpu_context.r1  = (unsigned long)childregs;  	/* we should consider the fact that childregs is a copy of the parent  	 * regs which were saved immediately after entering the kernel state  	 * before enabling VM. This MSR will be restored in switch_to and @@ -209,29 +201,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)  }  #endif -static void kernel_thread_helper(int (*fn)(void *), void *arg) -{ -	fn(arg); -	do_exit(-1); -} - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ -	struct pt_regs regs; - -	memset(®s, 0, sizeof(regs)); -	/* store them in non-volatile registers */ -	regs.r5 = (unsigned long)fn; -	regs.r6 = (unsigned long)arg; -	local_save_flags(regs.msr); -	regs.pc = (unsigned long)kernel_thread_helper; -	regs.pt_mode = 1; - -	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, -			®s, 0, NULL, NULL); -} -EXPORT_SYMBOL_GPL(kernel_thread); -  unsigned long get_wchan(struct task_struct *p)  {  /* TBD (used by procfs) */ @@ -246,6 +215,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)  	regs->pt_mode = 0;  #ifdef CONFIG_MMU  	regs->msr |= MSR_UMS; +	regs->msr &= ~MSR_VM;  #endif  } diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 404c0f24bd41..a6a7bae9f5c6 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -48,24 +48,6 @@ asmlinkage long microblaze_clone(int flags, unsigned long stack,  	return do_fork(flags, stack, regs, 0, NULL, NULL);  } -asmlinkage long microblaze_execve(const char __user *filenamei, -				  const char __user *const __user *argv, -				  const char __user *const __user *envp, -				  struct pt_regs *regs) -{ -	int error; -	struct filename *filename; - -	filename = getname(filenamei); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		goto out; -	error = do_execve(filename->name, argv, envp, regs); -	putname(filename); -out: -	return error; -} -  asmlinkage long sys_mmap(unsigned long addr, unsigned long len,  			unsigned long prot, unsigned long flags,  			unsigned long fd, off_t pgoff) @@ -75,24 +57,3 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,  	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);  } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, -		  const char *const argv[], -		  const char *const envp[]) -{ -	register const char *__a __asm__("r5") = filename; -	register const void *__b __asm__("r6") = argv; -	register const void *__c __asm__("r7") = envp; -	register unsigned long __syscall __asm__("r12") = __NR_execve; -	register unsigned long __ret __asm__("r3"); -	__asm__ __volatile__ ("brki r14, 0x8" -			: "=r" (__ret), "=r" (__syscall) -			: "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) -			: "r4", "r8", "r9", -			"r10", "r11", "r14", "cc", "memory"); -	return __ret; -} diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index 55bde6035216..ad2b924167d7 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -9,6 +9,8 @@  #define LPM_ANYPATH 0xff  #define __MAX_CSSID 0 +#define __MAX_SUBCHANNEL 65535 +#define __MAX_SSID 3  #include <asm/scsw.h> diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index dd647c919a66..2d3b7cb26005 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)  static inline int pmd_present(pmd_t pmd)  { -	return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; +	unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO; +	return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE || +	       !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);  }  static inline int pmd_none(pmd_t pmd)  { -	return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; +	return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) && +	       !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);  }  static inline int pmd_large(pmd_t pmd) @@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)  }  #ifdef CONFIG_TRANSPARENT_HUGEPAGE + +#define SEGMENT_NONE	__pgprot(_HPAGE_TYPE_NONE) +#define SEGMENT_RO	__pgprot(_HPAGE_TYPE_RO) +#define SEGMENT_RW	__pgprot(_HPAGE_TYPE_RW) +  #define __HAVE_ARCH_PGTABLE_DEPOSIT  extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable); @@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,  static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)  { -	unsigned long pgprot_pmd = 0; - -	if (pgprot_val(pgprot) & _PAGE_INVALID) { -		if (pgprot_val(pgprot) & _PAGE_SWT) -			pgprot_pmd |= _HPAGE_TYPE_NONE; -		pgprot_pmd |= _SEGMENT_ENTRY_INV; -	} -	if (pgprot_val(pgprot) & _PAGE_RO) -		pgprot_pmd |= _SEGMENT_ENTRY_RO; -	return pgprot_pmd; +	/* +	 * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx) +	 * Convert to segment table entry format. +	 */ +	if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE)) +		return pgprot_val(SEGMENT_NONE); +	if (pgprot_val(pgprot) == pgprot_val(PAGE_RO)) +		return pgprot_val(SEGMENT_RO); +	return pgprot_val(SEGMENT_RW);  }  static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) @@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)  static inline pmd_t pmd_mkwrite(pmd_t pmd)  { -	pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; +	/* Do not clobber _HPAGE_TYPE_NONE pages! */ +	if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV)) +		pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;  	return pmd;  } diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index bf053898630d..b6506ee32a36 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S @@ -44,6 +44,12 @@ _sclp_wait_int:  #endif  	mvc	.LoldpswS1-.LbaseS1(16,%r13),0(%r8)  	mvc	0(16,%r8),0(%r9) +#ifdef CONFIG_64BIT +	epsw	%r6,%r7				# set current addressing mode +	nill	%r6,0x1				# in new psw (31 or 64 bit mode) +	nilh	%r7,0x8000 +	stm	%r6,%r7,0(%r8) +#endif  	lhi	%r6,0x0200			# cr mask for ext int (cr0.54)  	ltr	%r2,%r2  	jz	.LsetctS1 @@ -87,7 +93,7 @@ _sclp_wait_int:  	.long	0x00080000, 0x80000000+.LwaitS1	# PSW to handle ext int  #ifdef CONFIG_64BIT  .LextpswS1_64: -	.quad	0x0000000180000000, .LwaitS1	# PSW to handle ext int, 64 bit +	.quad	0, .LwaitS1			# PSW to handle ext int, 64 bit  #endif  .LwaitpswS1:  	.long	0x010a0000, 0x00000000+.LloopS1	# PSW to wait for ext int diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 2d37bb861faf..9017a63dda3d 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c @@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,  	pmd = pmd_offset(pud, addr);  	if (pmd_none(*pmd))  		return -0x10UL; -	if (pmd_huge(*pmd)) { +	if (pmd_large(*pmd)) {  		if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))  			return -0x04UL;  		return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 60acb93a4680..8b8285310b5a 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,  		 */  		if (pmd_none(pmd) || pmd_trans_splitting(pmd))  			return 0; -		if (unlikely(pmd_huge(pmd))) { +		if (unlikely(pmd_large(pmd))) {  			if (!gup_huge_pmd(pmdp, pmd, addr, next,  					  write, pages, nr))  				return 0; diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index e52f3c2ad3dd..0c7d365fa402 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -20,6 +20,7 @@ config SPARC  	select HAVE_ARCH_TRACEHOOK  	select SYSCTL_EXCEPTION_TRACE  	select ARCH_WANT_OPTIONAL_GPIOLIB +	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE  	select RTC_CLASS  	select RTC_DRV_M48T59  	select HAVE_IRQ_WORK diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile index 6ae1ad5e502b..5d469d81761f 100644 --- a/arch/sparc/crypto/Makefile +++ b/arch/sparc/crypto/Makefile @@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o  obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o -sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o -sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o -sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o -md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o +sha1-sparc64-y := sha1_asm.o sha1_glue.o +sha256-sparc64-y := sha256_asm.o sha256_glue.o +sha512-sparc64-y := sha512_asm.o sha512_glue.o +md5-sparc64-y := md5_asm.o md5_glue.o -aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o -des-sparc64-y := des_asm.o des_glue.o crop_devid.o -camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o +aes-sparc64-y := aes_asm.o aes_glue.o +des-sparc64-y := des_asm.o des_glue.o +camellia-sparc64-y := camellia_asm.o camellia_glue.o -crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o +crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c index 8f1c9980f637..3965d1d36dfa 100644 --- a/arch/sparc/crypto/aes_glue.c +++ b/arch/sparc/crypto/aes_glue.c @@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");  MODULE_ALIAS("aes"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c index 42905c084299..62c89af3fd3f 100644 --- a/arch/sparc/crypto/camellia_glue.c +++ b/arch/sparc/crypto/camellia_glue.c @@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");  MODULE_ALIAS("aes"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c index 0bd89cea8d8e..5162fad912ce 100644 --- a/arch/sparc/crypto/crc32c_glue.c +++ b/arch/sparc/crypto/crc32c_glue.c @@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");  MODULE_ALIAS("crc32c"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c index c4940c2d3073..41524cebcc49 100644 --- a/arch/sparc/crypto/des_glue.c +++ b/arch/sparc/crypto/des_glue.c @@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");  MODULE_ALIAS("des"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c index 603d723038ce..09a9ea1dfb69 100644 --- a/arch/sparc/crypto/md5_glue.c +++ b/arch/sparc/crypto/md5_glue.c @@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");  MODULE_ALIAS("md5"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c index 2bbb20bee9f1..6cd5f29e1e0d 100644 --- a/arch/sparc/crypto/sha1_glue.c +++ b/arch/sparc/crypto/sha1_glue.c @@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");  MODULE_ALIAS("sha1"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c index 591e656bd891..04f555ab2680 100644 --- a/arch/sparc/crypto/sha256_glue.c +++ b/arch/sparc/crypto/sha256_glue.c @@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op  MODULE_ALIAS("sha224");  MODULE_ALIAS("sha256"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c index 486f0a2b7001..f04d1994d19a 100644 --- a/arch/sparc/crypto/sha512_glue.c +++ b/arch/sparc/crypto/sha512_glue.c @@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op  MODULE_ALIAS("sha384");  MODULE_ALIAS("sha512"); + +#include "crop_devid.c" diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index ce35a1cf1a20..be56a244c9cf 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -1,7 +1,7 @@  /* atomic.h: Thankfully the V9 is at least reasonable for this   *           stuff.   * - * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)   */  #ifndef __ARCH_SPARC64_ATOMIC__ @@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)  #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +extern long atomic64_dec_if_positive(atomic64_t *v); +  /* Atomic operations are already serializing */  #define smp_mb__before_atomic_dec()	barrier()  #define smp_mb__after_atomic_dec()	barrier() diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h index db3af0d30fb1..4e02086b839c 100644 --- a/arch/sparc/include/asm/backoff.h +++ b/arch/sparc/include/asm/backoff.h @@ -1,6 +1,46 @@  #ifndef _SPARC64_BACKOFF_H  #define _SPARC64_BACKOFF_H +/* The macros in this file implement an exponential backoff facility + * for atomic operations. + * + * When multiple threads compete on an atomic operation, it is + * possible for one thread to be continually denied a successful + * completion of the compare-and-swap instruction.  Heavily + * threaded cpu implementations like Niagara can compound this + * problem even further. + * + * When an atomic operation fails and needs to be retried, we spin a + * certain number of times.  At each subsequent failure of the same + * operation we double the spin count, realizing an exponential + * backoff. + * + * When we spin, we try to use an operation that will cause the + * current cpu strand to block, and therefore make the core fully + * available to any other other runnable strands.  There are two + * options, based upon cpu capabilities. + * + * On all cpus prior to SPARC-T4 we do three dummy reads of the + * condition code register.  Each read blocks the strand for something + * between 40 and 50 cpu cycles. + * + * For SPARC-T4 and later we have a special "pause" instruction + * available.  This is implemented using writes to register %asr27. + * The cpu will block the number of cycles written into the register, + * unless a disrupting trap happens first.  SPARC-T4 specifically + * implements pause with a granularity of 8 cycles.  Each strand has + * an internal pause counter which decrements every 8 cycles.  So the + * chip shifts the %asr27 value down by 3 bits, and writes the result + * into the pause counter.  If a value smaller than 8 is written, the + * chip blocks for 1 cycle. + * + * To achieve the same amount of backoff as the three %ccr reads give + * on earlier chips, we shift the backoff value up by 7 bits.  (Three + * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the + * whole amount we want to block into the pause register, rather than + * loop writing 128 each time. + */ +  #define BACKOFF_LIMIT	(4 * 1024)  #ifdef CONFIG_SMP @@ -11,16 +51,25 @@  #define BACKOFF_LABEL(spin_label, continue_label) \  	spin_label -#define BACKOFF_SPIN(reg, tmp, label)	\ -	mov	reg, tmp; \ -88:	brnz,pt	tmp, 88b; \ -	 sub	tmp, 1, tmp; \ -	set	BACKOFF_LIMIT, tmp; \ -	cmp	reg, tmp; \ -	bg,pn	%xcc, label; \ -	 nop; \ -	ba,pt	%xcc, label; \ -	 sllx	reg, 1, reg; +#define BACKOFF_SPIN(reg, tmp, label)		\ +	mov		reg, tmp;		\ +88:	rd		%ccr, %g0;		\ +	rd		%ccr, %g0;		\ +	rd		%ccr, %g0;		\ +	.section	.pause_3insn_patch,"ax";\ +	.word		88b;			\ +	sllx		tmp, 7, tmp;		\ +	wr		tmp, 0, %asr27;		\ +	clr		tmp;			\ +	.previous;				\ +	brnz,pt		tmp, 88b;		\ +	 sub		tmp, 1, tmp;		\ +	set		BACKOFF_LIMIT, tmp;	\ +	cmp		reg, tmp;		\ +	bg,pn		%xcc, label;		\ +	 nop;					\ +	ba,pt		%xcc, label;		\ +	 sllx		reg, 1, reg;  #else diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h index 0305d56d9b1a..cce72ce4c334 100644 --- a/arch/sparc/include/asm/processor_64.h +++ b/arch/sparc/include/asm/processor_64.h @@ -203,7 +203,22 @@ extern unsigned long get_wchan(struct task_struct *task);  #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)  #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP]) -#define cpu_relax()	barrier() +/* Please see the commentary in asm/backoff.h for a description of + * what these instructions are doing and how they have been choosen. + * To make a long story short, we are trying to yield the current cpu + * strand during busy loops. + */ +#define cpu_relax()	asm volatile("\n99:\n\t"			\ +				     "rd	%%ccr, %%g0\n\t"	\ +				     "rd	%%ccr, %%g0\n\t"	\ +				     "rd	%%ccr, %%g0\n\t"	\ +				     ".section	.pause_3insn_patch,\"ax\"\n\t"\ +				     ".word	99b\n\t"		\ +				     "wr	%%g0, 128, %%asr27\n\t"	\ +				     "nop\n\t"				\ +				     "nop\n\t"				\ +				     ".previous"			\ +				     ::: "memory")  /* Prefetch support.  This is tuned for UltraSPARC-III and later.   * UltraSPARC-I will treat these as nops, and UltraSPARC-II has diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index c28765110706..f93003123bce 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -63,5 +63,10 @@ extern char *of_console_options;  extern void irq_trans_init(struct device_node *dp);  extern char *build_path_component(struct device_node *dp); +/* SPARC has a local implementation */ +extern int of_address_to_resource(struct device_node *dev, int index, +				  struct resource *r); +#define of_address_to_resource of_address_to_resource +  #endif /* __KERNEL__ */  #endif /* _SPARC_PROM_H */ diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index bed86a820d09..cac719d1bc5c 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -406,8 +406,9 @@  #define __NR_process_vm_readv	338  #define __NR_process_vm_writev	339  #define __NR_kern_features	340 +#define __NR_kcmp		341 -#define NR_syscalls		341 +#define NR_syscalls		342  /* Bitmask values returned from kern_features system call.  */  #define KERN_FEATURE_MIXED_MODE_STACK	0x00000001 diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 0c218e4c0881..cc3c5cb47cda 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {  extern struct popc_6insn_patch_entry __popc_6insn_patch,  	__popc_6insn_patch_end; +struct pause_patch_entry { +	unsigned int	addr; +	unsigned int	insns[3]; +}; +extern struct pause_patch_entry __pause_3insn_patch, +	__pause_3insn_patch_end; +  extern void __init per_cpu_patch(void);  extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,  				    struct sun4v_1insn_patch_entry *); diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index f8b6eee40bde..87f60ee65433 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)  static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)  {  	unsigned int eirq; +	struct irq_bucket *p;  	int cpu = sparc_leon3_cpuid();  	eirq = leon_eirq_get(cpu); -	if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ -		generic_handle_irq(irq_map[eirq]->irq); +	p = irq_map[eirq]; +	if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */ +		generic_handle_irq(p->irq);  }  /* The extended IRQ controller has been found, this function registers it */ diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 0800e71d8a88..0eaf0059aaef 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -316,6 +316,25 @@ static void __init popc_patch(void)  	}  } +static void __init pause_patch(void) +{ +	struct pause_patch_entry *p; + +	p = &__pause_3insn_patch; +	while (p < &__pause_3insn_patch_end) { +		unsigned long i, addr = p->addr; + +		for (i = 0; i < 3; i++) { +			*(unsigned int *) (addr +  (i * 4)) = p->insns[i]; +			wmb(); +			__asm__ __volatile__("flush	%0" +					     : : "r" (addr +  (i * 4))); +		} + +		p++; +	} +} +  #ifdef CONFIG_SMP  void __init boot_cpu_id_too_large(int cpu)  { @@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)  	if (sparc64_elf_hwcap & AV_SPARC_POPC)  		popc_patch(); +	if (sparc64_elf_hwcap & AV_SPARC_PAUSE) +		pause_patch();  }  void __init setup_arch(char **cmdline_p) diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 63402f9e9f51..5147f574f125 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -85,3 +85,4 @@ sys_call_table:  /*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init  /*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime  /*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev +/*340*/	.long sys_ni_syscall, sys_kcmp diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index d8b22b3266d0..ebb7f5fc58fb 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -86,7 +86,7 @@ sys_call_table32:  	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init  /*330*/	.word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime  	.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev -/*340*/	.word sys_kern_features +/*340*/	.word sys_kern_features, sys_kcmp  #endif /* CONFIG_COMPAT */ @@ -164,4 +164,4 @@ sys_call_table:  	.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init  /*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime  	.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev -/*340*/	.word sys_kern_features +/*340*/	.word sys_kern_features, sys_kcmp diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 89c2c29f154b..0bacceb19150 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -132,6 +132,11 @@ SECTIONS  		*(.popc_6insn_patch)  		__popc_6insn_patch_end = .;  	} +	.pause_3insn_patch : { +		__pause_3insn_patch = .; +		*(.pause_3insn_patch) +		__pause_3insn_patch_end = .; +	}  	PERCPU_SECTION(SMP_CACHE_BYTES)  	. = ALIGN(PAGE_SIZE); diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S index 4d502da3de78..85c233d0a340 100644 --- a/arch/sparc/lib/atomic_64.S +++ b/arch/sparc/lib/atomic_64.S @@ -1,6 +1,6 @@  /* atomic.S: These things are too big to do inline.   * - * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net)   */  #include <linux/linkage.h> @@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */  	 sub	%g1, %o0, %o0  2:	BACKOFF_SPIN(%o2, %o3, 1b)  ENDPROC(atomic64_sub_ret) + +ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */ +	BACKOFF_SETUP(%o2) +1:	ldx	[%o0], %g1 +	brlez,pn %g1, 3f +	 sub	%g1, 1, %g7 +	casx	[%o0], %g1, %g7 +	cmp	%g1, %g7 +	bne,pn	%xcc, BACKOFF_LABEL(2f, 1b) +	 nop +3:	retl +	 sub	%g1, 1, %o0 +2:	BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic64_dec_if_positive) diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c index ee31b884c61b..0c4e35e522fa 100644 --- a/arch/sparc/lib/ksyms.c +++ b/arch/sparc/lib/ksyms.c @@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add);  EXPORT_SYMBOL(atomic64_add_ret);  EXPORT_SYMBOL(atomic64_sub);  EXPORT_SYMBOL(atomic64_sub_ret); +EXPORT_SYMBOL(atomic64_dec_if_positive);  /* Atomic bit operations. */  EXPORT_SYMBOL(test_and_set_bit); diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index 59c226d120cd..c20d1ce62dc6 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,  		return _hypercall4(int, update_va_mapping, va,  				   new_val.pte, new_val.pte >> 32, flags);  } +extern int __must_check xen_event_channel_op_compat(int, void *);  static inline int  HYPERVISOR_event_channel_op(int cmd, void *arg)  {  	int rc = _hypercall2(int, event_channel_op, cmd, arg); -	if (unlikely(rc == -ENOSYS)) { -		struct evtchn_op op; -		op.cmd = cmd; -		memcpy(&op.u, arg, sizeof(op.u)); -		rc = _hypercall1(int, event_channel_op_compat, &op); -		memcpy(arg, &op.u, sizeof(op.u)); -	} +	if (unlikely(rc == -ENOSYS)) +		rc = xen_event_channel_op_compat(cmd, arg);  	return rc;  } @@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)  	return _hypercall3(int, console_io, cmd, count, str);  } +extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); +  static inline int  HYPERVISOR_physdev_op(int cmd, void *arg)  {  	int rc = _hypercall2(int, physdev_op, cmd, arg); -	if (unlikely(rc == -ENOSYS)) { -		struct physdev_op op; -		op.cmd = cmd; -		memcpy(&op.u, arg, sizeof(op.u)); -		rc = _hypercall1(int, physdev_op_compat, &op); -		memcpy(arg, &op.u, sizeof(op.u)); -	} +	if (unlikely(rc == -ENOSYS)) +		rc = HYPERVISOR_physdev_op_compat(cmd, arg);  	return rc;  } |