arch/tile: Miscellaneous cleanup changes.

This commit is primarily changes caused by reviewing "sparse"
and "checkpatch" output on our sources, so is somewhat noisy, since
things like "printk() -> pr_err()" (or whatever) throughout the
codebase tend to get tedious to read.  Rather than trying to tease
apart precisely which things changed due to which type of code
review, this commit includes various cleanups in the code:

- sparse: Add declarations in headers for globals.
- sparse: Fix __user annotations.
- sparse: Using gfp_t consistently instead of int.
- sparse: removing functions not actually used.
- checkpatch: Clean up printk() warnings by using pr_info(), etc.;
  also avoid partial-line printks except in bootup code.
  - checkpatch: Use exposed structs rather than typedefs.
  - checkpatch: Change some C99 comments to C89 comments.

In addition, a couple of minor other changes are rolled in
to this commit:

- Add support for a "raise" instruction to cause SIGFPE, etc., to be raised.
- Remove some compat code that is unnecessary when we fully eliminate
  some of the deprecated syscalls from the generic syscall ABI.
- Update the tile_defconfig to reflect current config contents.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c
index 1b0a410..77265f3 100644
--- a/arch/tile/kernel/backtrace.c
+++ b/arch/tile/kernel/backtrace.c
@@ -30,18 +30,18 @@
 
 
 /** A decoded bundle used for backtracer analysis. */
-typedef struct {
+struct BacktraceBundle {
 	tile_bundle_bits bits;
 	int num_insns;
 	struct tile_decoded_instruction
 	insns[TILE_MAX_INSTRUCTIONS_PER_BUNDLE];
-} BacktraceBundle;
+};
 
 
 /* This implementation only makes sense for native tools. */
 /** Default function to read memory. */
-static bool
-bt_read_memory(void *result, VirtualAddress addr, size_t size, void *extra)
+static bool bt_read_memory(void *result, VirtualAddress addr,
+			   size_t size, void *extra)
 {
 	/* FIXME: this should do some horrible signal stuff to catch
 	 * SEGV cleanly and fail.
@@ -58,11 +58,11 @@
  * has the specified mnemonic, and whose first 'num_operands_to_match'
  * operands exactly match those in 'operand_values'.
  */
-static const struct tile_decoded_instruction*
-find_matching_insn(const BacktraceBundle *bundle,
-		   tile_mnemonic mnemonic,
-		   const int *operand_values,
-		   int num_operands_to_match)
+static const struct tile_decoded_instruction *find_matching_insn(
+	const struct BacktraceBundle *bundle,
+	tile_mnemonic mnemonic,
+	const int *operand_values,
+	int num_operands_to_match)
 {
 	int i, j;
 	bool match;
@@ -90,8 +90,7 @@
 }
 
 /** Does this bundle contain an 'iret' instruction? */
-static inline bool
-bt_has_iret(const BacktraceBundle *bundle)
+static inline bool bt_has_iret(const struct BacktraceBundle *bundle)
 {
 	return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL;
 }
@@ -99,8 +98,7 @@
 /** Does this bundle contain an 'addi sp, sp, OFFSET' or
  * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET?
  */
-static bool
-bt_has_addi_sp(const BacktraceBundle *bundle, int *adjust)
+static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust)
 {
 	static const int vals[2] = { TREG_SP, TREG_SP };
 
@@ -120,8 +118,7 @@
  * as an unsigned value by this code since that's what the caller wants.
  * Returns the number of info ops found.
  */
-static int
-bt_get_info_ops(const BacktraceBundle *bundle,
+static int bt_get_info_ops(const struct BacktraceBundle *bundle,
 		int operands[MAX_INFO_OPS_PER_BUNDLE])
 {
 	int num_ops = 0;
@@ -143,8 +140,7 @@
 /** Does this bundle contain a jrp instruction, and if so, to which
  * register is it jumping?
  */
-static bool
-bt_has_jrp(const BacktraceBundle *bundle, int *target_reg)
+static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg)
 {
 	const struct tile_decoded_instruction *insn =
 		find_matching_insn(bundle, TILE_OPC_JRP, NULL, 0);
@@ -156,8 +152,7 @@
 }
 
 /** Does this bundle modify the specified register in any way? */
-static bool
-bt_modifies_reg(const BacktraceBundle *bundle, int reg)
+static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg)
 {
 	int i, j;
 	for (i = 0; i < bundle->num_insns; i++) {
@@ -177,30 +172,26 @@
 }
 
 /** Does this bundle modify sp? */
-static inline bool
-bt_modifies_sp(const BacktraceBundle *bundle)
+static inline bool bt_modifies_sp(const struct BacktraceBundle *bundle)
 {
 	return bt_modifies_reg(bundle, TREG_SP);
 }
 
 /** Does this bundle modify lr? */
-static inline bool
-bt_modifies_lr(const BacktraceBundle *bundle)
+static inline bool bt_modifies_lr(const struct BacktraceBundle *bundle)
 {
 	return bt_modifies_reg(bundle, TREG_LR);
 }
 
 /** Does this bundle contain the instruction 'move fp, sp'? */
-static inline bool
-bt_has_move_r52_sp(const BacktraceBundle *bundle)
+static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle)
 {
 	static const int vals[2] = { 52, TREG_SP };
 	return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL;
 }
 
 /** Does this bundle contain the instruction 'sw sp, lr'? */
-static inline bool
-bt_has_sw_sp_lr(const BacktraceBundle *bundle)
+static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle)
 {
 	static const int vals[2] = { TREG_SP, TREG_LR };
 	return find_matching_insn(bundle, TILE_OPC_SW, vals, 2) != NULL;
@@ -209,11 +200,10 @@
 /** Locates the caller's PC and SP for a program starting at the
  * given address.
  */
-static void
-find_caller_pc_and_caller_sp(CallerLocation *location,
-			     const VirtualAddress start_pc,
-			     BacktraceMemoryReader read_memory_func,
-			     void *read_memory_func_extra)
+static void find_caller_pc_and_caller_sp(CallerLocation *location,
+					 const VirtualAddress start_pc,
+					 BacktraceMemoryReader read_memory_func,
+					 void *read_memory_func_extra)
 {
 	/* Have we explicitly decided what the sp is,
 	 * rather than just the default?
@@ -253,7 +243,7 @@
 
 	for (pc = start_pc;; pc += sizeof(tile_bundle_bits)) {
 
-		BacktraceBundle bundle;
+		struct BacktraceBundle bundle;
 		int num_info_ops, info_operands[MAX_INFO_OPS_PER_BUNDLE];
 		int one_ago, jrp_reg;
 		bool has_jrp;
@@ -475,12 +465,11 @@
 	}
 }
 
-void
-backtrace_init(BacktraceIterator *state,
-	       BacktraceMemoryReader read_memory_func,
-	       void *read_memory_func_extra,
-	       VirtualAddress pc, VirtualAddress lr,
-	       VirtualAddress sp, VirtualAddress r52)
+void backtrace_init(BacktraceIterator *state,
+		    BacktraceMemoryReader read_memory_func,
+		    void *read_memory_func_extra,
+		    VirtualAddress pc, VirtualAddress lr,
+		    VirtualAddress sp, VirtualAddress r52)
 {
 	CallerLocation location;
 	VirtualAddress fp, initial_frame_caller_pc;
@@ -558,8 +547,7 @@
 	state->read_memory_func_extra = read_memory_func_extra;
 }
 
-bool
-backtrace_next(BacktraceIterator *state)
+bool backtrace_next(BacktraceIterator *state)
 {
 	VirtualAddress next_fp, next_pc, next_frame[2];
 
@@ -614,12 +602,11 @@
 
 #else /* TILE_CHIP < 10 */
 
-void
-backtrace_init(BacktraceIterator *state,
-	       BacktraceMemoryReader read_memory_func,
-	       void *read_memory_func_extra,
-	       VirtualAddress pc, VirtualAddress lr,
-	       VirtualAddress sp, VirtualAddress r52)
+void backtrace_init(BacktraceIterator *state,
+		    BacktraceMemoryReader read_memory_func,
+		    void *read_memory_func_extra,
+		    VirtualAddress pc, VirtualAddress lr,
+		    VirtualAddress sp, VirtualAddress r52)
 {
 	state->pc = pc;
 	state->sp = sp;
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index a374c99..b1e06d0 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -88,34 +88,14 @@
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
+	ret = sys_sched_rr_get_interval(pid,
+					(struct timespec __force __user *)&t);
 	set_fs(old_fs);
 	if (put_compat_timespec(&t, interval))
 		return -EFAULT;
 	return ret;
 }
 
-ssize_t compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
-			    size_t count)
-{
-	mm_segment_t old_fs = get_fs();
-	int ret;
-	off_t of;
-
-	if (offset && get_user(of, offset))
-		return -EFAULT;
-
-	set_fs(KERNEL_DS);
-	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
-			   count);
-	set_fs(old_fs);
-
-	if (offset && put_user(of, offset))
-		return -EFAULT;
-	return ret;
-}
-
-
 /*
  * The usual compat_sys_msgsnd() and _msgrcv() seem to be assuming
  * some different calling convention than our normal 32-bit tile code.
@@ -177,6 +157,10 @@
 /* Pass full 64-bit values through ptrace. */
 #define compat_sys_ptrace tile_compat_sys_ptrace
 
