root/arch/c6x/kernel/process.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. arch_cpu_idle
  2. halt_loop
  3. machine_restart
  4. machine_halt
  5. machine_power_off
  6. flush_thread
  7. start_thread
  8. copy_thread
  9. get_wchan

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  Port on Texas Instruments TMS320C6x architecture
   4  *
   5  *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
   6  *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
   7  */
   8 #include <linux/module.h>
   9 #include <linux/unistd.h>
  10 #include <linux/ptrace.h>
  11 #include <linux/init_task.h>
  12 #include <linux/tick.h>
  13 #include <linux/mqueue.h>
  14 #include <linux/syscalls.h>
  15 #include <linux/reboot.h>
  16 #include <linux/sched/task.h>
  17 #include <linux/sched/task_stack.h>
  18 
  19 #include <asm/syscalls.h>
  20 
  21 /* hooks for board specific support */
  22 void    (*c6x_restart)(void);
  23 void    (*c6x_halt)(void);
  24 
  25 extern asmlinkage void ret_from_fork(void);
  26 extern asmlinkage void ret_from_kernel_thread(void);
  27 
  28 /*
  29  * power off function, if any
  30  */
  31 void (*pm_power_off)(void);
  32 EXPORT_SYMBOL(pm_power_off);
  33 
  34 void arch_cpu_idle(void)
  35 {
  36         unsigned long tmp;
  37 
  38         /*
  39          * Put local_irq_enable and idle in same execute packet
  40          * to make them atomic and avoid race to idle with
  41          * interrupts enabled.
  42          */
  43         asm volatile ("   mvc .s2 CSR,%0\n"
  44                       "   or  .d2 1,%0,%0\n"
  45                       "   mvc .s2 %0,CSR\n"
  46                       "|| idle\n"
  47                       : "=b"(tmp));
  48 }
  49 
  50 static void halt_loop(void)
  51 {
  52         printk(KERN_EMERG "System Halted, OK to turn off power\n");
  53         local_irq_disable();
  54         while (1)
  55                 asm volatile("idle\n");
  56 }
  57 
  58 void machine_restart(char *__unused)
  59 {
  60         if (c6x_restart)
  61                 c6x_restart();
  62         halt_loop();
  63 }
  64 
  65 void machine_halt(void)
  66 {
  67         if (c6x_halt)
  68                 c6x_halt();
  69         halt_loop();
  70 }
  71 
  72 void machine_power_off(void)
  73 {
  74         if (pm_power_off)
  75                 pm_power_off();
  76         halt_loop();
  77 }
  78 
  79 void flush_thread(void)
  80 {
  81 }
  82 
  83 /*
  84  * Do necessary setup to start up a newly executed thread.
  85  */
  86 void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp)
  87 {
  88         /*
  89          * The binfmt loader will setup a "full" stack, but the C6X
  90          * operates an "empty" stack. So we adjust the usp so that
  91          * argc doesn't get destroyed if an interrupt is taken before
  92          * it is read from the stack.
  93          *
  94          * NB: Library startup code needs to match this.
  95          */
  96         usp -= 8;
  97 
  98         regs->pc  = pc;
  99         regs->sp  = usp;
 100         regs->tsr |= 0x40; /* set user mode */
 101         current->thread.usp = usp;
 102 }
 103 
 104 /*
 105  * Copy a new thread context in its stack.
 106  */
 107 int copy_thread(unsigned long clone_flags, unsigned long usp,
 108                 unsigned long ustk_size,
 109                 struct task_struct *p)
 110 {
 111         struct pt_regs *childregs;
 112 
 113         childregs = task_pt_regs(p);
 114 
 115         if (unlikely(p->flags & PF_KTHREAD)) {
 116                 /* case of  __kernel_thread: we return to supervisor space */
 117                 memset(childregs, 0, sizeof(struct pt_regs));
 118                 childregs->sp = (unsigned long)(childregs + 1);
 119                 p->thread.pc = (unsigned long) ret_from_kernel_thread;
 120                 childregs->a0 = usp;            /* function */
 121                 childregs->a1 = ustk_size;      /* argument */
 122         } else {
 123                 /* Otherwise use the given stack */
 124                 *childregs = *current_pt_regs();
 125                 if (usp)
 126                         childregs->sp = usp;
 127                 p->thread.pc = (unsigned long) ret_from_fork;
 128         }
 129 
 130         /* Set usp/ksp */
 131         p->thread.usp = childregs->sp;
 132         thread_saved_ksp(p) = (unsigned long)childregs - 8;
 133         p->thread.wchan = p->thread.pc;
 134 #ifdef __DSBT__
 135         {
 136                 unsigned long dp;
 137 
 138                 asm volatile ("mv .S2 b14,%0\n" : "=b"(dp));
 139 
 140                 thread_saved_dp(p) = dp;
 141                 if (usp == -1)
 142                         childregs->dp = dp;
 143         }
 144 #endif
 145         return 0;
 146 }
 147 
 148 unsigned long get_wchan(struct task_struct *p)
 149 {
 150         return p->thread.wchan;
 151 }

/* [<][>][^][v][top][bottom][index][help] */