linux/arch/sparc/kernel/process_64.c
<<
>>
Prefs
   1/*  arch/sparc64/kernel/process.c
   2 *
   3 *  Copyright (C) 1995, 1996, 2008 David S. Miller (davem@davemloft.net)
   4 *  Copyright (C) 1996       Eddie C. Dost   (ecd@skynet.be)
   5 *  Copyright (C) 1997, 1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
   6 */
   7
   8/*
   9 * This file handles the architecture-dependent parts of process handling..
  10 */
  11
  12#include <stdarg.h>
  13
  14#include <linux/errno.h>
  15#include <linux/export.h>
  16#include <linux/sched.h>
  17#include <linux/kernel.h>
  18#include <linux/mm.h>
  19#include <linux/fs.h>
  20#include <linux/smp.h>
  21#include <linux/stddef.h>
  22#include <linux/ptrace.h>
  23#include <linux/slab.h>
  24#include <linux/user.h>
  25#include <linux/delay.h>
  26#include <linux/compat.h>
  27#include <linux/tick.h>
  28#include <linux/init.h>
  29#include <linux/cpu.h>
  30#include <linux/perf_event.h>
  31#include <linux/elfcore.h>
  32#include <linux/sysrq.h>
  33#include <linux/nmi.h>
  34#include <linux/context_tracking.h>
  35
  36#include <asm/uaccess.h>
  37#include <asm/page.h>
  38#include <asm/pgalloc.h>
  39#include <asm/pgtable.h>
  40#include <asm/processor.h>
  41#include <asm/pstate.h>
  42#include <asm/elf.h>
  43#include <asm/fpumacro.h>
  44#include <asm/head.h>
  45#include <asm/cpudata.h>
  46#include <asm/mmu_context.h>
  47#include <asm/unistd.h>
  48#include <asm/hypervisor.h>
  49#include <asm/syscalls.h>
  50#include <asm/irq_regs.h>
  51#include <asm/smp.h>
  52#include <asm/pcr.h>
  53
  54#include "kstack.h"
  55
  56/* Idle loop support on sparc64. */
  57void arch_cpu_idle(void)
  58{
  59        if (tlb_type != hypervisor) {
  60                touch_nmi_watchdog();
  61                local_irq_enable();
  62        } else {
  63                unsigned long pstate;
  64
  65                local_irq_enable();
  66
  67                /* The sun4v sleeping code requires that we have PSTATE.IE cleared over
  68                 * the cpu sleep hypervisor call.
  69                 */
  70                __asm__ __volatile__(
  71                        "rdpr %%pstate, %0\n\t"
  72                        "andn %0, %1, %0\n\t"
  73                        "wrpr %0, %%g0, %%pstate"
  74                        : "=&r" (pstate)
  75                        : "i" (PSTATE_IE));
  76
  77                if (!need_resched() && !cpu_is_offline(smp_processor_id()))
  78                        sun4v_cpu_yield();
  79
  80                /* Re-enable interrupts. */
  81                __asm__ __volatile__(
  82                        "rdpr %%pstate, %0\n\t"
  83                        "or %0, %1, %0\n\t"
  84                        "wrpr %0, %%g0, %%pstate"
  85                        : "=&r" (pstate)
  86                        : "i" (PSTATE_IE));
  87        }
  88}
  89
  90#ifdef CONFIG_HOTPLUG_CPU
  91void arch_cpu_idle_dead(void)
  92{
  93        sched_preempt_enable_no_resched();
  94        cpu_play_dead();
  95}
  96#endif
  97
  98#ifdef CONFIG_COMPAT
  99static void show_regwindow32(struct pt_regs *regs)
 100{
 101        struct reg_window32 __user *rw;
 102        struct reg_window32 r_w;
 103        mm_segment_t old_fs;
 104        
 105        __asm__ __volatile__ ("flushw");
 106        rw = compat_ptr((unsigned)regs->u_regs[14]);
 107        old_fs = get_fs();
 108        set_fs (USER_DS);
 109        if (copy_from_user (&r_w, rw, sizeof(r_w))) {
 110                set_fs (old_fs);
 111                return;
 112        }
 113
 114        set_fs (old_fs);                        
 115        printk("l0: %08x l1: %08x l2: %08x l3: %08x "
 116               "l4: %08x l5: %08x l6: %08x l7: %08x\n",
 117               r_w.locals[0], r_w.locals[1], r_w.locals[2], r_w.locals[3],
 118               r_w.locals[4], r_w.locals[5], r_w.locals[6], r_w.locals[7]);
 119        printk("i0: %08x i1: %08x i2: %08x i3: %08x "
 120               "i4: %08x i5: %08x i6: %08x i7: %08x\n",
 121               r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3],
 122               r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);
 123}
 124#else
 125#define show_regwindow32(regs)  do { } while (0)
 126#endif
 127
 128static void show_regwindow(struct pt_regs *regs)
 129{
 130        struct reg_window __user *rw;
 131        struct reg_window *rwk;
 132        struct reg_window r_w;
 133        mm_segment_t old_fs;
 134
 135        if ((regs->tstate & TSTATE_PRIV) || !(test_thread_flag(TIF_32BIT))) {
 136                __asm__ __volatile__ ("flushw");
 137                rw = (struct reg_window __user *)
 138                        (regs->u_regs[14] + STACK_BIAS);
 139                rwk = (struct reg_window *)
 140                        (regs->u_regs[14] + STACK_BIAS);
 141                if (!(regs->tstate & TSTATE_PRIV)) {
 142                        old_fs = get_fs();
 143                        set_fs (USER_DS);
 144                        if (copy_from_user (&r_w, rw, sizeof(r_w))) {
 145                                set_fs (old_fs);
 146                                return;
 147                        }
 148                        rwk = &r_w;
 149                        set_fs (old_fs);                        
 150                }
 151        } else {
 152                show_regwindow32(regs);
 153                return;
 154        }
 155        printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n",
 156               rwk->locals[0], rwk->locals[1], rwk->locals[2], rwk->locals[3]);
 157        printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n",
 158               rwk->locals[4], rwk->locals[5], rwk->locals[6], rwk->locals[7]);
 159        printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n",
 160               rwk->ins[0], rwk->ins[1], rwk->ins[2], rwk->ins[3]);
 161        printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n",
 162               rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]);
 163        if (regs->tstate & TSTATE_PRIV)
 164                printk("I7: <%pS>\n", (void *) rwk->ins[7]);
 165}
 166
 167void show_regs(struct pt_regs *regs)
 168{
 169        show_regs_print_info(KERN_DEFAULT);
 170
 171        printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x    %s\n", regs->tstate,
 172               regs->tpc, regs->tnpc, regs->y, print_tainted());
 173        printk("TPC: <%pS>\n", (void *) regs->tpc);
 174        printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
 175               regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
 176               regs->u_regs[3]);
 177        printk("g4: %016lx g5: %016lx g6: %016lx g7: %016lx\n",
 178               regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
 179               regs->u_regs[7]);
 180        printk("o0: %016lx o1: %016lx o2: %016lx o3: %016lx\n",
 181               regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
 182               regs->u_regs[11]);
 183        printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
 184               regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
 185               regs->u_regs[15]);
 186        printk("RPC: <%pS>\n", (void *) regs->u_regs[15]);
 187        show_regwindow(regs);
 188        show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]);
 189}
 190
 191union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
 192static DEFINE_SPINLOCK(global_cpu_snapshot_lock);
 193
 194static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
 195                              int this_cpu)
 196{
 197        struct global_reg_snapshot *rp;
 198
 199        flushw_all();
 200
 201        rp = &global_cpu_snapshot[this_cpu].reg;
 202
 203        rp->tstate = regs->tstate;
 204        rp->tpc = regs->tpc;
 205        rp->tnpc = regs->tnpc;
 206        rp->o7 = regs->u_regs[UREG_I7];
 207
 208        if (regs->tstate & TSTATE_PRIV) {
 209                struct reg_window *rw;
 210
 211                rw = (struct reg_window *)
 212                        (regs->u_regs[UREG_FP] + STACK_BIAS);
 213                if (kstack_valid(tp, (unsigned long) rw)) {
 214                        rp->i7 = rw->ins[7];
 215                        rw = (struct reg_window *)
 216                                (rw->ins[6] + STACK_BIAS);
 217                        if (kstack_valid(tp, (unsigned long) rw))
 218                                rp->rpc = rw->ins[7];
 219                }
 220        } else {
 221                rp->i7 = 0;
 222                rp->rpc = 0;
 223        }
 224        rp->thread = tp;
 225}
 226
 227/* In order to avoid hangs we do not try to synchronize with the
 228 * global register dump client cpus.  The last store they make is to
 229 * the thread pointer, so do a short poll waiting for that to become
 230 * non-NULL.
 231 */
 232static void __global_reg_poll(struct global_reg_snapshot *gp)
 233{
 234        int limit = 0;
 235
 236        while (!gp->thread && ++limit < 100) {
 237                barrier();
 238                udelay(1);
 239        }
 240}
 241
 242void arch_trigger_all_cpu_backtrace(bool include_self)
 243{
 244        struct thread_info *tp = current_thread_info();
 245        struct pt_regs *regs = get_irq_regs();
 246        unsigned long flags;
 247        int this_cpu, cpu;
 248
 249        if (!regs)
 250                regs = tp->kregs;
 251
 252        spin_lock_irqsave(&global_cpu_snapshot_lock, flags);
 253
 254        this_cpu = raw_smp_processor_id();
 255
 256        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 257
 258        if (include_self)
 259                __global_reg_self(tp, regs, this_cpu);
 260
 261        smp_fetch_global_regs();
 262
 263        for_each_online_cpu(cpu) {
 264                struct global_reg_snapshot *gp;
 265
 266                if (!include_self && cpu == this_cpu)
 267                        continue;
 268
 269                gp = &global_cpu_snapshot[cpu].reg;
 270
 271                __global_reg_poll(gp);
 272
 273                tp = gp->thread;
 274                printk("%c CPU[%3d]: TSTATE[%016lx] TPC[%016lx] TNPC[%016lx] TASK[%s:%d]\n",
 275                       (cpu == this_cpu ? '*' : ' '), cpu,
 276                       gp->tstate, gp->tpc, gp->tnpc,
 277                       ((tp && tp->task) ? tp->task->comm : "NULL"),
 278                       ((tp && tp->task) ? tp->task->pid : -1));
 279
 280                if (gp->tstate & TSTATE_PRIV) {
 281                        printk("             TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n",
 282                               (void *) gp->tpc,
 283                               (void *) gp->o7,
 284                               (void *) gp->i7,
 285                               (void *) gp->rpc);
 286                } else {
 287                        printk("             TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
 288                               gp->tpc, gp->o7, gp->i7, gp->rpc);
 289                }
 290
 291                touch_nmi_watchdog();
 292        }
 293
 294        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 295
 296        spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
 297}
 298
 299#ifdef CONFIG_MAGIC_SYSRQ
 300
 301static void sysrq_handle_globreg(int key)
 302{
 303        arch_trigger_all_cpu_backtrace(true);
 304}
 305
 306static struct sysrq_key_op sparc_globalreg_op = {
 307        .handler        = sysrq_handle_globreg,
 308        .help_msg       = "global-regs(y)",
 309        .action_msg     = "Show Global CPU Regs",
 310};
 311
 312static void __global_pmu_self(int this_cpu)
 313{
 314        struct global_pmu_snapshot *pp;
 315        int i, num;
 316
 317        if (!pcr_ops)
 318                return;
 319
 320        pp = &global_cpu_snapshot[this_cpu].pmu;
 321
 322        num = 1;
 323        if (tlb_type == hypervisor &&
 324            sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
 325                num = 4;
 326
 327        for (i = 0; i < num; i++) {
 328                pp->pcr[i] = pcr_ops->read_pcr(i);
 329                pp->pic[i] = pcr_ops->read_pic(i);
 330        }
 331}
 332
 333static void __global_pmu_poll(struct global_pmu_snapshot *pp)
 334{
 335        int limit = 0;
 336
 337        while (!pp->pcr[0] && ++limit < 100) {
 338                barrier();
 339                udelay(1);
 340        }
 341}
 342
 343static void pmu_snapshot_all_cpus(void)
 344{
 345        unsigned long flags;
 346        int this_cpu, cpu;
 347
 348        spin_lock_irqsave(&global_cpu_snapshot_lock, flags);
 349
 350        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 351
 352        this_cpu = raw_smp_processor_id();
 353
 354        __global_pmu_self(this_cpu);
 355
 356        smp_fetch_global_pmu();
 357
 358        for_each_online_cpu(cpu) {
 359                struct global_pmu_snapshot *pp = &global_cpu_snapshot[cpu].pmu;
 360
 361                __global_pmu_poll(pp);
 362
 363                printk("%c CPU[%3d]: PCR[%08lx:%08lx:%08lx:%08lx] PIC[%08lx:%08lx:%08lx:%08lx]\n",
 364                       (cpu == this_cpu ? '*' : ' '), cpu,
 365                       pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
 366                       pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
 367
 368                touch_nmi_watchdog();
 369        }
 370
 371        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 372
 373        spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
 374}
 375
 376static void sysrq_handle_globpmu(int key)
 377{
 378        pmu_snapshot_all_cpus();
 379}
 380
 381static struct sysrq_key_op sparc_globalpmu_op = {
 382        .handler        = sysrq_handle_globpmu,
 383        .help_msg       = "global-pmu(x)",
 384        .action_msg     = "Show Global PMU Regs",
 385};
 386
 387static int __init sparc_sysrq_init(void)
 388{
 389        int ret = register_sysrq_key('y', &sparc_globalreg_op);
 390
 391        if (!ret)
 392                ret = register_sysrq_key('x', &sparc_globalpmu_op);
 393        return ret;
 394}
 395
 396core_initcall(sparc_sysrq_init);
 397
 398#endif
 399
 400unsigned long thread_saved_pc(struct task_struct *tsk)
 401{
 402        struct thread_info *ti = task_thread_info(tsk);
 403        unsigned long ret = 0xdeadbeefUL;
 404        
 405        if (ti && ti->ksp) {
 406                unsigned long *sp;
 407                sp = (unsigned long *)(ti->ksp + STACK_BIAS);
 408                if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
 409                    sp[14]) {
 410                        unsigned long *fp;
 411                        fp = (unsigned long *)(sp[14] + STACK_BIAS);
 412                        if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
 413                                ret = fp[15];
 414                }
 415        }
 416        return ret;
 417}
 418
 419/* Free current thread data structures etc.. */
 420void exit_thread(void)
 421{
 422        struct thread_info *t = current_thread_info();
 423
 424        if (t->utraps) {
 425                if (t->utraps[0] < 2)
 426                        kfree (t->utraps);
 427                else
 428                        t->utraps[0]--;
 429        }
 430}
 431
 432void flush_thread(void)
 433{
 434        struct thread_info *t = current_thread_info();
 435        struct mm_struct *mm;
 436
 437        mm = t->task->mm;
 438        if (mm)
 439                tsb_context_switch(mm);
 440
 441        set_thread_wsaved(0);
 442
 443        /* Clear FPU register state. */
 444        t->fpsaved[0] = 0;
 445}
 446
 447/* It's a bit more tricky when 64-bit tasks are involved... */
 448static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
 449{
 450        bool stack_64bit = test_thread_64bit_stack(psp);
 451        unsigned long fp, distance, rval;
 452
 453        if (stack_64bit) {
 454                csp += STACK_BIAS;
 455                psp += STACK_BIAS;
 456                __get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
 457                fp += STACK_BIAS;
 458                if (test_thread_flag(TIF_32BIT))
 459                        fp &= 0xffffffff;
 460        } else
 461                __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
 462
 463        /* Now align the stack as this is mandatory in the Sparc ABI
 464         * due to how register windows work.  This hides the
 465         * restriction from thread libraries etc.
 466         */
 467        csp &= ~15UL;
 468
 469        distance = fp - psp;
 470        rval = (csp - distance);
 471        if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
 472                rval = 0;
 473        else if (!stack_64bit) {
 474                if (put_user(((u32)csp),
 475                             &(((struct reg_window32 __user *)rval)->ins[6])))
 476                        rval = 0;
 477        } else {
 478                if (put_user(((u64)csp - STACK_BIAS),
 479                             &(((struct reg_window __user *)rval)->ins[6])))
 480                        rval = 0;
 481                else
 482                        rval = rval - STACK_BIAS;
 483        }
 484
 485        return rval;
 486}
 487
 488/* Standard stuff. */
 489static inline void shift_window_buffer(int first_win, int last_win,
 490                                       struct thread_info *t)
 491{
 492        int i;
 493
 494        for (i = first_win; i < last_win; i++) {
 495                t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1];
 496                memcpy(&t->reg_window[i], &t->reg_window[i+1],
 497                       sizeof(struct reg_window));
 498        }
 499}
 500
 501void synchronize_user_stack(void)
 502{
 503        struct thread_info *t = current_thread_info();
 504        unsigned long window;
 505
 506        flush_user_windows();
 507        if ((window = get_thread_wsaved()) != 0) {
 508                window -= 1;
 509                do {
 510                        struct reg_window *rwin = &t->reg_window[window];
 511                        int winsize = sizeof(struct reg_window);
 512                        unsigned long sp;
 513
 514                        sp = t->rwbuf_stkptrs[window];
 515
 516                        if (test_thread_64bit_stack(sp))
 517                                sp += STACK_BIAS;
 518                        else
 519                                winsize = sizeof(struct reg_window32);
 520
 521                        if (!copy_to_user((char __user *)sp, rwin, winsize)) {
 522                                shift_window_buffer(window, get_thread_wsaved() - 1, t);
 523                                set_thread_wsaved(get_thread_wsaved() - 1);
 524                        }
 525                } while (window--);
 526        }
 527}
 528
 529static void stack_unaligned(unsigned long sp)
 530{
 531        siginfo_t info;
 532
 533        info.si_signo = SIGBUS;
 534        info.si_errno = 0;
 535        info.si_code = BUS_ADRALN;
 536        info.si_addr = (void __user *) sp;
 537        info.si_trapno = 0;
 538        force_sig_info(SIGBUS, &info, current);
 539}
 540
 541void fault_in_user_windows(void)
 542{
 543        struct thread_info *t = current_thread_info();
 544        unsigned long window;
 545
 546        flush_user_windows();
 547        window = get_thread_wsaved();
 548
 549        if (likely(window != 0)) {
 550                window -= 1;
 551                do {
 552                        struct reg_window *rwin = &t->reg_window[window];
 553                        int winsize = sizeof(struct reg_window);
 554                        unsigned long sp;
 555
 556                        sp = t->rwbuf_stkptrs[window];
 557
 558                        if (test_thread_64bit_stack(sp))
 559                                sp += STACK_BIAS;
 560                        else
 561                                winsize = sizeof(struct reg_window32);
 562
 563                        if (unlikely(sp & 0x7UL))
 564                                stack_unaligned(sp);
 565
 566                        if (unlikely(copy_to_user((char __user *)sp,
 567                                                  rwin, winsize)))
 568                                goto barf;
 569                } while (window--);
 570        }
 571        set_thread_wsaved(0);
 572        return;
 573
 574barf:
 575        set_thread_wsaved(window + 1);
 576        user_exit();
 577        do_exit(SIGILL);
 578}
 579
 580asmlinkage long sparc_do_fork(unsigned long clone_flags,
 581                              unsigned long stack_start,
 582                              struct pt_regs *regs,
 583                              unsigned long stack_size)
 584{
 585        int __user *parent_tid_ptr, *child_tid_ptr;
 586        unsigned long orig_i1 = regs->u_regs[UREG_I1];
 587        long ret;
 588
 589#ifdef CONFIG_COMPAT
 590        if (test_thread_flag(TIF_32BIT)) {
 591                parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]);
 592                child_tid_ptr = compat_ptr(regs->u_regs[UREG_I4]);
 593        } else
 594#endif
 595        {
 596                parent_tid_ptr = (int __user *) regs->u_regs[UREG_I2];
 597                child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
 598        }
 599
 600        ret = do_fork(clone_flags, stack_start, stack_size,
 601                      parent_tid_ptr, child_tid_ptr);
 602
 603        /* If we get an error and potentially restart the system
 604         * call, we're screwed because copy_thread() clobbered
 605         * the parent's %o1.  So detect that case and restore it
 606         * here.
 607         */
 608        if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
 609                regs->u_regs[UREG_I1] = orig_i1;
 610
 611        return ret;
 612}
 613
 614/* Copy a Sparc thread.  The fork() return value conventions
 615 * under SunOS are nothing short of bletcherous:
 616 * Parent -->  %o0 == childs  pid, %o1 == 0
 617 * Child  -->  %o0 == parents pid, %o1 == 1
 618 */
 619int copy_thread(unsigned long clone_flags, unsigned long sp,
 620                unsigned long arg, struct task_struct *p)
 621{
 622        struct thread_info *t = task_thread_info(p);
 623        struct pt_regs *regs = current_pt_regs();
 624        struct sparc_stackf *parent_sf;
 625        unsigned long child_stack_sz;
 626        char *child_trap_frame;
 627
 628        /* Calculate offset to stack_frame & pt_regs */
 629        child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);
 630        child_trap_frame = (task_stack_page(p) +
 631                            (THREAD_SIZE - child_stack_sz));
 632
 633        t->new_child = 1;
 634        t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
 635        t->kregs = (struct pt_regs *) (child_trap_frame +
 636                                       sizeof(struct sparc_stackf));
 637        t->fpsaved[0] = 0;
 638
 639        if (unlikely(p->flags & PF_KTHREAD)) {
 640                memset(child_trap_frame, 0, child_stack_sz);
 641                __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 
 642                        (current_pt_regs()->tstate + 1) & TSTATE_CWP;
 643                t->current_ds = ASI_P;
 644                t->kregs->u_regs[UREG_G1] = sp; /* function */
 645                t->kregs->u_regs[UREG_G2] = arg;
 646                return 0;
 647        }
 648
 649        parent_sf = ((struct sparc_stackf *) regs) - 1;
 650        memcpy(child_trap_frame, parent_sf, child_stack_sz);
 651        if (t->flags & _TIF_32BIT) {
 652                sp &= 0x00000000ffffffffUL;
 653                regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 654        }
 655        t->kregs->u_regs[UREG_FP] = sp;
 656        __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 
 657                (regs->tstate + 1) & TSTATE_CWP;
 658        t->current_ds = ASI_AIUS;
 659        if (sp != regs->u_regs[UREG_FP]) {
 660                unsigned long csp;
 661
 662                csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
 663                if (!csp)
 664                        return -EFAULT;
 665                t->kregs->u_regs[UREG_FP] = csp;
 666        }
 667        if (t->utraps)
 668                t->utraps[0]++;
 669
 670        /* Set the return value for the child. */
 671        t->kregs->u_regs[UREG_I0] = current->pid;
 672        t->kregs->u_regs[UREG_I1] = 1;
 673
 674        /* Set the second return value for the parent. */
 675        regs->u_regs[UREG_I1] = 0;
 676
 677        if (clone_flags & CLONE_SETTLS)
 678                t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3];
 679
 680        return 0;
 681}
 682
 683typedef struct {
 684        union {
 685                unsigned int    pr_regs[32];
 686                unsigned long   pr_dregs[16];
 687        } pr_fr;
 688        unsigned int __unused;
 689        unsigned int    pr_fsr;
 690        unsigned char   pr_qcnt;
 691        unsigned char   pr_q_entrysize;
 692        unsigned char   pr_en;
 693        unsigned int    pr_q[64];
 694} elf_fpregset_t32;
 695
 696/*
 697 * fill in the fpu structure for a core dump.
 698 */
 699int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 700{
 701        unsigned long *kfpregs = current_thread_info()->fpregs;
 702        unsigned long fprs = current_thread_info()->fpsaved[0];
 703
 704        if (test_thread_flag(TIF_32BIT)) {
 705                elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
 706
 707                if (fprs & FPRS_DL)
 708                        memcpy(&fpregs32->pr_fr.pr_regs[0], kfpregs,
 709                               sizeof(unsigned int) * 32);
 710                else
 711                        memset(&fpregs32->pr_fr.pr_regs[0], 0,
 712                               sizeof(unsigned int) * 32);
 713                fpregs32->pr_qcnt = 0;
 714                fpregs32->pr_q_entrysize = 8;
 715                memset(&fpregs32->pr_q[0], 0,
 716                       (sizeof(unsigned int) * 64));
 717                if (fprs & FPRS_FEF) {
 718                        fpregs32->pr_fsr = (unsigned int) current_thread_info()->xfsr[0];
 719                        fpregs32->pr_en = 1;
 720                } else {
 721                        fpregs32->pr_fsr = 0;
 722                        fpregs32->pr_en = 0;
 723                }
 724        } else {
 725                if(fprs & FPRS_DL)
 726                        memcpy(&fpregs->pr_regs[0], kfpregs,
 727                               sizeof(unsigned int) * 32);
 728                else
 729                        memset(&fpregs->pr_regs[0], 0,
 730                               sizeof(unsigned int) * 32);
 731                if(fprs & FPRS_DU)
 732                        memcpy(&fpregs->pr_regs[16], kfpregs+16,
 733                               sizeof(unsigned int) * 32);
 734                else
 735                        memset(&fpregs->pr_regs[16], 0,
 736                               sizeof(unsigned int) * 32);
 737                if(fprs & FPRS_FEF) {
 738                        fpregs->pr_fsr = current_thread_info()->xfsr[0];
 739                        fpregs->pr_gsr = current_thread_info()->gsr[0];
 740                } else {
 741                        fpregs->pr_fsr = fpregs->pr_gsr = 0;
 742                }
 743                fpregs->pr_fprs = fprs;
 744        }
 745        return 1;
 746}
 747EXPORT_SYMBOL(dump_fpu);
 748
 749unsigned long get_wchan(struct task_struct *task)
 750{
 751        unsigned long pc, fp, bias = 0;
 752        struct thread_info *tp;
 753        struct reg_window *rw;
 754        unsigned long ret = 0;
 755        int count = 0; 
 756
 757        if (!task || task == current ||
 758            task->state == TASK_RUNNING)
 759                goto out;
 760
 761        tp = task_thread_info(task);
 762        bias = STACK_BIAS;
 763        fp = task_thread_info(task)->ksp + bias;
 764
 765        do {
 766                if (!kstack_valid(tp, fp))
 767                        break;
 768                rw = (struct reg_window *) fp;
 769                pc = rw->ins[7];
 770                if (!in_sched_functions(pc)) {
 771                        ret = pc;
 772                        goto out;
 773                }
 774                fp = rw->ins[6] + bias;
 775        } while (++count < 16);
 776
 777out:
 778        return ret;
 779}
 780