diff options
Diffstat (limited to 'arch/sparc')
52 files changed, 378 insertions, 194 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6db51367405..9908d477ccd 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -37,6 +37,9 @@ config SPARC64  	def_bool 64BIT  	select ARCH_SUPPORTS_MSI  	select HAVE_FUNCTION_TRACER +	select HAVE_FUNCTION_GRAPH_TRACER +	select HAVE_FUNCTION_GRAPH_FP_TEST +	select HAVE_FUNCTION_TRACE_MCOUNT_TEST  	select HAVE_KRETPROBES  	select HAVE_KPROBES  	select HAVE_LMB diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index 9d3c889718a..1b4a831565f 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug @@ -19,13 +19,10 @@ config DEBUG_DCFLUSH  	bool "D-cache flush debugging"  	depends on SPARC64 && DEBUG_KERNEL -config STACK_DEBUG -	bool "Stack Overflow Detection Support" -  config MCOUNT  	bool  	depends on SPARC64 -	depends on STACK_DEBUG || FUNCTION_TRACER +	depends on FUNCTION_TRACER  	default y  config FRAME_POINTER diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig index 56e3163673e..259e3fd5099 100644 --- a/arch/sparc/configs/sparc64_defconfig +++ b/arch/sparc/configs/sparc64_defconfig @@ -1,7 +1,7 @@  #  # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33 -# Wed Mar  3 02:54:29 2010 +# Linux kernel version: 2.6.34-rc3 +# Sat Apr  3 15:49:56 2010  #  CONFIG_64BIT=y  CONFIG_SPARC=y @@ -23,6 +23,7 @@ CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y  CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y  CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y  CONFIG_MMU=y +CONFIG_NEED_DMA_MAP_STATE=y  CONFIG_ARCH_NO_VIRT_TO_BUS=y  CONFIG_OF=y  CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y @@ -439,6 +440,7 @@ CONFIG_MISC_DEVICES=y  # CONFIG_ENCLOSURE_SERVICES is not set  # CONFIG_HP_ILO is not set  # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set  # CONFIG_DS1682 is not set  # CONFIG_C2PORT is not set @@ -511,6 +513,7 @@ CONFIG_BLK_DEV_IDEDMA=y  #  # SCSI device support  # +CONFIG_SCSI_MOD=y  CONFIG_RAID_ATTRS=m  CONFIG_SCSI=y  CONFIG_SCSI_DMA=y @@ -888,6 +891,7 @@ CONFIG_SERIAL_SUNHV=y  CONFIG_SERIAL_CORE=y  CONFIG_SERIAL_CORE_CONSOLE=y  # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set  # CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set  CONFIG_UNIX98_PTYS=y  # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set @@ -935,6 +939,7 @@ CONFIG_I2C_ALGOBIT=y  #  # CONFIG_I2C_OCORES is not set  # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set  #  # External I2C/SMBus adapter drivers @@ -948,15 +953,9 @@ CONFIG_I2C_ALGOBIT=y  #  # CONFIG_I2C_PCA_PLATFORM is not set  # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set  # CONFIG_I2C_DEBUG_CORE is not set  # CONFIG_I2C_DEBUG_ALGO is not set  # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set  # CONFIG_SPI is not set  # @@ -982,10 +981,11 @@ CONFIG_HWMON=y  # CONFIG_SENSORS_ADM1029 is not set  # CONFIG_SENSORS_ADM1031 is not set  # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set  # CONFIG_SENSORS_ADT7462 is not set  # CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set  # CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set  # CONFIG_SENSORS_ATXP1 is not set  # CONFIG_SENSORS_DS1621 is not set  # CONFIG_SENSORS_I5K_AMB is not set @@ -1052,18 +1052,21 @@ CONFIG_SSB_POSSIBLE=y  # Multifunction device drivers  #  # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set  # CONFIG_MFD_SM501 is not set  # CONFIG_HTC_PASIC3 is not set  # CONFIG_TWL4030_CORE is not set  # CONFIG_MFD_TMIO is not set  # CONFIG_PMIC_DA903X is not set  # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set  # CONFIG_MFD_WM8400 is not set  # CONFIG_MFD_WM831X is not set  # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set  # CONFIG_MFD_PCF50633 is not set  # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set +# CONFIG_LPC_SCH is not set  # CONFIG_REGULATOR is not set  # CONFIG_MEDIA_SUPPORT is not set @@ -1113,6 +1116,7 @@ CONFIG_FB_FFB=y  # CONFIG_FB_LEO is not set  CONFIG_FB_XVR500=y  CONFIG_FB_XVR2500=y +CONFIG_FB_XVR1000=y  # CONFIG_FB_S1D13XXX is not set  # CONFIG_FB_NVIDIA is not set  # CONFIG_FB_RIVA is not set @@ -1430,7 +1434,6 @@ CONFIG_USB_STORAGE=m  # CONFIG_USB_RIO500 is not set  # CONFIG_USB_LEGOTOWER is not set  # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set  # CONFIG_USB_LED is not set  # CONFIG_USB_CYPRESS_CY7C63 is not set  # CONFIG_USB_CYTHERM is not set @@ -1443,7 +1446,6 @@ CONFIG_USB_STORAGE=m  # CONFIG_USB_IOWARRIOR is not set  # CONFIG_USB_TEST is not set  # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set  # CONFIG_USB_GADGET is not set  # @@ -1610,6 +1612,7 @@ CONFIG_MISC_FILESYSTEMS=y  # CONFIG_BEFS_FS is not set  # CONFIG_BFS_FS is not set  # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set  # CONFIG_CRAMFS is not set  # CONFIG_SQUASHFS is not set  # CONFIG_VXFS_FS is not set @@ -1624,6 +1627,7 @@ CONFIG_NETWORK_FILESYSTEMS=y  # CONFIG_NFS_FS is not set  # CONFIG_NFSD is not set  # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set  # CONFIG_CIFS is not set  # CONFIG_NCP_FS is not set  # CONFIG_CODA_FS is not set diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 926397d345f..050ef35b9dc 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h @@ -17,7 +17,7 @@ typedef struct {  	unsigned int	__nmi_count;  	unsigned long	clock_tick;	/* %tick's per second */  	unsigned long	__pad; -	unsigned int	__pad1; +	unsigned int	irq0_irqs;  	unsigned int	__pad2;  	/* Dcache line 2, rarely used */ diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h index 8b49bf920df..bfa1ea45b4c 100644 --- a/arch/sparc/include/asm/irqflags_64.h +++ b/arch/sparc/include/asm/irqflags_64.h @@ -76,9 +76,26 @@ static inline int raw_irqs_disabled(void)   */  static inline unsigned long __raw_local_irq_save(void)  { -	unsigned long flags = __raw_local_save_flags(); +	unsigned long flags, tmp; -	raw_local_irq_disable(); +	/* Disable interrupts to PIL_NORMAL_MAX unless we already +	 * are using PIL_NMI, in which case PIL_NMI is retained. +	 * +	 * The only values we ever program into the %pil are 0, +	 * PIL_NORMAL_MAX and PIL_NMI. +	 * +	 * Since PIL_NMI is the largest %pil value and all bits are +	 * set in it (0xf), it doesn't matter what PIL_NORMAL_MAX +	 * actually is. +	 */ +	__asm__ __volatile__( +		"rdpr	%%pil, %0\n\t" +		"or	%0, %2, %1\n\t" +		"wrpr	%1, 0x0, %%pil" +		: "=r" (flags), "=r" (tmp) +		: "i" (PIL_NORMAL_MAX) +		: "memory" +	);  	return flags;  } diff --git a/arch/sparc/include/asm/stat.h b/arch/sparc/include/asm/stat.h index 39327d6a57e..a232e9e1f4e 100644 --- a/arch/sparc/include/asm/stat.h +++ b/arch/sparc/include/asm/stat.h @@ -53,8 +53,8 @@ struct stat {  	ino_t		st_ino;  	mode_t		st_mode;  	short		st_nlink; -	uid16_t		st_uid; -	gid16_t		st_gid; +	unsigned short	st_uid; +	unsigned short	st_gid;  	unsigned short	st_rdev;  	off_t		st_size;  	time_t		st_atime; diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 9e2d9447f2a..4827a3aeac7 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -111,7 +111,7 @@ struct thread_info {  #define THREAD_SHIFT PAGE_SHIFT  #endif /* PAGE_SHIFT == 13 */ -#define PREEMPT_ACTIVE		0x4000000 +#define PREEMPT_ACTIVE		0x10000000  /*   * macros/functions for gaining access to the thread information structure diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index c6316142db4..0c2dc1f24a9 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -13,6 +13,14 @@ extra-y     += init_task.o  CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS)  extra-y              += vmlinux.lds +ifdef CONFIG_FUNCTION_TRACER +# Do not profile debug and lowlevel utilities +CFLAGS_REMOVE_ftrace.o := -pg +CFLAGS_REMOVE_time_$(BITS).o := -pg +CFLAGS_REMOVE_perf_event.o := -pg +CFLAGS_REMOVE_pcr.o := -pg +endif +  obj-$(CONFIG_SPARC32)   += entry.o wof.o wuf.o  obj-$(CONFIG_SPARC32)   += etrap_32.o  obj-$(CONFIG_SPARC32)   += rtrap_32.o @@ -85,7 +93,7 @@ obj-$(CONFIG_KGDB)        += kgdb_$(BITS).o  obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o -CFLAGS_REMOVE_ftrace.o := -pg +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o  obj-$(CONFIG_EARLYFB) += btext.o  obj-$(CONFIG_STACKTRACE)     += stacktrace.o diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c index 4589ca33220..415c86d5a8d 100644 --- a/arch/sparc/kernel/central.c +++ b/arch/sparc/kernel/central.c @@ -5,6 +5,7 @@  #include <linux/kernel.h>  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/string.h>  #include <linux/init.h>  #include <linux/of_device.h> diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c index 7430ed080b2..8de64c8126b 100644 --- a/arch/sparc/kernel/cpumap.c +++ b/arch/sparc/kernel/cpumap.c @@ -4,6 +4,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/cpumask.h> diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index 9103a56b39e..03ab022e51c 100644 --- a/arch/sparc/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c @@ -13,7 +13,7 @@ static const u32 ftrace_nop = 0x01000000;  static u32 ftrace_call_replace(unsigned long ip, unsigned long addr)  { -	static u32 call; +	u32 call;  	s32 off;  	off = ((s32)addr - (s32)ip); @@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data)  	return 0;  }  #endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + +#ifdef CONFIG_DYNAMIC_FTRACE +extern void ftrace_graph_call(void); + +int ftrace_enable_ftrace_graph_caller(void) +{ +	unsigned long ip = (unsigned long)(&ftrace_graph_call); +	u32 old, new; + +	old = *(u32 *) &ftrace_graph_call; +	new = ftrace_call_replace(ip, (unsigned long) &ftrace_graph_caller); +	return ftrace_modify_code(ip, old, new); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ +	unsigned long ip = (unsigned long)(&ftrace_graph_call); +	u32 old, new; + +	old = *(u32 *) &ftrace_graph_call; +	new = ftrace_call_replace(ip, (unsigned long) &ftrace_stub); + +	return ftrace_modify_code(ip, old, new); +} + +#endif /* !CONFIG_DYNAMIC_FTRACE */ + +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +unsigned long prepare_ftrace_return(unsigned long parent, +				    unsigned long self_addr, +				    unsigned long frame_pointer) +{ +	unsigned long return_hooker = (unsigned long) &return_to_handler; +	struct ftrace_graph_ent trace; + +	if (unlikely(atomic_read(¤t->tracing_graph_pause))) +		return parent + 8UL; + +	if (ftrace_push_return_trace(parent, self_addr, &trace.depth, +				     frame_pointer) == -EBUSY) +		return parent + 8UL; + +	trace.func = self_addr; + +	/* Only trace if the calling function expects to */ +	if (!ftrace_graph_entry(&trace)) { +		current->curr_ret_stack--; +		return parent + 8UL; +	} + +	return return_hooker; +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/sparc/kernel/helpers.S b/arch/sparc/kernel/helpers.S index 314dd0c9fc5..92090cc9e82 100644 --- a/arch/sparc/kernel/helpers.S +++ b/arch/sparc/kernel/helpers.S @@ -46,6 +46,81 @@ stack_trace_flush:  	 nop  	.size		stack_trace_flush,.-stack_trace_flush +#ifdef CONFIG_PERF_EVENTS +	.globl		perf_arch_fetch_caller_regs +	.type		perf_arch_fetch_caller_regs,#function +perf_arch_fetch_caller_regs: +	/* We always read the %pstate into %o5 since we will use +	 * that to construct a fake %tstate to store into the regs. +	 */ +	rdpr		%pstate, %o5 +	brz,pn		%o2, 50f +	 mov		%o2, %g7 + +	/* Turn off interrupts while we walk around the register +	 * window by hand. +	 */ +	wrpr		%o5, PSTATE_IE, %pstate + +	/* The %canrestore tells us how many register windows are +	 * still live in the chip above us, past that we have to +	 * walk the frame as saved on the stack.   We stash away +	 * the %cwp in %g1 so we can return back to the original +	 * register window. +	 */ +	rdpr		%cwp, %g1 +	rdpr		%canrestore, %g2 +	sub		%g1, 1, %g3 + +	/* We have the skip count in %g7, if it hits zero then +	 * %fp/%i7 are the registers we need.  Otherwise if our +	 * %canrestore count maintained in %g2 hits zero we have +	 * to start traversing the stack. +	 */ +10:	brz,pn		%g2, 4f +	 sub		%g2, 1, %g2 +	wrpr		%g3, %cwp +	subcc		%g7, 1, %g7 +	bne,pt		%xcc, 10b +	 sub		%g3, 1, %g3 + +	/* We found the values we need in the cpu's register +	 * windows. +	 */ +	mov		%fp, %g3 +	ba,pt		%xcc, 3f +	 mov		%i7, %g2 + +50:	mov		%fp, %g3 +	ba,pt		%xcc, 2f +	 mov		%i7, %g2 + +	/* We hit the end of the valid register windows in the +	 * cpu, start traversing the stack frame. +	 */ +4:	mov		%fp, %g3 + +20:	ldx		[%g3 + STACK_BIAS + RW_V9_I7], %g2 +	subcc		%g7, 1, %g7 +	bne,pn		%xcc, 20b +	 ldx		[%g3 + STACK_BIAS + RW_V9_I6], %g3 + +	/* Restore the current register window position and +	 * re-enable interrupts. +	 */ +3:	wrpr		%g1, %cwp +	wrpr		%o5, %pstate + +2:	stx		%g3, [%o0 + PT_V9_FP] +	sllx		%o5, 8, %o5 +	stx		%o5, [%o0 + PT_V9_TSTATE] +	stx		%g2, [%o0 + PT_V9_TPC] +	add		%g2, 4, %g2 +	retl +	 stx		%g2, [%o0 + PT_V9_TNPC] +	.size		perf_arch_fetch_caller_regs,.-perf_arch_fetch_caller_regs +#endif /* CONFIG_PERF_EVENTS */ +  #ifdef CONFIG_SMP  	.globl		hard_smp_processor_id  	.type		hard_smp_processor_id,#function diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c index 1d272c3b574..7c60afb835b 100644 --- a/arch/sparc/kernel/hvapi.c +++ b/arch/sparc/kernel/hvapi.c @@ -5,7 +5,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/slab.h>  #include <asm/hypervisor.h>  #include <asm/oplib.h> diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 8414549c183..47977a77f6c 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c @@ -6,6 +6,7 @@  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/delay.h>  #include <linux/device.h>  #include <linux/dma-mapping.h> diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index e1cbdb94d97..830d70a3e20 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -20,7 +20,9 @@  #include <linux/delay.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> +#include <linux/ftrace.h>  #include <linux/irq.h> +#include <linux/kmemleak.h>  #include <asm/ptrace.h>  #include <asm/processor.h> @@ -45,6 +47,7 @@  #include "entry.h"  #include "cpumap.h" +#include "kstack.h"  #define NUM_IVECS	(IMAP_INR + 1) @@ -647,6 +650,14 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)  	bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);  	if (unlikely(!bucket))  		return 0; + +	/* The only reference we store to the IRQ bucket is +	 * by physical address which kmemleak can't see, tell +	 * it that this object explicitly is not a leak and +	 * should be scanned. +	 */ +	kmemleak_not_leak(bucket); +  	__flush_dcache_range((unsigned long) bucket,  			     ((unsigned long) bucket +  			      sizeof(struct ino_bucket))); @@ -703,25 +714,7 @@ void ack_bad_irq(unsigned int virt_irq)  void *hardirq_stack[NR_CPUS];  void *softirq_stack[NR_CPUS]; -static __attribute__((always_inline)) void *set_hardirq_stack(void) -{ -	void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; - -	__asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); -	if (orig_sp < sp || -	    orig_sp > (sp + THREAD_SIZE)) { -		sp += THREAD_SIZE - 192 - STACK_BIAS; -		__asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); -	} - -	return orig_sp; -} -static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) -{ -	__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); -} - -void handler_irq(int irq, struct pt_regs *regs) +void __irq_entry handler_irq(int irq, struct pt_regs *regs)  {  	unsigned long pstate, bucket_pa;  	struct pt_regs *old_regs; diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c index f5a0fd490b5..0a2bd0f99fc 100644 --- a/arch/sparc/kernel/kgdb_64.c +++ b/arch/sparc/kernel/kgdb_64.c @@ -5,6 +5,7 @@  #include <linux/kgdb.h>  #include <linux/kdebug.h> +#include <linux/ftrace.h>  #include <asm/kdebug.h>  #include <asm/ptrace.h> @@ -108,7 +109,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)  }  #ifdef CONFIG_SMP -void smp_kgdb_capture_client(int irq, struct pt_regs *regs) +void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)  {  	unsigned long flags; diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c index 6716584e48a..a39d1ba5a11 100644 --- a/arch/sparc/kernel/kprobes.c +++ b/arch/sparc/kernel/kprobes.c @@ -7,6 +7,7 @@  #include <linux/kprobes.h>  #include <linux/module.h>  #include <linux/kdebug.h> +#include <linux/slab.h>  #include <asm/signal.h>  #include <asm/cacheflush.h>  #include <asm/uaccess.h> diff --git a/arch/sparc/kernel/kstack.h b/arch/sparc/kernel/kstack.h index 5247283d1c0..53dfb92e09f 100644 --- a/arch/sparc/kernel/kstack.h +++ b/arch/sparc/kernel/kstack.h @@ -61,4 +61,23 @@ check_magic:  } +static inline __attribute__((always_inline)) void *set_hardirq_stack(void) +{ +	void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; + +	__asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); +	if (orig_sp < sp || +	    orig_sp > (sp + THREAD_SIZE)) { +		sp += THREAD_SIZE - 192 - STACK_BIAS; +		__asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); +	} + +	return orig_sp; +} + +static inline __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) +{ +	__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); +} +  #endif /* _KSTACK_H */ diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c index 00d034ea216..3ae36f36e75 100644 --- a/arch/sparc/kernel/led.c +++ b/arch/sparc/kernel/led.c @@ -3,6 +3,7 @@  #include <linux/init.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <linux/string.h>  #include <linux/jiffies.h>  #include <linux/timer.h> diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 0409d62d8ca..6a7b4dbc8e0 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -7,7 +7,6 @@  #include <linux/module.h>  #include <linux/errno.h>  #include <linux/mutex.h> -#include <linux/slab.h>  #include <linux/of.h>  #include <linux/of_platform.h>  #include <linux/interrupt.h> diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 85787577f68..e1656fc41cc 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -22,6 +22,7 @@  #include <linux/profile.h>  #include <linux/pm.h>  #include <linux/delay.h> +#include <linux/gfp.h>  #include <asm/cacheflush.h>  #include <asm/tlbflush.h> diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 0ee642f6323..f848aadf54d 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -9,9 +9,9 @@  #include <linux/elf.h>  #include <linux/vmalloc.h>  #include <linux/fs.h> +#include <linux/gfp.h>  #include <linux/string.h>  #include <linux/ctype.h> -#include <linux/slab.h>  #include <linux/mm.h>  #include <asm/processor.h> diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index b287b62c7ea..a4bd7ba74c8 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -23,6 +23,8 @@  #include <asm/ptrace.h>  #include <asm/pcr.h> +#include "kstack.h" +  /* We don't have a real NMI on sparc64, but we can fake one   * up using profiling counter overflow interrupts and interrupt   * levels. @@ -92,7 +94,7 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)  notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)  {  	unsigned int sum, touched = 0; -	int cpu = smp_processor_id(); +	void *orig_sp;  	clear_softint(1 << irq); @@ -100,13 +102,15 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)  	nmi_enter(); +	orig_sp = set_hardirq_stack(); +  	if (notify_die(DIE_NMI, "nmi", regs, 0,  		       pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)  		touched = 1;  	else  		pcr_ops->write(PCR_PIC_PRIV); -	sum = kstat_irqs_cpu(0, cpu); +	sum = local_cpu_data().irq0_irqs;  	if (__get_cpu_var(nmi_touch)) {  		__get_cpu_var(nmi_touch) = 0;  		touched = 1; @@ -125,6 +129,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)  		pcr_ops->write(pcr_enable);  	} +	restore_hardirq_stack(orig_sp); +  	nmi_exit();  } diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index cb8eb799bb6..0247e68210b 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c @@ -4,7 +4,6 @@  #include <linux/init.h>  #include <linux/module.h>  #include <linux/mod_devicetable.h> -#include <linux/slab.h>  #include <linux/errno.h>  #include <linux/irq.h>  #include <linux/of_device.h> diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index b775658a927..8a000583b5c 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c @@ -371,14 +371,19 @@ static void pci_register_iommu_region(struct pci_pbm_info *pbm)  		struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL);  		if (!rp) { -			prom_printf("Cannot allocate IOMMU resource.\n"); -			prom_halt(); +			pr_info("%s: Cannot allocate IOMMU resource.\n", +				pbm->name); +			return;  		}  		rp->name = "IOMMU";  		rp->start = pbm->mem_space.start + (unsigned long) vdma[0];  		rp->end = rp->start + (unsigned long) vdma[1] - 1UL;  		rp->flags = IORESOURCE_BUSY; -		request_resource(&pbm->mem_space, rp); +		if (request_resource(&pbm->mem_space, rp)) { +			pr_info("%s: Unable to request IOMMU resource.\n", +				pbm->name); +			kfree(rp); +		}  	}  } diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c index e1b0541feb1..e0ef847219c 100644 --- a/arch/sparc/kernel/pci_msi.c +++ b/arch/sparc/kernel/pci_msi.c @@ -4,6 +4,7 @@   */  #include <linux/kernel.h>  #include <linux/interrupt.h> +#include <linux/slab.h>  #include <linux/irq.h>  #include "pci_impl.h" diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c index 2d94e7a03af..c4a6a50b484 100644 --- a/arch/sparc/kernel/pcr.c +++ b/arch/sparc/kernel/pcr.c @@ -8,6 +8,7 @@  #include <linux/irq.h>  #include <linux/perf_event.h> +#include <linux/ftrace.h>  #include <asm/pil.h>  #include <asm/pcr.h> @@ -34,7 +35,7 @@ unsigned int picl_shift;   * Therefore in such situations we defer the work by signalling   * a lower level cpu IRQ.   */ -void deferred_pcr_work_irq(int irq, struct pt_regs *regs) +void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs)  {  	struct pt_regs *old_regs; diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 68cb9b42088..e2771939341 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1337,7 +1337,7 @@ static void perf_callchain_user_32(struct pt_regs *regs,  	callchain_store(entry, PERF_CONTEXT_USER);  	callchain_store(entry, regs->tpc); -	ufp = regs->u_regs[UREG_I6]; +	ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;  	do {  		struct sparc_stackf32 *usf, sf;  		unsigned long pc; diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index c49865b3071..40e29fc8a4d 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -17,13 +17,13 @@  #include <linux/mm.h>  #include <linux/stddef.h>  #include <linux/ptrace.h> -#include <linux/slab.h>  #include <linux/user.h>  #include <linux/smp.h>  #include <linux/reboot.h>  #include <linux/delay.h>  #include <linux/pm.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <asm/auxio.h>  #include <asm/oplib.h> diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c index 7e3dfd9bb97..e608f397e11 100644 --- a/arch/sparc/kernel/ptrace_32.c +++ b/arch/sparc/kernel/ptrace_32.c @@ -65,6 +65,7 @@ static int genregs32_get(struct task_struct *target,  			*k++ = regs->u_regs[pos++];  		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		for (; count > 0 && pos < 32; count--) {  			if (get_user(*k++, ®_window[pos++]))  				return -EFAULT; @@ -76,6 +77,7 @@ static int genregs32_get(struct task_struct *target,  		}  		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		for (; count > 0 && pos < 32; count--) {  			if (get_user(reg, ®_window[pos++]) ||  			    put_user(reg, u++)) @@ -141,6 +143,7 @@ static int genregs32_set(struct task_struct *target,  			regs->u_regs[pos++] = *k++;  		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		for (; count > 0 && pos < 32; count--) {  			if (put_user(*k++, ®_window[pos++]))  				return -EFAULT; @@ -153,6 +156,7 @@ static int genregs32_set(struct task_struct *target,  		}  		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		for (; count > 0 && pos < 32; count--) {  			if (get_user(reg, u++) ||  			    put_user(reg, ®_window[pos++])) diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 2f6524d1a81..aa90da08bf6 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -492,6 +492,7 @@ static int genregs32_get(struct task_struct *target,  			*k++ = regs->u_regs[pos++];  		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		if (target == current) {  			for (; count > 0 && pos < 32; count--) {  				if (get_user(*k++, ®_window[pos++])) @@ -516,6 +517,7 @@ static int genregs32_get(struct task_struct *target,  		}  		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		if (target == current) {  			for (; count > 0 && pos < 32; count--) {  				if (get_user(reg, ®_window[pos++]) || @@ -599,6 +601,7 @@ static int genregs32_set(struct task_struct *target,  			regs->u_regs[pos++] = *k++;  		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		if (target == current) {  			for (; count > 0 && pos < 32; count--) {  				if (put_user(*k++, ®_window[pos++])) @@ -625,6 +628,7 @@ static int genregs32_set(struct task_struct *target,  		}  		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; +		reg_window -= 16;  		if (target == current) {  			for (; count > 0 && pos < 32; count--) {  				if (get_user(reg, u++) || diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 83f1873c6c1..090b9e9ad5e 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -130,7 +130,17 @@ rtrap_xcall:  		 nop  		call			trace_hardirqs_on  		 nop -		wrpr			%l4, %pil +		/* Do not actually set the %pil here.  We will do that +		 * below after we clear PSTATE_IE in the %pstate register. +		 * If we re-enable interrupts here, we can recurse down +		 * the hardirq stack potentially endlessly, causing a +		 * stack overflow. +		 * +		 * It is tempting to put this test and trace_hardirqs_on +		 * call at the 'rt_continue' label, but that will not work +		 * as that path hits unconditionally and we do not want to +		 * execute this in NMI return paths, for example. +		 */  #endif  rtrap_no_irq_enable:  		andcc			%l1, TSTATE_PRIV, %l3 diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index a2a79e76344..5f72de67588 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -12,7 +12,6 @@  #include <linux/stddef.h>  #include <linux/unistd.h>  #include <linux/ptrace.h> -#include <linux/slab.h>  #include <asm/smp.h>  #include <linux/user.h>  #include <linux/screen_info.h> diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index eb14844a002..b6a2b8f4704 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -22,7 +22,9 @@  #include <linux/profile.h>  #include <linux/bootmem.h>  #include <linux/vmalloc.h> +#include <linux/ftrace.h>  #include <linux/cpu.h> +#include <linux/slab.h>  #include <asm/head.h>  #include <asm/ptrace.h> @@ -822,13 +824,13 @@ void arch_send_call_function_single_ipi(int cpu)  		      &cpumask_of_cpu(cpu));  } -void smp_call_function_client(int irq, struct pt_regs *regs) +void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)  {  	clear_softint(1 << irq);  	generic_smp_call_function_interrupt();  } -void smp_call_function_single_client(int irq, struct pt_regs *regs) +void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs)  {  	clear_softint(1 << irq);  	generic_smp_call_function_single_interrupt(); @@ -964,7 +966,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)  	put_cpu();  } -void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) +void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)  {  	struct mm_struct *mm;  	unsigned long flags; @@ -1148,7 +1150,7 @@ void smp_release(void)   */  extern void prom_world(int); -void smp_penguin_jailcell(int irq, struct pt_regs *regs) +void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs)  {  	clear_softint(1 << irq); @@ -1364,7 +1366,7 @@ void smp_send_reschedule(int cpu)  		      &cpumask_of_cpu(cpu));  } -void smp_receive_signal_client(int irq, struct pt_regs *regs) +void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)  {  	clear_softint(1 << irq);  } diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index bc3adbf79c6..892fb884910 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -16,7 +16,6 @@  #include <linux/sched.h>  #include <linux/ptrace.h>  #include <linux/interrupt.h> -#include <linux/slab.h>  #include <linux/init.h>  #include <linux/of.h>  #include <linux/of_device.h> diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 301892e2d71..7f3b97ff62c 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -17,7 +17,6 @@  #include <linux/ptrace.h>  #include <linux/smp.h>  #include <linux/interrupt.h> -#include <linux/slab.h>  #include <linux/init.h>  #include <linux/ioport.h>  #include <linux/of.h> diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index daded3b9639..c0ca87553e1 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -21,7 +21,6 @@  #include <linux/sem.h>  #include <linux/msg.h>  #include <linux/shm.h> -#include <linux/slab.h>  #include <linux/uio.h>  #include <linux/nfs_fs.h>  #include <linux/quota.h> @@ -44,6 +43,7 @@  #include <linux/compat.h>  #include <linux/vfs.h>  #include <linux/ptrace.h> +#include <linux/slab.h>  #include <asm/types.h>  #include <asm/uaccess.h> diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index ca39c606fe8..1eb8b00aed7 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -107,12 +107,12 @@ static unsigned long run_on_cpu(unsigned long cpu,  	unsigned long ret;  	/* should return -EINVAL to userspace */ -	if (set_cpus_allowed(current, cpumask_of_cpu(cpu))) +	if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))  		return 0;  	ret = func(arg); -	set_cpus_allowed(current, old_affinity); +	set_cpus_allowed_ptr(current, &old_affinity);  	return ret;  } diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 67e16510288..c7bbe6cf7b8 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -35,6 +35,7 @@  #include <linux/clocksource.h>  #include <linux/of_device.h>  #include <linux/platform_device.h> +#include <linux/ftrace.h>  #include <asm/oplib.h>  #include <asm/timer.h> @@ -717,7 +718,7 @@ static struct clock_event_device sparc64_clockevent = {  };  static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); -void timer_interrupt(int irq, struct pt_regs *regs) +void __irq_entry timer_interrupt(int irq, struct pt_regs *regs)  {  	struct pt_regs *old_regs = set_irq_regs(regs);  	unsigned long tick_mask = tick_ops->softint_mask; @@ -728,6 +729,7 @@ void timer_interrupt(int irq, struct pt_regs *regs)  	irq_enter(); +	local_cpu_data().irq0_irqs++;  	kstat_incr_irqs_this_cpu(0, irq_to_desc(0));  	if (unlikely(!evt->event_handler)) { diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index bdc05a21908..9da57f03298 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -17,6 +17,7 @@  #include <linux/mm.h>  #include <linux/init.h>  #include <linux/kdebug.h> +#include <linux/gfp.h>  #include <asm/smp.h>  #include <asm/delay.h> @@ -2202,27 +2203,6 @@ void dump_stack(void)  EXPORT_SYMBOL(dump_stack); -static inline int is_kernel_stack(struct task_struct *task, -				  struct reg_window *rw) -{ -	unsigned long rw_addr = (unsigned long) rw; -	unsigned long thread_base, thread_end; - -	if (rw_addr < PAGE_OFFSET) { -		if (task != &init_task) -			return 0; -	} - -	thread_base = (unsigned long) task_stack_page(task); -	thread_end = thread_base + sizeof(union thread_union); -	if (rw_addr >= thread_base && -	    rw_addr < thread_end && -	    !(rw_addr & 0x7UL)) -		return 1; - -	return 0; -} -  static inline struct reg_window *kernel_stack_up(struct reg_window *rw)  {  	unsigned long fp = rw->ins[6]; @@ -2251,6 +2231,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)  	show_regs(regs);  	add_taint(TAINT_DIE);  	if (regs->tstate & TSTATE_PRIV) { +		struct thread_info *tp = current_thread_info();  		struct reg_window *rw = (struct reg_window *)  			(regs->u_regs[UREG_FP] + STACK_BIAS); @@ -2258,8 +2239,8 @@ void die_if_kernel(char *str, struct pt_regs *regs)  		 * find some badly aligned kernel stack.  		 */  		while (rw && -		       count++ < 30&& -		       is_kernel_stack(current, rw)) { +		       count++ < 30 && +		       kstack_valid(tp, (unsigned long) rw)) {  			printk("Caller[%016lx]: %pS\n", rw->ins[7],  			       (void *) rw->ins[7]); diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index ebce43018c4..c752c4c479b 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -50,7 +50,7 @@ static inline enum direction decode_direction(unsigned int insn)  }  /* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */ -static inline int decode_access_size(unsigned int insn) +static inline int decode_access_size(struct pt_regs *regs, unsigned int insn)  {  	unsigned int tmp; @@ -66,7 +66,7 @@ static inline int decode_access_size(unsigned int insn)  		return 2;  	else {  		printk("Impossible unaligned trap. insn=%08x\n", insn); -		die_if_kernel("Byte sized unaligned access?!?!", current_thread_info()->kregs); +		die_if_kernel("Byte sized unaligned access?!?!", regs);  		/* GCC should never warn that control reaches the end  		 * of this function without returning a value because @@ -286,7 +286,7 @@ static void log_unaligned(struct pt_regs *regs)  asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)  {  	enum direction dir = decode_direction(insn); -	int size = decode_access_size(insn); +	int size = decode_access_size(regs, insn);  	int orig_asi, asi;  	current_thread_info()->kern_una_regs = regs; diff --git a/arch/sparc/kernel/us2e_cpufreq.c b/arch/sparc/kernel/us2e_cpufreq.c index 791c15138f3..8f982b76c71 100644 --- a/arch/sparc/kernel/us2e_cpufreq.c +++ b/arch/sparc/kernel/us2e_cpufreq.c @@ -238,12 +238,12 @@ static unsigned int us2e_freq_get(unsigned int cpu)  		return 0;  	cpus_allowed = current->cpus_allowed; -	set_cpus_allowed(current, cpumask_of_cpu(cpu)); +	set_cpus_allowed_ptr(current, cpumask_of(cpu));  	clock_tick = sparc64_get_clock_tick(cpu) / 1000;  	estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR); -	set_cpus_allowed(current, cpus_allowed); +	set_cpus_allowed_ptr(current, &cpus_allowed);  	return clock_tick / estar_to_divisor(estar);  } @@ -259,7 +259,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)  		return;  	cpus_allowed = current->cpus_allowed; -	set_cpus_allowed(current, cpumask_of_cpu(cpu)); +	set_cpus_allowed_ptr(current, cpumask_of(cpu));  	new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000;  	new_bits = index_to_estar_mode(index); @@ -281,7 +281,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)  	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -	set_cpus_allowed(current, cpus_allowed); +	set_cpus_allowed_ptr(current, &cpus_allowed);  }  static int us2e_freq_target(struct cpufreq_policy *policy, diff --git a/arch/sparc/kernel/us3_cpufreq.c b/arch/sparc/kernel/us3_cpufreq.c index 365b6464e2c..f35d1e79454 100644 --- a/arch/sparc/kernel/us3_cpufreq.c +++ b/arch/sparc/kernel/us3_cpufreq.c @@ -86,12 +86,12 @@ static unsigned int us3_freq_get(unsigned int cpu)  		return 0;  	cpus_allowed = current->cpus_allowed; -	set_cpus_allowed(current, cpumask_of_cpu(cpu)); +	set_cpus_allowed_ptr(current, cpumask_of(cpu));  	reg = read_safari_cfg();  	ret = get_current_freq(cpu, reg); -	set_cpus_allowed(current, cpus_allowed); +	set_cpus_allowed_ptr(current, &cpus_allowed);  	return ret;  } @@ -106,7 +106,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)  		return;  	cpus_allowed = current->cpus_allowed; -	set_cpus_allowed(current, cpumask_of_cpu(cpu)); +	set_cpus_allowed_ptr(current, cpumask_of(cpu));  	new_freq = sparc64_get_clock_tick(cpu) / 1000;  	switch (index) { @@ -140,7 +140,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)  	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -	set_cpus_allowed(current, cpus_allowed); +	set_cpus_allowed_ptr(current, &cpus_allowed);  }  static int us3_freq_target(struct cpufreq_policy *policy, diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index c28c71449a6..3cb1def9806 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -10,6 +10,7 @@   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/irq.h>  #include <linux/init.h> diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 4e599259396..0c1e6783657 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -46,11 +46,16 @@ SECTIONS  		SCHED_TEXT  		LOCK_TEXT  		KPROBES_TEXT +		IRQENTRY_TEXT  		*(.gnu.warning)  	} = 0  	_etext = .;  	RO_DATA(PAGE_SIZE) + +	/* Start of data section */ +	_sdata = .; +  	.data1 : {  		*(.data1)  	} diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S index 24b8b12deed..3ad6cbdc216 100644 --- a/arch/sparc/lib/mcount.S +++ b/arch/sparc/lib/mcount.S @@ -7,26 +7,11 @@  #include <linux/linkage.h> -#include <asm/ptrace.h> -#include <asm/thread_info.h> -  /*   * This is the main variant and is called by C code.  GCC's -pg option   * automatically instruments every C function with a call to this.   */ -#ifdef CONFIG_STACK_DEBUG - -#define OVSTACKSIZE	4096		/* lets hope this is enough */ - -	.data -	.align		8 -panicstring: -	.asciz		"Stack overflow\n" -	.align		8 -ovstack: -	.skip		OVSTACKSIZE -#endif  	.text  	.align		32  	.globl		_mcount @@ -35,84 +20,48 @@ ovstack:  	.type		mcount,#function  _mcount:  mcount: -#ifdef CONFIG_STACK_DEBUG -	/* -	 * Check whether %sp is dangerously low. -	 */ -	ldub		[%g6 + TI_FPDEPTH], %g1 -	srl		%g1, 1, %g3 -	add		%g3, 1, %g3 -	sllx		%g3, 8, %g3			! each fpregs frame is 256b -	add		%g3, 192, %g3 -	add		%g6, %g3, %g3			! where does task_struct+frame end? -	sub		%g3, STACK_BIAS, %g3 -	cmp		%sp, %g3 -	bg,pt		%xcc, 1f -	 nop -	lduh		[%g6 + TI_CPU], %g1 -	sethi		%hi(hardirq_stack), %g3 -	or		%g3, %lo(hardirq_stack), %g3 -	sllx		%g1, 3, %g1 -	ldx		[%g3 + %g1], %g7 -	sub		%g7, STACK_BIAS, %g7 -	cmp		%sp, %g7 -	bleu,pt		%xcc, 2f -	 sethi		%hi(THREAD_SIZE), %g3 -	add		%g7, %g3, %g7 -	cmp		%sp, %g7 -	blu,pn		%xcc, 1f -2:	 sethi		%hi(softirq_stack), %g3 -	or		%g3, %lo(softirq_stack), %g3 -	ldx		[%g3 + %g1], %g7 -	sub		%g7, STACK_BIAS, %g7 -	cmp		%sp, %g7 -	bleu,pt		%xcc, 3f -	 sethi		%hi(THREAD_SIZE), %g3 -	add		%g7, %g3, %g7 -	cmp		%sp, %g7 -	blu,pn		%xcc, 1f -	 nop -	/* If we are already on ovstack, don't hop onto it -	 * again, we are already trying to output the stack overflow -	 * message. -	 */ -3:	sethi		%hi(ovstack), %g7		! cant move to panic stack fast enough -	 or		%g7, %lo(ovstack), %g7 -	add		%g7, OVSTACKSIZE, %g3 -	sub		%g3, STACK_BIAS + 192, %g3 -	sub		%g7, STACK_BIAS, %g7 -	cmp		%sp, %g7 -	blu,pn		%xcc, 2f -	 cmp		%sp, %g3 -	bleu,pn		%xcc, 1f -	 nop -2:	mov		%g3, %sp -	sethi		%hi(panicstring), %g3 -	call		prom_printf -	 or		%g3, %lo(panicstring), %o0 -	call		prom_halt -	 nop -1: -#endif  #ifdef CONFIG_FUNCTION_TRACER  #ifdef CONFIG_DYNAMIC_FTRACE -	mov		%o7, %o0 -	.globl		mcount_call -mcount_call: -	call		ftrace_stub -	 mov		%o0, %o7 +	/* Do nothing, the retl/nop below is all we need.  */  #else -	sethi		%hi(ftrace_trace_function), %g1 +	sethi		%hi(function_trace_stop), %g1 +	lduw		[%g1 + %lo(function_trace_stop)], %g2 +	brnz,pn		%g2, 2f +	 sethi		%hi(ftrace_trace_function), %g1  	sethi		%hi(ftrace_stub), %g2  	ldx		[%g1 + %lo(ftrace_trace_function)], %g1  	or		%g2, %lo(ftrace_stub), %g2  	cmp		%g1, %g2  	be,pn		%icc, 1f -	 mov		%i7, %o1 -	jmpl		%g1, %g0 -	 mov		%o7, %o0 +	 mov		%i7, %g3 +	save		%sp, -176, %sp +	mov		%g3, %o1 +	jmpl		%g1, %o7 +	 mov		%i7, %o0 +	ret +	 restore  	/* not reached */  1: +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +	sethi		%hi(ftrace_graph_return), %g1 +	ldx		[%g1 + %lo(ftrace_graph_return)], %g3 +	cmp		%g2, %g3 +	bne,pn		%xcc, 5f +	 sethi		%hi(ftrace_graph_entry_stub), %g2 +	sethi		%hi(ftrace_graph_entry), %g1 +	or		%g2, %lo(ftrace_graph_entry_stub), %g2 +	ldx		[%g1 + %lo(ftrace_graph_entry)], %g1 +	cmp		%g1, %g2 +	be,pt		%xcc, 2f +	 nop +5:	mov		%i7, %g2 +	mov		%fp, %g3 +	save		%sp, -176, %sp +	mov		%g2, %l0 +	ba,pt		%xcc, ftrace_graph_caller +	 mov		%g3, %l1 +#endif +2:  #endif  #endif  	retl @@ -131,14 +80,50 @@ ftrace_stub:  	.globl		ftrace_caller  	.type		ftrace_caller,#function  ftrace_caller: -	mov		%i7, %o1 -	mov		%o7, %o0 +	sethi		%hi(function_trace_stop), %g1 +	mov		%i7, %g2 +	lduw		[%g1 + %lo(function_trace_stop)], %g1 +	brnz,pn		%g1, ftrace_stub +	 mov		%fp, %g3 +	save		%sp, -176, %sp +	mov		%g2, %o1 +	mov		%g2, %l0 +	mov		%g3, %l1  	.globl		ftrace_call  ftrace_call:  	call		ftrace_stub -	 mov		%o0, %o7 -	retl +	 mov		%i7, %o0 +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +	.globl		ftrace_graph_call +ftrace_graph_call: +	call		ftrace_stub  	 nop +#endif +	ret +	 restore +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +	.size		ftrace_graph_call,.-ftrace_graph_call +#endif +	.size		ftrace_call,.-ftrace_call  	.size		ftrace_caller,.-ftrace_caller  #endif  #endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(ftrace_graph_caller) +	mov		%l0, %o0 +	mov		%i7, %o1 +	call		prepare_ftrace_return +	 mov		%l1, %o2 +	ret +	 restore	%o0, -8, %i7 +END(ftrace_graph_caller) + +ENTRY(return_to_handler) +	save		%sp, -176, %sp +	call		ftrace_return_to_handler +	 mov		%fp, %o0 +	jmpl		%o0 + 8, %g0 +	 restore +END(return_to_handler) +#endif diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index f27d10369e0..5fdddf134ca 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c @@ -10,7 +10,6 @@  #include <linux/mm.h>  #include <linux/hugetlb.h>  #include <linux/pagemap.h> -#include <linux/slab.h>  #include <linux/sysctl.h>  #include <asm/mman.h> diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index dc7c3b17a15..6d0e02c4fe0 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -24,6 +24,7 @@  #include <linux/bootmem.h>  #include <linux/pagemap.h>  #include <linux/poison.h> +#include <linux/gfp.h>  #include <asm/sections.h>  #include <asm/system.h> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 9245a822a2f..b2831dc3c12 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -13,7 +13,6 @@  #include <linux/bootmem.h>  #include <linux/mm.h>  #include <linux/hugetlb.h> -#include <linux/slab.h>  #include <linux/initrd.h>  #include <linux/swap.h>  #include <linux/pagemap.h> @@ -26,6 +25,7 @@  #include <linux/percpu.h>  #include <linux/lmb.h>  #include <linux/mmzone.h> +#include <linux/gfp.h>  #include <asm/head.h>  #include <asm/system.h> @@ -2117,7 +2117,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)  			       "node=%d entry=%lu/%lu\n", start, block, nr,  			       node,  			       addr >> VMEMMAP_CHUNK_SHIFT, -			       VMEMMAP_SIZE >> VMEMMAP_CHUNK_SHIFT); +			       VMEMMAP_SIZE);  		}  	}  	return 0; diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index df49b200ca4..f5f75a58e0b 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -10,7 +10,6 @@  #include <linux/kernel.h>  #include <linux/mm.h> -#include <linux/slab.h>  #include <linux/vmalloc.h>  #include <linux/pagemap.h>  #include <linux/init.h> @@ -20,6 +19,7 @@  #include <linux/seq_file.h>  #include <linux/kdebug.h>  #include <linux/log2.h> +#include <linux/gfp.h>  #include <asm/bitext.h>  #include <asm/page.h> diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 18652534b91..cf38846753d 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -12,6 +12,7 @@  #include <linux/kernel.h>  #include <linux/mm.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <linux/bootmem.h>  #include <linux/highmem.h>  #include <linux/fs.h> diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 36a0813f951..101d7c82870 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -5,6 +5,7 @@  #include <linux/kernel.h>  #include <linux/preempt.h> +#include <linux/slab.h>  #include <asm/system.h>  #include <asm/page.h>  #include <asm/tlbflush.h>  |