root/arch/riscv/kernel/process.c

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

DEFINITIONS

This source file includes following definitions.
  1. arch_cpu_idle
  2. show_regs
  3. start_thread
  4. flush_thread
  5. arch_dup_task_struct
  6. copy_thread_tls

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
   4  *  Chen Liqin <liqin.chen@sunplusct.com>
   5  *  Lennox Wu <lennox.wu@sunplusct.com>
   6  * Copyright (C) 2012 Regents of the University of California
   7  * Copyright (C) 2017 SiFive
   8  */
   9 
  10 #include <linux/cpu.h>
  11 #include <linux/kernel.h>
  12 #include <linux/sched.h>
  13 #include <linux/sched/task_stack.h>
  14 #include <linux/tick.h>
  15 #include <linux/ptrace.h>
  16 #include <linux/uaccess.h>
  17 
  18 #include <asm/unistd.h>
  19 #include <asm/processor.h>
  20 #include <asm/csr.h>
  21 #include <asm/string.h>
  22 #include <asm/switch_to.h>
  23 #include <asm/thread_info.h>
  24 
  25 extern asmlinkage void ret_from_fork(void);
  26 extern asmlinkage void ret_from_kernel_thread(void);
  27 
  28 void arch_cpu_idle(void)
  29 {
  30         wait_for_interrupt();
  31         local_irq_enable();
  32 }
  33 
  34 void show_regs(struct pt_regs *regs)
  35 {
  36         show_regs_print_info(KERN_DEFAULT);
  37 
  38         pr_cont("sepc: " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n",
  39                 regs->sepc, regs->ra, regs->sp);
  40         pr_cont(" gp : " REG_FMT " tp : " REG_FMT " t0 : " REG_FMT "\n",
  41                 regs->gp, regs->tp, regs->t0);
  42         pr_cont(" t1 : " REG_FMT " t2 : " REG_FMT " s0 : " REG_FMT "\n",
  43                 regs->t1, regs->t2, regs->s0);
  44         pr_cont(" s1 : " REG_FMT " a0 : " REG_FMT " a1 : " REG_FMT "\n",
  45                 regs->s1, regs->a0, regs->a1);
  46         pr_cont(" a2 : " REG_FMT " a3 : " REG_FMT " a4 : " REG_FMT "\n",
  47                 regs->a2, regs->a3, regs->a4);
  48         pr_cont(" a5 : " REG_FMT " a6 : " REG_FMT " a7 : " REG_FMT "\n",
  49                 regs->a5, regs->a6, regs->a7);
  50         pr_cont(" s2 : " REG_FMT " s3 : " REG_FMT " s4 : " REG_FMT "\n",
  51                 regs->s2, regs->s3, regs->s4);
  52         pr_cont(" s5 : " REG_FMT " s6 : " REG_FMT " s7 : " REG_FMT "\n",
  53                 regs->s5, regs->s6, regs->s7);
  54         pr_cont(" s8 : " REG_FMT " s9 : " REG_FMT " s10: " REG_FMT "\n",
  55                 regs->s8, regs->s9, regs->s10);
  56         pr_cont(" s11: " REG_FMT " t3 : " REG_FMT " t4 : " REG_FMT "\n",
  57                 regs->s11, regs->t3, regs->t4);
  58         pr_cont(" t5 : " REG_FMT " t6 : " REG_FMT "\n",
  59                 regs->t5, regs->t6);
  60 
  61         pr_cont("sstatus: " REG_FMT " sbadaddr: " REG_FMT " scause: " REG_FMT "\n",
  62                 regs->sstatus, regs->sbadaddr, regs->scause);
  63 }
  64 
  65 void start_thread(struct pt_regs *regs, unsigned long pc,
  66         unsigned long sp)
  67 {
  68         regs->sstatus = SR_SPIE;
  69         if (has_fpu) {
  70                 regs->sstatus |= SR_FS_INITIAL;
  71                 /*
  72                  * Restore the initial value to the FP register
  73                  * before starting the user program.
  74                  */
  75                 fstate_restore(current, regs);
  76         }
  77         regs->sepc = pc;
  78         regs->sp = sp;
  79         set_fs(USER_DS);
  80 }
  81 
  82 void flush_thread(void)
  83 {
  84 #ifdef CONFIG_FPU
  85         /*
  86          * Reset FPU state and context
  87          *      frm: round to nearest, ties to even (IEEE default)
  88          *      fflags: accrued exceptions cleared
  89          */
  90         fstate_off(current, task_pt_regs(current));
  91         memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
  92 #endif
  93 }
  94 
  95 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  96 {
  97         fstate_save(src, task_pt_regs(src));
  98         *dst = *src;
  99         return 0;
 100 }
 101 
 102 int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
 103         unsigned long arg, struct task_struct *p, unsigned long tls)
 104 {
 105         struct pt_regs *childregs = task_pt_regs(p);
 106 
 107         /* p->thread holds context to be restored by __switch_to() */
 108         if (unlikely(p->flags & PF_KTHREAD)) {
 109                 /* Kernel thread */
 110                 const register unsigned long gp __asm__ ("gp");
 111                 memset(childregs, 0, sizeof(struct pt_regs));
 112                 childregs->gp = gp;
 113                 childregs->sstatus = SR_SPP | SR_SPIE; /* Supervisor, irqs on */
 114 
 115                 p->thread.ra = (unsigned long)ret_from_kernel_thread;
 116                 p->thread.s[0] = usp; /* fn */
 117                 p->thread.s[1] = arg;
 118         } else {
 119                 *childregs = *(current_pt_regs());
 120                 if (usp) /* User fork */
 121                         childregs->sp = usp;
 122                 if (clone_flags & CLONE_SETTLS)
 123                         childregs->tp = tls;
 124                 childregs->a0 = 0; /* Return value of fork() */
 125                 p->thread.ra = (unsigned long)ret_from_fork;
 126         }
 127         p->thread.sp = (unsigned long)childregs; /* kernel sp */
 128         return 0;
 129 }

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