]>
git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - arch/sh64/kernel/process.c
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * arch/sh64/kernel/process.c
8 * Copyright (C) 2000, 2001 Paolo Alberelli
9 * Copyright (C) 2003 Paul Mundt
10 * Copyright (C) 2003, 2004 Richard Curnow
12 * Started from SH3/4 version:
13 * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
15 * In turn started from i386 version:
16 * Copyright (C) 1995 Linus Torvalds
21 * This file handles the architecture-dependent parts of process handling..
24 /* Temporary flags/tests. All to be removed/undefined. BEGIN */
26 #define VM_SHOW_TABLES
28 #define VM_TEST_RTLBMISS
29 #define VM_TEST_WTLBMISS
33 /* Temporary flags/tests. All to be removed/undefined. END */
35 #define __KERNEL_SYSCALLS__
38 #include <linux/kernel.h>
39 #include <linux/rwsem.h>
41 #include <linux/smp.h>
42 #include <linux/smp_lock.h>
43 #include <linux/ptrace.h>
44 #include <linux/slab.h>
45 #include <linux/vmalloc.h>
46 #include <linux/user.h>
47 #include <linux/a.out.h>
48 #include <linux/interrupt.h>
49 #include <linux/unistd.h>
50 #include <linux/delay.h>
51 #include <linux/reboot.h>
52 #include <linux/init.h>
54 #include <asm/uaccess.h>
55 #include <asm/pgtable.h>
56 #include <asm/system.h>
58 #include <asm/processor.h> /* includes also <asm/registers.h> */
59 #include <asm/mmu_context.h>
63 #include <linux/irq.h>
65 struct task_struct
*last_task_used_math
= NULL
;
70 static void print_PTE(long base
)
73 long long x
, y
, *p
= (long long *) base
;
75 for (i
=0; i
< 512; i
++, p
++){
84 y
= (*p
) & 0xffffffff;
85 printk("%08Lx%08Lx ", x
, y
);
86 if (!((i
+1)&0x3)) printk("\n");
92 static void print_DIR(long base
)
95 long *p
= (long *) base
;
97 for (i
=0; i
< 512; i
++, p
++){
105 printk("%08lx ", *p
);
106 if (!((i
+1)&0x7)) printk("\n");
112 static void print_vmalloc_first_tables(void)
115 #define PRESENT 0x800 /* Bit 11 */
118 * Do it really dirty by looking at raw addresses,
119 * raw offsets, no types. If we used pgtable/pgalloc
120 * macros/definitions we could hide potential bugs.
122 * Note that pointers are 32-bit for CDC.
124 long pgdt
, pmdt
, ptet
;
126 pgdt
= (long) &swapper_pg_dir
;
127 printk("-->PGD (0x%08lx):\n", pgdt
);
131 /* VMALLOC pool is mapped at 0xc0000000, second (pointer) entry in PGD */
133 pmdt
= (long) (* (long *) pgdt
);
134 if (!(pmdt
& PRESENT
)) {
137 } else pmdt
&= 0xfffff000;
139 printk("-->PMD (0x%08lx):\n", pmdt
);
143 /* Get the pmdt displacement for 0xc0000000 */
146 /* just look at first two address ranges ... */
147 /* ... 0xc0000000 ... */
148 ptet
= (long) (* (long *) pmdt
);
149 if (!(ptet
& PRESENT
)) {
152 } else ptet
&= 0xfffff000;
154 printk("-->PTE0 (0x%08lx):\n", ptet
);
158 /* ... 0xc0001000 ... */
160 if (!(ptet
& PRESENT
)) {
163 } else ptet
&= 0xfffff000;
164 printk("-->PTE1 (0x%08lx):\n", ptet
);
169 #define print_vmalloc_first_tables()
170 #endif /* VM_SHOW_TABLES */
172 static void test_VM(void)
176 #ifdef VM_SHOW_TABLES
177 printk("Initial PGD/PMD/PTE\n");
179 print_vmalloc_first_tables();
181 printk("Allocating 2 bytes\n");
183 print_vmalloc_first_tables();
185 printk("Allocating 4100 bytes\n");
187 print_vmalloc_first_tables();
189 printk("Allocating 20234 bytes\n");
191 print_vmalloc_first_tables();
194 /* Here you may want to fault ! */
196 #ifdef VM_TEST_RTLBMISS
197 printk("Ready to fault upon read.\n");
199 printk("RTLBMISSed on area a !\n");
201 printk("RTLBMISSed on area a !\n");
204 #ifdef VM_TEST_WTLBMISS
205 printk("Ready to fault upon write.\n");
207 printk("WTLBMISSed on area b !\n");
210 #endif /* VM_TEST_FAULT */
212 printk("Deallocating the 4100 byte chunk\n");
214 print_vmalloc_first_tables();
216 printk("Deallocating the 2 byte chunk\n");
218 print_vmalloc_first_tables();
220 printk("Deallocating the last chunk\n");
222 print_vmalloc_first_tables();
225 extern unsigned long volatile jiffies
;
227 unsigned long old_jiffies
;
228 int pid
= -1, pgid
= -1;
230 void idle_trace(void)
233 _syscall0(int, getpid
)
234 _syscall1(int, getpgid
, int, pid
)
237 /* VM allocation/deallocation simple test */
241 printk("Got all through to Idle !!\n");
242 printk("I'm now going to loop forever ...\n");
243 printk("Any ! below is a timer tick.\n");
244 printk("Any . below is a getpgid system call from pid = %d.\n", pid
);
247 old_jiffies
= jiffies
;
251 if (old_jiffies
!= jiffies
) {
252 old_jiffies
= jiffies
- old_jiffies
;
253 switch (old_jiffies
) {
267 printk("(%d!)", (int) old_jiffies
);
269 old_jiffies
= jiffies
;
275 #define idle_trace() do { } while (0)
276 #endif /* IDLE_TRACE */
278 static int hlt_counter
= 1;
280 #define HARD_IDLE_TIMEOUT (HZ / 3)
282 void disable_hlt(void)
287 void enable_hlt(void)
292 static int __init
nohlt_setup(char *__unused
)
298 static int __init
hlt_setup(char *__unused
)
304 __setup("nohlt", nohlt_setup
);
305 __setup("hlt", hlt_setup
);
307 static inline void hlt(void)
309 __asm__
__volatile__ ("sleep" : : : "memory");
313 * The idle loop on a uniprocessor SH..
317 /* endless idle loop with no priority at all */
320 while (!need_resched())
324 while (!need_resched()) {
332 preempt_enable_no_resched();
339 void machine_restart(char * __unused
)
341 extern void phys_stext(void);
346 void machine_halt(void)
351 void machine_power_off(void)
353 extern void enter_deep_standby(void);
355 enter_deep_standby();
358 void show_regs(struct pt_regs
* regs
)
360 unsigned long long ah
, al
, bh
, bl
, ch
, cl
;
364 ah
= (regs
->pc
) >> 32;
365 al
= (regs
->pc
) & 0xffffffff;
366 bh
= (regs
->regs
[18]) >> 32;
367 bl
= (regs
->regs
[18]) & 0xffffffff;
368 ch
= (regs
->regs
[15]) >> 32;
369 cl
= (regs
->regs
[15]) & 0xffffffff;
370 printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n",
371 ah
, al
, bh
, bl
, ch
, cl
);
373 ah
= (regs
->sr
) >> 32;
374 al
= (regs
->sr
) & 0xffffffff;
375 asm volatile ("getcon " __TEA
", %0" : "=r" (bh
));
376 asm volatile ("getcon " __TEA
", %0" : "=r" (bl
));
378 bl
= (bl
) & 0xffffffff;
379 asm volatile ("getcon " __KCR0
", %0" : "=r" (ch
));
380 asm volatile ("getcon " __KCR0
", %0" : "=r" (cl
));
382 cl
= (cl
) & 0xffffffff;
383 printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n",
384 ah
, al
, bh
, bl
, ch
, cl
);
386 ah
= (regs
->regs
[0]) >> 32;
387 al
= (regs
->regs
[0]) & 0xffffffff;
388 bh
= (regs
->regs
[1]) >> 32;
389 bl
= (regs
->regs
[1]) & 0xffffffff;
390 ch
= (regs
->regs
[2]) >> 32;
391 cl
= (regs
->regs
[2]) & 0xffffffff;
392 printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n",
393 ah
, al
, bh
, bl
, ch
, cl
);
395 ah
= (regs
->regs
[3]) >> 32;
396 al
= (regs
->regs
[3]) & 0xffffffff;
397 bh
= (regs
->regs
[4]) >> 32;
398 bl
= (regs
->regs
[4]) & 0xffffffff;
399 ch
= (regs
->regs
[5]) >> 32;
400 cl
= (regs
->regs
[5]) & 0xffffffff;
401 printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n",
402 ah
, al
, bh
, bl
, ch
, cl
);
404 ah
= (regs
->regs
[6]) >> 32;
405 al
= (regs
->regs
[6]) & 0xffffffff;
406 bh
= (regs
->regs
[7]) >> 32;
407 bl
= (regs
->regs
[7]) & 0xffffffff;
408 ch
= (regs
->regs
[8]) >> 32;
409 cl
= (regs
->regs
[8]) & 0xffffffff;
410 printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n",
411 ah
, al
, bh
, bl
, ch
, cl
);
413 ah
= (regs
->regs
[9]) >> 32;
414 al
= (regs
->regs
[9]) & 0xffffffff;
415 bh
= (regs
->regs
[10]) >> 32;
416 bl
= (regs
->regs
[10]) & 0xffffffff;
417 ch
= (regs
->regs
[11]) >> 32;
418 cl
= (regs
->regs
[11]) & 0xffffffff;
419 printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n",
420 ah
, al
, bh
, bl
, ch
, cl
);
422 ah
= (regs
->regs
[12]) >> 32;
423 al
= (regs
->regs
[12]) & 0xffffffff;
424 bh
= (regs
->regs
[13]) >> 32;
425 bl
= (regs
->regs
[13]) & 0xffffffff;
426 ch
= (regs
->regs
[14]) >> 32;
427 cl
= (regs
->regs
[14]) & 0xffffffff;
428 printk("R12 : %08Lx%08Lx R13 : %08Lx%08Lx R14 : %08Lx%08Lx\n",
429 ah
, al
, bh
, bl
, ch
, cl
);
431 ah
= (regs
->regs
[16]) >> 32;
432 al
= (regs
->regs
[16]) & 0xffffffff;
433 bh
= (regs
->regs
[17]) >> 32;
434 bl
= (regs
->regs
[17]) & 0xffffffff;
435 ch
= (regs
->regs
[19]) >> 32;
436 cl
= (regs
->regs
[19]) & 0xffffffff;
437 printk("R16 : %08Lx%08Lx R17 : %08Lx%08Lx R19 : %08Lx%08Lx\n",
438 ah
, al
, bh
, bl
, ch
, cl
);
440 ah
= (regs
->regs
[20]) >> 32;
441 al
= (regs
->regs
[20]) & 0xffffffff;
442 bh
= (regs
->regs
[21]) >> 32;
443 bl
= (regs
->regs
[21]) & 0xffffffff;
444 ch
= (regs
->regs
[22]) >> 32;
445 cl
= (regs
->regs
[22]) & 0xffffffff;
446 printk("R20 : %08Lx%08Lx R21 : %08Lx%08Lx R22 : %08Lx%08Lx\n",
447 ah
, al
, bh
, bl
, ch
, cl
);
449 ah
= (regs
->regs
[23]) >> 32;
450 al
= (regs
->regs
[23]) & 0xffffffff;
451 bh
= (regs
->regs
[24]) >> 32;
452 bl
= (regs
->regs
[24]) & 0xffffffff;
453 ch
= (regs
->regs
[25]) >> 32;
454 cl
= (regs
->regs
[25]) & 0xffffffff;
455 printk("R23 : %08Lx%08Lx R24 : %08Lx%08Lx R25 : %08Lx%08Lx\n",
456 ah
, al
, bh
, bl
, ch
, cl
);
458 ah
= (regs
->regs
[26]) >> 32;
459 al
= (regs
->regs
[26]) & 0xffffffff;
460 bh
= (regs
->regs
[27]) >> 32;
461 bl
= (regs
->regs
[27]) & 0xffffffff;
462 ch
= (regs
->regs
[28]) >> 32;
463 cl
= (regs
->regs
[28]) & 0xffffffff;
464 printk("R26 : %08Lx%08Lx R27 : %08Lx%08Lx R28 : %08Lx%08Lx\n",
465 ah
, al
, bh
, bl
, ch
, cl
);
467 ah
= (regs
->regs
[29]) >> 32;
468 al
= (regs
->regs
[29]) & 0xffffffff;
469 bh
= (regs
->regs
[30]) >> 32;
470 bl
= (regs
->regs
[30]) & 0xffffffff;
471 ch
= (regs
->regs
[31]) >> 32;
472 cl
= (regs
->regs
[31]) & 0xffffffff;
473 printk("R29 : %08Lx%08Lx R30 : %08Lx%08Lx R31 : %08Lx%08Lx\n",
474 ah
, al
, bh
, bl
, ch
, cl
);
476 ah
= (regs
->regs
[32]) >> 32;
477 al
= (regs
->regs
[32]) & 0xffffffff;
478 bh
= (regs
->regs
[33]) >> 32;
479 bl
= (regs
->regs
[33]) & 0xffffffff;
480 ch
= (regs
->regs
[34]) >> 32;
481 cl
= (regs
->regs
[34]) & 0xffffffff;
482 printk("R32 : %08Lx%08Lx R33 : %08Lx%08Lx R34 : %08Lx%08Lx\n",
483 ah
, al
, bh
, bl
, ch
, cl
);
485 ah
= (regs
->regs
[35]) >> 32;
486 al
= (regs
->regs
[35]) & 0xffffffff;
487 bh
= (regs
->regs
[36]) >> 32;
488 bl
= (regs
->regs
[36]) & 0xffffffff;
489 ch
= (regs
->regs
[37]) >> 32;
490 cl
= (regs
->regs
[37]) & 0xffffffff;
491 printk("R35 : %08Lx%08Lx R36 : %08Lx%08Lx R37 : %08Lx%08Lx\n",
492 ah
, al
, bh
, bl
, ch
, cl
);
494 ah
= (regs
->regs
[38]) >> 32;
495 al
= (regs
->regs
[38]) & 0xffffffff;
496 bh
= (regs
->regs
[39]) >> 32;
497 bl
= (regs
->regs
[39]) & 0xffffffff;
498 ch
= (regs
->regs
[40]) >> 32;
499 cl
= (regs
->regs
[40]) & 0xffffffff;
500 printk("R38 : %08Lx%08Lx R39 : %08Lx%08Lx R40 : %08Lx%08Lx\n",
501 ah
, al
, bh
, bl
, ch
, cl
);
503 ah
= (regs
->regs
[41]) >> 32;
504 al
= (regs
->regs
[41]) & 0xffffffff;
505 bh
= (regs
->regs
[42]) >> 32;
506 bl
= (regs
->regs
[42]) & 0xffffffff;
507 ch
= (regs
->regs
[43]) >> 32;
508 cl
= (regs
->regs
[43]) & 0xffffffff;
509 printk("R41 : %08Lx%08Lx R42 : %08Lx%08Lx R43 : %08Lx%08Lx\n",
510 ah
, al
, bh
, bl
, ch
, cl
);
512 ah
= (regs
->regs
[44]) >> 32;
513 al
= (regs
->regs
[44]) & 0xffffffff;
514 bh
= (regs
->regs
[45]) >> 32;
515 bl
= (regs
->regs
[45]) & 0xffffffff;
516 ch
= (regs
->regs
[46]) >> 32;
517 cl
= (regs
->regs
[46]) & 0xffffffff;
518 printk("R44 : %08Lx%08Lx R45 : %08Lx%08Lx R46 : %08Lx%08Lx\n",
519 ah
, al
, bh
, bl
, ch
, cl
);
521 ah
= (regs
->regs
[47]) >> 32;
522 al
= (regs
->regs
[47]) & 0xffffffff;
523 bh
= (regs
->regs
[48]) >> 32;
524 bl
= (regs
->regs
[48]) & 0xffffffff;
525 ch
= (regs
->regs
[49]) >> 32;
526 cl
= (regs
->regs
[49]) & 0xffffffff;
527 printk("R47 : %08Lx%08Lx R48 : %08Lx%08Lx R49 : %08Lx%08Lx\n",
528 ah
, al
, bh
, bl
, ch
, cl
);
530 ah
= (regs
->regs
[50]) >> 32;
531 al
= (regs
->regs
[50]) & 0xffffffff;
532 bh
= (regs
->regs
[51]) >> 32;
533 bl
= (regs
->regs
[51]) & 0xffffffff;
534 ch
= (regs
->regs
[52]) >> 32;
535 cl
= (regs
->regs
[52]) & 0xffffffff;
536 printk("R50 : %08Lx%08Lx R51 : %08Lx%08Lx R52 : %08Lx%08Lx\n",
537 ah
, al
, bh
, bl
, ch
, cl
);
539 ah
= (regs
->regs
[53]) >> 32;
540 al
= (regs
->regs
[53]) & 0xffffffff;
541 bh
= (regs
->regs
[54]) >> 32;
542 bl
= (regs
->regs
[54]) & 0xffffffff;
543 ch
= (regs
->regs
[55]) >> 32;
544 cl
= (regs
->regs
[55]) & 0xffffffff;
545 printk("R53 : %08Lx%08Lx R54 : %08Lx%08Lx R55 : %08Lx%08Lx\n",
546 ah
, al
, bh
, bl
, ch
, cl
);
548 ah
= (regs
->regs
[56]) >> 32;
549 al
= (regs
->regs
[56]) & 0xffffffff;
550 bh
= (regs
->regs
[57]) >> 32;
551 bl
= (regs
->regs
[57]) & 0xffffffff;
552 ch
= (regs
->regs
[58]) >> 32;
553 cl
= (regs
->regs
[58]) & 0xffffffff;
554 printk("R56 : %08Lx%08Lx R57 : %08Lx%08Lx R58 : %08Lx%08Lx\n",
555 ah
, al
, bh
, bl
, ch
, cl
);
557 ah
= (regs
->regs
[59]) >> 32;
558 al
= (regs
->regs
[59]) & 0xffffffff;
559 bh
= (regs
->regs
[60]) >> 32;
560 bl
= (regs
->regs
[60]) & 0xffffffff;
561 ch
= (regs
->regs
[61]) >> 32;
562 cl
= (regs
->regs
[61]) & 0xffffffff;
563 printk("R59 : %08Lx%08Lx R60 : %08Lx%08Lx R61 : %08Lx%08Lx\n",
564 ah
, al
, bh
, bl
, ch
, cl
);
566 ah
= (regs
->regs
[62]) >> 32;
567 al
= (regs
->regs
[62]) & 0xffffffff;
568 bh
= (regs
->tregs
[0]) >> 32;
569 bl
= (regs
->tregs
[0]) & 0xffffffff;
570 ch
= (regs
->tregs
[1]) >> 32;
571 cl
= (regs
->tregs
[1]) & 0xffffffff;
572 printk("R62 : %08Lx%08Lx T0 : %08Lx%08Lx T1 : %08Lx%08Lx\n",
573 ah
, al
, bh
, bl
, ch
, cl
);
575 ah
= (regs
->tregs
[2]) >> 32;
576 al
= (regs
->tregs
[2]) & 0xffffffff;
577 bh
= (regs
->tregs
[3]) >> 32;
578 bl
= (regs
->tregs
[3]) & 0xffffffff;
579 ch
= (regs
->tregs
[4]) >> 32;
580 cl
= (regs
->tregs
[4]) & 0xffffffff;
581 printk("T2 : %08Lx%08Lx T3 : %08Lx%08Lx T4 : %08Lx%08Lx\n",
582 ah
, al
, bh
, bl
, ch
, cl
);
584 ah
= (regs
->tregs
[5]) >> 32;
585 al
= (regs
->tregs
[5]) & 0xffffffff;
586 bh
= (regs
->tregs
[6]) >> 32;
587 bl
= (regs
->tregs
[6]) & 0xffffffff;
588 ch
= (regs
->tregs
[7]) >> 32;
589 cl
= (regs
->tregs
[7]) & 0xffffffff;
590 printk("T5 : %08Lx%08Lx T6 : %08Lx%08Lx T7 : %08Lx%08Lx\n",
591 ah
, al
, bh
, bl
, ch
, cl
);
594 * If we're in kernel mode, dump the stack too..
596 if (!user_mode(regs
)) {
597 void show_stack(struct task_struct
*tsk
, unsigned long *sp
);
598 unsigned long sp
= regs
->regs
[15] & 0xffffffff;
599 struct task_struct
*tsk
= get_current();
601 tsk
->thread
.kregs
= regs
;
603 show_stack(tsk
, (unsigned long *)sp
);
607 struct task_struct
* alloc_task_struct(void)
609 /* Get task descriptor pages */
610 return (struct task_struct
*)
611 __get_free_pages(GFP_KERNEL
, get_order(THREAD_SIZE
));
614 void free_task_struct(struct task_struct
*p
)
616 free_pages((unsigned long) p
, get_order(THREAD_SIZE
));
620 * Create a kernel thread
624 * This is the mechanism for creating a new kernel thread.
626 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
627 * who haven't done an "execve()") should use this: it will work within
628 * a system call from a "real" process, but the process memory space will
629 * not be free'd until both the parent and the child have exited.
631 int kernel_thread(int (*fn
)(void *), void * arg
, unsigned long flags
)
633 /* A bit less processor dependent than older sh ... */
636 static __inline__
_syscall2(int,clone
,unsigned long,flags
,unsigned long,newsp
)
637 static __inline__
_syscall1(int,exit
,int,ret
)
639 reply
= clone(flags
| CLONE_VM
, 0);
642 reply
= exit(fn(arg
));
649 * Free current thread data structures etc..
651 void exit_thread(void)
653 /* See arch/sparc/kernel/process.c for the precedent for doing this -- RPC.
655 The SH-5 FPU save/restore approach relies on last_task_used_math
656 pointing to a live task_struct. When another task tries to use the
657 FPU for the 1st time, the FPUDIS trap handling (see
658 arch/sh64/kernel/fpu.c) will save the existing FPU state to the
659 FP regs field within last_task_used_math before re-loading the new
660 task's FPU state (or initialising it if the FPU has been used
661 before). So if last_task_used_math is stale, and its page has already been
662 re-allocated for another use, the consequences are rather grim. Unless we
663 null it here, there is no other path through which it would get safely
667 if (last_task_used_math
== current
) {
668 last_task_used_math
= NULL
;
673 void flush_thread(void)
676 /* Called by fs/exec.c (flush_old_exec) to remove traces of a
677 * previously running executable. */
679 if (last_task_used_math
== current
) {
680 last_task_used_math
= NULL
;
682 /* Force FPU state to be reinitialised after exec */
686 /* if we are a kernel thread, about to change to user thread,
689 if(current
->thread
.kregs
==&fake_swapper_regs
) {
690 current
->thread
.kregs
=
691 ((struct pt_regs
*)(THREAD_SIZE
+ (unsigned long) current
) - 1);
692 current
->thread
.uregs
= current
->thread
.kregs
;
696 void release_thread(struct task_struct
*dead_task
)
701 /* Fill in the fpu structure for a core dump.. */
702 int dump_fpu(struct pt_regs
*regs
, elf_fpregset_t
*fpu
)
706 struct task_struct
*tsk
= current
;
708 fpvalid
= !!tsk_used_math(tsk
);
710 if (current
== last_task_used_math
) {
712 fpsave(&tsk
->thread
.fpu
.hard
);
714 last_task_used_math
= 0;
718 memcpy(fpu
, &tsk
->thread
.fpu
.hard
, sizeof(*fpu
));
723 return 0; /* Task didn't use the fpu at all. */
727 asmlinkage
void ret_from_fork(void);
729 int copy_thread(int nr
, unsigned long clone_flags
, unsigned long usp
,
730 unsigned long unused
,
731 struct task_struct
*p
, struct pt_regs
*regs
)
733 struct pt_regs
*childregs
;
734 unsigned long long se
; /* Sign extension */
737 if(last_task_used_math
== current
) {
739 fpsave(¤t
->thread
.fpu
.hard
);
741 last_task_used_math
= NULL
;
745 /* Copy from sh version */
746 childregs
= (struct pt_regs
*)(THREAD_SIZE
+ task_stack_page(p
)) - 1;
750 if (user_mode(regs
)) {
751 childregs
->regs
[15] = usp
;
752 p
->thread
.uregs
= childregs
;
754 childregs
->regs
[15] = (unsigned long)task_stack_page(p
) + THREAD_SIZE
;
757 childregs
->regs
[9] = 0; /* Set return value for child */
758 childregs
->sr
|= SR_FD
; /* Invalidate FPU flag */
760 p
->thread
.sp
= (unsigned long) childregs
;
761 p
->thread
.pc
= (unsigned long) ret_from_fork
;
764 * Sign extend the edited stack.
765 * Note that thread.pc and thread.pc will stay
766 * 32-bit wide and context switch must take care
767 * of NEFF sign extension.
770 se
= childregs
->regs
[15];
771 se
= (se
& NEFF_SIGN
) ? (se
| NEFF_MASK
) : se
;
772 childregs
->regs
[15] = se
;
777 asmlinkage
int sys_fork(unsigned long r2
, unsigned long r3
,
778 unsigned long r4
, unsigned long r5
,
779 unsigned long r6
, unsigned long r7
,
780 struct pt_regs
*pregs
)
782 return do_fork(SIGCHLD
, pregs
->regs
[15], pregs
, 0, 0, 0);
785 asmlinkage
int sys_clone(unsigned long clone_flags
, unsigned long newsp
,
786 unsigned long r4
, unsigned long r5
,
787 unsigned long r6
, unsigned long r7
,
788 struct pt_regs
*pregs
)
791 newsp
= pregs
->regs
[15];
792 return do_fork(clone_flags
, newsp
, pregs
, 0, 0, 0);
796 * This is trivial, and on the face of it looks like it
797 * could equally well be done in user mode.
799 * Not so, for quite unobvious reasons - register pressure.
800 * In user mode vfork() cannot have a stack frame, and if
801 * done by calling the "clone()" system call directly, you
802 * do not have enough call-clobbered registers to hold all
803 * the information you need.
805 asmlinkage
int sys_vfork(unsigned long r2
, unsigned long r3
,
806 unsigned long r4
, unsigned long r5
,
807 unsigned long r6
, unsigned long r7
,
808 struct pt_regs
*pregs
)
810 return do_fork(CLONE_VFORK
| CLONE_VM
| SIGCHLD
, pregs
->regs
[15], pregs
, 0, 0, 0);
814 * sys_execve() executes a new program.
816 asmlinkage
int sys_execve(char *ufilename
, char **uargv
,
817 char **uenvp
, unsigned long r5
,
818 unsigned long r6
, unsigned long r7
,
819 struct pt_regs
*pregs
)
825 filename
= getname((char __user
*)ufilename
);
826 error
= PTR_ERR(filename
);
827 if (IS_ERR(filename
))
830 error
= do_execve(filename
,
831 (char __user
* __user
*)uargv
,
832 (char __user
* __user
*)uenvp
,
836 current
->ptrace
&= ~PT_DTRACE
;
837 task_unlock(current
);
846 * These bracket the sleeping functions..
848 extern void interruptible_sleep_on(wait_queue_head_t
*q
);
850 #define mid_sched ((unsigned long) interruptible_sleep_on)
852 static int in_sh64_switch_to(unsigned long pc
)
854 extern char __sh64_switch_to_end
;
855 /* For a sleeping task, the PC is somewhere in the middle of the function,
856 so we don't have to worry about masking the LSB off */
857 return (pc
>= (unsigned long) sh64_switch_to
) &&
858 (pc
< (unsigned long) &__sh64_switch_to_end
);
861 unsigned long get_wchan(struct task_struct
*p
)
863 unsigned long schedule_fp
;
864 unsigned long sh64_switch_to_fp
;
865 unsigned long schedule_caller_pc
;
868 if (!p
|| p
== current
|| p
->state
== TASK_RUNNING
)
872 * The same comment as on the Alpha applies here, too ...
874 pc
= thread_saved_pc(p
);
876 #ifdef CONFIG_FRAME_POINTER
877 if (in_sh64_switch_to(pc
)) {
878 sh64_switch_to_fp
= (long) p
->thread
.sp
;
879 /* r14 is saved at offset 4 in the sh64_switch_to frame */
880 schedule_fp
= *(unsigned long *) (long)(sh64_switch_to_fp
+ 4);
882 /* and the caller of 'schedule' is (currently!) saved at offset 24
883 in the frame of schedule (from disasm) */
884 schedule_caller_pc
= *(unsigned long *) (long)(schedule_fp
+ 24);
885 return schedule_caller_pc
;
891 /* Provide a /proc/asids file that lists out the
892 ASIDs currently associated with the processes. (If the DM.PC register is
893 examined through the debug link, this shows ASID + PC. To make use of this,
894 the PID->ASID relationship needs to be known. This is primarily for
898 #if defined(CONFIG_SH64_PROC_ASIDS)
899 #include <linux/init.h>
900 #include <linux/proc_fs.h>
903 asids_proc_info(char *buf
, char **start
, off_t fpos
, int length
, int *eof
, void *data
)
906 struct task_struct
*p
;
907 read_lock(&tasklist_lock
);
908 for_each_process(p
) {
910 struct mm_struct
*mm
;
914 unsigned long asid
, context
;
915 context
= mm
->context
;
916 asid
= (context
& 0xff);
917 len
+= sprintf(buf
+len
, "%5d : %02lx\n", pid
, asid
);
919 len
+= sprintf(buf
+len
, "%5d : (none)\n", pid
);
922 read_unlock(&tasklist_lock
);
927 static int __init
register_proc_asids(void)
929 create_proc_read_entry("asids", 0, NULL
, asids_proc_info
, NULL
);
933 __initcall(register_proc_asids
);