process.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:22k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*  $Id: process.c,v 1.125.2.1 2001/12/18 19:40:17 davem Exp $
  2.  *  arch/sparc64/kernel/process.c
  3.  *
  4.  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
  5.  *  Copyright (C) 1996       Eddie C. Dost   (ecd@skynet.be)
  6.  *  Copyright (C) 1997, 1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
  7.  */
  8. /*
  9.  * This file handles the architecture-dependent parts of process handling..
  10.  */
  11. #define __KERNEL_SYSCALLS__
  12. #include <stdarg.h>
  13. #include <linux/errno.h>
  14. #include <linux/sched.h>
  15. #include <linux/kernel.h>
  16. #include <linux/mm.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/stddef.h>
  20. #include <linux/unistd.h>
  21. #include <linux/ptrace.h>
  22. #include <linux/slab.h>
  23. #include <linux/user.h>
  24. #include <linux/a.out.h>
  25. #include <linux/config.h>
  26. #include <linux/reboot.h>
  27. #include <linux/delay.h>
  28. #include <asm/oplib.h>
  29. #include <asm/uaccess.h>
  30. #include <asm/system.h>
  31. #include <asm/page.h>
  32. #include <asm/pgalloc.h>
  33. #include <asm/pgtable.h>
  34. #include <asm/processor.h>
  35. #include <asm/pstate.h>
  36. #include <asm/elf.h>
  37. #include <asm/fpumacro.h>
  38. /* #define VERBOSE_SHOWREGS */
  39. #ifndef CONFIG_SMP
  40. /*
  41.  * the idle loop on a Sparc... ;)
  42.  */
  43. int cpu_idle(void)
  44. {
  45. if (current->pid != 0)
  46. return -EPERM;
  47. /* endless idle loop with no priority at all */
  48. current->nice = 20;
  49. current->counter = -100;
  50. init_idle();
  51. for (;;) {
  52. /* If current->need_resched is zero we should really
  53.  * setup for a system wakup event and execute a shutdown
  54.  * instruction.
  55.  *
  56.  * But this requires writing back the contents of the
  57.  * L2 cache etc. so implement this later. -DaveM
  58.  */
  59. while (!current->need_resched)
  60. barrier();
  61. schedule();
  62. check_pgt_cache();
  63. }
  64. return 0;
  65. }
  66. #else
  67. /*
  68.  * the idle loop on a UltraMultiPenguin...
  69.  */
  70. #define idle_me_harder() (cpu_data[current->processor].idle_volume += 1)
  71. #define unidle_me() (cpu_data[current->processor].idle_volume = 0)
  72. int cpu_idle(void)
  73. {
  74. current->nice = 20;
  75. current->counter = -100;
  76. init_idle();
  77. while(1) {
  78. if (current->need_resched != 0) {
  79. unidle_me();
  80. schedule();
  81. check_pgt_cache();
  82. }
  83. idle_me_harder();
  84. /* The store ordering is so that IRQ handlers on
  85.  * other cpus see our increasing idleness for the buddy
  86.  * redistribution algorithm.  -DaveM
  87.  */
  88. membar("#StoreStore | #StoreLoad");
  89. }
  90. }
  91. #endif
  92. extern char reboot_command [];
  93. #ifdef CONFIG_SUN_CONSOLE
  94. extern void (*prom_palette)(int);
  95. extern int serial_console;
  96. #endif
  97. extern void (*prom_keyboard)(void);
  98. void machine_halt(void)
  99. {
  100. sti();
  101. mdelay(8);
  102. cli();
  103. #ifdef CONFIG_SUN_CONSOLE
  104. if (!serial_console && prom_palette)
  105. prom_palette (1);
  106. #endif
  107. if (prom_keyboard)
  108. prom_keyboard();
  109. prom_halt();
  110. panic("Halt failed!");
  111. }
  112. void machine_restart(char * cmd)
  113. {
  114. char *p;
  115. sti();
  116. mdelay(8);
  117. cli();
  118. p = strchr (reboot_command, 'n');
  119. if (p) *p = 0;
  120. #ifdef CONFIG_SUN_CONSOLE
  121. if (!serial_console && prom_palette)
  122. prom_palette (1);
  123. #endif
  124. if (prom_keyboard)
  125. prom_keyboard();
  126. if (cmd)
  127. prom_reboot(cmd);
  128. if (*reboot_command)
  129. prom_reboot(reboot_command);
  130. prom_reboot("");
  131. panic("Reboot failed!");
  132. }
  133. static void show_regwindow32(struct pt_regs *regs)
  134. {
  135. struct reg_window32 *rw;
  136. struct reg_window32 r_w;
  137. mm_segment_t old_fs;
  138. __asm__ __volatile__ ("flushw");
  139. rw = (struct reg_window32 *)((long)(unsigned)regs->u_regs[14]);
  140. old_fs = get_fs();
  141. set_fs (USER_DS);
  142. if (copy_from_user (&r_w, rw, sizeof(r_w))) {
  143. set_fs (old_fs);
  144. return;
  145. }
  146. rw = &r_w;
  147. set_fs (old_fs);
  148. printk("l0: %08x l1: %08x l2: %08x l3: %08x "
  149.        "l4: %08x l5: %08x l6: %08x l7: %08xn",
  150.        rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
  151.        rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
  152. printk("i0: %08x i1: %08x i2: %08x i3: %08x "
  153.        "i4: %08x i5: %08x i6: %08x i7: %08xn",
  154.        rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
  155.        rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
  156. }
  157. static void show_regwindow(struct pt_regs *regs)
  158. {
  159. struct reg_window *rw;
  160. struct reg_window r_w;
  161. mm_segment_t old_fs;
  162. if ((regs->tstate & TSTATE_PRIV) || !(current->thread.flags & SPARC_FLAG_32BIT)) {
  163. __asm__ __volatile__ ("flushw");
  164. rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS);
  165. if (!(regs->tstate & TSTATE_PRIV)) {
  166. old_fs = get_fs();
  167. set_fs (USER_DS);
  168. if (copy_from_user (&r_w, rw, sizeof(r_w))) {
  169. set_fs (old_fs);
  170. return;
  171. }
  172. rw = &r_w;
  173. set_fs (old_fs);
  174. }
  175. } else {
  176. show_regwindow32(regs);
  177. return;
  178. }
  179. printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lxn",
  180.        rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3]);
  181. printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lxn",
  182.        rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
  183. printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lxn",
  184.        rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3]);
  185. printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lxn",
  186.        rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
  187. }
  188. void show_stackframe(struct sparc_stackf *sf)
  189. {
  190. unsigned long size;
  191. unsigned long *stk;
  192. int i;
  193. printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lxn"
  194.        "l4: %016lx l5: %016lx l6: %016lx l7: %016lxn",
  195.        sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3],
  196.        sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
  197. printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lxn"
  198.        "i4: %016lx i5: %016lx fp: %016lx ret_pc: %016lxn",
  199.        sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3],
  200.        sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc);
  201. printk("sp: %016lx x0: %016lx x1: %016lx x2: %016lxn"
  202.        "x3: %016lx x4: %016lx x5: %016lx xx: %016lxn",
  203.        (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1],
  204.        sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
  205.        sf->xxargs[0]);
  206. size = ((unsigned long)sf->fp) - ((unsigned long)sf);
  207. size -= STACKFRAME_SZ;
  208. stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ);
  209. i = 0;
  210. do {
  211. printk("s%d: %016lxn", i++, *stk++);
  212. } while ((size -= sizeof(unsigned long)));
  213. }
  214. void show_stackframe32(struct sparc_stackf32 *sf)
  215. {
  216. unsigned long size;
  217. unsigned *stk;
  218. int i;
  219. printk("l0: %08x l1: %08x l2: %08x l3: %08xn",
  220.        sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3]);
  221. printk("l4: %08x l5: %08x l6: %08x l7: %08xn",
  222.        sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
  223. printk("i0: %08x i1: %08x i2: %08x i3: %08xn",
  224.        sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3]);
  225. printk("i4: %08x i5: %08x fp: %08x ret_pc: %08xn",
  226.        sf->ins[4], sf->ins[5], sf->fp, sf->callers_pc);
  227. printk("sp: %08x x0: %08x x1: %08x x2: %08xn"
  228.        "x3: %08x x4: %08x x5: %08x xx: %08xn",
  229.        sf->structptr, sf->xargs[0], sf->xargs[1],
  230.        sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
  231.        sf->xxargs[0]);
  232. size = ((unsigned long)sf->fp) - ((unsigned long)sf);
  233. size -= STACKFRAME32_SZ;
  234. stk = (unsigned *)((unsigned long)sf + STACKFRAME32_SZ);
  235. i = 0;
  236. do {
  237. printk("s%d: %08xn", i++, *stk++);
  238. } while ((size -= sizeof(unsigned)));
  239. }
  240. #ifdef CONFIG_SMP
  241. static spinlock_t regdump_lock = SPIN_LOCK_UNLOCKED;
  242. #endif
  243. void __show_regs(struct pt_regs * regs)
  244. {
  245. #ifdef CONFIG_SMP
  246. unsigned long flags;
  247. /* Protect against xcall ipis which might lead to livelock on the lock */
  248. __asm__ __volatile__("rdpr      %%pstate, %0nt"
  249.      "wrpr      %0, %1, %%pstate"
  250.      : "=r" (flags)
  251.      : "i" (PSTATE_IE));
  252. spin_lock(&regdump_lock);
  253. printk("CPU[%d]: local_irq_count[%u] irqs_running[%d]n",
  254.        smp_processor_id(),
  255.        local_irq_count(smp_processor_id()),
  256.        irqs_running());
  257. #endif
  258. printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x    %sn", regs->tstate,
  259.        regs->tpc, regs->tnpc, regs->y, print_tainted());
  260. printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lxn",
  261.        regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
  262.        regs->u_regs[3]);
  263. printk("g4: %016lx g5: %016lx g6: %016lx g7: %016lxn",
  264.        regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
  265.        regs->u_regs[7]);
  266. printk("o0: %016lx o1: %016lx o2: %016lx o3: %016lxn",
  267.        regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
  268.        regs->u_regs[11]);
  269. printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lxn",
  270.        regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
  271.        regs->u_regs[15]);
  272. show_regwindow(regs);
  273. #ifdef CONFIG_SMP
  274. spin_unlock(&regdump_lock);
  275. __asm__ __volatile__("wrpr %0, 0, %%pstate"
  276.      : : "r" (flags));
  277. #endif
  278. }
  279. #ifdef VERBOSE_SHOWREGS
  280. static void idump_from_user (unsigned int *pc)
  281. {
  282. int i;
  283. int code;
  284. if((((unsigned long) pc) & 3))
  285. return;
  286. pc -= 3;
  287. for(i = -3; i < 6; i++) {
  288. get_user(code, pc);
  289. printk("%c%08x%c",i?' ':'<',code,i?' ':'>');
  290. pc++;
  291. }
  292. printk("n");
  293. }
  294. #endif
  295. void show_regs(struct pt_regs *regs)
  296. {
  297. #ifdef VERBOSE_SHOWREGS
  298. extern long etrap, etraptl1;
  299. #endif
  300. __show_regs(regs);
  301. #ifdef CONFIG_SMP
  302. {
  303. extern void smp_report_regs(void);
  304. smp_report_regs();
  305. }
  306. #endif
  307. #ifdef VERBOSE_SHOWREGS
  308. if (regs->tpc >= &etrap && regs->tpc < &etraptl1 &&
  309.     regs->u_regs[14] >= (long)current - PAGE_SIZE &&
  310.     regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) {
  311. printk ("*********parent**********n");
  312. __show_regs((struct pt_regs *)(regs->u_regs[14] + STACK_BIAS + REGWIN_SZ));
  313. idump_from_user(((struct pt_regs *)(regs->u_regs[14] + STACK_BIAS + REGWIN_SZ))->tpc);
  314. printk ("*********endpar**********n");
  315. }
  316. #endif
  317. }
  318. void show_regs32(struct pt_regs32 *regs)
  319. {
  320. printk("PSR: %08x PC: %08x NPC: %08x Y: %08x    %sn", regs->psr,
  321.        regs->pc, regs->npc, regs->y, print_tainted());
  322. printk("g0: %08x g1: %08x g2: %08x g3: %08x ",
  323.        regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
  324.        regs->u_regs[3]);
  325. printk("g4: %08x g5: %08x g6: %08x g7: %08xn",
  326.        regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
  327.        regs->u_regs[7]);
  328. printk("o0: %08x o1: %08x o2: %08x o3: %08x ",
  329.        regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
  330.        regs->u_regs[11]);
  331. printk("o4: %08x o5: %08x sp: %08x ret_pc: %08xn",
  332.        regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
  333.        regs->u_regs[15]);
  334. }
  335. void show_thread(struct thread_struct *thread)
  336. {
  337. int i;
  338. #if 0
  339. printk("kregs:             0x%016lxn", (unsigned long)thread->kregs);
  340. show_regs(thread->kregs);
  341. #endif
  342. printk("ksp:               0x%016lxn", thread->ksp);
  343. if (thread->w_saved) {
  344. for (i = 0; i < NSWINS; i++) {
  345. if (!thread->rwbuf_stkptrs[i])
  346. continue;
  347. printk("reg_window[%d]:n", i);
  348. printk("stack ptr:         0x%016lxn", thread->rwbuf_stkptrs[i]);
  349. }
  350. printk("w_saved:           0x%04xn", thread->w_saved);
  351. }
  352. printk("flags:             0x%08xn", thread->flags);
  353. printk("current_ds:        0x%xn", thread->current_ds.seg);
  354. }
  355. /* Free current thread data structures etc.. */
  356. void exit_thread(void)
  357. {
  358. struct thread_struct *t = &current->thread;
  359. if (t->utraps) {
  360. if (t->utraps[0] < 2)
  361. kfree (t->utraps);
  362. else
  363. t->utraps[0]--;
  364. }
  365. /* Turn off performance counters if on. */
  366. if (t->flags & SPARC_FLAG_PERFCTR) {
  367. t->user_cntd0 = t->user_cntd1 = NULL;
  368. t->pcr_reg = 0;
  369. t->flags &= ~(SPARC_FLAG_PERFCTR);
  370. write_pcr(0);
  371. }
  372. }
  373. void flush_thread(void)
  374. {
  375. struct thread_struct *t = &current->thread;
  376. if (current->mm) {
  377. if (t->flags & SPARC_FLAG_32BIT) {
  378. struct mm_struct *mm = current->mm;
  379. pgd_t *pgd0 = &mm->pgd[0];
  380. unsigned long pgd_cache;
  381. if (pgd_none(*pgd0)) {
  382. pmd_t *page = pmd_alloc_one_fast(NULL, 0);
  383. if (!page)
  384. page = pmd_alloc_one(NULL, 0);
  385. pgd_set(pgd0, page);
  386. }
  387. pgd_cache = pgd_val(*pgd0) << 11UL;
  388. __asm__ __volatile__("stxa %0, [%1] %2nt"
  389.      "membar #Sync"
  390.      : /* no outputs */
  391.      : "r" (pgd_cache),
  392.        "r" (TSB_REG),
  393.        "i" (ASI_DMMU));
  394. }
  395. }
  396. t->w_saved = 0;
  397. /* Turn off performance counters if on. */
  398. if (t->flags & SPARC_FLAG_PERFCTR) {
  399. t->user_cntd0 = t->user_cntd1 = NULL;
  400. t->pcr_reg = 0;
  401. t->flags &= ~(SPARC_FLAG_PERFCTR);
  402. write_pcr(0);
  403. }
  404. /* Clear FPU register state. */
  405. t->fpsaved[0] = 0;
  406. if (t->current_ds.seg != ASI_AIUS)
  407. set_fs(USER_DS);
  408. /* Init new signal delivery disposition. */
  409. t->flags &= ~SPARC_FLAG_NEWSIGNALS;
  410. }
  411. /* It's a bit more tricky when 64-bit tasks are involved... */
  412. static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
  413. {
  414. unsigned long fp, distance, rval;
  415. if (!(current->thread.flags & SPARC_FLAG_32BIT)) {
  416. csp += STACK_BIAS;
  417. psp += STACK_BIAS;
  418. __get_user(fp, &(((struct reg_window *)psp)->ins[6]));
  419. fp += STACK_BIAS;
  420. } else
  421. __get_user(fp, &(((struct reg_window32 *)psp)->ins[6]));
  422. /* Now 8-byte align the stack as this is mandatory in the
  423.  * Sparc ABI due to how register windows work.  This hides
  424.  * the restriction from thread libraries etc.  -DaveM
  425.  */
  426. csp &= ~7UL;
  427. distance = fp - psp;
  428. rval = (csp - distance);
  429. if (copy_in_user(rval, psp, distance))
  430. rval = 0;
  431. else if (current->thread.flags & SPARC_FLAG_32BIT) {
  432. if (put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6])))
  433. rval = 0;
  434. } else {
  435. if (put_user(((u64)csp - STACK_BIAS),
  436.      &(((struct reg_window *)rval)->ins[6])))
  437. rval = 0;
  438. else
  439. rval = rval - STACK_BIAS;
  440. }
  441. return rval;
  442. }
  443. /* Standard stuff. */
  444. static inline void shift_window_buffer(int first_win, int last_win,
  445.        struct thread_struct *t)
  446. {
  447. int i;
  448. for (i = first_win; i < last_win; i++) {
  449. t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1];
  450. memcpy(&t->reg_window[i], &t->reg_window[i+1],
  451.        sizeof(struct reg_window));
  452. }
  453. }
  454. void synchronize_user_stack(void)
  455. {
  456. struct thread_struct *t = &current->thread;
  457. unsigned long window;
  458. flush_user_windows();
  459. if ((window = t->w_saved) != 0) {
  460. int winsize = REGWIN_SZ;
  461. int bias = 0;
  462. if (t->flags & SPARC_FLAG_32BIT)
  463. winsize = REGWIN32_SZ;
  464. else
  465. bias = STACK_BIAS;
  466. window -= 1;
  467. do {
  468. unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
  469. struct reg_window *rwin = &t->reg_window[window];
  470. if (!copy_to_user((char *)sp, rwin, winsize)) {
  471. shift_window_buffer(window, t->w_saved - 1, t);
  472. t->w_saved--;
  473. }
  474. } while (window--);
  475. }
  476. }
  477. void fault_in_user_windows(void)
  478. {
  479. struct thread_struct *t = &current->thread;
  480. unsigned long window;
  481. int winsize = REGWIN_SZ;
  482. int bias = 0;
  483. if (t->flags & SPARC_FLAG_32BIT)
  484. winsize = REGWIN32_SZ;
  485. else
  486. bias = STACK_BIAS;
  487. flush_user_windows();
  488. window = t->w_saved;
  489. if (window != 0) {
  490. window -= 1;
  491. do {
  492. unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
  493. struct reg_window *rwin = &t->reg_window[window];
  494. if (copy_to_user((char *)sp, rwin, winsize))
  495. goto barf;
  496. } while (window--);
  497. }
  498. t->w_saved = 0;
  499. return;
  500. barf:
  501. t->w_saved = window + 1;
  502. do_exit(SIGILL);
  503. }
  504. /* Copy a Sparc thread.  The fork() return value conventions
  505.  * under SunOS are nothing short of bletcherous:
  506.  * Parent -->  %o0 == childs  pid, %o1 == 0
  507.  * Child  -->  %o0 == parents pid, %o1 == 1
  508.  *
  509.  * NOTE: We have a separate fork kpsr/kwim because
  510.  *       the parent could change these values between
  511.  *       sys_fork invocation and when we reach here
  512.  *       if the parent should sleep while trying to
  513.  *       allocate the task_struct and kernel stack in
  514.  *       do_fork().
  515.  */
  516. int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
  517. unsigned long unused,
  518. struct task_struct *p, struct pt_regs *regs)
  519. {
  520. struct thread_struct *t = &p->thread;
  521. char *child_trap_frame;
  522. #ifdef CONFIG_DEBUG_SPINLOCK
  523. t->smp_lock_count = 0;
  524. t->smp_lock_pc = 0;
  525. #endif
  526. /* Calculate offset to stack_frame & pt_regs */
  527. child_trap_frame = ((char *)p) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ));
  528. memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ));
  529. t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
  530. t->flags |= SPARC_FLAG_NEWCHILD;
  531. t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
  532. t->cwp = (regs->tstate + 1) & TSTATE_CWP;
  533. t->fpsaved[0] = 0;
  534. if (regs->tstate & TSTATE_PRIV) {
  535. /* Special case, if we are spawning a kernel thread from
  536.  * a userspace task (via KMOD, NFS, or similar) we must
  537.  * disable performance counters in the child because the
  538.  * address space and protection realm are changing.
  539.  */
  540. if (t->flags & SPARC_FLAG_PERFCTR) {
  541. t->user_cntd0 = t->user_cntd1 = NULL;
  542. t->pcr_reg = 0;
  543. t->flags &= ~(SPARC_FLAG_PERFCTR);
  544. }
  545. t->kregs->u_regs[UREG_FP] = p->thread.ksp;
  546. t->current_ds = KERNEL_DS;
  547. flush_register_windows();
  548. memcpy((void *)(t->ksp + STACK_BIAS),
  549.        (void *)(regs->u_regs[UREG_FP] + STACK_BIAS),
  550.        sizeof(struct reg_window));
  551. t->kregs->u_regs[UREG_G6] = (unsigned long) p;
  552. } else {
  553. if (t->flags & SPARC_FLAG_32BIT) {
  554. sp &= 0x00000000ffffffffUL;
  555. regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
  556. }
  557. t->kregs->u_regs[UREG_FP] = sp;
  558. t->current_ds = USER_DS;
  559. if (sp != regs->u_regs[UREG_FP]) {
  560. unsigned long csp;
  561. csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
  562. if (!csp)
  563. return -EFAULT;
  564. t->kregs->u_regs[UREG_FP] = csp;
  565. }
  566. if (t->utraps)
  567. t->utraps[0]++;
  568. }
  569. /* Set the return value for the child. */
  570. t->kregs->u_regs[UREG_I0] = current->pid;
  571. t->kregs->u_regs[UREG_I1] = 1;
  572. /* Set the second return value for the parent. */
  573. regs->u_regs[UREG_I1] = 0;
  574. return 0;
  575. }
  576. /*
  577.  * This is the mechanism for creating a new kernel thread.
  578.  *
  579.  * NOTE! Only a kernel-only process(ie the swapper or direct descendants
  580.  * who haven't done an "execve()") should use this: it will work within
  581.  * a system call from a "real" process, but the process memory space will
  582.  * not be free'd until both the parent and the child have exited.
  583.  */
  584. pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  585. {
  586. long retval;
  587. /* If the parent runs before fn(arg) is called by the child,
  588.  * the input registers of this function can be clobbered.
  589.  * So we stash 'fn' and 'arg' into global registers which
  590.  * will not be modified by the parent.
  591.  */
  592. __asm__ __volatile("mov %4, %%g2nt"    /* Save FN into global */
  593.    "mov %5, %%g3nt"    /* Save ARG into global */
  594.    "mov %1, %%g1nt"    /* Clone syscall nr. */
  595.    "mov %2, %%o0nt"    /* Clone flags. */
  596.    "mov 0, %%o1nt"    /* usp arg == 0 */
  597.    "t 0x6dnt"    /* Linux/Sparc clone(). */
  598.    "brz,a,pn %%o1, 1fnt" /* Parent, just return. */
  599.    " mov %%o0, %0nt"
  600.    "jmpl %%g2, %%o7nt"   /* Call the function. */
  601.    " mov %%g3, %%o0nt"   /* Set arg in delay. */
  602.    "mov %3, %%g1nt"
  603.    "t 0x6dnt"    /* Linux/Sparc exit(). */
  604.    /* Notreached by child. */
  605.    "1:" :
  606.    "=r" (retval) :
  607.    "i" (__NR_clone), "r" (flags | CLONE_VM),
  608.    "i" (__NR_exit),  "r" (fn), "r" (arg) :
  609.    "g1", "g2", "g3", "o0", "o1", "memory", "cc");
  610. return retval;
  611. }
  612. /*
  613.  * fill in the user structure for a core dump..
  614.  */
  615. void dump_thread(struct pt_regs * regs, struct user * dump)
  616. {
  617. #if 1
  618. /* Only should be used for SunOS and ancient a.out
  619.  * SparcLinux binaries...  Fixme some day when bored.
  620.  * But for now at least plug the security hole :-)
  621.  */
  622. memset(dump, 0, sizeof(struct user));
  623. #else
  624. unsigned long first_stack_page;
  625. dump->magic = SUNOS_CORE_MAGIC;
  626. dump->len = sizeof(struct user);
  627. dump->regs.psr = regs->psr;
  628. dump->regs.pc = regs->pc;
  629. dump->regs.npc = regs->npc;
  630. dump->regs.y = regs->y;
  631. /* fuck me plenty */
  632. memcpy(&dump->regs.regs[0], &regs->u_regs[1], (sizeof(unsigned long) * 15));
  633. dump->u_tsize = (((unsigned long) current->mm->end_code) -
  634. ((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1);
  635. dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1)));
  636. dump->u_dsize -= dump->u_tsize;
  637. dump->u_dsize &= ~(PAGE_SIZE - 1);
  638. first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
  639. dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
  640. memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
  641. dump->fpu.fpstatus.fsr = current->thread.fsr;
  642. dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
  643. #endif
  644. }
  645. typedef struct {
  646. union {
  647. unsigned int pr_regs[32];
  648. unsigned long pr_dregs[16];
  649. } pr_fr;
  650. unsigned int __unused;
  651. unsigned int pr_fsr;
  652. unsigned char pr_qcnt;
  653. unsigned char pr_q_entrysize;
  654. unsigned char pr_en;
  655. unsigned int pr_q[64];
  656. } elf_fpregset_t32;
  657. /*
  658.  * fill in the fpu structure for a core dump.
  659.  */
  660. int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
  661. {
  662. unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
  663. unsigned long fprs = current->thread.fpsaved[0];
  664. if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
  665. elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
  666. if (fprs & FPRS_DL)
  667. memcpy(&fpregs32->pr_fr.pr_regs[0], kfpregs,
  668.        sizeof(unsigned int) * 32);
  669. else
  670. memset(&fpregs32->pr_fr.pr_regs[0], 0,
  671.        sizeof(unsigned int) * 32);
  672. fpregs32->pr_qcnt = 0;
  673. fpregs32->pr_q_entrysize = 8;
  674. memset(&fpregs32->pr_q[0], 0,
  675.        (sizeof(unsigned int) * 64));
  676. if (fprs & FPRS_FEF) {
  677. fpregs32->pr_fsr = (unsigned int) current->thread.xfsr[0];
  678. fpregs32->pr_en = 1;
  679. } else {
  680. fpregs32->pr_fsr = 0;
  681. fpregs32->pr_en = 0;
  682. }
  683. } else {
  684. if(fprs & FPRS_DL)
  685. memcpy(&fpregs->pr_regs[0], kfpregs,
  686.        sizeof(unsigned int) * 32);
  687. else
  688. memset(&fpregs->pr_regs[0], 0,
  689.        sizeof(unsigned int) * 32);
  690. if(fprs & FPRS_DU)
  691. memcpy(&fpregs->pr_regs[16], kfpregs+16,
  692.        sizeof(unsigned int) * 32);
  693. else
  694. memset(&fpregs->pr_regs[16], 0,
  695.        sizeof(unsigned int) * 32);
  696. if(fprs & FPRS_FEF) {
  697. fpregs->pr_fsr = current->thread.xfsr[0];
  698. fpregs->pr_gsr = current->thread.gsr[0];
  699. } else {
  700. fpregs->pr_fsr = fpregs->pr_gsr = 0;
  701. }
  702. fpregs->pr_fprs = fprs;
  703. }
  704. return 1;
  705. }
  706. /*
  707.  * sparc_execve() executes a new program after the asm stub has set
  708.  * things up for us.  This should basically do what I want it to.
  709.  */
  710. asmlinkage int sparc_execve(struct pt_regs *regs)
  711. {
  712. int error, base = 0;
  713. char *filename;
  714. /* User register window flush is done by entry.S */
  715. /* Check for indirect call. */
  716. if (regs->u_regs[UREG_G1] == 0)
  717. base = 1;
  718. filename = getname((char *)regs->u_regs[base + UREG_I0]);
  719. error = PTR_ERR(filename);
  720. if (IS_ERR(filename))
  721. goto out;
  722. error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1],
  723.   (char **) regs->u_regs[base + UREG_I2], regs);
  724. putname(filename);
  725. if (!error) {
  726. fprs_write(0);
  727. current->thread.xfsr[0] = 0;
  728. current->thread.fpsaved[0] = 0;
  729. regs->tstate &= ~TSTATE_PEF;
  730. }
  731. out:
  732. return error;
  733. }