linux/arch/cris/arch-v32/kernel/process.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2000-2003  Axis Communications AB
   3 *
   4 *  Authors:   Bjorn Wesen (bjornw@axis.com)
   5 *             Mikael Starvik (starvik@axis.com)
   6 *             Tobias Anderberg (tobiasa@axis.com), CRISv32 port.
   7 *
   8 * This file handles the architecture-dependent parts of process handling..
   9 */
  10
  11#include <linux/sched.h>
  12#include <linux/err.h>
  13#include <linux/fs.h>
  14#include <linux/slab.h>
  15#include <hwregs/reg_rdwr.h>
  16#include <hwregs/reg_map.h>
  17#include <hwregs/timer_defs.h>
  18#include <hwregs/intr_vect_defs.h>
  19
  20extern void stop_watchdog(void);
  21
  22extern int cris_hlt_counter;
  23
  24/* We use this if we don't have any better idle routine. */
  25void default_idle(void)
  26{
  27        local_irq_disable();
  28        if (!need_resched() && !cris_hlt_counter) {
  29                /* Halt until exception. */
  30                __asm__ volatile("ei    \n\t"
  31                                 "halt      ");
  32        }
  33        local_irq_enable();
  34}
  35
  36/*
  37 * Free current thread data structures etc..
  38 */
  39
  40extern void deconfigure_bp(long pid);
  41void exit_thread(void)
  42{
  43        deconfigure_bp(current->pid);
  44}
  45
  46/*
  47 * If the watchdog is enabled, disable interrupts and enter an infinite loop.
  48 * The watchdog will reset the CPU after 0.1s. If the watchdog isn't enabled
  49 * then enable it and wait.
  50 */
  51extern void arch_enable_nmi(void);
  52
  53void
  54hard_reset_now(void)
  55{
  56        /*
  57         * Don't declare this variable elsewhere.  We don't want any other
  58         * code to know about it than the watchdog handler in entry.S and
  59         * this code, implementing hard reset through the watchdog.
  60         */
  61#if defined(CONFIG_ETRAX_WATCHDOG)
  62        extern int cause_of_death;
  63#endif
  64
  65        printk("*** HARD RESET ***\n");
  66        local_irq_disable();
  67
  68#if defined(CONFIG_ETRAX_WATCHDOG)
  69        cause_of_death = 0xbedead;
  70#else
  71{
  72        reg_timer_rw_wd_ctrl wd_ctrl = {0};
  73
  74        stop_watchdog();
  75
  76        wd_ctrl.key = 16;       /* Arbitrary key. */
  77        wd_ctrl.cnt = 1;        /* Minimum time. */
  78        wd_ctrl.cmd = regk_timer_start;
  79
  80        arch_enable_nmi();
  81        REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl);
  82}
  83#endif
  84
  85        while (1)
  86                ; /* Wait for reset. */
  87}
  88
  89/*
  90 * Return saved PC of a blocked thread.
  91 */
  92unsigned long thread_saved_pc(struct task_struct *t)
  93{
  94        return task_pt_regs(t)->erp;
  95}
  96
  97static void
  98kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
  99{
 100        fn(arg);
 101        do_exit(-1); /* Should never be called, return bad exit value. */
 102}
 103
 104/* Create a kernel thread. */
 105int
 106kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 107{
 108        struct pt_regs regs;
 109
 110        memset(&regs, 0, sizeof(regs));
 111
 112        /* Don't use r10 since that is set to 0 in copy_thread. */
 113        regs.r11 = (unsigned long) fn;
 114        regs.r12 = (unsigned long) arg;
 115        regs.erp = (unsigned long) kernel_thread_helper;
 116        regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
 117
 118        /* Create the new process. */
 119        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 120}
 121
 122/*
 123 * Setup the child's kernel stack with a pt_regs and call switch_stack() on it.
 124 * It will be unnested during _resume and _ret_from_sys_call when the new thread
 125 * is scheduled.
 126 *
 127 * Also setup the thread switching structure which is used to keep
 128 * thread-specific data during _resumes.
 129 */
 130
 131extern asmlinkage void ret_from_fork(void);
 132
 133int
 134copy_thread(unsigned long clone_flags, unsigned long usp,
 135        unsigned long unused,
 136        struct task_struct *p, struct pt_regs *regs)
 137{
 138        struct pt_regs *childregs;
 139        struct switch_stack *swstack;
 140
 141        /*
 142         * Put the pt_regs structure at the end of the new kernel stack page and
 143         * fix it up. Note: the task_struct doubles as the kernel stack for the
 144         * task.
 145         */
 146        childregs = task_pt_regs(p);
 147        *childregs = *regs;     /* Struct copy of pt_regs. */
 148        p->set_child_tid = p->clear_child_tid = NULL;
 149        childregs->r10 = 0;     /* Child returns 0 after a fork/clone. */
 150
 151        /* Set a new TLS ?
 152         * The TLS is in $mof beacuse it is the 5th argument to sys_clone.
 153         */
 154        if (p->mm && (clone_flags & CLONE_SETTLS)) {
 155                task_thread_info(p)->tls = regs->mof;
 156        }
 157
 158        /* Put the switch stack right below the pt_regs. */
 159        swstack = ((struct switch_stack *) childregs) - 1;
 160
 161        /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */
 162        swstack->r9 = 0;
 163
 164        /*
 165         * We want to return into ret_from_sys_call after the _resume.
 166         * ret_from_fork will call ret_from_sys_call.
 167         */
 168        swstack->return_ip = (unsigned long) ret_from_fork;
 169
 170        /* Fix the user-mode and kernel-mode stackpointer. */
 171        p->thread.usp = usp;
 172        p->thread.ksp = (unsigned long) swstack;
 173
 174        return 0;
 175}
 176
 177/*
 178 * Be aware of the "magic" 7th argument in the four system-calls below.
 179 * They need the latest stackframe, which is put as the 7th argument by
 180 * entry.S. The previous arguments are dummies or actually used, but need
 181 * to be defined to reach the 7th argument.
 182 *
 183 * N.B.: Another method to get the stackframe is to use current_regs(). But
 184 * it returns the latest stack-frame stacked when going from _user mode_ and
 185 * some of these (at least sys_clone) are called from kernel-mode sometimes
 186 * (for example during kernel_thread, above) and thus cannot use it. Thus,
 187 * to be sure not to get any surprises, we use the method for the other calls
 188 * as well.
 189 */
 190asmlinkage int
 191sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
 192        struct pt_regs *regs)
 193{
 194        return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
 195}
 196
 197/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
 198asmlinkage int
 199sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid,
 200        unsigned long tls, long srp, struct pt_regs *regs)
 201{
 202        if (!newusp)
 203                newusp = rdusp();
 204
 205        return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
 206}
 207
 208/*
 209 * vfork is a system call in i386 because of register-pressure - maybe
 210 * we can remove it and handle it in libc but we put it here until then.
 211 */
 212asmlinkage int
 213sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
 214        struct pt_regs *regs)
 215{
 216        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
 217}
 218
 219/* sys_execve() executes a new program. */
 220asmlinkage int
 221sys_execve(const char *fname, char **argv, char **envp, long r13, long mof, long srp,
 222        struct pt_regs *regs)
 223{
 224        int error;
 225        char *filename;
 226
 227        filename = getname(fname);
 228        error = PTR_ERR(filename);
 229
 230        if (IS_ERR(filename))
 231                goto out;
 232
 233        error = do_execve(filename, argv, envp, regs);
 234        putname(filename);
 235 out:
 236        return error;
 237}
 238
 239unsigned long
 240get_wchan(struct task_struct *p)
 241{
 242        /* TODO */
 243        return 0;
 244}
 245#undef last_sched
 246#undef first_sched
 247
 248void show_regs(struct pt_regs * regs)
 249{
 250        unsigned long usp = rdusp();
 251        printk("ERP: %08lx SRP: %08lx  CCS: %08lx USP: %08lx MOF: %08lx\n",
 252                regs->erp, regs->srp, regs->ccs, usp, regs->mof);
 253
 254        printk(" r0: %08lx  r1: %08lx   r2: %08lx  r3: %08lx\n",
 255                regs->r0, regs->r1, regs->r2, regs->r3);
 256
 257        printk(" r4: %08lx  r5: %08lx   r6: %08lx  r7: %08lx\n",
 258                regs->r4, regs->r5, regs->r6, regs->r7);
 259
 260        printk(" r8: %08lx  r9: %08lx  r10: %08lx r11: %08lx\n",
 261                regs->r8, regs->r9, regs->r10, regs->r11);
 262
 263        printk("r12: %08lx r13: %08lx oR10: %08lx\n",
 264                regs->r12, regs->r13, regs->orig_r10);
 265}
 266