+/*
+ * Note that we can't include <linux/unistd.h> here since the header
+ * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
+ */
 void *compat_sys_call_table[__NR_syscalls] = {
 	[0 ... __NR_syscalls-1] = sys_ni_syscall,
 #include <asm/unistd.h>
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index 9fa4ba8..d5efb21 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -32,13 +32,14 @@
 #include <asm/processor.h>
 #include <asm/ucontext.h>
 #include <asm/sigframe.h>
+#include <asm/syscalls.h>
 #include <arch/interrupts.h>
 
 struct compat_sigaction {
 	compat_uptr_t sa_handler;
 	compat_ulong_t sa_flags;
 	compat_uptr_t sa_restorer;
-	sigset_t sa_mask;		/* mask last for extensibility */
+	sigset_t sa_mask __packed;
 };
 
 struct compat_sigaltstack {
@@ -170,7 +171,7 @@
 	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info);
 	set_fs(old_fs);
 	return ret;
 }
@@ -274,7 +275,8 @@
 	}
 	seg = get_fs();
 	set_fs(KERNEL_DS);
-	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss,
+	ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
+			     (stack_t __user __force *)&uoss,
 			     (unsigned long)compat_ptr(regs->sp));
 	set_fs(seg);
 	if (ret >= 0 && uoss_ptr)  {
@@ -336,7 +338,7 @@
 	 * will die with SIGSEGV.
 	 */
 	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
-		return (void __user *) -1L;
+		return (void __user __force *)-1UL;
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
diff --git a/arch/tile/kernel/early_printk.c b/arch/tile/kernel/early_printk.c
index e44d441..2c54fd4 100644
--- a/arch/tile/kernel/early_printk.c
+++ b/arch/tile/kernel/early_printk.c
@@ -32,7 +32,7 @@
 };
 
 /* Direct interface for emergencies */
-struct console *early_console = &early_hv_console;
+static struct console *early_console = &early_hv_console;
 static int early_console_initialized;
 static int early_console_complete;
 
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index 136261f..3d01383 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -13,9 +13,9 @@
  */
 
 #include <linux/linkage.h>
-#include <arch/abi.h>
-#include <asm/unistd.h>
+#include <linux/unistd.h>
 #include <asm/irqflags.h>
+#include <arch/abi.h>
 
 #ifdef __tilegx__
 #define bnzt bnezt
