linux/arch/arc/kernel/process.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * Amit Bhor, Kanika Nema: Codito Technologies 2004
   9 */
  10
  11#include <linux/errno.h>
  12#include <linux/module.h>
  13#include <linux/sched.h>
  14#include <linux/sched/task.h>
  15#include <linux/sched/task_stack.h>
  16
  17#include <linux/mm.h>
  18#include <linux/fs.h>
  19#include <linux/unistd.h>
  20#include <linux/ptrace.h>
  21#include <linux/slab.h>
  22#include <linux/syscalls.h>
  23#include <linux/elf.h>
  24#include <linux/tick.h>
  25
  26SYSCALL_DEFINE1(arc_settls, void *, user_tls_data_ptr)
  27{
  28        task_thread_info(current)->thr_ptr = (unsigned int)user_tls_data_ptr;
  29        return 0;
  30}
  31
  32/*
  33 * We return the user space TLS data ptr as sys-call return code
  34 * Ideally it should be copy to user.
  35 * However we can cheat by the fact that some sys-calls do return
  36 * absurdly high values
  37 * Since the tls dat aptr is not going to be in range of 0xFFFF_xxxx
  38 * it won't be considered a sys-call error
  39 * and it will be loads better than copy-to-user, which is a definite
  40 * D-TLB Miss
  41 */
  42SYSCALL_DEFINE0(arc_gettls)
  43{
  44        return task_thread_info(current)->thr_ptr;
  45}
  46
  47SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
  48{
  49        struct pt_regs *regs = current_pt_regs();
  50        int uval = -EFAULT;
  51
  52        /*
  53         * This is only for old cores lacking LLOCK/SCOND, which by defintion
  54         * can't possibly be SMP. Thus doesn't need to be SMP safe.
  55         * And this also helps reduce the overhead for serializing in
  56         * the UP case
  57         */
  58        WARN_ON_ONCE(IS_ENABLED(CONFIG_SMP));
  59
  60        /* Z indicates to userspace if operation succeded */
  61        regs->status32 &= ~STATUS_Z_MASK;
  62
  63        if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
  64                return -EFAULT;
  65
  66        preempt_disable();
  67
  68        if (__get_user(uval, uaddr))
  69                goto done;
  70
  71        if (uval == expected) {
  72                if (!__put_user(new, uaddr))
  73                        regs->status32 |= STATUS_Z_MASK;
  74        }
  75
  76done:
  77        preempt_enable();
  78
  79        return uval;
  80}
  81
  82#ifdef CONFIG_ISA_ARCV2
  83
  84void arch_cpu_idle(void)
  85{
  86        /* Re-enable interrupts <= default irq priority before commiting SLEEP */
  87        const unsigned int arg = 0x10 | ARCV2_IRQ_DEF_PRIO;
  88
  89        __asm__ __volatile__(
  90                "sleep %0       \n"
  91                :
  92                :"I"(arg)); /* can't be "r" has to be embedded const */
  93}
  94
  95#elif defined(CONFIG_EZNPS_MTM_EXT)     /* ARC700 variant in NPS */
  96
  97void arch_cpu_idle(void)
  98{
  99        /* only the calling HW thread needs to sleep */
 100        __asm__ __volatile__(
 101                ".word %0       \n"
 102                :
 103                :"i"(CTOP_INST_HWSCHD_WFT_IE12));
 104}
 105
 106#else   /* ARC700 */
 107
 108void arch_cpu_idle(void)
 109{
 110        /* sleep, but enable both set E1/E2 (levels of interrutps) before committing */
 111        __asm__ __volatile__("sleep 0x3 \n");
 112}
 113
 114#endif
 115
 116asmlinkage void ret_from_fork(void);
 117
 118/*
 119 * Copy architecture-specific thread state
 120 *
 121 * Layout of Child kernel mode stack as setup at the end of this function is
 122 *
 123 * |     ...        |
 124 * |     ...        |
 125 * |    unused      |
 126 * |                |
 127 * ------------------
 128 * |     r25        |   <==== top of Stack (thread.ksp)
 129 * ~                ~
 130 * |    --to--      |   (CALLEE Regs of kernel mode)
 131 * |     r13        |
 132 * ------------------
 133 * |     fp         |
 134 * |    blink       |   @ret_from_fork
 135 * ------------------
 136 * |                |
 137 * ~                ~
 138 * ~                ~
 139 * |                |
 140 * ------------------
 141 * |     r12        |
 142 * ~                ~
 143 * |    --to--      |   (scratch Regs of user mode)
 144 * |     r0         |
 145 * ------------------
 146 * |      SP        |
 147 * |    orig_r0     |
 148 * |    event/ECR   |
 149 * |    user_r25    |
 150 * ------------------  <===== END of PAGE
 151 */
 152int copy_thread(unsigned long clone_flags,
 153                unsigned long usp, unsigned long kthread_arg,
 154                struct task_struct *p)
 155{
 156        struct pt_regs *c_regs;        /* child's pt_regs */
 157        unsigned long *childksp;       /* to unwind out of __switch_to() */
 158        struct callee_regs *c_callee;  /* child's callee regs */
 159        struct callee_regs *parent_callee;  /* paren't callee */
 160        struct pt_regs *regs = current_pt_regs();
 161
 162        /* Mark the specific anchors to begin with (see pic above) */
 163        c_regs = task_pt_regs(p);
 164        childksp = (unsigned long *)c_regs - 2;  /* 2 words for FP/BLINK */
 165        c_callee = ((struct callee_regs *)childksp) - 1;
 166
 167        /*
 168         * __switch_to() uses thread.ksp to start unwinding stack
 169         * For kernel threads we don't need to create callee regs, the
 170         * stack layout nevertheless needs to remain the same.
 171         * Also, since __switch_to anyways unwinds callee regs, we use
 172         * this to populate kernel thread entry-pt/args into callee regs,
 173         * so that ret_from_kernel_thread() becomes simpler.
 174         */
 175        p->thread.ksp = (unsigned long)c_callee;        /* THREAD_KSP */
 176
 177        /* __switch_to expects FP(0), BLINK(return addr) at top */
 178        childksp[0] = 0;                        /* fp */
 179        childksp[1] = (unsigned long)ret_from_fork; /* blink */
 180
 181        if (unlikely(p->flags & PF_KTHREAD)) {
 182                memset(c_regs, 0, sizeof(struct pt_regs));
 183
 184                c_callee->r13 = kthread_arg;
 185                c_callee->r14 = usp;  /* function */
 186
 187                return 0;
 188        }
 189
 190        /*--------- User Task Only --------------*/
 191
 192        /* __switch_to expects FP(0), BLINK(return addr) at top of stack */
 193        childksp[0] = 0;                                /* for POP fp */
 194        childksp[1] = (unsigned long)ret_from_fork;     /* for POP blink */
 195
 196        /* Copy parents pt regs on child's kernel mode stack */
 197        *c_regs = *regs;
 198
 199        if (usp)
 200                c_regs->sp = usp;
 201
 202        c_regs->r0 = 0;         /* fork returns 0 in child */
 203
 204        parent_callee = ((struct callee_regs *)regs) - 1;
 205        *c_callee = *parent_callee;
 206
 207        if (unlikely(clone_flags & CLONE_SETTLS)) {
 208                /*
 209                 * set task's userland tls data ptr from 4th arg
 210                 * clone C-lib call is difft from clone sys-call
 211                 */
 212                task_thread_info(p)->thr_ptr = regs->r3;
 213        } else {
 214                /* Normal fork case: set parent's TLS ptr in child */
 215                task_thread_info(p)->thr_ptr =
 216                task_thread_info(current)->thr_ptr;
 217        }
 218
 219        return 0;
 220}
 221
 222/*
 223 * Do necessary setup to start up a new user task
 224 */
 225void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)
 226{
 227        regs->sp = usp;
 228        regs->ret = pc;
 229
 230        /*
 231         * [U]ser Mode bit set
 232         * [L] ZOL loop inhibited to begin with - cleared by a LP insn
 233         * Interrupts enabled
 234         */
 235        regs->status32 = STATUS_U_MASK | STATUS_L_MASK | ISA_INIT_STATUS_BITS;
 236
 237#ifdef CONFIG_EZNPS_MTM_EXT
 238        regs->eflags = 0;
 239#endif
 240
 241        /* bogus seed values for debugging */
 242        regs->lp_start = 0x10;
 243        regs->lp_end = 0x80;
 244}
 245
 246/*
 247 * Some archs flush debug and FPU info here
 248 */
 249void flush_thread(void)
 250{
 251}
 252
 253int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 254{
 255        return 0;
 256}
 257
 258int elf_check_arch(const struct elf32_hdr *x)
 259{
 260        unsigned int eflags;
 261
 262        if (x->e_machine != EM_ARC_INUSE) {
 263                pr_err("ELF not built for %s ISA\n",
 264                        is_isa_arcompact() ? "ARCompact":"ARCv2");
 265                return 0;
 266        }
 267
 268        eflags = x->e_flags;
 269        if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) {
 270                pr_err("ABI mismatch - you need newer toolchain\n");
 271                force_sigsegv(SIGSEGV, current);
 272                return 0;
 273        }
 274
 275        return 1;
 276}
 277EXPORT_SYMBOL(elf_check_arch);
 278