diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/cris/arch-v32/kernel | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'arch/cris/arch-v32/kernel')
| -rw-r--r-- | arch/cris/arch-v32/kernel/debugport.c | 1 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/entry.S | 22 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/fasttimer.c | 1 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/head.S | 58 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/kgdb.c | 28 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/process.c | 118 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/ptrace.c | 3 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/signal.c | 100 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/smp.c | 16 | ||||
| -rw-r--r-- | arch/cris/arch-v32/kernel/time.c | 11 |
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 | ||
| 89 | ret_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 |
| 101 | ret_from_intr: | 88 | ret_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 | ||
| 536 | kernel_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 |
| 40 | tstart: | 47 | tstart: |
| 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 | ||
| 371 | 4: | 415 | 4: |
| 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 */ |
| 382 | int getDebugChar(void); | 382 | int getDebugChar(void); |
| 383 | 383 | ||
| 384 | #ifdef CONFIG_ETRAX_VCS_SIM | ||
| 385 | int 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 */ |
| 385 | void putDebugChar(int val); | 392 | void putDebugChar(int val); |
| 386 | 393 | ||
| 394 | #ifdef CONFIG_ETRAX_VCS_SIM | ||
| 395 | void 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. */ |
| 388 | static int hex(char ch); | 402 | static 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, ®_cont); | 990 | read_register(PC, ®_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 *)®_cont, register_size[PC]); | 993 | ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[PC]); |
| 980 | *ptr++ = ';'; | 994 | *ptr++ = ';'; |
| 981 | 995 | ||
| 982 | read_register(R8, ®_cont); | 996 | read_register(R8, ®_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 *)®_cont, register_size[R8]); | 999 | ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[R8]); |
| 986 | *ptr++ = ';'; | 1000 | *ptr++ = ';'; |
| 987 | 1001 | ||
| 988 | read_register(SP, ®_cont); | 1002 | read_register(SP, ®_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 *)®_cont, register_size[SP]); | 1005 | ptr = mem2hex(ptr, (unsigned char *)®_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, ®_cont); | 1009 | read_register(ERP, ®_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 *)®_cont, register_size[ERP]); | 1012 | ptr = mem2hex(ptr, (unsigned char *)®_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 | ||
| 21 | extern void stop_watchdog(void); | 20 | extern 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 | ||
| 97 | static void | ||
| 98 | kernel_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. */ | ||
| 105 | int | ||
| 106 | kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 107 | { | ||
| 108 | struct pt_regs regs; | ||
| 109 | |||
| 110 | memset(®s, 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, ®s, 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 | ||
| 107 | extern asmlinkage void ret_from_fork(void); | 131 | extern asmlinkage void ret_from_fork(void); |
| 108 | extern asmlinkage void ret_from_kernel_thread(void); | ||
| 109 | 132 | ||
| 110 | int | 133 | int |
| 111 | copy_thread(unsigned long clone_flags, unsigned long usp, | 134 | copy_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 | */ | ||
| 190 | asmlinkage int | ||
| 191 | sys_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? */ | ||
| 198 | asmlinkage int | ||
| 199 | sys_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 | */ | ||
| 212 | asmlinkage int | ||
| 213 | sys_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. */ | ||
| 220 | asmlinkage int | ||
| 221 | sys_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 | |||
| 161 | unsigned long | 241 | unsigned long |
| 162 | get_wchan(struct task_struct *p) | 242 | get_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) | |||
| 114 | void | 115 | void |
| 115 | ptrace_disable(struct task_struct *child) | 116 | ptrace_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 | ||
| 25 | extern unsigned long cris_signal_return_page; | 25 | extern 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 | */ |
| 58 | int | 61 | int |
| 59 | sys_sigsuspend(old_sigset_t mask) | 62 | sys_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(¤t->sighand->siglock); |
| 63 | return sigsuspend(&blocked); | 67 | current->saved_sigmask = current->blocked; |
| 68 | siginitset(¤t->blocked, mask); | ||
| 69 | recalc_sigpending(); | ||
| 70 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 71 | current->state = TASK_INTERRUPTIBLE; | ||
| 72 | schedule(); | ||
| 73 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 74 | return -ERESTARTNOHAND; | ||
| 64 | } | 75 | } |
| 65 | 76 | ||
| 66 | int | 77 | int |
| @@ -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(¤t->sighand->siglock); | ||
| 180 | |||
| 181 | current->blocked = set; | ||
| 182 | |||
| 183 | recalc_sigpending(); | ||
| 184 | spin_unlock_irq(¤t->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(¤t->sighand->siglock); | ||
| 226 | |||
| 227 | current->blocked = set; | ||
| 228 | |||
| 229 | recalc_sigpending(); | ||
| 230 | spin_unlock_irq(¤t->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 | ||
| 342 | give_sigsegv: | 365 | give_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 | ||
| 426 | give_sigsegv: | 452 | give_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. */ |
| 432 | static inline void | 461 | static inline int |
| 433 | handle_signal(int canrestart, unsigned long sig, | 462 | handle_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(¤t->sighand->siglock); | ||
| 520 | sigorsets(¤t->blocked, ¤t->blocked, | ||
| 521 | &ka->sa.sa_mask); | ||
| 522 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
| 523 | sigaddset(¤t->blocked, sig); | ||
| 524 | recalc_sigpending(); | ||
| 525 | spin_unlock_irq(¤t->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 = ¤t->saved_sigmask; | ||
| 560 | else | ||
| 561 | oldset = ¤t->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, ¤t->saved_sigmask, NULL); | ||
| 600 | } | ||
| 543 | } | 601 | } |
| 544 | 602 | ||
| 545 | asmlinkage void | 603 | asmlinkage 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 | ||
| 87 | void smp_prepare_boot_cpu(void) | 87 | void __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.*/ |
| 110 | static int __init | 110 | static int __init |
| 111 | smp_boot_one_cpu(int cpuid, struct task_struct idle) | 111 | smp_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 | */ |
| 200 | unsigned long cache_decay_ticks = 1; | 208 | unsigned long cache_decay_ticks = 1; |
| 201 | 209 | ||
| 202 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) | 210 | int __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 | ||
| 52 | static int __init etrax_init_cont_rotime(void) | 54 | static 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 | } |
| 57 | arch_initcall(etrax_init_cont_rotime); | 60 | arch_initcall(etrax_init_cont_rotime); |
| @@ -66,6 +69,7 @@ unsigned long timer_regs[NR_CPUS] = | |||
| 66 | }; | 69 | }; |
| 67 | 70 | ||
| 68 | extern int set_rtc_mmss(unsigned long nowtime); | 71 | extern int set_rtc_mmss(unsigned long nowtime); |
| 72 | extern int have_rtc; | ||
| 69 | 73 | ||
| 70 | #ifdef CONFIG_CPU_FREQ | 74 | #ifdef CONFIG_CPU_FREQ |
| 71 | static int | 75 | static 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 | ||