diff --git a/arch/tile/kernel/machine_kexec.c b/arch/tile/kernel/machine_kexec.c
index ed3e1cb..ba7a265 100644
--- a/arch/tile/kernel/machine_kexec.c
+++ b/arch/tile/kernel/machine_kexec.c
@@ -75,13 +75,13 @@
 int machine_kexec_prepare(struct kimage *image)
 {
 	if (num_online_cpus() > 1) {
-		printk(KERN_WARNING "%s: detected attempt to kexec "
+		pr_warning("%s: detected attempt to kexec "
 		       "with num_online_cpus() > 1\n",
 		       __func__);
 		return -ENOSYS;
 	}
 	if (image->type != KEXEC_TYPE_DEFAULT) {
-		printk(KERN_WARNING "%s: detected attempt to kexec "
+		pr_warning("%s: detected attempt to kexec "
 		       "with unsupported type: %d\n",
 		       __func__,
 		       image->type);
@@ -124,22 +124,13 @@
 		return 0;
 
 	/*
-	 * If we get a checksum mismatch, it's possible that this is
-	 * just a false positive, but relatively unlikely.  We dump
-	 * out the contents of the section so we can diagnose better.
+	 * If we get a checksum mismatch, warn with the checksum
+	 * so we can diagnose better.
 	 */
 	csum = ip_compute_csum(pg, bhdrp->b_size);
 	if (csum != 0) {
-		int i;
-		unsigned char *p = pg;
-		int nbytes = min((Elf32_Word)1000, bhdrp->b_size);
-		printk(KERN_INFO "%s: bad checksum %#x\n", __func__, csum);
-		printk(KERN_INFO "bytes (%d):", bhdrp->b_size);
-		for (i = 0; i < nbytes; ++i)
-			printk(" %02x", p[i]);
-		if (bhdrp->b_size != nbytes)
-			printk(" ...");
-		printk("\n");
+		pr_warning("%s: bad checksum %#x (size %d)\n",
+			   __func__, csum, bhdrp->b_size);
 		return 0;
 	}
 
@@ -156,7 +147,7 @@
 		if ((unsigned char *) (nhdrp + 1) >
 		    ((unsigned char *) pg) + bhdrp->b_size) {
 
-			printk(KERN_INFO "%s: out of bounds\n", __func__);
+			pr_info("%s: out of bounds\n", __func__);
 			return 0;
 		}
 	}
@@ -167,7 +158,7 @@
 	while (*desc != '\0') {
 		desc++;
 		if (((unsigned long)desc & PAGE_MASK) != (unsigned long)pg) {
-			printk(KERN_INFO "%s: ran off end of page\n",
+			pr_info("%s: ran off end of page\n",
 			       __func__);
 			return 0;
 		}
@@ -202,23 +193,20 @@
 	}
 
 	if (command_line != 0) {
-		printk(KERN_INFO "setting new command line to \"%s\"\n",
+		pr_info("setting new command line to \"%s\"\n",
 		       command_line);
 
 		hverr = hv_set_command_line(
 			(HV_VirtAddr) command_line, strlen(command_line));
 		kunmap_atomic(command_line, KM_USER0);
 	} else {
-		printk(KERN_INFO "%s: no command line found; making empty\n",
+		pr_info("%s: no command line found; making empty\n",
 		       __func__);
 		hverr = hv_set_command_line((HV_VirtAddr) command_line, 0);
 	}
-	if (hverr) {
-		printk(KERN_WARNING
-		      "%s: call to hv_set_command_line returned error: %d\n",
-		      __func__, hverr);
-
-	}
+	if (hverr)
+		pr_warning("%s: hv_set_command_line returned error: %d\n",
+			   __func__, hverr);
 }
 
 /*
diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c
index f991f52..6d23ed2 100644
--- a/arch/tile/kernel/messaging.c
+++ b/arch/tile/kernel/messaging.c
@@ -18,13 +18,14 @@
 #include <linux/ptrace.h>
 #include <asm/hv_driver.h>
 #include <asm/irq_regs.h>
+#include <asm/traps.h>
 #include <hv/hypervisor.h>
 #include <arch/interrupts.h>
 
 /* All messages are stored here */
 static DEFINE_PER_CPU(HV_MsgState, msg_state);
 
-void __cpuinit init_messaging()
+void __cpuinit init_messaging(void)
 {
 	/* Allocate storage for messages in kernel space */
 	HV_MsgState *state = &__get_cpu_var(msg_state);
@@ -58,7 +59,7 @@
 	{
 		long sp = stack_pointer - (long) current_thread_info();
 		if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
-			printk(KERN_EMERG "hv_message_intr: "
+			pr_emerg("hv_message_intr: "
 			       "stack overflow: %ld\n",
 			       sp - sizeof(struct thread_info));
 			dump_stack();
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index ed3e911..e2ab82b 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -107,7 +107,7 @@
 		   unsigned int relsec,
 		   struct module *me)
 {
-	printk(KERN_ERR "module %s: .rel relocation unsupported\n", me->name);
+	pr_err("module %s: .rel relocation unsupported\n", me->name);
 	return -ENOEXEC;
 }
 
@@ -119,8 +119,8 @@
 static int validate_hw2_last(long value, struct module *me)
 {
 	if (((value << 16) >> 16) != value) {
-		printk("module %s: Out of range HW2_LAST value %#lx\n",
-		       me->name, value);
+		pr_warning("module %s: Out of range HW2_LAST value %#lx\n",
+			   me->name, value);
 		return 0;
 	}
 	return 1;
@@ -223,10 +223,10 @@
 			value -= (unsigned long) location;  /* pc-relative */
 			value = (long) value >> 3;     /* count by instrs */
 			if (!validate_jumpoff(value)) {
-				printk("module %s: Out of range jump to"
-				       " %#llx at %#llx (%p)\n", me->name,
-				       sym->st_value + rel[i].r_addend,
-				       rel[i].r_offset, location);
+				pr_warning("module %s: Out of range jump to"
+					   " %#llx at %#llx (%p)\n", me->name,
+					   sym->st_value + rel[i].r_addend,
+					   rel[i].r_offset, location);
 				return -ENOEXEC;
 			}
 			MUNGE(create_JumpOff_X1);
@@ -236,7 +236,7 @@
 #undef MUNGE
 
 		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %d\n",
+			pr_err("module %s: Unknown relocation: %d\n",
 			       me->name, (int) ELF_R_TYPE(rel[i].r_info));
 			return -ENOEXEC;
 		}
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index c70ff14..ed590ad 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -24,9 +24,14 @@
 #include <linux/compat.h>
 #include <linux/hardirq.h>
 #include <linux/syscalls.h>
+#include <linux/kernel.h>
 #include <asm/system.h>
 #include <asm/stack.h>
 #include <asm/homecache.h>
+#include <asm/syscalls.h>
+#ifdef CONFIG_HARDWALL
+#include <asm/hardwall.h>
+#endif
 #include <arch/chip.h>
 #include <arch/abi.h>
 
@@ -43,7 +48,7 @@
 		return -EINVAL;
 
 	if (!strcmp(str, "poll")) {
-		printk("using polling idle threads.\n");
+		pr_info("using polling idle threads.\n");
 		no_idle_nap = 1;
 	} else if (!strcmp(str, "halt"))
 		no_idle_nap = 0;
@@ -62,7 +67,6 @@
  */
 void cpu_idle(void)
 {
-	extern void _cpu_idle(void);
 	int cpu = smp_processor_id();
 
 
@@ -108,7 +112,7 @@
 struct thread_info *alloc_thread_info(struct task_struct *task)
 {
 	struct page *page;
-	int flags = GFP_KERNEL;
+	gfp_t flags = GFP_KERNEL;
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
 	flags |= __GFP_ZERO;
@@ -116,7 +120,7 @@
 
 	page = alloc_pages(flags, THREAD_SIZE_ORDER);
 	if (!page)
-		return 0;
+		return NULL;
 
 	return (struct thread_info *)page_address(page);
 }
@@ -129,6 +133,18 @@
 {
 	struct single_step_state *step_state = info->step_state;
 
+#ifdef CONFIG_HARDWALL
+	/*
+	 * We free a thread_info from the context of the task that has
+	 * been scheduled next, so the original task is already dead.
+	 * Calling deactivate here just frees up the data structures.
+	 * If the task we're freeing held the last reference to a
+	 * hardwall fd, it would have been released prior to this point
+	 * anyway via exit_files(), and "hardwall" would be NULL by now.
+	 */
+	if (info->task->thread.hardwall)
+		hardwall_deactivate(info->task);
+#endif
 
 	if (step_state) {
 
@@ -154,8 +170,6 @@
 
 static void save_arch_state(struct thread_struct *t);
 
-extern void ret_from_fork(void);
-
 int copy_thread(unsigned long clone_flags, unsigned long sp,
 		unsigned long stack_size,
 		struct task_struct *p, struct pt_regs *regs)
@@ -235,6 +249,10 @@
 	p->thread.proc_status = 0;
 #endif
 
+#ifdef CONFIG_HARDWALL
+	/* New thread does not own any networks. */
+	p->thread.hardwall = NULL;
+#endif
 
 
 	/*
@@ -257,7 +275,7 @@
 	if (unlikely((unsigned long)tsk < PAGE_OFFSET ||
 		     (void *)tsk > high_memory ||
 		     ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) {
-		printk("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer);
+		pr_err("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer);
 		tsk = &corrupt;
 	}
 	return tsk;
@@ -447,10 +465,6 @@
 }
 
 
-extern struct task_struct *__switch_to(struct task_struct *prev,
-				       struct task_struct *next,
-				       unsigned long new_system_save_1_0);
-
 struct task_struct *__sched _switch_to(struct task_struct *prev,
 				       struct task_struct *next)
 {
@@ -486,6 +500,15 @@
 	}
 #endif
 
+#ifdef CONFIG_HARDWALL
+	/* Enable or disable access to the network registers appropriately. */
+	if (prev->thread.hardwall != NULL) {
+		if (next->thread.hardwall == NULL)
+			restrict_network_mpls();
+	} else if (next->thread.hardwall != NULL) {
+		grant_network_mpls();
+	}
+#endif
 
 	/*
 	 * Switch kernel SP, PC, and callee-saved registers.
@@ -496,14 +519,14 @@
 	return __switch_to(prev, next, next_current_ksp0(next));
 }
 
-int _sys_fork(struct pt_regs *regs)
+long _sys_fork(struct pt_regs *regs)
 {
 	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
 }
 
-int _sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tidptr, void __user *child_tidptr,
-	       struct pt_regs *regs)
+long _sys_clone(unsigned long clone_flags, unsigned long newsp,
+		void __user *parent_tidptr, void __user *child_tidptr,
+		struct pt_regs *regs)
 {
 	if (!newsp)
 		newsp = regs->sp;
@@ -511,7 +534,7 @@
 		       parent_tidptr, child_tidptr);
 }
 
-int _sys_vfork(struct pt_regs *regs)
+long _sys_vfork(struct pt_regs *regs)
 {
 	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp,
 		       regs, 0, NULL, NULL);
@@ -520,10 +543,10 @@
 /*
  * sys_execve() executes a new program.
  */
-int _sys_execve(char __user *path, char __user *__user *argv,
-		char __user *__user *envp, struct pt_regs *regs)
+long _sys_execve(char __user *path, char __user *__user *argv,
+		 char __user *__user *envp, struct pt_regs *regs)
 {
-	int error;
+	long error;
 	char *filename;
 
 	filename = getname(path);
@@ -537,10 +560,10 @@
 }
 
 #ifdef CONFIG_COMPAT
-int _compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
-		       compat_uptr_t __user *envp, struct pt_regs *regs)
+long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
+			compat_uptr_t __user *envp, struct pt_regs *regs)
 {
-	int error;
+	long error;
 	char *filename;
 
 	filename = getname(path);
@@ -616,31 +639,32 @@
 	/* Nothing */
 }
 
-#ifdef __tilegx__
-# define LINECOUNT 3
-# define EXTRA_NL "\n"
-#else
-# define LINECOUNT 4
-# define EXTRA_NL ""
-#endif
-
 void show_regs(struct pt_regs *regs)
 {
 	struct task_struct *tsk = validate_current();
-	int i, linebreak;
-	printk("\n");
-	printk(" Pid: %d, comm: %20s, CPU: %d\n",
+	int i;
+
+	pr_err("\n");
+	pr_err(" Pid: %d, comm: %20s, CPU: %d\n",
 	       tsk->pid, tsk->comm, smp_processor_id());
-	for (i = linebreak = 0; i < 53; ++i) {
-		printk(" r%-2d: "REGFMT, i, regs->regs[i]);
-		if (++linebreak == LINECOUNT) {
-			linebreak = 0;
-			printk("\n");
-		}
-	}
-	printk(" tp : "REGFMT EXTRA_NL " sp : "REGFMT" lr : "REGFMT"\n",
-	       regs->tp, regs->sp, regs->lr);
-	printk(" pc : "REGFMT" ex1: %ld     faultnum: %ld\n",
+#ifdef __tilegx__
+	for (i = 0; i < 51; i += 3)
+		pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
+		       i, regs->regs[i], i+1, regs->regs[i+1],
+		       i+2, regs->regs[i+2]);
+	pr_err(" r51: "REGFMT" r52: "REGFMT" tp : "REGFMT"\n",
+	       regs->regs[51], regs->regs[52], regs->tp);
+	pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr);
+#else
+	for (i = 0; i < 52; i += 3)
+		pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT
+		       " r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
+		       i, regs->regs[i], i+1, regs->regs[i+1],
+		       i+2, regs->regs[i+2], i+3, regs->regs[i+3]);
+	pr_err(" r52: "REGFMT" tp : "REGFMT" sp : "REGFMT" lr : "REGFMT"\n",
+	       regs->regs[52], regs->tp, regs->sp, regs->lr);
+#endif
+	pr_err(" pc : "REGFMT" ex1: %ld     faultnum: %ld\n",
 	       regs->pc, regs->ex1, regs->faultnum);
 
 	dump_stack_regs(regs);
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index 4680549..e5701d1 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -19,6 +19,7 @@
 #include <linux/kprobes.h>
 #include <linux/compat.h>
 #include <linux/uaccess.h>
+#include <asm/traps.h>
 
 void user_enable_single_step(struct task_struct *child)
 {
@@ -76,7 +77,7 @@
 	if (task_thread_info(child)->status & TS_COMPAT)
 		addr = (u32)addr;
 #endif
-	datap = (unsigned long __user *)data;
+	datap = (unsigned long __user __force *)data;
 
 	switch (request) {
 
diff --git a/arch/tile/kernel/reboot.c b/arch/tile/kernel/reboot.c
index a452392..acd86d2 100644
--- a/arch/tile/kernel/reboot.c
+++ b/arch/tile/kernel/reboot.c
@@ -15,6 +15,7 @@
 #include <linux/stddef.h>
 #include <linux/reboot.h>
 #include <linux/smp.h>
+#include <linux/pm.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <hv/hypervisor.h>
@@ -46,7 +47,5 @@
 	hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd);
 }
 
-/*
- * Power off function, if any
- */
-void (*pm_power_off)(void) = machine_power_off;
+/* No interesting distinction to be made here. */
+void (*pm_power_off)(void) = NULL;
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 934136b..4dd21c1 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -20,6 +20,7 @@
 #include <linux/node.h>
 #include <linux/cpu.h>
 #include <linux/ioport.h>
+#include <linux/irq.h>
 #include <linux/kexec.h>
 #include <linux/pci.h>
 #include <linux/initrd.h>
@@ -109,7 +110,7 @@
 
 	maxmem_pfn = (maxmem_mb >> (HPAGE_SHIFT - 20)) <<
 		(HPAGE_SHIFT - PAGE_SHIFT);
-	printk("Forcing RAM used to no more than %dMB\n",
+	pr_info("Forcing RAM used to no more than %dMB\n",
 	       maxmem_pfn >> (20 - PAGE_SHIFT));
 	return 0;
 }
@@ -127,7 +128,7 @@
 
 	maxnodemem_pfn[node] = (maxnodemem_mb >> (HPAGE_SHIFT - 20)) <<
 		(HPAGE_SHIFT - PAGE_SHIFT);
-	printk("Forcing RAM used on node %ld to no more than %dMB\n",
+	pr_info("Forcing RAM used on node %ld to no more than %dMB\n",
 	       node, maxnodemem_pfn[node] >> (20 - PAGE_SHIFT));
 	return 0;
 }
@@ -140,7 +141,7 @@
 		return -EINVAL;
 
 	nodelist_scnprintf(buf, sizeof(buf), isolnodes);
-	printk("Set isolnodes value to '%s'\n", buf);
+	pr_info("Set isolnodes value to '%s'\n", buf);
 	return 0;
 }
 early_param("isolnodes", setup_isolnodes);
@@ -155,7 +156,7 @@
 		return -EINVAL;
 
 	pci_reserve_mb = mb;
-	printk("Reserving %dMB for PCIE root complex mappings\n",
+	pr_info("Reserving %dMB for PCIE root complex mappings\n",
 	       pci_reserve_mb);
 	return 0;
 }
@@ -269,7 +270,7 @@
  * This is up to 4 mappings for lowmem, one mapping per memory
  * controller, plus one for our text segment.
  */
-void __cpuinit store_permanent_mappings(void)
+static void __cpuinit store_permanent_mappings(void)
 {
 	int i;
 
@@ -320,14 +321,14 @@
 			break;
 #ifdef CONFIG_FLATMEM
 		if (i > 0) {
-			printk("Can't use discontiguous PAs: %#llx..%#llx\n",
+			pr_err("Can't use discontiguous PAs: %#llx..%#llx\n",
 			       range.size, range.start + range.size);
 			continue;
 		}
 #endif
 #ifndef __tilegx__
 		if ((unsigned long)range.start) {
-			printk("Range not at 4GB multiple: %#llx..%#llx\n",
+			pr_err("Range not at 4GB multiple: %#llx..%#llx\n",
 			       range.start, range.start + range.size);
 			continue;
 		}
@@ -335,51 +336,51 @@
 		if ((range.start & (HPAGE_SIZE-1)) != 0 ||
 		    (range.size & (HPAGE_SIZE-1)) != 0) {
 			unsigned long long start_pa = range.start;
-			unsigned long long size = range.size;
+			unsigned long long orig_size = range.size;
 			range.start = (start_pa + HPAGE_SIZE - 1) & HPAGE_MASK;
 			range.size -= (range.start - start_pa);
 			range.size &= HPAGE_MASK;
-			printk("Range not hugepage-aligned: %#llx..%#llx:"
+			pr_err("Range not hugepage-aligned: %#llx..%#llx:"
 			       " now %#llx-%#llx\n",
-			       start_pa, start_pa + size,
+			       start_pa, start_pa + orig_size,
 			       range.start, range.start + range.size);
 		}
 		highbits = __pa_to_highbits(range.start);
 		if (highbits >= NR_PA_HIGHBIT_VALUES) {
-			printk("PA high bits too high: %#llx..%#llx\n",
+			pr_err("PA high bits too high: %#llx..%#llx\n",
 			       range.start, range.start + range.size);
 			continue;
 		}
 		if (highbits_seen[highbits]) {
-			printk("Range overlaps in high bits: %#llx..%#llx\n",
+			pr_err("Range overlaps in high bits: %#llx..%#llx\n",
 			       range.start, range.start + range.size);
 			continue;
 		}
 		highbits_seen[highbits] = 1;
 		if (PFN_DOWN(range.size) > maxnodemem_pfn[i]) {
-			int size = maxnodemem_pfn[i];
-			if (size > 0) {
-				printk("Maxnodemem reduced node %d to"
-				       " %d pages\n", i, size);
-				range.size = (HV_PhysAddr)size << PAGE_SHIFT;
+			int max_size = maxnodemem_pfn[i];
+			if (max_size > 0) {
+				pr_err("Maxnodemem reduced node %d to"
+				       " %d pages\n", i, max_size);
+				range.size = PFN_PHYS(max_size);
 			} else {
-				printk("Maxnodemem disabled node %d\n", i);
+				pr_err("Maxnodemem disabled node %d\n", i);
 				continue;
 			}
 		}
 		if (num_physpages + PFN_DOWN(range.size) > maxmem_pfn) {
-			int size = maxmem_pfn - num_physpages;
-			if (size > 0) {
-				printk("Maxmem reduced node %d to %d pages\n",
-				       i, size);
-				range.size = (HV_PhysAddr)size << PAGE_SHIFT;
+			int max_size = maxmem_pfn - num_physpages;
+			if (max_size > 0) {
+				pr_err("Maxmem reduced node %d to %d pages\n",
+				       i, max_size);
+				range.size = PFN_PHYS(max_size);
 			} else {
-				printk("Maxmem disabled node %d\n", i);
+				pr_err("Maxmem disabled node %d\n", i);
 				continue;
 			}
 		}
 		if (i >= MAX_NUMNODES) {
-			printk("Too many PA nodes (#%d): %#llx...%#llx\n",
+			pr_err("Too many PA nodes (#%d): %#llx...%#llx\n",
 			       i, range.size, range.size + range.start);
 			continue;
 		}
@@ -391,7 +392,7 @@
 #ifndef __tilegx__
 		if (((HV_PhysAddr)end << PAGE_SHIFT) !=
 		    (range.start + range.size)) {
-			printk("PAs too high to represent: %#llx..%#llx\n",
+			pr_err("PAs too high to represent: %#llx..%#llx\n",
 			       range.start, range.start + range.size);
 			continue;
 		}
@@ -412,7 +413,7 @@
 				NR_CPUS * (PFN_UP(per_cpu_size) >> PAGE_SHIFT);
 			if (end < pci_reserve_end_pfn + percpu_pages) {
 				end = pci_reserve_start_pfn;
-				printk("PCI mapping region reduced node %d to"
+				pr_err("PCI mapping region reduced node %d to"
 				       " %ld pages\n", i, end - start);
 			}
 		}
@@ -456,11 +457,11 @@
 			}
 		}
 		num_physpages -= dropped_pages;
-		printk(KERN_WARNING "Only using %ldMB memory;"
+		pr_warning("Only using %ldMB memory;"
 		       " ignoring %ldMB.\n",
 		       num_physpages >> (20 - PAGE_SHIFT),
 		       dropped_pages >> (20 - PAGE_SHIFT));
-		printk(KERN_WARNING "Consider using a larger page size.\n");
+		pr_warning("Consider using a larger page size.\n");
 	}
 #endif
 
@@ -478,9 +479,9 @@
 		MAXMEM_PFN : mappable_physpages;
 	highmem_pages = (long) (num_physpages - lowmem_pages);
 
-	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+	pr_notice("%ldMB HIGHMEM available.\n",
 	       pages_to_mb(highmem_pages > 0 ? highmem_pages : 0));
-	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+	pr_notice("%ldMB LOWMEM available.\n",
 			pages_to_mb(lowmem_pages));
 #else
 	/* Set max_low_pfn based on what node 0 can directly address. */
@@ -488,15 +489,15 @@
 
 #ifndef __tilegx__
 	if (node_end_pfn[0] > MAXMEM_PFN) {
-		printk(KERN_WARNING "Only using %ldMB LOWMEM.\n",
+		pr_warning("Only using %ldMB LOWMEM.\n",
 		       MAXMEM>>20);
-		printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+		pr_warning("Use a HIGHMEM enabled kernel.\n");
 		max_low_pfn = MAXMEM_PFN;
 		max_pfn = MAXMEM_PFN;
 		num_physpages = MAXMEM_PFN;
 		node_end_pfn[0] = MAXMEM_PFN;
 	} else {
-		printk(KERN_NOTICE "%ldMB memory available.\n",
+		pr_notice("%ldMB memory available.\n",
 		       pages_to_mb(node_end_pfn[0]));
 	}
 	for (i = 1; i < MAX_NUMNODES; ++i) {
@@ -512,7 +513,7 @@
 		if (pages)
 			high_memory = pfn_to_kaddr(node_end_pfn[i]);
 	}
-	printk(KERN_NOTICE "%ldMB memory available.\n",
+	pr_notice("%ldMB memory available.\n",
 	       pages_to_mb(lowmem_pages));
 #endif
 #endif
@@ -744,7 +745,7 @@
 	nodes_andnot(default_nodes, node_online_map, isolnodes);
 	if (nodes_empty(default_nodes)) {
 		BUG_ON(!node_isset(0, node_online_map));
-		printk("Forcing NUMA node zero available as a default node\n");
+		pr_err("Forcing NUMA node zero available as a default node\n");
 		node_set(0, default_nodes);
 	}
 
@@ -822,13 +823,13 @@
 		printk(KERN_DEBUG "NUMA cpu-to-node row %d:", y);
 		for (x = 0; x < smp_width; ++x, ++cpu) {
 			if (cpu_to_node(cpu) < 0) {
-				printk(" -");
+				pr_cont(" -");
 				cpu_2_node[cpu] = first_node(default_nodes);
 			} else {
-				printk(" %d", cpu_to_node(cpu));
+				pr_cont(" %d", cpu_to_node(cpu));
 			}
 		}
-		printk("\n");
+		pr_cont("\n");
 	}
 }
 
@@ -856,12 +857,17 @@
 #endif /* CONFIG_NUMA */
 
 /**
- * setup_mpls() - Allow the user-space code to access various SPRs.
+ * setup_cpu() - Do all necessary per-cpu, tile-specific initialization.
+ * @boot: Is this the boot cpu?
  *
- * Also called from online_secondary().
+ * Called from setup_arch() on the boot cpu, or online_secondary().
  */
-void __cpuinit setup_mpls(void)
+void __cpuinit setup_cpu(int boot)
 {
+	/* The boot cpu sets up its permanent mappings much earlier. */
+	if (!boot)
+		store_permanent_mappings();
+
 	/* Allow asynchronous TLB interrupts. */
 #if CHIP_HAS_TILE_DMA()
 	raw_local_irq_unmask(INT_DMATLB_MISS);
@@ -892,6 +898,14 @@
 	 * as well as the PL 0 interrupt mask.
 	 */
 	__insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1);
+
+	/* Initialize IRQ support for this cpu. */
+	setup_irq_regs();
+
+#ifdef CONFIG_HARDWALL
+	/* Reset the network state on this cpu. */
+	reset_network_state();
+#endif
 }
 
 static int __initdata set_initramfs_file;
@@ -922,22 +936,22 @@
 	fd = hv_fs_findfile((HV_VirtAddr) initramfs_file);
 	if (fd == HV_ENOENT) {
 		if (set_initramfs_file)
-			printk("No such hvfs initramfs file '%s'\n",
-			       initramfs_file);
+			pr_warning("No such hvfs initramfs file '%s'\n",
+				   initramfs_file);
 		return;
 	}
 	BUG_ON(fd < 0);
 	stat = hv_fs_fstat(fd);
 	BUG_ON(stat.size < 0);
 	if (stat.flags & HV_FS_ISDIR) {
-		printk("Ignoring hvfs file '%s': it's a directory.\n",
-		       initramfs_file);
+		pr_warning("Ignoring hvfs file '%s': it's a directory.\n",
+			   initramfs_file);
 		return;
 	}
 	initrd = alloc_bootmem_pages(stat.size);
 	rc = hv_fs_pread(fd, (HV_VirtAddr) initrd, stat.size, 0);
 	if (rc != stat.size) {
-		printk("Error reading %d bytes from hvfs file '%s': %d\n",
+		pr_err("Error reading %d bytes from hvfs file '%s': %d\n",
 		       stat.size, initramfs_file, rc);
 		free_bootmem((unsigned long) initrd, stat.size);
 		return;
@@ -966,9 +980,9 @@
 	HV_Topology topology = hv_inquire_topology();
 	BUG_ON(topology.coord.x != 0 || topology.coord.y != 0);
 	if (topology.width != 1 || topology.height != 1) {
-		printk("Warning: booting UP kernel on %dx%d grid;"
-		       " will ignore all but first tile.\n",
-		       topology.width, topology.height);
+		pr_warning("Warning: booting UP kernel on %dx%d grid;"
+			   " will ignore all but first tile.\n",
+			   topology.width, topology.height);
 	}
 #endif
 
@@ -1004,7 +1018,7 @@
 
 	if (hv_confstr(HV_CONFSTR_CHIP_MODEL, (HV_VirtAddr)chip_model,
 		       sizeof(chip_model)) < 0) {
-		printk("Warning: HV_CONFSTR_CHIP_MODEL not available\n");
+		pr_err("Warning: HV_CONFSTR_CHIP_MODEL not available\n");
 		strlcpy(chip_model, "unknown", sizeof(chip_model));
 	}
 }
@@ -1096,7 +1110,7 @@
 	if (str == NULL || cpulist_parse_crop(str, &disabled_map) != 0)
 		return -EINVAL;
 	if (cpumask_test_cpu(boot_cpu, &disabled_map)) {
-		printk("disabled_cpus: can't disable boot cpu %d\n", boot_cpu);
+		pr_err("disabled_cpus: can't disable boot cpu %d\n", boot_cpu);
 		cpumask_clear_cpu(boot_cpu, &disabled_map);
 	}
 	return 0;
@@ -1104,12 +1118,12 @@
 
 early_param("disabled_cpus", disabled_cpus);
 
-void __init print_disabled_cpus()
+void __init print_disabled_cpus(void)
 {
 	if (!cpumask_empty(&disabled_map)) {
 		char buf[100];
 		cpulist_scnprintf(buf, sizeof(buf), &disabled_map);
-		printk(KERN_INFO "CPUs not available for Linux: %s\n", buf);
+		pr_info("CPUs not available for Linux: %s\n", buf);
 	}
 }
 
@@ -1162,7 +1176,7 @@
 			      (HV_VirtAddr) cpumask_bits(&cpu_lotar_map),
 			      sizeof(cpu_lotar_map));
 	if (rc < 0) {
-		printk("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n");
+		pr_err("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n");
 		cpu_lotar_map = cpu_possible_map;
 	}
 
@@ -1182,7 +1196,7 @@
 
 static int __init dataplane(char *str)
 {
-	printk("WARNING: dataplane support disabled in this kernel\n");
+	pr_warning("WARNING: dataplane support disabled in this kernel\n");
 	return 0;
 }
 
@@ -1200,8 +1214,8 @@
 	len = hv_get_command_line((HV_VirtAddr) boot_command_line,
 				  COMMAND_LINE_SIZE);
 	if (boot_command_line[0])
-		printk("WARNING: ignoring dynamic command line \"%s\"\n",
-		       boot_command_line);
+		pr_warning("WARNING: ignoring dynamic command line \"%s\"\n",
+			   boot_command_line);
 	strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
 #else
 	char *hv_cmdline;
@@ -1269,7 +1283,7 @@
 	setup_numa_mapping();
 	zone_sizes_init();
 	set_page_homes();
-	setup_mpls();
+	setup_cpu(1);
 	setup_clock();
 	load_hv_initrd();
 }
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index 45835cf..45b66a3 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -33,6 +33,7 @@
 #include <asm/processor.h>
 #include <asm/ucontext.h>
 #include <asm/sigframe.h>
+#include <asm/syscalls.h>
 #include <arch/interrupts.h>
 
 #define DEBUG_SIG 0
@@ -40,11 +41,8 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-/* Caller before callee in this file; other callee is in assembler */
-void do_signal(struct pt_regs *regs);
-
 long _sys_sigaltstack(const stack_t __user *uss,
-                      stack_t __user *uoss, struct pt_regs *regs)
+		      stack_t __user *uoss, struct pt_regs *regs)
 {
 	return do_sigaltstack(uss, uoss, regs->sp);
 }
@@ -65,7 +63,7 @@
 
 	for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
 		err |= __get_user(((long *)regs)[i],
-				  &((long *)(&sc->regs))[i]);
+				  &((long __user *)(&sc->regs))[i]);
 
 	regs->faultnum = INT_SWINT_1_SIGRETURN;
 
@@ -73,7 +71,8 @@
 	return err;
 }
 
-int _sys_rt_sigreturn(struct pt_regs *regs)
+/* sigreturn() returns long since it restores r0 in the interrupted code. */
+long _sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame =
 		(struct rt_sigframe __user *)(regs->sp);
@@ -114,7 +113,7 @@
 
 	for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
 		err |= __put_user(((long *)regs)[i],
-				  &((long *)(&sc->regs))[i]);
+				  &((long __user *)(&sc->regs))[i]);
 
 	return err;
 }
@@ -137,7 +136,7 @@
 	 * will die with SIGSEGV.
 	 */
 	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
-		return (void __user *) -1L;
+		return (void __user __force *)-1UL;
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
@@ -185,8 +184,8 @@
 	/* Create the ucontext.  */
 	err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
 	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user((void *)(current->sas_ss_sp),
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void __user *)(current->sas_ss_sp),
 			  &frame->uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->sp),
 			  &frame->uc.uc_stack.ss_flags);
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 266aae1..5ec4b9c 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -23,6 +23,7 @@
 #include <linux/uaccess.h>
 #include <linux/mman.h>
 #include <linux/types.h>
+#include <linux/err.h>
 #include <asm/cacheflush.h>
 #include <asm/opcode-tile.h>
 #include <asm/opcode_constants.h>
@@ -39,8 +40,8 @@
 	if (strict_strtol(str, 0, &val) != 0)
 		return 0;
 	unaligned_printk = val;
-	printk("Printk for each unaligned data accesses is %s\n",
-	       unaligned_printk ? "enabled" : "disabled");
+	pr_info("Printk for each unaligned data accesses is %s\n",
+		unaligned_printk ? "enabled" : "disabled");
 	return 1;
 }
 __setup("unaligned_printk=", setup_unaligned_printk);
@@ -113,7 +114,7 @@
 	enum mem_op mem_op,
 	int size, int sign_ext)
 {
-	unsigned char *addr;
+	unsigned char __user *addr;
 	int val_reg, addr_reg, err, val;
 
 	/* Get address and value registers */
@@ -148,7 +149,7 @@
 		return bundle;
 
 	/* If it's aligned, don't handle it specially */
-	addr = (void *)regs->regs[addr_reg];
+	addr = (void __user *)regs->regs[addr_reg];
 	if (((unsigned long)addr % size) == 0)
 		return bundle;
 
@@ -183,7 +184,7 @@
 		siginfo_t info = {
 			.si_signo = SIGSEGV,
 			.si_code = SEGV_MAPERR,
-			.si_addr = (void __user *)addr
+			.si_addr = addr
 		};
 		force_sig_info(info.si_signo, &info, current);
 		return (tile_bundle_bits) 0;
@@ -193,30 +194,33 @@
 		siginfo_t info = {
 			.si_signo = SIGBUS,
 			.si_code = BUS_ADRALN,
-			.si_addr = (void __user *)addr
+			.si_addr = addr
 		};
 		force_sig_info(info.si_signo, &info, current);
 		return (tile_bundle_bits) 0;
 	}
 
 	if (unaligned_printk || unaligned_fixup_count == 0) {
-		printk("Process %d/%s: PC %#lx: Fixup of"
-		       " unaligned %s at %#lx.\n",
-		       current->pid, current->comm, regs->pc,
-		       (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) ?
-			 "load" : "store",
-		       (unsigned long)addr);
+		pr_info("Process %d/%s: PC %#lx: Fixup of"
+			" unaligned %s at %#lx.\n",
+			current->pid, current->comm, regs->pc,
+			(mem_op == MEMOP_LOAD ||
+			 mem_op == MEMOP_LOAD_POSTINCR) ?
+			"load" : "store",
+			(unsigned long)addr);
 		if (!unaligned_printk) {
-			printk("\n"
-"Unaligned fixups in the kernel will slow your application considerably.\n"
-"You can find them by writing \"1\" to /proc/sys/tile/unaligned_fixup/printk,\n"
-"which requests the kernel show all unaligned fixups, or writing a \"0\"\n"
-"to /proc/sys/tile/unaligned_fixup/enabled, in which case each unaligned\n"
-"access will become a SIGBUS you can debug. No further warnings will be\n"
-"shown so as to avoid additional slowdown, but you can track the number\n"
-"of fixups performed via /proc/sys/tile/unaligned_fixup/count.\n"
-"Use the tile-addr2line command (see \"info addr2line\") to decode PCs.\n"
-				"\n");
+#define P pr_info
+P("\n");
+P("Unaligned fixups in the kernel will slow your application considerably.\n");
+P("To find them, write a \"1\" to /proc/sys/tile/unaligned_fixup/printk,\n");
+P("which requests the kernel show all unaligned fixups, or write a \"0\"\n");
+P("to /proc/sys/tile/unaligned_fixup/enabled, in which case each unaligned\n");
+P("access will become a SIGBUS you can debug. No further warnings will be\n");
+P("shown so as to avoid additional slowdown, but you can track the number\n");
+P("of fixups performed via /proc/sys/tile/unaligned_fixup/count.\n");
+P("Use the tile-addr2line command (see \"info addr2line\") to decode PCs.\n");
+P("\n");
+#undef P
 		}
 	}
 	++unaligned_fixup_count;
@@ -276,7 +280,7 @@
 	struct thread_info *info = (void *)current_thread_info();
 	struct single_step_state *state = info->step_state;
 	int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
-	tile_bundle_bits *buffer, *pc;
+	tile_bundle_bits __user *buffer, *pc;
 	tile_bundle_bits bundle;
 	int temp_reg;
 	int target_reg = TREG_LR;
@@ -306,21 +310,21 @@
 		/* allocate a page of writable, executable memory */
 		state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL);
 		if (state == NULL) {
-			printk("Out of kernel memory trying to single-step\n");
+			pr_err("Out of kernel memory trying to single-step\n");
 			return;
 		}
 
 		/* allocate a cache line of writable, executable memory */
 		down_write(&current->mm->mmap_sem);
-		buffer = (void *) do_mmap(0, 0, 64,
+		buffer = (void __user *) do_mmap(NULL, 0, 64,
 					  PROT_EXEC | PROT_READ | PROT_WRITE,
 					  MAP_PRIVATE | MAP_ANONYMOUS,
 					  0);
 		up_write(&current->mm->mmap_sem);
 
-		if ((int)buffer < 0 && (int)buffer > -PAGE_SIZE) {
+		if (IS_ERR((void __force *)buffer)) {
 			kfree(state);
-			printk("Out of kernel pages trying to single-step\n");
+			pr_err("Out of kernel pages trying to single-step\n");
 			return;
 		}
 
@@ -349,11 +353,14 @@
 	if (regs->faultnum == INT_SWINT_1)
 		regs->pc -= 8;
 
-	pc = (tile_bundle_bits *)(regs->pc);
-	bundle = pc[0];
+	pc = (tile_bundle_bits __user *)(regs->pc);
+	if (get_user(bundle, pc) != 0) {
+		pr_err("Couldn't read instruction at %p trying to step\n", pc);
+		return;
+	}
 
 	/* We'll follow the instruction with 2 ill op bundles */
-	state->orig_pc = (unsigned long) pc;
+	state->orig_pc = (unsigned long)pc;
 	state->next_pc = (unsigned long)(pc + 1);
 	state->branch_next_pc = 0;
 	state->update = 0;
@@ -633,7 +640,7 @@
 	}
 
 	if (err) {
-		printk("Fault when writing to single-step buffer\n");
+		pr_err("Fault when writing to single-step buffer\n");
 		return;
 	}
 
@@ -641,12 +648,12 @@
 	 * Flush the buffer.
 	 * We do a local flush only, since this is a thread-specific buffer.
 	 */
-	__flush_icache_range((unsigned long) state->buffer,
-			     (unsigned long) buffer);
+	__flush_icache_range((unsigned long)state->buffer,
+			     (unsigned long)buffer);
 
 	/* Indicate enabled */
 	state->is_enabled = is_single_step;
-	regs->pc = (unsigned long) state->buffer;
+	regs->pc = (unsigned long)state->buffer;
 
 	/* Fault immediately if we are coming back from a syscall. */
 	if (regs->faultnum == INT_SWINT_1)
diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c
index aa3aafd..74d62d0 100644
--- a/arch/tile/kernel/smpboot.c
+++ b/arch/tile/kernel/smpboot.c
@@ -25,19 +25,13 @@
 #include <linux/percpu.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/irq.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 
-/*
- * This assembly function is provided in entry.S.
- * When called, it loops on a nap instruction forever.
- * FIXME: should be in a header somewhere.
- */
-extern void smp_nap(void);
-
 /* State of each CPU. */
-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 /* The messaging code jumps to this pointer during boot-up */
 unsigned long start_cpu_function_addr;
@@ -74,7 +68,7 @@
 	 */
 	rc = sched_setaffinity(current->pid, cpumask_of(boot_cpu));
 	if (rc != 0)
-		printk("Couldn't set init affinity to boot cpu (%ld)\n", rc);
+		pr_err("Couldn't set init affinity to boot cpu (%ld)\n", rc);
 
 	/* Print information about disabled and dataplane cpus. */
 	print_disabled_cpus();
@@ -134,13 +128,13 @@
 {
 	long rc = sched_setaffinity(current->pid, &init_affinity);
 	if (rc != 0)
-		printk(KERN_WARNING "couldn't reset init affinity (%ld)\n",
+		pr_warning("couldn't reset init affinity (%ld)\n",
 		       rc);
 	return 0;
 }
 late_initcall(reset_init_affinity);
 
-struct cpumask cpu_started __cpuinitdata;
+static struct cpumask cpu_started __cpuinitdata;
 
 /*
  * Activate a secondary processor.  Very minimal; don't add anything
@@ -172,9 +166,6 @@
 		BUG();
 	enter_lazy_tlb(&init_mm, current);
 
-	/* Enable IRQs. */
-	init_per_tile_IRQs();
-
 	/* Allow hypervisor messages to be received */
 	init_messaging();
 	local_irq_enable();
@@ -182,7 +173,7 @@
 	/* Indicate that we're ready to come up. */
 	/* Must not do this before we're ready to receive messages */
 	if (cpumask_test_and_set_cpu(cpuid, &cpu_started)) {
-		printk(KERN_WARNING "CPU#%d already started!\n", cpuid);
+		pr_warning("CPU#%d already started!\n", cpuid);
 		for (;;)
 			local_irq_enable();
 	}
@@ -190,13 +181,10 @@
 	smp_nap();
 }
 
-void setup_mpls(void);  /* from kernel/setup.c */
-void store_permanent_mappings(void);
-
 /*
  * Bring a secondary processor online.
  */
-void __cpuinit online_secondary()
+void __cpuinit online_secondary(void)
 {
 	/*
 	 * low-memory mappings have been cleared, flush them from
@@ -222,17 +210,14 @@
 	ipi_call_unlock();
 	__get_cpu_var(cpu_state) = CPU_ONLINE;
 
-	/* Set up MPLs for this processor */
-	setup_mpls();
-
+	/* Set up tile-specific state for this cpu. */
+	setup_cpu(0);
 
 	/* Set up tile-timer clock-event device on this cpu */
 	setup_tile_timer();
 
 	preempt_enable();
 
-	store_permanent_mappings();
-
 	cpu_idle();
 }
 
@@ -242,7 +227,7 @@
 	static int timeout;
 	for (; !cpumask_test_cpu(cpu, &cpu_started); timeout++) {
 		if (timeout >= 50000) {
-			printk(KERN_INFO "skipping unresponsive cpu%d\n", cpu);
+			pr_info("skipping unresponsive cpu%d\n", cpu);
 			local_irq_enable();
 			return -EIO;
 		}
@@ -289,5 +274,5 @@
 		;
 	rc = sched_setaffinity(current->pid, cpumask_of(cpu));
 	if (rc != 0)
-		printk("Couldn't set init affinity to cpu %d (%d)\n", cpu, rc);
+		pr_err("Couldn't set init affinity to cpu %d (%d)\n", cpu, rc);
 }
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index 382170b..b6268d3 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -56,13 +56,16 @@
 	HV_PTE pte;
 	struct page *page;
 
+	if (l1_pgtable == NULL)
+		return 0;	/* can't read user space in other tasks */
+
 	pte = l1_pgtable[HV_L1_INDEX(address)];
 	if (!hv_pte_get_present(pte))
 		return 0;
 	pfn = hv_pte_get_pfn(pte);
 	if (pte_huge(pte)) {
 		if (!pfn_valid(pfn)) {
-			printk(KERN_ERR "huge page has bad pfn %#lx\n", pfn);
+			pr_err("huge page has bad pfn %#lx\n", pfn);
 			return 0;
 		}
 		return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
@@ -70,7 +73,7 @@
 
 	page = pfn_to_page(pfn);
 	if (PageHighMem(page)) {
-		printk(KERN_ERR "L2 page table not in LOWMEM (%#llx)\n",
+		pr_err("L2 page table not in LOWMEM (%#llx)\n",
 		       HV_PFN_TO_CPA(pfn));
 		return 0;
 	}
@@ -91,13 +94,12 @@
 		/* We only tolerate kernel-space reads of this task's stack */
 		if (!in_kernel_stack(kbt, address))
 			return 0;
-	} else if (kbt->pgtable == NULL) {
-		return 0;	/* can't read user space in other tasks */
 	} else if (!valid_address(kbt, address)) {
 		return 0;	/* invalid user-space address */
 	}
 	pagefault_disable();
-	retval = __copy_from_user_inatomic(result, (const void *)address,
+	retval = __copy_from_user_inatomic(result,
+					   (void __user __force *)address,
 					   size);
 	pagefault_enable();
 	return (retval == 0);
@@ -131,14 +133,14 @@
 	    in_kernel_stack(kbt, p->sp) &&
 	    p->sp >= sp) {
 		if (kbt->verbose)
-			printk(KERN_ERR "  <%s while in kernel mode>\n", fault);
+			pr_err("  <%s while in kernel mode>\n", fault);
 	} else if (EX1_PL(p->ex1) == USER_PL &&
 	    p->pc < PAGE_OFFSET &&
 	    p->sp < PAGE_OFFSET) {
 		if (kbt->verbose)
-			printk(KERN_ERR "  <%s while in user mode>\n", fault);
+			pr_err("  <%s while in user mode>\n", fault);
 	} else if (kbt->verbose) {
-		printk(KERN_ERR "  (odd fault: pc %#lx, sp %#lx, ex1 %#lx?)\n",
+		pr_err("  (odd fault: pc %#lx, sp %#lx, ex1 %#lx?)\n",
 		       p->pc, p->sp, p->ex1);
 		p = NULL;
 	}
@@ -166,13 +168,13 @@
 		if (!valid_address(kbt, b->sp) ||
 		    !valid_address(kbt, sigframe_top)) {
 			if (kbt->verbose)
-				printk("  (odd signal: sp %#lx?)\n",
+				pr_err("  (odd signal: sp %#lx?)\n",
 				       (unsigned long)(b->sp));
 			return NULL;
 		}
 		frame = (struct rt_sigframe *)b->sp;
 		if (kbt->verbose) {
-			printk(KERN_ERR "  <received signal %d>\n",
+			pr_err("  <received signal %d>\n",
 			       frame->info.si_signo);
 		}
 		return &frame->uc.uc_mcontext.regs;
@@ -180,7 +182,7 @@
 	return NULL;
 }
 
-int KBacktraceIterator_is_sigreturn(struct KBacktraceIterator *kbt)
+static int KBacktraceIterator_is_sigreturn(struct KBacktraceIterator *kbt)
 {
 	return is_sigreturn(kbt->it.pc);
 }
@@ -231,13 +233,13 @@
 	unsigned long sp = stack_pointer;
 
 	if (EX1_PL(regs->ex1) == KERNEL_PL && regs->sp >= ksp0) {
-		printk("WARNING: cpu %d: kernel stack page %#lx underrun!\n"
+		pr_err("WARNING: cpu %d: kernel stack page %#lx underrun!\n"
 		       "  sp %#lx (%#lx in caller), caller pc %#lx, lr %#lx\n",
 		       cpu, ksp0_base, sp, regs->sp, regs->pc, regs->lr);
 	}
 
 	else if (sp < ksp0_base + sizeof(struct thread_info)) {
-		printk("WARNING: cpu %d: kernel stack page %#lx overrun!\n"
+		pr_err("WARNING: cpu %d: kernel stack page %#lx overrun!\n"
 		       "  sp %#lx (%#lx in caller), caller pc %#lx, lr %#lx\n",
 		       cpu, ksp0_base, sp, regs->sp, regs->pc, regs->lr);
 	}
@@ -280,7 +282,7 @@
 			if (!PageHighMem(page))
 				kbt->pgtable = __va(pgdir_pa);
 			else
-				printk(KERN_ERR "page table not in LOWMEM"
+				pr_err("page table not in LOWMEM"
 				       " (%#llx)\n", pgdir_pa);
 		}
 		local_flush_tlb_all();
@@ -288,13 +290,12 @@
 	}
 
 	if (regs == NULL) {
-		extern const void *get_switch_to_pc(void);
 		if (is_current || t->state == TASK_RUNNING) {
 			/* Can't do this; we need registers */
 			kbt->end = 1;
 			return;
 		}
-		pc = (ulong) get_switch_to_pc();
+		pc = get_switch_to_pc();
 		lr = t->thread.pc;
 		sp = t->thread.ksp;
 		r52 = 0;
@@ -344,8 +345,8 @@
 		 * then bust_spinlocks() spit out a space in front of us
 		 * and it will mess up our KERN_ERR.
 		 */
-		printk("\n");
-		printk(KERN_ERR "Starting stack dump of tid %d, pid %d (%s)"
+		pr_err("\n");
+		pr_err("Starting stack dump of tid %d, pid %d (%s)"
 		       " on cpu %d at cycle %lld\n",
 		       kbt->task->pid, kbt->task->tgid, kbt->task->comm,
 		       smp_processor_id(), get_cycles());
@@ -385,17 +386,17 @@
 			namebuf[sizeof(namebuf)-1] = '\0';
 		}
 
-		printk(KERN_ERR "  frame %d: 0x%lx %s(sp 0x%lx)\n",
+		pr_err("  frame %d: 0x%lx %s(sp 0x%lx)\n",
 		       i++, address, namebuf, (unsigned long)(kbt->it.sp));
 
 		if (i >= 100) {
-			printk(KERN_ERR "Stack dump truncated"
+			pr_err("Stack dump truncated"
 			       " (%d frames)\n", i);
 			break;
 		}
 	}
 	if (headers)
-		printk(KERN_ERR "Stack dump complete\n");
+		pr_err("Stack dump complete\n");
 }
 EXPORT_SYMBOL(tile_show_stack);
 
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c
index 0427978..f0f87ea 100644
--- a/arch/tile/kernel/sys.c
+++ b/arch/tile/kernel/sys.c
@@ -27,11 +27,10 @@
 #include <linux/mempolicy.h>
 #include <linux/binfmts.h>
 #include <linux/fs.h>
-#include <linux/syscalls.h>
+#include <linux/compat.h>
 #include <linux/uaccess.h>
 #include <linux/signal.h>
 #include <asm/syscalls.h>
-
 #include <asm/pgtable.h>
 #include <asm/homecache.h>
 #include <arch/chip.h>
@@ -74,10 +73,7 @@
 
 #endif /* 32-bit syscall wrappers */
 
-/*
- * This API uses a 4KB-page-count offset into the file descriptor.
- * It is likely not the right API to use on a 64-bit platform.
- */
+/* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
 		unsigned long, prot, unsigned long, flags,
 		unsigned long, fd, unsigned long, off_4k)
@@ -89,10 +85,7 @@
 			      off_4k >> PAGE_ADJUST);
 }
 
-/*
- * This API uses a byte offset into the file descriptor.
- * It is likely not the right API to use on a 32-bit platform.
- */
+#ifdef __tilegx__
 SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 		unsigned long, prot, unsigned long, flags,
 		unsigned long, fd, off_t, offset)
@@ -102,6 +95,7 @@
 	return sys_mmap_pgoff(addr, len, prot, flags, fd,
 			      offset >> PAGE_SHIFT);
 }
+#endif
 
 
 /* Provide the actual syscall number to call mapping. */
@@ -116,6 +110,10 @@
 #define sys_sync_file_range sys_sync_file_range2
 #endif
 
+/*
+ * Note that we can't include <linux/unistd.h> here since the header
+ * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
+ */
 void *sys_call_table[__NR_syscalls] = {
 	[0 ... __NR_syscalls-1] = sys_ni_syscall,
 #include <asm/unistd.h>
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index 47500a3..b9ab25a 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -23,6 +23,7 @@
 #include <linux/smp.h>
 #include <linux/delay.h>
 #include <asm/irq_regs.h>
+#include <asm/traps.h>
 #include <hv/hypervisor.h>
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
@@ -45,13 +46,13 @@
  */
 #define TILE_MINSEC 5
 
-cycles_t get_clock_rate()
+cycles_t get_clock_rate(void)
 {
 	return cycles_per_sec;
 }
 
 #if CHIP_HAS_SPLIT_CYCLE()
-cycles_t get_cycles()
+cycles_t get_cycles(void)
 {
 	unsigned int high = __insn_mfspr(SPR_CYCLE_HIGH);
 	unsigned int low = __insn_mfspr(SPR_CYCLE_LOW);
@@ -67,7 +68,7 @@
 }
 #endif
 
-cycles_t clocksource_get_cycles(struct clocksource *cs)
+static cycles_t clocksource_get_cycles(struct clocksource *cs)
 {
 	return get_cycles();
 }
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 12cb10f..3870abb 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -20,6 +20,9 @@
 #include <linux/uaccess.h>
 #include <linux/ptrace.h>
 #include <asm/opcode-tile.h>
+#include <asm/opcode_constants.h>
+#include <asm/stack.h>
+#include <asm/traps.h>
 
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
@@ -42,7 +45,7 @@
 	if (strict_strtol(str, 0, &val) != 0)
 		return 0;
 	unaligned_fixup = val;
-	printk("Fixups for unaligned data accesses are %s\n",
+	pr_info("Fixups for unaligned data accesses are %s\n",
 	       unaligned_fixup >= 0 ?
 	       (unaligned_fixup ? "enabled" : "disabled") :
 	       "completely disabled");
@@ -56,7 +59,7 @@
 
 static int __init nodma(char *str)
 {
-	printk("User-space DMA is disabled\n");
+	pr_info("User-space DMA is disabled\n");
 	dma_disabled = 1;
 	return 1;
 }
@@ -97,20 +100,106 @@
 
 #endif /* CHIP_HAS_TILE_DMA() */
 
-/* Defined inside do_trap(), below. */
 #ifdef __tilegx__
-extern tilegx_bundle_bits bpt_code;
+#define bundle_bits tilegx_bundle_bits
 #else
-extern tile_bundle_bits bpt_code;
+#define bundle_bits tile_bundle_bits
 #endif
 
+extern bundle_bits bpt_code;
+
+asm(".pushsection .rodata.bpt_code,\"a\";"
+    ".align 8;"
+    "bpt_code: bpt;"
+    ".size bpt_code,.-bpt_code;"
+    ".popsection");
+
+static int special_ill(bundle_bits bundle, int *sigp, int *codep)
+{
+	int sig, code, maxcode;
+
+	if (bundle == bpt_code) {
+		*sigp = SIGTRAP;
+		*codep = TRAP_BRKPT;
+		return 1;
+	}
+
+	/* If it's a "raise" bundle, then "ill" must be in pipe X1. */
+#ifdef __tilegx__
+	if ((bundle & TILEGX_BUNDLE_MODE_MASK) != 0)
+		return 0;
+	if (get_Opcode_X1(bundle) != UNARY_OPCODE_X1)
+		return 0;
+	if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1)
+		return 0;
+#else
+	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK)
+		return 0;
+	if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1)
+		return 0;
+	if (get_UnShOpcodeExtension_X1(bundle) != UN_0_SHUN_0_OPCODE_X1)
+		return 0;
+	if (get_UnOpcodeExtension_X1(bundle) != ILL_UN_0_SHUN_0_OPCODE_X1)
+		return 0;
+#endif
+
+	/* Check that the magic distinguishers are set to mean "raise". */
+	if (get_Dest_X1(bundle) != 29 || get_SrcA_X1(bundle) != 37)
+		return 0;
+
+	/* There must be an "addli zero, zero, VAL" in X0. */
+	if (get_Opcode_X0(bundle) != ADDLI_OPCODE_X0)
+		return 0;
+	if (get_Dest_X0(bundle) != TREG_ZERO)
+		return 0;
+	if (get_SrcA_X0(bundle) != TREG_ZERO)
+		return 0;
+
+	/*
+	 * Validate the proposed signal number and si_code value.
+	 * Note that we embed these in the static instruction itself
+	 * so that we perturb the register state as little as possible
+	 * at the time of the actual fault; it's unlikely you'd ever
+	 * need to dynamically choose which kind of fault to raise
+	 * from user space.
+	 */
+	sig = get_Imm16_X0(bundle) & 0x3f;
+	switch (sig) {
+	case SIGILL:
+		maxcode = NSIGILL;
+		break;
+	case SIGFPE:
+		maxcode = NSIGFPE;
+		break;
+	case SIGSEGV:
+		maxcode = NSIGSEGV;
+		break;
+	case SIGBUS:
+		maxcode = NSIGBUS;
+		break;
+	case SIGTRAP:
+		maxcode = NSIGTRAP;
+		break;
+	default:
+		return 0;
+	}
+	code = (get_Imm16_X0(bundle) >> 6) & 0xf;
+	if (code <= 0 || code > maxcode)
+		return 0;
+
+	/* Make it the requested signal. */
+	*sigp = sig;
+	*codep = code | __SI_FAULT;
+	return 1;
+}
+
 void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 		       unsigned long reason)
 {
 	siginfo_t info = { 0 };
 	int signo, code;
 	unsigned long address;
-	__typeof__(bpt_code) instr;
+	bundle_bits instr;
 
 	/* Re-enable interrupts. */
 	local_irq_enable();
@@ -122,10 +211,10 @@
 	if (!user_mode(regs)) {
 		if (fixup_exception(regs))  /* only UNALIGN_DATA in practice */
 			return;
-		printk(KERN_ALERT "Kernel took bad trap %d at PC %#lx\n",
+		pr_alert("Kernel took bad trap %d at PC %#lx\n",
 		       fault_num, regs->pc);
 		if (fault_num == INT_GPV)
-			printk(KERN_ALERT "GPV_REASON is %#lx\n", reason);
+			pr_alert("GPV_REASON is %#lx\n", reason);
 		show_regs(regs);
 		do_exit(SIGKILL);  /* FIXME: implement i386 die() */
 		return;
@@ -133,22 +222,14 @@
 
 	switch (fault_num) {
 	case INT_ILL:
-		asm(".pushsection .rodata.bpt_code,\"a\";"
-		    ".align 8;"
-		    "bpt_code: bpt;"
-		    ".size bpt_code,.-bpt_code;"
-		    ".popsection");
-
-		if (copy_from_user(&instr, (void *)regs->pc, sizeof(instr))) {
-			printk(KERN_ERR "Unreadable instruction for INT_ILL:"
+		if (copy_from_user(&instr, (void __user *)regs->pc,
+				   sizeof(instr))) {
+			pr_err("Unreadable instruction for INT_ILL:"
 			       " %#lx\n", regs->pc);
 			do_exit(SIGKILL);
 			return;
 		}
-		if (instr == bpt_code) {
-			signo = SIGTRAP;
-			code = TRAP_BRKPT;
-		} else {
+		if (!special_ill(instr, &signo, &code)) {
 			signo = SIGILL;
 			code = ILL_ILLOPC;
 		}
@@ -181,7 +262,8 @@
 		if (unaligned_fixup >= 0) {
 			struct single_step_state *state =
 				current_thread_info()->step_state;
-			if (!state || (void *)(regs->pc) != state->buffer) {
+			if (!state ||
+			    (void __user *)(regs->pc) != state->buffer) {
 				single_step_once(regs);
 				return;
 			}
@@ -221,17 +303,15 @@
 
 	info.si_signo = signo;
 	info.si_code = code;
-	info.si_addr = (void *)address;
+	info.si_addr = (void __user *)address;
 	if (signo == SIGILL)
 		info.si_trapno = fault_num;
 	force_sig_info(signo, &info, current);
 }
 
-extern void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52);
-
 void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52)
 {
 	_dump_stack(dummy, pc, lr, sp, r52);
-	printk("Double fault: exiting\n");
+	pr_emerg("Double fault: exiting\n");
 	machine_halt();
 }
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 77388c1..25fdc0c 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -36,8 +36,8 @@
 
   /* Now the real code */
   . = ALIGN(0x20000);
-  HEAD_TEXT_SECTION :text =0
   .text : AT (ADDR(.text) - LOAD_OFFSET) {
+    HEAD_TEXT
     SCHED_TEXT
     LOCK_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
@@ -46,7 +46,7 @@
     *(.coldtext*)
     *(.fixup)
     *(.gnu.warning)
-  }
+  } :text =0
   _etext = .;
 
   /* "Init" is divided into two areas with very different virtual addresses. */