aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v32/kernel
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/cris/arch-v32/kernel
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'arch/cris/arch-v32/kernel')
-rw-r--r--arch/cris/arch-v32/kernel/debugport.c1
-rw-r--r--arch/cris/arch-v32/kernel/entry.S22
-rw-r--r--arch/cris/arch-v32/kernel/fasttimer.c1
-rw-r--r--arch/cris/arch-v32/kernel/head.S58
-rw-r--r--arch/cris/arch-v32/kernel/kgdb.c28
-rw-r--r--arch/cris/arch-v32/kernel/process.c118
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c3
-rw-r--r--arch/cris/arch-v32/kernel/signal.c100
-rw-r--r--arch/cris/arch-v32/kernel/smp.c16
-rw-r--r--arch/cris/arch-v32/kernel/time.c11
10 files changed, 291 insertions, 67 deletions
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c
index 610909b003f..794b364d9f7 100644
--- a/arch/cris/arch-v32/kernel/debugport.c
+++ b/arch/cris/arch-v32/kernel/debugport.c
@@ -4,6 +4,7 @@
4 4
5#include <linux/console.h> 5#include <linux/console.h>
6#include <linux/init.h> 6#include <linux/init.h>
7#include <asm/system.h>
7#include <hwregs/reg_rdwr.h> 8#include <hwregs/reg_rdwr.h>
8#include <hwregs/reg_map.h> 9#include <hwregs/reg_map.h>
9#include <hwregs/ser_defs.h> 10#include <hwregs/ser_defs.h>
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index faa644111fe..c3ea4694fba 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -31,7 +31,6 @@
31 .globl system_call 31 .globl system_call
32 .globl ret_from_intr 32 .globl ret_from_intr
33 .globl ret_from_fork 33 .globl ret_from_fork
34 .globl ret_from_kernel_thread
35 .globl resume 34 .globl resume
36 .globl multiple_interrupt 35 .globl multiple_interrupt
37 .globl nmi_interrupt 36 .globl nmi_interrupt
@@ -85,18 +84,6 @@ ret_from_fork:
85 nop 84 nop
86 .size ret_from_fork, . - ret_from_fork 85 .size ret_from_fork, . - ret_from_fork
87 86
88 .type ret_from_kernel_thread,@function
89ret_from_kernel_thread:
90 jsr schedule_tail
91 nop
92 move.d $r2, $r10
93 jsr $r1
94 nop
95 moveq 0, $r9 ; no syscall restarts, TYVM...
96 ba ret_from_sys_call
97 nop
98 .size ret_from_kernel_thread, . - ret_from_kernel_thread
99
100 .type ret_from_intr,@function 87 .type ret_from_intr,@function
101ret_from_intr: 88ret_from_intr:
102 ;; Check for resched if preemptive kernel, or if we're going back to 89 ;; Check for resched if preemptive kernel, or if we're going back to
@@ -544,6 +531,15 @@ _ugdb_handle_exception:
544 ba do_sigtrap ; SIGTRAP the offending process. 531 ba do_sigtrap ; SIGTRAP the offending process.
545 move.d [$sp+], $r0 ; Restore R0 in delay slot. 532 move.d [$sp+], $r0 ; Restore R0 in delay slot.
546 533
534 .global kernel_execve
535 .type kernel_execve,@function
536kernel_execve:
537 move.d __NR_execve, $r9
538 break 13
539 ret
540 nop
541 .size kernel_execve, . - kernel_execve
542
547 .data 543 .data
548 544
549 .section .rodata,"a" 545 .section .rodata,"a"
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c
index ab1551ee43c..111caa1a2ef 100644
--- a/arch/cris/arch-v32/kernel/fasttimer.c
+++ b/arch/cris/arch-v32/kernel/fasttimer.c
@@ -17,6 +17,7 @@
17#include <linux/delay.h> 17#include <linux/delay.h>
18 18
19#include <asm/irq.h> 19#include <asm/irq.h>
20#include <asm/system.h>
20 21
21#include <hwregs/reg_map.h> 22#include <hwregs/reg_map.h>
22#include <hwregs/reg_rdwr.h> 23#include <hwregs/reg_rdwr.h>
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 51e34165ece..5d502b9ab56 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -36,6 +36,13 @@
36 .global nand_boot 36 .global nand_boot
37 .global swapper_pg_dir 37 .global swapper_pg_dir
38 38
39 ;; Dummy section to make it bootable with current VCS simulator
40#ifdef CONFIG_ETRAX_VCS_SIM
41 .section ".boot", "ax"
42 ba tstart
43 nop
44#endif
45
39 .text 46 .text
40tstart: 47tstart:
41 ;; This is the entry point of the kernel. The CPU is currently in 48 ;; This is the entry point of the kernel. The CPU is currently in
@@ -68,10 +75,17 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
68 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ 75 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
69 | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5) \ 76 | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5) \
70 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 77 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
71#else 78#elif !defined(CONFIG_ETRAX_VCS_SIM)
72 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ 79 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \
73 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ 80 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
74 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 81 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
82#else
83 ;; Map the virtual DRAM to the RW eprom area at address 0.
84 ;; Also map 0xa for the hook calls,
85 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \
86 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
87 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) \
88 | REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
75#endif 89#endif
76 90
77 ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00. 91 ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
@@ -112,7 +126,7 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
112 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ 126 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \
113 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ 127 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \
114 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 128 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
115#else 129#elif !defined(CONFIG_ETRAX_VCS_SIM)
116 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ 130 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \
117 | REG_STATE(mmu, rw_mm_cfg, acc, on) \ 131 | REG_STATE(mmu, rw_mm_cfg, acc, on) \
118 | REG_STATE(mmu, rw_mm_cfg, ex, on) \ 132 | REG_STATE(mmu, rw_mm_cfg, ex, on) \
@@ -133,6 +147,27 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
133 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ 147 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \
134 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ 148 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \
135 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 149 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
150#else
151 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \
152 | REG_STATE(mmu, rw_mm_cfg, acc, on) \
153 | REG_STATE(mmu, rw_mm_cfg, ex, on) \
154 | REG_STATE(mmu, rw_mm_cfg, inv, on) \
155 | REG_STATE(mmu, rw_mm_cfg, seg_f, linear) \
156 | REG_STATE(mmu, rw_mm_cfg, seg_e, linear) \
157 | REG_STATE(mmu, rw_mm_cfg, seg_d, page) \
158 | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \
159 | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \
160 | REG_STATE(mmu, rw_mm_cfg, seg_a, linear) \
161 | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \
162 | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \
163 | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \
164 | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \
165 | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \
166 | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \
167 | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \
168 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \
169 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \
170 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
136#endif 171#endif
137 172
138 ;; Update instruction MMU. 173 ;; Update instruction MMU.
@@ -191,6 +226,7 @@ master_cpu:
191 move.d secondary_cpu_entry, $r1 226 move.d secondary_cpu_entry, $r1
192 move.d $r1, [$r0] 227 move.d $r1, [$r0]
193#endif 228#endif
229#ifndef CONFIG_ETRAX_VCS_SIM
194 ; Check if starting from DRAM (network->RAM boot or unpacked 230 ; Check if starting from DRAM (network->RAM boot or unpacked
195 ; compressed kernel), or directly from flash. 231 ; compressed kernel), or directly from flash.
196 lapcq ., $r0 232 lapcq ., $r0
@@ -198,6 +234,7 @@ master_cpu:
198 cmp.d 0x10000, $r0 ; Arbitrary, something above this code. 234 cmp.d 0x10000, $r0 ; Arbitrary, something above this code.
199 blo _inflash0 235 blo _inflash0
200 nop 236 nop
237#endif
201 238
202 jump _inram ; Jump to cached RAM. 239 jump _inram ; Jump to cached RAM.
203 nop 240 nop
@@ -289,6 +326,7 @@ move_cramfs:
289 move.d romfs_length, $r1 326 move.d romfs_length, $r1
290 move.d $r0, [$r1] 327 move.d $r0, [$r1]
291 328
329#ifndef CONFIG_ETRAX_VCS_SIM
292 ;; The kernel could have been unpacked to DRAM by the loader, but 330 ;; The kernel could have been unpacked to DRAM by the loader, but
293 ;; the cramfs image could still be in the flash immediately 331 ;; the cramfs image could still be in the flash immediately
294 ;; following the compressed kernel image. The loader passes the address 332 ;; following the compressed kernel image. The loader passes the address
@@ -297,6 +335,10 @@ move_cramfs:
297 cmp.d 0x0ffffff8, $r9 335 cmp.d 0x0ffffff8, $r9
298 bhs _no_romfs_in_flash ; R9 points outside the flash area. 336 bhs _no_romfs_in_flash ; R9 points outside the flash area.
299 nop 337 nop
338#else
339 ba _no_romfs_in_flash
340 nop
341#endif
300 ;; cramfs rootfs might to be in flash. Check for it. 342 ;; cramfs rootfs might to be in flash. Check for it.
301 move.d [$r9], $r0 ; cramfs_super.magic 343 move.d [$r9], $r0 ; cramfs_super.magic
302 cmp.d CRAMFS_MAGIC, $r0 344 cmp.d CRAMFS_MAGIC, $r0
@@ -354,6 +396,7 @@ _no_romfs_in_flash:
354 move.d romfs_length, $r3 396 move.d romfs_length, $r3
355 move.d $r2, [$r3] ; store size at romfs_length 397 move.d $r2, [$r3] ; store size at romfs_length
356 398
399#ifndef CONFIG_ETRAX_VCS_SIM
357 add.d $r2, $r0 ; copy from end and downwards 400 add.d $r2, $r0 ; copy from end and downwards
358 add.d $r2, $r1 401 add.d $r2, $r1
359 402
@@ -367,6 +410,7 @@ _no_romfs_in_flash:
367 subq 1, $r2 410 subq 1, $r2
368 bne 1b 411 bne 1b
369 nop 412 nop
413#endif
370 414
3714: 4154:
372 ;; BSS move done. 416 ;; BSS move done.
@@ -411,6 +455,7 @@ no_command_line:
411 move.d etrax_irv, $r1 ; Set the exception base register and pointer. 455 move.d etrax_irv, $r1 ; Set the exception base register and pointer.
412 move.d $r0, [$r1] 456 move.d $r0, [$r1]
413 457
458#ifndef CONFIG_ETRAX_VCS_SIM
414 ;; Clear the BSS region from _bss_start to _end. 459 ;; Clear the BSS region from _bss_start to _end.
415 move.d __bss_start, $r0 460 move.d __bss_start, $r0
416 move.d _end, $r1 461 move.d _end, $r1
@@ -418,6 +463,15 @@ no_command_line:
418 cmp.d $r1, $r0 463 cmp.d $r1, $r0
419 blo 1b 464 blo 1b
420 nop 465 nop
466#endif
467
468#ifdef CONFIG_ETRAX_VCS_SIM
469 /* Set the watchdog timeout to something big. Will be removed when */
470 /* watchdog can be disabled with command line option */
471 move.d 0x7fffffff, $r10
472 jsr CPU_WATCHDOG_TIMEOUT
473 nop
474#endif
421 475
422 ; Initialize registers to increase determinism 476 ; Initialize registers to increase determinism
423 move.d __bss_start, $r0 477 move.d __bss_start, $r0
diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c
index b06813aeb12..c0343c3ea7f 100644
--- a/arch/cris/arch-v32/kernel/kgdb.c
+++ b/arch/cris/arch-v32/kernel/kgdb.c
@@ -381,9 +381,23 @@ static int read_register(char regno, unsigned int *valptr);
381/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */ 381/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */
382int getDebugChar(void); 382int getDebugChar(void);
383 383
384#ifdef CONFIG_ETRAX_VCS_SIM
385int getDebugChar(void)
386{
387 return socketread();
388}
389#endif
390
384/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ 391/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */
385void putDebugChar(int val); 392void putDebugChar(int val);
386 393
394#ifdef CONFIG_ETRAX_VCS_SIM
395void putDebugChar(int val)
396{
397 socketwrite((char *)&val, 1);
398}
399#endif
400
387/* Returns the integer equivalent of a hexadecimal character. */ 401/* Returns the integer equivalent of a hexadecimal character. */
388static int hex(char ch); 402static int hex(char ch);
389 403
@@ -663,7 +677,7 @@ mem2hex(char *buf, unsigned char *mem, int count)
663 /* Valid mem address. */ 677 /* Valid mem address. */
664 for (i = 0; i < count; i++) { 678 for (i = 0; i < count; i++) {
665 ch = *mem++; 679 ch = *mem++;
666 buf = hex_byte_pack(buf, ch); 680 buf = pack_hex_byte(buf, ch);
667 } 681 }
668 } 682 }
669 /* Terminate properly. */ 683 /* Terminate properly. */
@@ -681,7 +695,7 @@ mem2hex_nbo(char *buf, unsigned char *mem, int count)
681 mem += count - 1; 695 mem += count - 1;
682 for (i = 0; i < count; i++) { 696 for (i = 0; i < count; i++) {
683 ch = *mem--; 697 ch = *mem--;
684 buf = hex_byte_pack(buf, ch); 698 buf = pack_hex_byte(buf, ch);
685 } 699 }
686 700
687 /* Terminate properly. */ 701 /* Terminate properly. */
@@ -866,7 +880,7 @@ stub_is_stopped(int sigval)
866 /* Send trap type (converted to signal) */ 880 /* Send trap type (converted to signal) */
867 881
868 *ptr++ = 'T'; 882 *ptr++ = 'T';
869 ptr = hex_byte_pack(ptr, sigval); 883 ptr = pack_hex_byte(ptr, sigval);
870 884
871 if (((reg.exs & 0xff00) >> 8) == 0xc) { 885 if (((reg.exs & 0xff00) >> 8) == 0xc) {
872 886
@@ -974,26 +988,26 @@ stub_is_stopped(int sigval)
974 } 988 }
975 /* Only send PC, frame and stack pointer. */ 989 /* Only send PC, frame and stack pointer. */
976 read_register(PC, &reg_cont); 990 read_register(PC, &reg_cont);
977 ptr = hex_byte_pack(ptr, PC); 991 ptr = pack_hex_byte(ptr, PC);
978 *ptr++ = ':'; 992 *ptr++ = ':';
979 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[PC]); 993 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[PC]);
980 *ptr++ = ';'; 994 *ptr++ = ';';
981 995
982 read_register(R8, &reg_cont); 996 read_register(R8, &reg_cont);
983 ptr = hex_byte_pack(ptr, R8); 997 ptr = pack_hex_byte(ptr, R8);
984 *ptr++ = ':'; 998 *ptr++ = ':';
985 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[R8]); 999 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[R8]);
986 *ptr++ = ';'; 1000 *ptr++ = ';';
987 1001
988 read_register(SP, &reg_cont); 1002 read_register(SP, &reg_cont);
989 ptr = hex_byte_pack(ptr, SP); 1003 ptr = pack_hex_byte(ptr, SP);
990 *ptr++ = ':'; 1004 *ptr++ = ':';
991 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[SP]); 1005 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[SP]);
992 *ptr++ = ';'; 1006 *ptr++ = ';';
993 1007
994 /* Send ERP as well; this will save us an entire register fetch in some cases. */ 1008 /* Send ERP as well; this will save us an entire register fetch in some cases. */
995 read_register(ERP, &reg_cont); 1009 read_register(ERP, &reg_cont);
996 ptr = hex_byte_pack(ptr, ERP); 1010 ptr = pack_hex_byte(ptr, ERP);
997 *ptr++ = ':'; 1011 *ptr++ = ':';
998 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[ERP]); 1012 ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[ERP]);
999 *ptr++ = ';'; 1013 *ptr++ = ';';
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c
index 2b23ef0e445..0570e8ce603 100644
--- a/arch/cris/arch-v32/kernel/process.c
+++ b/arch/cris/arch-v32/kernel/process.c
@@ -16,7 +16,6 @@
16#include <hwregs/reg_map.h> 16#include <hwregs/reg_map.h>
17#include <hwregs/timer_defs.h> 17#include <hwregs/timer_defs.h>
18#include <hwregs/intr_vect_defs.h> 18#include <hwregs/intr_vect_defs.h>
19#include <linux/ptrace.h>
20 19
21extern void stop_watchdog(void); 20extern void stop_watchdog(void);
22 21
@@ -95,6 +94,31 @@ unsigned long thread_saved_pc(struct task_struct *t)
95 return task_pt_regs(t)->erp; 94 return task_pt_regs(t)->erp;
96} 95}
97 96
97static void
98kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
99{
100 fn(arg);
101 do_exit(-1); /* Should never be called, return bad exit value. */
102}
103
104/* Create a kernel thread. */
105int
106kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
107{
108 struct pt_regs regs;
109
110 memset(&regs, 0, sizeof(regs));
111
112 /* Don't use r10 since that is set to 0 in copy_thread. */
113 regs.r11 = (unsigned long) fn;
114 regs.r12 = (unsigned long) arg;
115 regs.erp = (unsigned long) kernel_thread_helper;
116 regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
117
118 /* Create the new process. */
119 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
120}
121
98/* 122/*
99 * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. 123 * Setup the child's kernel stack with a pt_regs and call switch_stack() on it.
100 * It will be unnested during _resume and _ret_from_sys_call when the new thread 124 * It will be unnested during _resume and _ret_from_sys_call when the new thread
@@ -105,42 +129,34 @@ unsigned long thread_saved_pc(struct task_struct *t)
105 */ 129 */
106 130
107extern asmlinkage void ret_from_fork(void); 131extern asmlinkage void ret_from_fork(void);
108extern asmlinkage void ret_from_kernel_thread(void);
109 132
110int 133int
111copy_thread(unsigned long clone_flags, unsigned long usp, 134copy_thread(unsigned long clone_flags, unsigned long usp,
112 unsigned long arg, struct task_struct *p) 135 unsigned long unused,
136 struct task_struct *p, struct pt_regs *regs)
113{ 137{
114 struct pt_regs *childregs = task_pt_regs(p); 138 struct pt_regs *childregs;
115 struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; 139 struct switch_stack *swstack;
116 140
117 /* 141 /*
118 * Put the pt_regs structure at the end of the new kernel stack page and 142 * Put the pt_regs structure at the end of the new kernel stack page and
119 * fix it up. Note: the task_struct doubles as the kernel stack for the 143 * fix it up. Note: the task_struct doubles as the kernel stack for the
120 * task. 144 * task.
121 */ 145 */
122 if (unlikely(p->flags & PF_KTHREAD)) { 146 childregs = task_pt_regs(p);
123 memset(swstack, 0, 147 *childregs = *regs; /* Struct copy of pt_regs. */
124 sizeof(struct switch_stack) + sizeof(struct pt_regs)); 148 p->set_child_tid = p->clear_child_tid = NULL;
125 swstack->r1 = usp;
126 swstack->r2 = arg;
127 childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
128 swstack->return_ip = (unsigned long) ret_from_kernel_thread;
129 p->thread.ksp = (unsigned long) swstack;
130 p->thread.usp = 0;
131 return 0;
132 }
133 *childregs = *current_pt_regs(); /* Struct copy of pt_regs. */
134 childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ 149 childregs->r10 = 0; /* Child returns 0 after a fork/clone. */
135 150
136 /* Set a new TLS ? 151 /* Set a new TLS ?
137 * The TLS is in $mof because it is the 5th argument to sys_clone. 152 * The TLS is in $mof because it is the 5th argument to sys_clone.
138 */ 153 */
139 if (p->mm && (clone_flags & CLONE_SETTLS)) { 154 if (p->mm && (clone_flags & CLONE_SETTLS)) {
140 task_thread_info(p)->tls = childregs->mof; 155 task_thread_info(p)->tls = regs->mof;
141 } 156 }
142 157
143 /* Put the switch stack right below the pt_regs. */ 158 /* Put the switch stack right below the pt_regs. */
159 swstack = ((struct switch_stack *) childregs) - 1;
144 160
145 /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ 161 /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */
146 swstack->r9 = 0; 162 swstack->r9 = 0;
@@ -152,12 +168,76 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
152 swstack->return_ip = (unsigned long) ret_from_fork; 168 swstack->return_ip = (unsigned long) ret_from_fork;
153 169
154 /* Fix the user-mode and kernel-mode stackpointer. */ 170 /* Fix the user-mode and kernel-mode stackpointer. */
155 p->thread.usp = usp ?: rdusp(); 171 p->thread.usp = usp;
156 p->thread.ksp = (unsigned long) swstack; 172 p->thread.ksp = (unsigned long) swstack;
157 173
158 return 0; 174 return 0;
159} 175}
160 176
177/*
178 * Be aware of the "magic" 7th argument in the four system-calls below.
179 * They need the latest stackframe, which is put as the 7th argument by
180 * entry.S. The previous arguments are dummies or actually used, but need
181 * to be defined to reach the 7th argument.
182 *
183 * N.B.: Another method to get the stackframe is to use current_regs(). But
184 * it returns the latest stack-frame stacked when going from _user mode_ and
185 * some of these (at least sys_clone) are called from kernel-mode sometimes
186 * (for example during kernel_thread, above) and thus cannot use it. Thus,
187 * to be sure not to get any surprises, we use the method for the other calls
188 * as well.
189 */
190asmlinkage int
191sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
192 struct pt_regs *regs)
193{
194 return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
195}
196
197/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
198asmlinkage int
199sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid,
200 unsigned long tls, long srp, struct pt_regs *regs)
201{
202 if (!newusp)
203 newusp = rdusp();
204
205 return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
206}
207
208/*
209 * vfork is a system call in i386 because of register-pressure - maybe
210 * we can remove it and handle it in libc but we put it here until then.
211 */
212asmlinkage int
213sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
214 struct pt_regs *regs)
215{
216 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
217}
218
219/* sys_execve() executes a new program. */
220asmlinkage int
221sys_execve(const char *fname,
222 const char *const *argv,
223 const char *const *envp, long r13, long mof, long srp,
224 struct pt_regs *regs)
225{
226 int error;
227 char *filename;
228
229 filename = getname(fname);
230 error = PTR_ERR(filename);
231
232 if (IS_ERR(filename))
233 goto out;
234
235 error = do_execve(filename, argv, envp, regs);
236 putname(filename);
237 out:
238 return error;
239}
240
161unsigned long 241unsigned long
162get_wchan(struct task_struct *p) 242get_wchan(struct task_struct *p)
163{ 243{
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index f085229cf87..511ece94a57 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -15,6 +15,7 @@
15#include <asm/uaccess.h> 15#include <asm/uaccess.h>
16#include <asm/page.h> 16#include <asm/page.h>
17#include <asm/pgtable.h> 17#include <asm/pgtable.h>
18#include <asm/system.h>
18#include <asm/processor.h> 19#include <asm/processor.h>
19#include <arch/hwregs/supp_reg.h> 20#include <arch/hwregs/supp_reg.h>
20 21
@@ -114,6 +115,8 @@ void user_disable_single_step(struct task_struct *child)
114void 115void
115ptrace_disable(struct task_struct *child) 116ptrace_disable(struct task_struct *child)
116{ 117{
118 unsigned long tmp;
119
117 /* Deconfigure SPC and S-bit. */ 120 /* Deconfigure SPC and S-bit. */
118 user_disable_single_step(child); 121 user_disable_single_step(child);
119 put_reg(child, PT_SPC, 0); 122 put_reg(child, PT_SPC, 0);
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index b60d1b65a42..ce4ab1a5552 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -24,6 +24,9 @@
24 24
25extern unsigned long cris_signal_return_page; 25extern unsigned long cris_signal_return_page;
26 26
27/* Flag to check if a signal is blockable. */
28#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
29
27/* 30/*
28 * A syscall in CRIS is really a "break 13" instruction, which is 2 31 * A syscall in CRIS is really a "break 13" instruction, which is 2
29 * bytes. The registers is manipulated so upon return the instruction 32 * bytes. The registers is manipulated so upon return the instruction
@@ -56,11 +59,19 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc,
56 * dummy arguments to be able to reach the regs argument. 59 * dummy arguments to be able to reach the regs argument.
57 */ 60 */
58int 61int
59sys_sigsuspend(old_sigset_t mask) 62sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
63 long srp, struct pt_regs *regs)
60{ 64{
61 sigset_t blocked; 65 mask &= _BLOCKABLE;
62 siginitset(&blocked, mask); 66 spin_lock_irq(&current->sighand->siglock);
63 return sigsuspend(&blocked); 67 current->saved_sigmask = current->blocked;
68 siginitset(&current->blocked, mask);
69 recalc_sigpending();
70 spin_unlock_irq(&current->sighand->siglock);
71 current->state = TASK_INTERRUPTIBLE;
72 schedule();
73 set_thread_flag(TIF_RESTORE_SIGMASK);
74 return -ERESTARTNOHAND;
64} 75}
65 76
66int 77int
@@ -76,11 +87,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
76 87
77 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 88 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
78 __get_user(newk.sa.sa_handler, &act->sa_handler) || 89 __get_user(newk.sa.sa_handler, &act->sa_handler) ||
79 __get_user(newk.sa.sa_restorer, &act->sa_restorer) || 90 __get_user(newk.sa.sa_restorer, &act->sa_restorer))
80 __get_user(newk.sa.sa_flags, &act->sa_flags) ||
81 __get_user(mask, &act->sa_mask))
82 return -EFAULT; 91 return -EFAULT;
83 92
93 __get_user(newk.sa.sa_flags, &act->sa_flags);
94 __get_user(mask, &act->sa_mask);
84 siginitset(&newk.sa.sa_mask, mask); 95 siginitset(&newk.sa.sa_mask, mask);
85 } 96 }
86 97
@@ -89,11 +100,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
89 if (!retval && oact) { 100 if (!retval && oact) {
90 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 101 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
91 __put_user(oldk.sa.sa_handler, &oact->sa_handler) || 102 __put_user(oldk.sa.sa_handler, &oact->sa_handler) ||
92 __put_user(oldk.sa.sa_restorer, &oact->sa_restorer) || 103 __put_user(oldk.sa.sa_restorer, &oact->sa_restorer))
93 __put_user(oldk.sa.sa_flags, &oact->sa_flags) ||
94 __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask))
95 return -EFAULT; 104 return -EFAULT;
96 105
106 __put_user(oldk.sa.sa_flags, &oact->sa_flags);
107 __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask);
97 } 108 }
98 109
99 return retval; 110 return retval;
@@ -164,7 +175,13 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
164 sizeof(frame->extramask)))) 175 sizeof(frame->extramask))))
165 goto badframe; 176 goto badframe;
166 177
167 set_current_blocked(&set); 178 sigdelsetmask(&set, ~_BLOCKABLE);
179 spin_lock_irq(&current->sighand->siglock);
180
181 current->blocked = set;
182
183 recalc_sigpending();
184 spin_unlock_irq(&current->sighand->siglock);
168 185
169 if (restore_sigcontext(regs, &frame->sc)) 186 if (restore_sigcontext(regs, &frame->sc))
170 goto badframe; 187 goto badframe;
@@ -204,7 +221,13 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
204 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 221 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
205 goto badframe; 222 goto badframe;
206 223
207 set_current_blocked(&set); 224 sigdelsetmask(&set, ~_BLOCKABLE);
225 spin_lock_irq(&current->sighand->siglock);
226
227 current->blocked = set;
228
229 recalc_sigpending();
230 spin_unlock_irq(&current->sighand->siglock);
208 231
209 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 232 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
210 goto badframe; 233 goto badframe;
@@ -340,7 +363,10 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
340 return 0; 363 return 0;
341 364
342give_sigsegv: 365give_sigsegv:
343 force_sigsegv(sig, current); 366 if (sig == SIGSEGV)
367 ka->sa.sa_handler = SIG_DFL;
368
369 force_sig(SIGSEGV, current);
344 return -EFAULT; 370 return -EFAULT;
345} 371}
346 372
@@ -424,17 +450,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
424 return 0; 450 return 0;
425 451
426give_sigsegv: 452give_sigsegv:
427 force_sigsegv(sig, current); 453 if (sig == SIGSEGV)
454 ka->sa.sa_handler = SIG_DFL;
455
456 force_sig(SIGSEGV, current);
428 return -EFAULT; 457 return -EFAULT;
429} 458}
430 459
431/* Invoke a signal handler to, well, handle the signal. */ 460/* Invoke a signal handler to, well, handle the signal. */
432static inline void 461static inline int
433handle_signal(int canrestart, unsigned long sig, 462handle_signal(int canrestart, unsigned long sig,
434 siginfo_t *info, struct k_sigaction *ka, 463 siginfo_t *info, struct k_sigaction *ka,
435 struct pt_regs * regs) 464 sigset_t *oldset, struct pt_regs * regs)
436{ 465{
437 sigset_t *oldset = sigmask_to_save();
438 int ret; 466 int ret;
439 467
440 /* Check if this got called from a system call. */ 468 /* Check if this got called from a system call. */
@@ -484,8 +512,20 @@ handle_signal(int canrestart, unsigned long sig,
484 else 512 else
485 ret = setup_frame(sig, ka, oldset, regs); 513 ret = setup_frame(sig, ka, oldset, regs);
486 514
487 if (ret == 0) 515 if (ka->sa.sa_flags & SA_ONESHOT)
488 signal_delivered(sig, info, ka, regs, 0); 516 ka->sa.sa_handler = SIG_DFL;
517
518 if (ret == 0) {
519 spin_lock_irq(&current->sighand->siglock);
520 sigorsets(&current->blocked, &current->blocked,
521 &ka->sa.sa_mask);
522 if (!(ka->sa.sa_flags & SA_NODEFER))
523 sigaddset(&current->blocked, sig);
524 recalc_sigpending();
525 spin_unlock_irq(&current->sighand->siglock);
526 }
527
528 return ret;
489} 529}
490 530
491/* 531/*
@@ -505,6 +545,7 @@ do_signal(int canrestart, struct pt_regs *regs)
505 int signr; 545 int signr;
506 siginfo_t info; 546 siginfo_t info;
507 struct k_sigaction ka; 547 struct k_sigaction ka;
548 sigset_t *oldset;
508 549
509 /* 550 /*
510 * The common case should go fast, which is why this point is 551 * The common case should go fast, which is why this point is
@@ -514,11 +555,25 @@ do_signal(int canrestart, struct pt_regs *regs)
514 if (!user_mode(regs)) 555 if (!user_mode(regs))
515 return; 556 return;
516 557
558 if (test_thread_flag(TIF_RESTORE_SIGMASK))
559 oldset = &current->saved_sigmask;
560 else
561 oldset = &current->blocked;
562
517 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 563 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
518 564
519 if (signr > 0) { 565 if (signr > 0) {
520 /* Whee! Actually deliver the signal. */ 566 /* Whee! Actually deliver the signal. */
521 handle_signal(canrestart, signr, &info, &ka, regs); 567 if (handle_signal(canrestart, signr, &info, &ka,
568 oldset, regs)) {
569 /* a signal was successfully delivered; the saved
570 * sigmask will have been stored in the signal frame,
571 * and will be restored by sigreturn, so we can simply
572 * clear the TIF_RESTORE_SIGMASK flag */
573 if (test_thread_flag(TIF_RESTORE_SIGMASK))
574 clear_thread_flag(TIF_RESTORE_SIGMASK);
575 }
576
522 return; 577 return;
523 } 578 }
524 579
@@ -539,7 +594,10 @@ do_signal(int canrestart, struct pt_regs *regs)
539 594
540 /* if there's no signal to deliver, we just put the saved sigmask 595 /* if there's no signal to deliver, we just put the saved sigmask
541 * back */ 596 * back */
542 restore_saved_sigmask(); 597 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
598 clear_thread_flag(TIF_RESTORE_SIGMASK);
599 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
600 }
543} 601}
544 602
545asmlinkage void 603asmlinkage void
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 04a16edd540..0b99df72d2a 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -84,7 +84,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
84 cpumask_set_cpu(i, &phys_cpu_present_map); 84 cpumask_set_cpu(i, &phys_cpu_present_map);
85} 85}
86 86
87void smp_prepare_boot_cpu(void) 87void __devinit smp_prepare_boot_cpu(void)
88{ 88{
89 /* PGD pointer has moved after per_cpu initialization so 89 /* PGD pointer has moved after per_cpu initialization so
90 * update the MMU. 90 * update the MMU.
@@ -108,12 +108,17 @@ void __init smp_cpus_done(unsigned int max_cpus)
108 108
109/* Bring one cpu online.*/ 109/* Bring one cpu online.*/
110static int __init 110static int __init
111smp_boot_one_cpu(int cpuid, struct task_struct idle) 111smp_boot_one_cpu(int cpuid)
112{ 112{
113 unsigned timeout; 113 unsigned timeout;
114 struct task_struct *idle;
114 cpumask_t cpu_mask; 115 cpumask_t cpu_mask;
115 116
116 cpumask_clear(&cpu_mask); 117 cpumask_clear(&cpu_mask);
118 idle = fork_idle(cpuid);
119 if (IS_ERR(idle))
120 panic("SMP: fork failed for CPU:%d", cpuid);
121
117 task_thread_info(idle)->cpu = cpuid; 122 task_thread_info(idle)->cpu = cpuid;
118 123
119 /* Information to the CPU that is about to boot */ 124 /* Information to the CPU that is about to boot */
@@ -137,6 +142,9 @@ smp_boot_one_cpu(int cpuid, struct task_struct idle)
137 barrier(); 142 barrier();
138 } 143 }
139 144
145 put_task_struct(idle);
146 idle = NULL;
147
140 printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); 148 printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
141 return -1; 149 return -1;
142} 150}
@@ -199,9 +207,9 @@ int setup_profiling_timer(unsigned int multiplier)
199 */ 207 */
200unsigned long cache_decay_ticks = 1; 208unsigned long cache_decay_ticks = 1;
201 209
202int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) 210int __cpuinit __cpu_up(unsigned int cpu)
203{ 211{
204 smp_boot_one_cpu(cpu, tidle); 212 smp_boot_one_cpu(cpu);
205 return cpu_online(cpu) ? 0 : -ENOSYS; 213 return cpu_online(cpu) ? 0 : -ENOSYS;
206} 214}
207 215
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index 8c4b45efd7b..bb978ede898 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -18,6 +18,7 @@
18#include <asm/signal.h> 18#include <asm/signal.h>
19#include <asm/io.h> 19#include <asm/io.h>
20#include <asm/delay.h> 20#include <asm/delay.h>
21#include <asm/rtc.h>
21#include <asm/irq.h> 22#include <asm/irq.h>
22#include <asm/irq_regs.h> 23#include <asm/irq_regs.h>
23 24
@@ -46,12 +47,14 @@ static struct clocksource cont_rotime = {
46 .rating = 300, 47 .rating = 300,
47 .read = read_cont_rotime, 48 .read = read_cont_rotime,
48 .mask = CLOCKSOURCE_MASK(32), 49 .mask = CLOCKSOURCE_MASK(32),
50 .shift = 10,
49 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 51 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
50}; 52};
51 53
52static int __init etrax_init_cont_rotime(void) 54static int __init etrax_init_cont_rotime(void)
53{ 55{
54 clocksource_register_khz(&cont_rotime, 100000); 56 cont_rotime.mult = clocksource_khz2mult(100000, cont_rotime.shift);
57 clocksource_register(&cont_rotime);
55 return 0; 58 return 0;
56} 59}
57arch_initcall(etrax_init_cont_rotime); 60arch_initcall(etrax_init_cont_rotime);
@@ -66,6 +69,7 @@ unsigned long timer_regs[NR_CPUS] =
66}; 69};
67 70
68extern int set_rtc_mmss(unsigned long nowtime); 71extern int set_rtc_mmss(unsigned long nowtime);
72extern int have_rtc;
69 73
70#ifdef CONFIG_CPU_FREQ 74#ifdef CONFIG_CPU_FREQ
71static int 75static int
@@ -263,6 +267,11 @@ void __init time_init(void)
263 */ 267 */
264 loops_per_usec = 50; 268 loops_per_usec = 50;
265 269
270 if(RTC_INIT() < 0)
271 have_rtc = 0;
272 else
273 have_rtc = 1;
274
266 /* Start CPU local timer. */ 275 /* Start CPU local timer. */
267 cris_timer_init(); 276 cris_timer_init();
268 277