summaryrefslogtreecommitdiff
path: root/arch/tile/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel/process.c')
-rw-r--r--arch/tile/kernel/process.c116
1 files changed, 46 insertions, 70 deletions
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 8ac304484f98..16ed58948757 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -33,6 +33,7 @@
#include <asm/syscalls.h>
#include <asm/traps.h>
#include <asm/setup.h>
+#include <asm/uaccess.h>
#ifdef CONFIG_HARDWALL
#include <asm/hardwall.h>
#endif
@@ -74,19 +75,6 @@ void arch_release_thread_info(struct thread_info *info)
{
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 the hardwall_task.info pointers
- * would be NULL by now.
- */
- hardwall_deactivate_all(info->task);
-#endif
-
if (step_state) {
/*
@@ -160,6 +148,14 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
*/
task_thread_info(p)->step_state = NULL;
+#ifdef __tilegx__
+ /*
+ * Do not clone unalign jit fixup from the parent; each thread
+ * must allocate its own on demand.
+ */
+ task_thread_info(p)->unalign_jit_base = NULL;
+#endif
+
/*
* Copy the registers onto the kernel stack so the
* return-from-interrupt code will reload it into registers.
@@ -191,16 +187,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
memset(&p->thread.dma_async_tlb, 0, sizeof(struct async_tlb));
#endif
-#if CHIP_HAS_SN_PROC()
- /* Likewise, the new thread is not running static processor code. */
- p->thread.sn_proc_running = 0;
- memset(&p->thread.sn_async_tlb, 0, sizeof(struct async_tlb));
-#endif
-
-#if CHIP_HAS_PROC_STATUS_SPR()
/* New thread has its miscellaneous processor state bits clear. */
p->thread.proc_status = 0;
-#endif
#ifdef CONFIG_HARDWALL
/* New thread does not own any networks. */
@@ -218,19 +206,32 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
return 0;
}
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+ task_thread_info(tsk)->align_ctl = val;
+ return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+ return put_user(task_thread_info(tsk)->align_ctl,
+ (unsigned int __user *)adr);
+}
+
+static struct task_struct corrupt_current = { .comm = "<corrupt>" };
+
/*
* Return "current" if it looks plausible, or else a pointer to a dummy.
* This can be helpful if we are just trying to emit a clean panic.
*/
struct task_struct *validate_current(void)
{
- static struct task_struct corrupt = { .comm = "<corrupt>" };
struct task_struct *tsk = current;
if (unlikely((unsigned long)tsk < PAGE_OFFSET ||
(high_memory && (void *)tsk > high_memory) ||
((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) {
pr_err("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer);
- tsk = &corrupt;
+ tsk = &corrupt_current;
}
return tsk;
}
@@ -369,15 +370,11 @@ static void save_arch_state(struct thread_struct *t)
t->system_save[2] = __insn_mfspr(SPR_SYSTEM_SAVE_0_2);
t->system_save[3] = __insn_mfspr(SPR_SYSTEM_SAVE_0_3);
t->intctrl_0 = __insn_mfspr(SPR_INTCTRL_0_STATUS);
-#if CHIP_HAS_PROC_STATUS_SPR()
t->proc_status = __insn_mfspr(SPR_PROC_STATUS);
-#endif
#if !CHIP_HAS_FIXED_INTVEC_BASE()
t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0);
#endif
-#if CHIP_HAS_TILE_RTF_HWM()
t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM);
-#endif
#if CHIP_HAS_DSTREAM_PF()
t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF);
#endif
@@ -398,15 +395,11 @@ static void restore_arch_state(const struct thread_struct *t)
__insn_mtspr(SPR_SYSTEM_SAVE_0_2, t->system_save[2]);
__insn_mtspr(SPR_SYSTEM_SAVE_0_3, t->system_save[3]);
__insn_mtspr(SPR_INTCTRL_0_STATUS, t->intctrl_0);
-#if CHIP_HAS_PROC_STATUS_SPR()
__insn_mtspr(SPR_PROC_STATUS, t->proc_status);
-#endif
#if !CHIP_HAS_FIXED_INTVEC_BASE()
__insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base);
#endif
-#if CHIP_HAS_TILE_RTF_HWM()
__insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm);
-#endif
#if CHIP_HAS_DSTREAM_PF()
__insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf);
#endif
@@ -415,26 +408,11 @@ static void restore_arch_state(const struct thread_struct *t)
void _prepare_arch_switch(struct task_struct *next)
{
-#if CHIP_HAS_SN_PROC()
- int snctl;
-#endif
#if CHIP_HAS_TILE_DMA()
struct tile_dma_state *dma = &current->thread.tile_dma_state;
if (dma->enabled)
save_tile_dma_state(dma);
#endif
-#if CHIP_HAS_SN_PROC()
- /*
- * Suspend the static network processor if it was running.
- * We do not suspend the fabric itself, just like we don't
- * try to suspend the UDN.
- */
- snctl = __insn_mfspr(SPR_SNCTL);
- current->thread.sn_proc_running =
- (snctl & SPR_SNCTL__FRZPROC_MASK) == 0;
- if (current->thread.sn_proc_running)
- __insn_mtspr(SPR_SNCTL, snctl | SPR_SNCTL__FRZPROC_MASK);
-#endif
}
@@ -462,17 +440,6 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
/* Restore other arch state. */
restore_arch_state(&next->thread);
-#if CHIP_HAS_SN_PROC()
- /*
- * Restart static network processor in the new process
- * if it was running before.
- */
- if (next->thread.sn_proc_running) {
- int snctl = __insn_mfspr(SPR_SNCTL);
- __insn_mtspr(SPR_SNCTL, snctl & ~SPR_SNCTL__FRZPROC_MASK);
- }
-#endif
-
#ifdef CONFIG_HARDWALL
/* Enable or disable access to the network registers appropriately. */
hardwall_switch_tasks(prev, next);
@@ -514,7 +481,7 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
schedule();
return 1;
}
-#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC()
+#if CHIP_HAS_TILE_DMA()
if (thread_info_flags & _TIF_ASYNC_TLB) {
do_async_page_fault(regs);
return 1;
@@ -564,7 +531,15 @@ void flush_thread(void)
*/
void exit_thread(void)
{
- /* Nothing */
+#ifdef CONFIG_HARDWALL
+ /*
+ * Remove the task from the list of tasks that are associated
+ * with any live hardwalls. (If the task that is exiting held
+ * the last reference to a hardwall fd, it would already have
+ * been released and deactivated at this point.)
+ */
+ hardwall_deactivate_all(current);
+#endif
}
void show_regs(struct pt_regs *regs)
@@ -573,23 +548,24 @@ void show_regs(struct pt_regs *regs)
int i;
pr_err("\n");
- show_regs_print_info(KERN_ERR);
+ if (tsk != &corrupt_current)
+ show_regs_print_info(KERN_ERR);
#ifdef __tilegx__
- for (i = 0; i < 51; i += 3)
+ for (i = 0; i < 17; i++)
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);
+ i, regs->regs[i], i+18, regs->regs[i+18],
+ i+36, regs->regs[i+36]);
+ pr_err(" r17: "REGFMT" r35: "REGFMT" tp : "REGFMT"\n",
+ regs->regs[17], regs->regs[35], regs->tp);
pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr);
#else
- for (i = 0; i < 52; i += 4)
+ for (i = 0; i < 13; i++)
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);
+ i, regs->regs[i], i+14, regs->regs[i+14],
+ i+27, regs->regs[i+27], i+40, regs->regs[i+40]);
+ pr_err(" r13: "REGFMT" tp : "REGFMT" sp : "REGFMT" lr : "REGFMT"\n",
+ regs->regs[13], regs->tp, regs->sp, regs->lr);
#endif
pr_err(" pc : "REGFMT" ex1: %ld faultnum: %ld\n",
regs->pc, regs->ex1, regs->faultnum);