linux/arch/sh/kernel/process.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/process.c
   3 *
   4 * This file handles the architecture-dependent parts of process handling..
   5 *
   6 *  Copyright (C) 1995  Linus Torvalds
   7 *
   8 *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
   9 *                   Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
  10 *                   Copyright (C) 2002 - 2007  Paul Mundt
  11 */
  12#include <linux/module.h>
  13#include <linux/mm.h>
  14#include <linux/elfcore.h>
  15#include <linux/pm.h>
  16#include <linux/kallsyms.h>
  17#include <linux/kexec.h>
  18#include <linux/kdebug.h>
  19#include <linux/tick.h>
  20#include <linux/reboot.h>
  21#include <linux/fs.h>
  22#include <linux/preempt.h>
  23#include <asm/uaccess.h>
  24#include <asm/mmu_context.h>
  25#include <asm/pgalloc.h>
  26#include <asm/system.h>
  27#include <asm/ubc.h>
  28
  29static int hlt_counter;
  30int ubc_usercnt = 0;
  31
  32void (*pm_idle)(void);
  33void (*pm_power_off)(void);
  34EXPORT_SYMBOL(pm_power_off);
  35
  36void disable_hlt(void)
  37{
  38        hlt_counter++;
  39}
  40EXPORT_SYMBOL(disable_hlt);
  41
  42void enable_hlt(void)
  43{
  44        hlt_counter--;
  45}
  46EXPORT_SYMBOL(enable_hlt);
  47
  48static int __init nohlt_setup(char *__unused)
  49{
  50        hlt_counter = 1;
  51        return 1;
  52}
  53__setup("nohlt", nohlt_setup);
  54
  55static int __init hlt_setup(char *__unused)
  56{
  57        hlt_counter = 0;
  58        return 1;
  59}
  60__setup("hlt", hlt_setup);
  61
  62void default_idle(void)
  63{
  64        if (!hlt_counter) {
  65                clear_thread_flag(TIF_POLLING_NRFLAG);
  66                smp_mb__after_clear_bit();
  67                set_bl_bit();
  68                while (!need_resched())
  69                        cpu_sleep();
  70                clear_bl_bit();
  71                set_thread_flag(TIF_POLLING_NRFLAG);
  72        } else
  73                while (!need_resched())
  74                        cpu_relax();
  75}
  76
  77void cpu_idle(void)
  78{
  79        set_thread_flag(TIF_POLLING_NRFLAG);
  80
  81        /* endless idle loop with no priority at all */
  82        while (1) {
  83                void (*idle)(void) = pm_idle;
  84
  85                if (!idle)
  86                        idle = default_idle;
  87
  88                tick_nohz_stop_sched_tick();
  89                while (!need_resched())
  90                        idle();
  91                tick_nohz_restart_sched_tick();
  92
  93                preempt_enable_no_resched();
  94                schedule();
  95                preempt_disable();
  96                check_pgt_cache();
  97        }
  98}
  99
 100void machine_restart(char * __unused)
 101{
 102        /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
 103        asm volatile("ldc %0, sr\n\t"
 104                     "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
 105}
 106
 107void machine_halt(void)
 108{
 109        local_irq_disable();
 110
 111        while (1)
 112                cpu_sleep();
 113}
 114
 115void machine_power_off(void)
 116{
 117        if (pm_power_off)
 118                pm_power_off();
 119}
 120
 121void show_regs(struct pt_regs * regs)
 122{
 123        printk("\n");
 124        printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm);
 125        print_symbol("PC is at %s\n", instruction_pointer(regs));
 126        printk("PC  : %08lx SP  : %08lx SR  : %08lx ",
 127               regs->pc, regs->regs[15], regs->sr);
 128#ifdef CONFIG_MMU
 129        printk("TEA : %08x    ", ctrl_inl(MMU_TEA));
 130#else
 131        printk("                  ");
 132#endif
 133        printk("%s\n", print_tainted());
 134
 135        printk("R0  : %08lx R1  : %08lx R2  : %08lx R3  : %08lx\n",
 136               regs->regs[0],regs->regs[1],
 137               regs->regs[2],regs->regs[3]);
 138        printk("R4  : %08lx R5  : %08lx R6  : %08lx R7  : %08lx\n",
 139               regs->regs[4],regs->regs[5],
 140               regs->regs[6],regs->regs[7]);
 141        printk("R8  : %08lx R9  : %08lx R10 : %08lx R11 : %08lx\n",
 142               regs->regs[8],regs->regs[9],
 143               regs->regs[10],regs->regs[11]);
 144        printk("R12 : %08lx R13 : %08lx R14 : %08lx\n",
 145               regs->regs[12],regs->regs[13],
 146               regs->regs[14]);
 147        printk("MACH: %08lx MACL: %08lx GBR : %08lx PR  : %08lx\n",
 148               regs->mach, regs->macl, regs->gbr, regs->pr);
 149
 150        show_trace(NULL, (unsigned long *)regs->regs[15], regs);
 151}
 152
 153/*
 154 * Create a kernel thread
 155 */
 156
 157/*
 158 * This is the mechanism for creating a new kernel thread.
 159 *
 160 */
 161extern void kernel_thread_helper(void);
 162__asm__(".align 5\n"
 163        "kernel_thread_helper:\n\t"
 164        "jsr    @r5\n\t"
 165        " nop\n\t"
 166        "mov.l  1f, r1\n\t"
 167        "jsr    @r1\n\t"
 168        " mov   r0, r4\n\t"
 169        ".align 2\n\t"
 170        "1:.long do_exit");
 171
 172/* Don't use this in BL=1(cli).  Or else, CPU resets! */
 173int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 174{
 175        struct pt_regs regs;
 176
 177        memset(&regs, 0, sizeof(regs));
 178        regs.regs[4] = (unsigned long)arg;
 179        regs.regs[5] = (unsigned long)fn;
 180
 181        regs.pc = (unsigned long)kernel_thread_helper;
 182        regs.sr = (1 << 30);
 183
 184        /* Ok, create the new process.. */
 185        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
 186                       &regs, 0, NULL, NULL);
 187}
 188
 189/*
 190 * Free current thread data structures etc..
 191 */
 192void exit_thread(void)
 193{
 194        if (current->thread.ubc_pc) {
 195                current->thread.ubc_pc = 0;
 196                ubc_usercnt -= 1;
 197        }
 198}
 199
 200void flush_thread(void)
 201{
 202#if defined(CONFIG_SH_FPU)
 203        struct task_struct *tsk = current;
 204        /* Forget lazy FPU state */
 205        clear_fpu(tsk, task_pt_regs(tsk));
 206        clear_used_math();
 207#endif
 208}
 209
 210void release_thread(struct task_struct *dead_task)
 211{
 212        /* do nothing */
 213}
 214
 215/* Fill in the fpu structure for a core dump.. */
 216int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 217{
 218        int fpvalid = 0;
 219
 220#if defined(CONFIG_SH_FPU)
 221        struct task_struct *tsk = current;
 222
 223        fpvalid = !!tsk_used_math(tsk);
 224        if (fpvalid) {
 225                unlazy_fpu(tsk, regs);
 226                memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
 227        }
 228#endif
 229
 230        return fpvalid;
 231}
 232
 233/*
 234 * Capture the user space registers if the task is not running (in user space)
 235 */
 236int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 237{
 238        struct pt_regs ptregs;
 239
 240        ptregs = *task_pt_regs(tsk);
 241        elf_core_copy_regs(regs, &ptregs);
 242
 243        return 1;
 244}
 245
 246int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu)
 247{
 248        int fpvalid = 0;
 249
 250#if defined(CONFIG_SH_FPU)
 251        fpvalid = !!tsk_used_math(tsk);
 252        if (fpvalid) {
 253                unlazy_fpu(tsk, task_pt_regs(tsk));
 254                memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
 255        }
 256#endif
 257
 258        return fpvalid;
 259}
 260
 261asmlinkage void ret_from_fork(void);
 262
 263int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 264                unsigned long unused,
 265                struct task_struct *p, struct pt_regs *regs)
 266{
 267        struct thread_info *ti = task_thread_info(p);
 268        struct pt_regs *childregs;
 269#if defined(CONFIG_SH_FPU)
 270        struct task_struct *tsk = current;
 271
 272        unlazy_fpu(tsk, regs);
 273        p->thread.fpu = tsk->thread.fpu;
 274        copy_to_stopped_child_used_math(p);
 275#endif
 276
 277        childregs = task_pt_regs(p);
 278        *childregs = *regs;
 279
 280        if (user_mode(regs)) {
 281                childregs->regs[15] = usp;
 282                ti->addr_limit = USER_DS;
 283        } else {
 284                childregs->regs[15] = (unsigned long)childregs;
 285                ti->addr_limit = KERNEL_DS;
 286        }
 287
 288        if (clone_flags & CLONE_SETTLS)
 289                childregs->gbr = childregs->regs[0];
 290
 291        childregs->regs[0] = 0; /* Set return value for child */
 292
 293        p->thread.sp = (unsigned long) childregs;
 294        p->thread.pc = (unsigned long) ret_from_fork;
 295
 296        p->thread.ubc_pc = 0;
 297
 298        return 0;
 299}
 300
 301/* Tracing by user break controller.  */
 302static void ubc_set_tracing(int asid, unsigned long pc)
 303{
 304#if defined(CONFIG_CPU_SH4A)
 305        unsigned long val;
 306
 307        val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
 308        val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
 309
 310        ctrl_outl(val, UBC_CBR0);
 311        ctrl_outl(pc,  UBC_CAR0);
 312        ctrl_outl(0x0, UBC_CAMR0);
 313        ctrl_outl(0x0, UBC_CBCR);
 314
 315        val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
 316        ctrl_outl(val, UBC_CRR0);
 317
 318        /* Read UBC register that we wrote last, for checking update */
 319        val = ctrl_inl(UBC_CRR0);
 320
 321#else   /* CONFIG_CPU_SH4A */
 322        ctrl_outl(pc, UBC_BARA);
 323
 324#ifdef CONFIG_MMU
 325        ctrl_outb(asid, UBC_BASRA);
 326#endif
 327
 328        ctrl_outl(0, UBC_BAMRA);
 329
 330        if (current_cpu_data.type == CPU_SH7729 ||
 331            current_cpu_data.type == CPU_SH7710 ||
 332            current_cpu_data.type == CPU_SH7712) {
 333                ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
 334                ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
 335        } else {
 336                ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
 337                ctrl_outw(BRCR_PCBA, UBC_BRCR);
 338        }
 339#endif  /* CONFIG_CPU_SH4A */
 340}
 341
 342/*
 343 *      switch_to(x,y) should switch tasks from x to y.
 344 *
 345 */
 346struct task_struct *__switch_to(struct task_struct *prev,
 347                                struct task_struct *next)
 348{
 349#if defined(CONFIG_SH_FPU)
 350        unlazy_fpu(prev, task_pt_regs(prev));
 351#endif
 352
 353#if defined(CONFIG_GUSA) && defined(CONFIG_PREEMPT)
 354        {
 355                struct pt_regs *regs;
 356
 357                preempt_disable();
 358                regs = task_pt_regs(prev);
 359                if (user_mode(regs) && regs->regs[15] >= 0xc0000000) {
 360                        int offset = (int)regs->regs[15];
 361
 362                        /* Reset stack pointer: clear critical region mark */
 363                        regs->regs[15] = regs->regs[1];
 364                        if (regs->pc < regs->regs[0])
 365                                /* Go to rewind point */
 366                                regs->pc = regs->regs[0] + offset;
 367                }
 368                preempt_enable_no_resched();
 369        }
 370#endif
 371
 372#ifdef CONFIG_MMU
 373        /*
 374         * Restore the kernel mode register
 375         *      k7 (r7_bank1)
 376         */
 377        asm volatile("ldc       %0, r7_bank"
 378                     : /* no output */
 379                     : "r" (task_thread_info(next)));
 380#endif
 381
 382        /* If no tasks are using the UBC, we're done */
 383        if (ubc_usercnt == 0)
 384                /* If no tasks are using the UBC, we're done */;
 385        else if (next->thread.ubc_pc && next->mm) {
 386                int asid = 0;
 387#ifdef CONFIG_MMU
 388                asid |= cpu_asid(smp_processor_id(), next->mm);
 389#endif
 390                ubc_set_tracing(asid, next->thread.ubc_pc);
 391        } else {
 392#if defined(CONFIG_CPU_SH4A)
 393                ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
 394                ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
 395#else
 396                ctrl_outw(0, UBC_BBRA);
 397                ctrl_outw(0, UBC_BBRB);
 398#endif
 399        }
 400
 401        return prev;
 402}
 403
 404asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
 405                        unsigned long r6, unsigned long r7,
 406                        struct pt_regs __regs)
 407{
 408#ifdef CONFIG_MMU
 409        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 410        return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
 411#else
 412        /* fork almost works, enough to trick you into looking elsewhere :-( */
 413        return -EINVAL;
 414#endif
 415}
 416
 417asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 418                         unsigned long parent_tidptr,
 419                         unsigned long child_tidptr,
 420                         struct pt_regs __regs)
 421{
 422        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 423        if (!newsp)
 424                newsp = regs->regs[15];
 425        return do_fork(clone_flags, newsp, regs, 0,
 426                        (int __user *)parent_tidptr,
 427                        (int __user *)child_tidptr);
 428}
 429
 430/*
 431 * This is trivial, and on the face of it looks like it
 432 * could equally well be done in user mode.
 433 *
 434 * Not so, for quite unobvious reasons - register pressure.
 435 * In user mode vfork() cannot have a stack frame, and if
 436 * done by calling the "clone()" system call directly, you
 437 * do not have enough call-clobbered registers to hold all
 438 * the information you need.
 439 */
 440asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
 441                         unsigned long r6, unsigned long r7,
 442                         struct pt_regs __regs)
 443{
 444        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 445        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
 446                       0, NULL, NULL);
 447}
 448
 449/*
 450 * sys_execve() executes a new program.
 451 */
 452asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
 453                          char __user * __user *uenvp, unsigned long r7,
 454                          struct pt_regs __regs)
 455{
 456        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 457        int error;
 458        char *filename;
 459
 460        filename = getname(ufilename);
 461        error = PTR_ERR(filename);
 462        if (IS_ERR(filename))
 463                goto out;
 464
 465        error = do_execve(filename, uargv, uenvp, regs);
 466        if (error == 0) {
 467                task_lock(current);
 468                current->ptrace &= ~PT_DTRACE;
 469                task_unlock(current);
 470        }
 471        putname(filename);
 472out:
 473        return error;
 474}
 475
 476unsigned long get_wchan(struct task_struct *p)
 477{
 478        unsigned long pc;
 479
 480        if (!p || p == current || p->state == TASK_RUNNING)
 481                return 0;
 482
 483        /*
 484         * The same comment as on the Alpha applies here, too ...
 485         */
 486        pc = thread_saved_pc(p);
 487
 488#ifdef CONFIG_FRAME_POINTER
 489        if (in_sched_functions(pc)) {
 490                unsigned long schedule_frame = (unsigned long)p->thread.sp;
 491                return ((unsigned long *)schedule_frame)[21];
 492        }
 493#endif
 494
 495        return pc;
 496}
 497
 498asmlinkage void break_point_trap(void)
 499{
 500        /* Clear tracing.  */
 501#if defined(CONFIG_CPU_SH4A)
 502        ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
 503        ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
 504#else
 505        ctrl_outw(0, UBC_BBRA);
 506        ctrl_outw(0, UBC_BBRB);
 507#endif
 508        current->thread.ubc_pc = 0;
 509        ubc_usercnt -= 1;
 510
 511        force_sig(SIGTRAP, current);
 512}
 513
 514/*
 515 * Generic trap handler.
 516 */
 517asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
 518                                   unsigned long r6, unsigned long r7,
 519                                   struct pt_regs __regs)
 520{
 521        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 522
 523        /* Rewind */
 524        regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 525
 526        if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
 527                       SIGTRAP) == NOTIFY_STOP)
 528                return;
 529
 530        force_sig(SIGTRAP, current);
 531}
 532
 533/*
 534 * Special handler for BUG() traps.
 535 */
 536asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
 537                                 unsigned long r6, unsigned long r7,
 538                                 struct pt_regs __regs)
 539{
 540        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 541
 542        /* Rewind */
 543        regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 544
 545        if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
 546                       SIGTRAP) == NOTIFY_STOP)
 547                return;
 548
 549#ifdef CONFIG_BUG
 550        if (__kernel_text_address(instruction_pointer(regs))) {
 551                u16 insn = *(u16 *)instruction_pointer(regs);
 552                if (insn == TRAPA_BUG_OPCODE)
 553                        handle_BUG(regs);
 554        }
 555#endif
 556
 557        force_sig(SIGTRAP, current);
 558}
 559