aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/Makefile1
-rw-r--r--arch/sparc/kernel/asm-offsets.c6
-rw-r--r--arch/sparc/kernel/entry.S127
-rw-r--r--arch/sparc/kernel/head.S9
-rw-r--r--arch/sparc/kernel/kgdb.c164
-rw-r--r--arch/sparc/kernel/process.c25
-rw-r--r--arch/sparc/kernel/ptrace.c6
-rw-r--r--arch/sparc/kernel/rtrap.S11
-rw-r--r--arch/sparc/kernel/setup.c5
-rw-r--r--arch/sparc/kernel/signal.c84
-rw-r--r--arch/sparc/kernel/sparc-stub.c724
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c2
-rw-r--r--arch/sparc/kernel/sun4d_smp.c32
-rw-r--r--arch/sparc/kernel/sun4m_smp.c45
-rw-r--r--arch/sparc/kernel/sys_sparc.c51
15 files changed, 299 insertions, 993 deletions
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 59700aaaae93..6e03a2a7863c 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_PCI) += ebus.o
25obj-$(CONFIG_SUN_PM) += apc.o pmc.o 25obj-$(CONFIG_SUN_PM) += apc.o pmc.o
26obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o 26obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o
27obj-$(CONFIG_SPARC_LED) += led.o 27obj-$(CONFIG_SPARC_LED) += led.o
28obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
index 6773ed76e414..cd3f7694e9b9 100644
--- a/arch/sparc/kernel/asm-offsets.c
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -12,11 +12,7 @@
12 12
13#include <linux/sched.h> 13#include <linux/sched.h>
14// #include <linux/mm.h> 14// #include <linux/mm.h>
15 15#include <linux/kbuild.h>
16#define DEFINE(sym, val) \
17 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
18
19#define BLANK() asm volatile("\n->" : : )
20 16
21int foo(void) 17int foo(void)
22{ 18{
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 484c83d23eef..4bcfe54f878d 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -12,7 +12,6 @@
12#include <asm/head.h> 12#include <asm/head.h>
13#include <asm/asi.h> 13#include <asm/asi.h>
14#include <asm/smp.h> 14#include <asm/smp.h>
15#include <asm/kgdb.h>
16#include <asm/contregs.h> 15#include <asm/contregs.h>
17#include <asm/ptrace.h> 16#include <asm/ptrace.h>
18#include <asm/asm-offsets.h> 17#include <asm/asm-offsets.h>
@@ -45,91 +44,20 @@
45 _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ 44 _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
46 _RS; _RS; _RS; _RS; _RS; _RS; _RS; 45 _RS; _RS; _RS; _RS; _RS; _RS; _RS;
47 46
48/* First, KGDB low level things. This is a rewrite
49 * of the routines found in the sparc-stub.c asm() statement
50 * from the gdb distribution. This is also dual-purpose
51 * as a software trap for userlevel programs.
52 */
53 .data
54 .align 4
55
56in_trap_handler:
57 .word 0
58
59 .text 47 .text
60 .align 4
61 48
62#if 0 /* kgdb is dropped from 2.5.33 */ 49#ifdef CONFIG_KGDB
63! This function is called when any SPARC trap (except window overflow or 50 .align 4
64! underflow) occurs. It makes sure that the invalid register window is still 51 .globl arch_kgdb_breakpoint
65! available before jumping into C code. It will also restore the world if you 52 .type arch_kgdb_breakpoint,#function
66! return from handle_exception. 53arch_kgdb_breakpoint:
67 54 ta 0x7d
68 .globl trap_low 55 retl
69trap_low: 56 nop
70 rd %wim, %l3 57 .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
71 SAVE_ALL
72
73 sethi %hi(in_trap_handler), %l4
74 ld [%lo(in_trap_handler) + %l4], %l5
75 inc %l5
76 st %l5, [%lo(in_trap_handler) + %l4]
77
78 /* Make sure kgdb sees the same state we just saved. */
79 LOAD_PT_GLOBALS(sp)
80 LOAD_PT_INS(sp)
81 ld [%sp + STACKFRAME_SZ + PT_Y], %l4
82 ld [%sp + STACKFRAME_SZ + PT_WIM], %l3
83 ld [%sp + STACKFRAME_SZ + PT_PSR], %l0
84 ld [%sp + STACKFRAME_SZ + PT_PC], %l1
85 ld [%sp + STACKFRAME_SZ + PT_NPC], %l2
86 rd %tbr, %l5 /* Never changes... */
87
88 /* Make kgdb exception frame. */
89 sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
90 ! + hidden arg + arg spill
91 ! + doubleword alignment
92 ! + registers[72] local var
93 SAVE_KGDB_GLOBALS(sp)
94 SAVE_KGDB_INS(sp)
95 SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
96
97 /* We are increasing PIL, so two writes. */
98 or %l0, PSR_PIL, %l0
99 wr %l0, 0, %psr
100 WRITE_PAUSE
101 wr %l0, PSR_ET, %psr
102 WRITE_PAUSE
103
104 call handle_exception
105 add %sp, STACKFRAME_SZ, %o0 ! Pass address of registers
106
107 /* Load new kgdb register set. */
108 LOAD_KGDB_GLOBALS(sp)
109 LOAD_KGDB_INS(sp)
110 LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
111 wr %l4, 0x0, %y
112
113 sethi %hi(in_trap_handler), %l4
114 ld [%lo(in_trap_handler) + %l4], %l5
115 dec %l5
116 st %l5, [%lo(in_trap_handler) + %l4]
117
118 add %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
119
120 /* Now take what kgdb did and place it into the pt_regs
121 * frame which SparcLinux RESTORE_ALL understands.,
122 */
123 STORE_PT_INS(sp)
124 STORE_PT_GLOBALS(sp)
125 STORE_PT_YREG(sp, g2)
126 STORE_PT_PRIV(sp, l0, l1, l2)
127
128 RESTORE_ALL
129#endif 58#endif
130 59
131#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) 60#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
132 .text
133 .align 4 61 .align 4
134 .globl floppy_hardint 62 .globl floppy_hardint
135floppy_hardint: 63floppy_hardint:
@@ -1378,6 +1306,8 @@ ret_from_fork:
1378 .align 4 1306 .align 4
1379 .globl linux_sparc_syscall 1307 .globl linux_sparc_syscall
1380linux_sparc_syscall: 1308linux_sparc_syscall:
1309 sethi %hi(PSR_SYSCALL), %l4
1310 or %l0, %l4, %l0
1381 /* Direct access to user regs, must faster. */ 1311 /* Direct access to user regs, must faster. */
1382 cmp %g1, NR_SYSCALLS 1312 cmp %g1, NR_SYSCALLS
1383 bgeu linux_sparc_ni_syscall 1313 bgeu linux_sparc_ni_syscall
@@ -1596,6 +1526,23 @@ breakpoint_trap:
1596 1526
1597 RESTORE_ALL 1527 RESTORE_ALL
1598 1528
1529#ifdef CONFIG_KGDB
1530 .align 4
1531 .globl kgdb_trap_low
1532 .type kgdb_trap_low,#function
1533kgdb_trap_low:
1534 rd %wim,%l3
1535 SAVE_ALL
1536 wr %l0, PSR_ET, %psr
1537 WRITE_PAUSE
1538
1539 call kgdb_trap
1540 add %sp, STACKFRAME_SZ, %o0
1541
1542 RESTORE_ALL
1543 .size kgdb_trap_low,.-kgdb_trap_low
1544#endif
1545
1599 .align 4 1546 .align 4
1600 .globl __handle_exception, flush_patch_exception 1547 .globl __handle_exception, flush_patch_exception
1601__handle_exception: 1548__handle_exception:
@@ -1698,4 +1645,22 @@ pcic_nmi_trap_patch:
1698 1645
1699#endif /* CONFIG_PCI */ 1646#endif /* CONFIG_PCI */
1700 1647
1648 .globl flushw_all
1649flushw_all:
1650 save %sp, -0x40, %sp
1651 save %sp, -0x40, %sp
1652 save %sp, -0x40, %sp
1653 save %sp, -0x40, %sp
1654 save %sp, -0x40, %sp
1655 save %sp, -0x40, %sp
1656 save %sp, -0x40, %sp
1657 restore
1658 restore
1659 restore
1660 restore
1661 restore
1662 restore
1663 ret
1664 restore
1665
1701/* End of entry.S */ 1666/* End of entry.S */
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
index b7f1e81c8ff2..8bec05fa5795 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -191,7 +191,8 @@ t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xe
191t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 191t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
192t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 192t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
193t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 193t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
194t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd) 194t_badfc:BAD_TRAP(0xfc)
195t_kgdb: KGDB_TRAP(0xfd)
195dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */ 196dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
196dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */ 197dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
197 198
@@ -267,7 +268,7 @@ trapbase_cpu1:
267 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 268 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
268 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 269 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
269 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 270 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
270 BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) 271 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
271 272
272trapbase_cpu2: 273trapbase_cpu2:
273 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) 274 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
@@ -335,7 +336,7 @@ trapbase_cpu2:
335 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 336 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
336 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 337 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
337 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 338 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
338 BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) 339 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
339 340
340trapbase_cpu3: 341trapbase_cpu3:
341 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) 342 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
@@ -403,7 +404,7 @@ trapbase_cpu3:
403 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 404 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
404 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 405 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
405 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 406 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
406 BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) 407 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
407 408
408#endif 409#endif
409 .align PAGE_SIZE 410 .align PAGE_SIZE
diff --git a/arch/sparc/kernel/kgdb.c b/arch/sparc/kernel/kgdb.c
new file mode 100644
index 000000000000..757805ce02ee
--- /dev/null
+++ b/arch/sparc/kernel/kgdb.c
@@ -0,0 +1,164 @@
1/* kgdb.c: KGDB support for 32-bit sparc.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kgdb.h>
7#include <linux/kdebug.h>
8
9#include <asm/kdebug.h>
10#include <asm/ptrace.h>
11#include <asm/irq.h>
12
13extern unsigned long trapbase;
14
15void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
16{
17 struct reg_window *win;
18 int i;
19
20 gdb_regs[GDB_G0] = 0;
21 for (i = 0; i < 15; i++)
22 gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
23
24 win = (struct reg_window *) regs->u_regs[UREG_FP];
25 for (i = 0; i < 8; i++)
26 gdb_regs[GDB_L0 + i] = win->locals[i];
27 for (i = 0; i < 8; i++)
28 gdb_regs[GDB_I0 + i] = win->ins[i];
29
30 for (i = GDB_F0; i <= GDB_F31; i++)
31 gdb_regs[i] = 0;
32
33 gdb_regs[GDB_Y] = regs->y;
34 gdb_regs[GDB_PSR] = regs->psr;
35 gdb_regs[GDB_WIM] = 0;
36 gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
37 gdb_regs[GDB_PC] = regs->pc;
38 gdb_regs[GDB_NPC] = regs->npc;
39 gdb_regs[GDB_FSR] = 0;
40 gdb_regs[GDB_CSR] = 0;
41}
42
43void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
44{
45 struct thread_info *t = task_thread_info(p);
46 struct reg_window *win;
47 int i;
48
49 for (i = GDB_G0; i < GDB_G6; i++)
50 gdb_regs[i] = 0;
51 gdb_regs[GDB_G6] = (unsigned long) t;
52 gdb_regs[GDB_G7] = 0;
53 for (i = GDB_O0; i < GDB_SP; i++)
54 gdb_regs[i] = 0;
55 gdb_regs[GDB_SP] = t->ksp;
56 gdb_regs[GDB_O7] = 0;
57
58 win = (struct reg_window *) t->ksp;
59 for (i = 0; i < 8; i++)
60 gdb_regs[GDB_L0 + i] = win->locals[i];
61 for (i = 0; i < 8; i++)
62 gdb_regs[GDB_I0 + i] = win->ins[i];
63
64 for (i = GDB_F0; i <= GDB_F31; i++)
65 gdb_regs[i] = 0;
66
67 gdb_regs[GDB_Y] = 0;
68
69 gdb_regs[GDB_PSR] = t->kpsr;
70 gdb_regs[GDB_WIM] = t->kwim;
71 gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
72 gdb_regs[GDB_PC] = t->kpc;
73 gdb_regs[GDB_NPC] = t->kpc + 4;
74 gdb_regs[GDB_FSR] = 0;
75 gdb_regs[GDB_CSR] = 0;
76}
77
78void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
79{
80 struct reg_window *win;
81 int i;
82
83 for (i = 0; i < 15; i++)
84 regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
85
86 /* If the PSR register is changing, we have to preserve
87 * the CWP field, otherwise window save/restore explodes.
88 */
89 if (regs->psr != gdb_regs[GDB_PSR]) {
90 unsigned long cwp = regs->psr & PSR_CWP;
91
92 regs->psr = (gdb_regs[GDB_PSR] & ~PSR_CWP) | cwp;
93 }
94
95 regs->pc = gdb_regs[GDB_PC];
96 regs->npc = gdb_regs[GDB_NPC];
97 regs->y = gdb_regs[GDB_Y];
98
99 win = (struct reg_window *) regs->u_regs[UREG_FP];
100 for (i = 0; i < 8; i++)
101 win->locals[i] = gdb_regs[GDB_L0 + i];
102 for (i = 0; i < 8; i++)
103 win->ins[i] = gdb_regs[GDB_I0 + i];
104}
105
106int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
107 char *remcomInBuffer, char *remcomOutBuffer,
108 struct pt_regs *linux_regs)
109{
110 unsigned long addr;
111 char *ptr;
112
113 switch (remcomInBuffer[0]) {
114 case 'c':
115 /* try to read optional parameter, pc unchanged if no parm */
116 ptr = &remcomInBuffer[1];
117 if (kgdb_hex2long(&ptr, &addr)) {
118 linux_regs->pc = addr;
119 linux_regs->npc = addr + 4;
120 }
121 /* fallthru */
122
123 case 'D':
124 case 'k':
125 if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
126 linux_regs->pc = linux_regs->npc;
127 linux_regs->npc += 4;
128 }
129 return 0;
130 }
131 return -1;
132}
133
134extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type);
135
136asmlinkage void kgdb_trap(struct pt_regs *regs)
137{
138 unsigned long flags;
139
140 if (user_mode(regs)) {
141 do_hw_interrupt(regs, 0xfd);
142 return;
143 }
144
145 flushw_all();
146
147 local_irq_save(flags);
148 kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
149 local_irq_restore(flags);
150}
151
152int kgdb_arch_init(void)
153{
154 return 0;
155}
156
157void kgdb_arch_exit(void)
158{
159}
160
161struct kgdb_arch arch_kgdb_ops = {
162 /* Breakpoint instruction: ta 0x7d */
163 .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
164};
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index e7f35198ae34..da48d248cc17 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -419,14 +419,26 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
419 unsigned long stack_size) 419 unsigned long stack_size)
420{ 420{
421 unsigned long parent_tid_ptr, child_tid_ptr; 421 unsigned long parent_tid_ptr, child_tid_ptr;
422 unsigned long orig_i1 = regs->u_regs[UREG_I1];
423 long ret;
422 424
423 parent_tid_ptr = regs->u_regs[UREG_I2]; 425 parent_tid_ptr = regs->u_regs[UREG_I2];
424 child_tid_ptr = regs->u_regs[UREG_I4]; 426 child_tid_ptr = regs->u_regs[UREG_I4];
425 427
426 return do_fork(clone_flags, stack_start, 428 ret = do_fork(clone_flags, stack_start,
427 regs, stack_size, 429 regs, stack_size,
428 (int __user *) parent_tid_ptr, 430 (int __user *) parent_tid_ptr,
429 (int __user *) child_tid_ptr); 431 (int __user *) child_tid_ptr);
432
433 /* If we get an error and potentially restart the system
434 * call, we're screwed because copy_thread() clobbered
435 * the parent's %o1. So detect that case and restore it
436 * here.
437 */
438 if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
439 regs->u_regs[UREG_I1] = orig_i1;
440
441 return ret;
430} 442}
431 443
432/* Copy a Sparc thread. The fork() return value conventions 444/* Copy a Sparc thread. The fork() return value conventions
@@ -626,11 +638,6 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
626 (char __user * __user *)regs->u_regs[base + UREG_I2], 638 (char __user * __user *)regs->u_regs[base + UREG_I2],
627 regs); 639 regs);
628 putname(filename); 640 putname(filename);
629 if (error == 0) {
630 task_lock(current);
631 current->ptrace &= ~PT_DTRACE;
632 task_unlock(current);
633 }
634out: 641out:
635 return error; 642 return error;
636} 643}
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 7f44ae69b29e..81f3b929743f 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -170,8 +170,8 @@ static int genregs32_set(struct task_struct *target,
170 switch (pos) { 170 switch (pos) {
171 case 32: /* PSR */ 171 case 32: /* PSR */
172 psr = regs->psr; 172 psr = regs->psr;
173 psr &= ~PSR_ICC; 173 psr &= ~(PSR_ICC | PSR_SYSCALL);
174 psr |= (reg & PSR_ICC); 174 psr |= (reg & (PSR_ICC | PSR_SYSCALL));
175 regs->psr = psr; 175 regs->psr = psr;
176 break; 176 break;
177 case 33: /* PC */ 177 case 33: /* PC */
@@ -441,6 +441,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
441 break; 441 break;
442 442
443 default: 443 default:
444 if (request == PTRACE_SPARC_DETACH)
445 request = PTRACE_DETACH;
444 ret = ptrace_request(child, request, addr, data); 446 ret = ptrace_request(child, request, addr, data);
445 break; 447 break;
446 } 448 }
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index 77ca6fd81253..ab818cdc4cc0 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -50,8 +50,9 @@ rtrap_7win_patch5: and %g1, 0x7f, %g1
50ret_trap_entry: 50ret_trap_entry:
51ret_trap_lockless_ipi: 51ret_trap_lockless_ipi:
52 andcc %t_psr, PSR_PS, %g0 52 andcc %t_psr, PSR_PS, %g0
53 sethi %hi(PSR_SYSCALL), %g1
53 be 1f 54 be 1f
54 nop 55 andn %t_psr, %g1, %t_psr
55 56
56 wr %t_psr, 0x0, %psr 57 wr %t_psr, 0x0, %psr
57 b ret_trap_kernel 58 b ret_trap_kernel
@@ -73,7 +74,6 @@ signal_p:
73 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 74 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
74 75
75 mov %l5, %o1 76 mov %l5, %o1
76 mov %l6, %o2
77 call do_signal 77 call do_signal
78 add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr 78 add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
79 79
@@ -81,6 +81,8 @@ signal_p:
81 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 81 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
82 clr %l6 82 clr %l6
83ret_trap_continue: 83ret_trap_continue:
84 sethi %hi(PSR_SYSCALL), %g1
85 andn %t_psr, %g1, %t_psr
84 wr %t_psr, 0x0, %psr 86 wr %t_psr, 0x0, %psr
85 WRITE_PAUSE 87 WRITE_PAUSE
86 88
@@ -137,8 +139,9 @@ ret_trap_userwins_ok:
137 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) 139 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
138 or %t_pc, %t_npc, %g2 140 or %t_pc, %t_npc, %g2
139 andcc %g2, 0x3, %g0 141 andcc %g2, 0x3, %g0
142 sethi %hi(PSR_SYSCALL), %g2
140 be 1f 143 be 1f
141 nop 144 andn %t_psr, %g2, %t_psr
142 145
143 b ret_trap_unaligned_pc 146 b ret_trap_unaligned_pc
144 add %sp, STACKFRAME_SZ, %o0 147 add %sp, STACKFRAME_SZ, %o0
@@ -201,6 +204,8 @@ rtrap_patch5: and %g1, 0xff, %g1
2011: 2041:
202 LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 205 LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
2032: 2062:
207 sethi %hi(PSR_SYSCALL), %twin_tmp1
208 andn %t_psr, %twin_tmp1, %t_psr
204 wr %t_psr, 0x0, %psr 209 wr %t_psr, 0x0, %psr
205 WRITE_PAUSE 210 WRITE_PAUSE
206 211
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 3c13137685da..8a55c4f0df84 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -180,11 +180,9 @@ static void __init boot_flags_init(char *commands)
180 180
181/* This routine will in the future do all the nasty prom stuff 181/* This routine will in the future do all the nasty prom stuff
182 * to probe for the mmu type and its parameters, etc. This will 182 * to probe for the mmu type and its parameters, etc. This will
183 * also be where SMP things happen plus the Sparc specific memory 183 * also be where SMP things happen.
184 * physical memory probe as on the alpha.
185 */ 184 */
186 185
187extern int prom_probe_memory(void);
188extern void sun4c_probe_vac(void); 186extern void sun4c_probe_vac(void);
189extern char cputypval; 187extern char cputypval;
190extern unsigned long start, end; 188extern unsigned long start, end;
@@ -268,7 +266,6 @@ void __init setup_arch(char **cmdline_p)
268 if (ARCH_SUN4C_SUN4) 266 if (ARCH_SUN4C_SUN4)
269 sun4c_probe_vac(); 267 sun4c_probe_vac();
270 load_mmu(); 268 load_mmu();
271 (void) prom_probe_memory();
272 269
273 phys_base = 0xffffffffUL; 270 phys_base = 0xffffffffUL;
274 highest_paddr = 0UL; 271 highest_paddr = 0UL;
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 3c312290c3c2..3fd1df9f9ba7 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -145,6 +145,9 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
145 regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) 145 regs->psr = (up_psr & ~(PSR_ICC | PSR_EF))
146 | (regs->psr & (PSR_ICC | PSR_EF)); 146 | (regs->psr & (PSR_ICC | PSR_EF));
147 147
148 /* Prevent syscall restart. */
149 pt_regs_clear_syscall(regs);
150
148 err |= __get_user(fpu_save, &sf->fpu_save); 151 err |= __get_user(fpu_save, &sf->fpu_save);
149 152
150 if (fpu_save) 153 if (fpu_save)
@@ -199,6 +202,9 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
199 202
200 regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC); 203 regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC);
201 204
205 /* Prevent syscall restart. */
206 pt_regs_clear_syscall(regs);
207
202 err |= __get_user(fpu_save, &sf->fpu_save); 208 err |= __get_user(fpu_save, &sf->fpu_save);
203 209
204 if (fpu_save) 210 if (fpu_save)
@@ -245,15 +251,29 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen)
245 251
246static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) 252static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
247{ 253{
248 unsigned long sp; 254 unsigned long sp = regs->u_regs[UREG_FP];
249 255
250 sp = regs->u_regs[UREG_FP]; 256 /*
257 * If we are on the alternate signal stack and would overflow it, don't.
258 * Return an always-bogus address instead so we will die with SIGSEGV.
259 */
260 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
261 return (void __user *) -1L;
251 262
252 /* This is the X/Open sanctioned signal stack switching. */ 263 /* This is the X/Open sanctioned signal stack switching. */
253 if (sa->sa_flags & SA_ONSTACK) { 264 if (sa->sa_flags & SA_ONSTACK) {
254 if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) 265 if (sas_ss_flags(sp) == 0)
255 sp = current->sas_ss_sp + current->sas_ss_size; 266 sp = current->sas_ss_sp + current->sas_ss_size;
256 } 267 }
268
269 /* Always align the stack frame. This handles two cases. First,
270 * sigaltstack need not be mindful of platform specific stack
271 * alignment. Second, if we took this signal because the stack
272 * is not aligned properly, we'd like to take the signal cleanly
273 * and report that.
274 */
275 sp &= ~7UL;
276
257 return (void __user *)(sp - framesize); 277 return (void __user *)(sp - framesize);
258} 278}
259 279
@@ -493,26 +513,36 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
493 * want to handle. Thus you cannot kill init even with a SIGKILL even by 513 * want to handle. Thus you cannot kill init even with a SIGKILL even by
494 * mistake. 514 * mistake.
495 */ 515 */
496asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) 516asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
497{ 517{
498 siginfo_t info;
499 struct sparc_deliver_cookie cookie;
500 struct k_sigaction ka; 518 struct k_sigaction ka;
501 int signr; 519 int restart_syscall;
502 sigset_t *oldset; 520 sigset_t *oldset;
521 siginfo_t info;
522 int signr;
503 523
504 cookie.restart_syscall = restart_syscall; 524 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
505 cookie.orig_i0 = orig_i0; 525 restart_syscall = 1;
526 else
527 restart_syscall = 0;
506 528
507 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 529 if (test_thread_flag(TIF_RESTORE_SIGMASK))
508 oldset = &current->saved_sigmask; 530 oldset = &current->saved_sigmask;
509 else 531 else
510 oldset = &current->blocked; 532 oldset = &current->blocked;
511 533
512 signr = get_signal_to_deliver(&info, &ka, regs, &cookie); 534 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
535
536 /* If the debugger messes with the program counter, it clears
537 * the software "in syscall" bit, directing us to not perform
538 * a syscall restart.
539 */
540 if (restart_syscall && !pt_regs_is_syscall(regs))
541 restart_syscall = 0;
542
513 if (signr > 0) { 543 if (signr > 0) {
514 if (cookie.restart_syscall) 544 if (restart_syscall)
515 syscall_restart(cookie.orig_i0, regs, &ka.sa); 545 syscall_restart(orig_i0, regs, &ka.sa);
516 handle_signal(signr, &ka, &info, oldset, regs); 546 handle_signal(signr, &ka, &info, oldset, regs);
517 547
518 /* a signal was successfully delivered; the saved 548 /* a signal was successfully delivered; the saved
@@ -524,16 +554,16 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
524 clear_thread_flag(TIF_RESTORE_SIGMASK); 554 clear_thread_flag(TIF_RESTORE_SIGMASK);
525 return; 555 return;
526 } 556 }
527 if (cookie.restart_syscall && 557 if (restart_syscall &&
528 (regs->u_regs[UREG_I0] == ERESTARTNOHAND || 558 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
529 regs->u_regs[UREG_I0] == ERESTARTSYS || 559 regs->u_regs[UREG_I0] == ERESTARTSYS ||
530 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { 560 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
531 /* replay the system call when we are done */ 561 /* replay the system call when we are done */
532 regs->u_regs[UREG_I0] = cookie.orig_i0; 562 regs->u_regs[UREG_I0] = orig_i0;
533 regs->pc -= 4; 563 regs->pc -= 4;
534 regs->npc -= 4; 564 regs->npc -= 4;
535 } 565 }
536 if (cookie.restart_syscall && 566 if (restart_syscall &&
537 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { 567 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
538 regs->u_regs[UREG_G1] = __NR_restart_syscall; 568 regs->u_regs[UREG_G1] = __NR_restart_syscall;
539 regs->pc -= 4; 569 regs->pc -= 4;
@@ -585,27 +615,3 @@ do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr,
585out: 615out:
586 return ret; 616 return ret;
587} 617}
588
589void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
590{
591 struct sparc_deliver_cookie *cp = cookie;
592
593 if (cp->restart_syscall &&
594 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
595 regs->u_regs[UREG_I0] == ERESTARTSYS ||
596 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
597 /* replay the system call when we are done */
598 regs->u_regs[UREG_I0] = cp->orig_i0;
599 regs->pc -= 4;
600 regs->npc -= 4;
601 cp->restart_syscall = 0;
602 }
603
604 if (cp->restart_syscall &&
605 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
606 regs->u_regs[UREG_G1] = __NR_restart_syscall;
607 regs->pc -= 4;
608 regs->npc -= 4;
609 cp->restart_syscall = 0;
610 }
611}
diff --git a/arch/sparc/kernel/sparc-stub.c b/arch/sparc/kernel/sparc-stub.c
deleted file mode 100644
index e84f815e6903..000000000000
--- a/arch/sparc/kernel/sparc-stub.c
+++ /dev/null
@@ -1,724 +0,0 @@
1/* $Id: sparc-stub.c,v 1.28 2001/10/30 04:54:21 davem Exp $
2 * sparc-stub.c: KGDB support for the Linux kernel.
3 *
4 * Modifications to run under Linux
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 *
7 * This file originally came from the gdb sources, and the
8 * copyright notices have been retained below.
9 */
10
11/****************************************************************************
12
13 THIS SOFTWARE IS NOT COPYRIGHTED
14
15 HP offers the following for use in the public domain. HP makes no
16 warranty with regard to the software or its performance and the
17 user accepts the software "AS IS" with all faults.
18
19 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
20 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
23****************************************************************************/
24
25/****************************************************************************
26 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
27 *
28 * Module name: remcom.c $
29 * Revision: 1.34 $
30 * Date: 91/03/09 12:29:49 $
31 * Contributor: Lake Stevens Instrument Division$
32 *
33 * Description: low level support for gdb debugger. $
34 *
35 * Considerations: only works on target hardware $
36 *
37 * Written by: Glenn Engel $
38 * ModuleState: Experimental $
39 *
40 * NOTES: See Below $
41 *
42 * Modified for SPARC by Stu Grossman, Cygnus Support.
43 *
44 * This code has been extensively tested on the Fujitsu SPARClite demo board.
45 *
46 * To enable debugger support, two things need to happen. One, a
47 * call to set_debug_traps() is necessary in order to allow any breakpoints
48 * or error conditions to be properly intercepted and reported to gdb.
49 * Two, a breakpoint needs to be generated to begin communication. This
50 * is most easily accomplished by a call to breakpoint(). Breakpoint()
51 * simulates a breakpoint by executing a trap #1.
52 *
53 *************
54 *
55 * The following gdb commands are supported:
56 *
57 * command function Return value
58 *
59 * g return the value of the CPU registers hex data or ENN
60 * G set the value of the CPU registers OK or ENN
61 *
62 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
63 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
64 *
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
67 *
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
70 *
71 * k kill
72 *
73 * ? What was the last sigval ? SNN (signal NN)
74 *
75 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
76 * baud rate
77 *
78 * All commands and responses are sent with a packet which includes a
79 * checksum. A packet consists of
80 *
81 * $<packet info>#<checksum>.
82 *
83 * where
84 * <packet info> :: <characters representing the command or response>
85 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
86 *
87 * When a packet is received, it is first acknowledged with either '+' or '-'.
88 * '+' indicates a successful transfer. '-' indicates a failed transfer.
89 *
90 * Example:
91 *
92 * Host: Reply:
93 * $m0,10#2a +$00010203040506070809101112131415#42
94 *
95 ****************************************************************************/
96
97#include <linux/kernel.h>
98#include <linux/string.h>
99#include <linux/mm.h>
100#include <linux/smp.h>
101#include <linux/smp_lock.h>
102
103#include <asm/system.h>
104#include <asm/signal.h>
105#include <asm/oplib.h>
106#include <asm/head.h>
107#include <asm/traps.h>
108#include <asm/vac-ops.h>
109#include <asm/kgdb.h>
110#include <asm/pgalloc.h>
111#include <asm/pgtable.h>
112#include <asm/cacheflush.h>
113
114/*
115 *
116 * external low-level support routines
117 */
118
119extern void putDebugChar(char); /* write a single character */
120extern char getDebugChar(void); /* read and return a single char */
121
122/*
123 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
124 * at least NUMREGBYTES*2 are needed for register packets
125 */
126#define BUFMAX 2048
127
128static int initialized; /* !0 means we've been initialized */
129
130static const char hexchars[]="0123456789abcdef";
131
132#define NUMREGS 72
133
134/* Number of bytes of registers. */
135#define NUMREGBYTES (NUMREGS * 4)
136enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
137 O0, O1, O2, O3, O4, O5, SP, O7,
138 L0, L1, L2, L3, L4, L5, L6, L7,
139 I0, I1, I2, I3, I4, I5, FP, I7,
140
141 F0, F1, F2, F3, F4, F5, F6, F7,
142 F8, F9, F10, F11, F12, F13, F14, F15,
143 F16, F17, F18, F19, F20, F21, F22, F23,
144 F24, F25, F26, F27, F28, F29, F30, F31,
145 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
146
147
148extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
149
150unsigned long get_sun4cpte(unsigned long addr)
151{
152 unsigned long entry;
153
154 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
155 "=r" (entry) :
156 "r" (addr), "i" (ASI_PTE));
157 return entry;
158}
159
160unsigned long get_sun4csegmap(unsigned long addr)
161{
162 unsigned long entry;
163
164 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
165 "=r" (entry) :
166 "r" (addr), "i" (ASI_SEGMAP));
167 return entry;
168}
169
170#if 0
171/* Have to sort this out. This cannot be done after initialization. */
172static void flush_cache_all_nop(void) {}
173#endif
174
175/* Place where we save old trap entries for restoration */
176struct tt_entry kgdb_savettable[256];
177typedef void (*trapfunc_t)(void);
178
179/* Helper routine for manipulation of kgdb_savettable */
180static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
181{
182 dest->inst_one = src->inst_one;
183 dest->inst_two = src->inst_two;
184 dest->inst_three = src->inst_three;
185 dest->inst_four = src->inst_four;
186}
187
188/* Initialize the kgdb_savettable so that debugging can commence */
189static void eh_init(void)
190{
191 int i;
192
193 for(i=0; i < 256; i++)
194 copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
195}
196
197/* Install an exception handler for kgdb */
198static void exceptionHandler(int tnum, trapfunc_t trap_entry)
199{
200 unsigned long te_addr = (unsigned long) trap_entry;
201
202 /* Make new vector */
203 sparc_ttable[tnum].inst_one =
204 SPARC_BRANCH((unsigned long) te_addr,
205 (unsigned long) &sparc_ttable[tnum].inst_one);
206 sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
207 sparc_ttable[tnum].inst_three = SPARC_NOP;
208 sparc_ttable[tnum].inst_four = SPARC_NOP;
209}
210
211/* Convert ch from a hex digit to an int */
212static int
213hex(unsigned char ch)
214{
215 if (ch >= 'a' && ch <= 'f')
216 return ch-'a'+10;
217 if (ch >= '0' && ch <= '9')
218 return ch-'0';
219 if (ch >= 'A' && ch <= 'F')
220 return ch-'A'+10;
221 return -1;
222}
223
224/* scan for the sequence $<data>#<checksum> */
225static void
226getpacket(char *buffer)
227{
228 unsigned char checksum;
229 unsigned char xmitcsum;
230 int i;
231 int count;
232 unsigned char ch;
233
234 do {
235 /* wait around for the start character, ignore all other characters */
236 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
237
238 checksum = 0;
239 xmitcsum = -1;
240
241 count = 0;
242
243 /* now, read until a # or end of buffer is found */
244 while (count < BUFMAX) {
245 ch = getDebugChar() & 0x7f;
246 if (ch == '#')
247 break;
248 checksum = checksum + ch;
249 buffer[count] = ch;
250 count = count + 1;
251 }
252
253 if (count >= BUFMAX)
254 continue;
255
256 buffer[count] = 0;
257
258 if (ch == '#') {
259 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
260 xmitcsum |= hex(getDebugChar() & 0x7f);
261 if (checksum != xmitcsum)
262 putDebugChar('-'); /* failed checksum */
263 else {
264 putDebugChar('+'); /* successful transfer */
265 /* if a sequence char is present, reply the ID */
266 if (buffer[2] == ':') {
267 putDebugChar(buffer[0]);
268 putDebugChar(buffer[1]);
269 /* remove sequence chars from buffer */
270 count = strlen(buffer);
271 for (i=3; i <= count; i++)
272 buffer[i-3] = buffer[i];
273 }
274 }
275 }
276 } while (checksum != xmitcsum);
277}
278
279/* send the packet in buffer. */
280
281static void
282putpacket(unsigned char *buffer)
283{
284 unsigned char checksum;
285 int count;
286 unsigned char ch, recv;
287
288 /* $<packet info>#<checksum>. */
289 do {
290 putDebugChar('$');
291 checksum = 0;
292 count = 0;
293
294 while ((ch = buffer[count])) {
295 putDebugChar(ch);
296 checksum += ch;
297 count += 1;
298 }
299
300 putDebugChar('#');
301 putDebugChar(hexchars[checksum >> 4]);
302 putDebugChar(hexchars[checksum & 0xf]);
303 recv = getDebugChar();
304 } while ((recv & 0x7f) != '+');
305}
306
307static char remcomInBuffer[BUFMAX];
308static char remcomOutBuffer[BUFMAX];
309
310/* Convert the memory pointed to by mem into hex, placing result in buf.
311 * Return a pointer to the last char put in buf (null), in case of mem fault,
312 * return 0.
313 */
314
315static unsigned char *
316mem2hex(char *mem, char *buf, int count)
317{
318 unsigned char ch;
319
320 while (count-- > 0) {
321 /* This assembler code is basically: ch = *mem++;
322 * except that we use the SPARC/Linux exception table
323 * mechanism (see how "fixup" works in kernel_mna_trap_fault)
324 * to arrange for a "return 0" upon a memory fault
325 */
326 __asm__(
327 "\n1:\n\t"
328 "ldub [%0], %1\n\t"
329 "inc %0\n\t"
330 ".section .fixup,#alloc,#execinstr\n\t"
331 ".align 4\n"
332 "2:\n\t"
333 "retl\n\t"
334 " mov 0, %%o0\n\t"
335 ".section __ex_table, #alloc\n\t"
336 ".align 4\n\t"
337 ".word 1b, 2b\n\t"
338 ".text\n"
339 : "=r" (mem), "=r" (ch) : "0" (mem));
340 *buf++ = hexchars[ch >> 4];
341 *buf++ = hexchars[ch & 0xf];
342 }
343
344 *buf = 0;
345 return buf;
346}
347
348/* convert the hex array pointed to by buf into binary to be placed in mem
349 * return a pointer to the character AFTER the last byte written.
350*/
351static char *
352hex2mem(char *buf, char *mem, int count)
353{
354 int i;
355 unsigned char ch;
356
357 for (i=0; i<count; i++) {
358
359 ch = hex(*buf++) << 4;
360 ch |= hex(*buf++);
361 /* Assembler code is *mem++ = ch; with return 0 on fault */
362 __asm__(
363 "\n1:\n\t"
364 "stb %1, [%0]\n\t"
365 "inc %0\n\t"
366 ".section .fixup,#alloc,#execinstr\n\t"
367 ".align 4\n"
368 "2:\n\t"
369 "retl\n\t"
370 " mov 0, %%o0\n\t"
371 ".section __ex_table, #alloc\n\t"
372 ".align 4\n\t"
373 ".word 1b, 2b\n\t"
374 ".text\n"
375 : "=r" (mem) : "r" (ch) , "0" (mem));
376 }
377 return mem;
378}
379
380/* This table contains the mapping between SPARC hardware trap types, and
381 signals, which are primarily what GDB understands. It also indicates
382 which hardware traps we need to commandeer when initializing the stub. */
383
384static struct hard_trap_info
385{
386 unsigned char tt; /* Trap type code for SPARC */
387 unsigned char signo; /* Signal that we map this trap into */
388} hard_trap_info[] = {
389 {SP_TRAP_SBPT, SIGTRAP}, /* ta 1 - Linux/KGDB software breakpoint */
390 {0, 0} /* Must be last */
391};
392
393/* Set up exception handlers for tracing and breakpoints */
394
395void
396set_debug_traps(void)
397{
398 struct hard_trap_info *ht;
399 unsigned long flags;
400
401 local_irq_save(flags);
402#if 0
403/* Have to sort this out. This cannot be done after initialization. */
404 BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
405#endif
406
407 /* Initialize our copy of the Linux Sparc trap table */
408 eh_init();
409
410 for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
411 /* Only if it doesn't destroy our fault handlers */
412 if((ht->tt != SP_TRAP_TFLT) &&
413 (ht->tt != SP_TRAP_DFLT))
414 exceptionHandler(ht->tt, trap_low);
415 }
416
417 /* In case GDB is started before us, ack any packets (presumably
418 * "$?#xx") sitting there.
419 *
420 * I've found this code causes more problems than it solves,
421 * so that's why it's commented out. GDB seems to work fine
422 * now starting either before or after the kernel -bwb
423 */
424#if 0
425 while((c = getDebugChar()) != '$');
426 while((c = getDebugChar()) != '#');
427 c = getDebugChar(); /* eat first csum byte */
428 c = getDebugChar(); /* eat second csum byte */
429 putDebugChar('+'); /* ack it */
430#endif
431
432 initialized = 1; /* connect! */
433 local_irq_restore(flags);
434}
435
436/* Convert the SPARC hardware trap type code to a unix signal number. */
437
438static int
439computeSignal(int tt)
440{
441 struct hard_trap_info *ht;
442
443 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
444 if (ht->tt == tt)
445 return ht->signo;
446
447 return SIGHUP; /* default for things we don't know about */
448}
449
450/*
451 * While we find nice hex chars, build an int.
452 * Return number of chars processed.
453 */
454
455static int
456hexToInt(char **ptr, int *intValue)
457{
458 int numChars = 0;
459 int hexValue;
460
461 *intValue = 0;
462
463 while (**ptr) {
464 hexValue = hex(**ptr);
465 if (hexValue < 0)
466 break;
467
468 *intValue = (*intValue << 4) | hexValue;
469 numChars ++;
470
471 (*ptr)++;
472 }
473
474 return (numChars);
475}
476
477/*
478 * This function does all command processing for interfacing to gdb. It
479 * returns 1 if you should skip the instruction at the trap address, 0
480 * otherwise.
481 */
482
483extern void breakinst(void);
484
485void
486handle_exception (unsigned long *registers)
487{
488 int tt; /* Trap type */
489 int sigval;
490 int addr;
491 int length;
492 char *ptr;
493 unsigned long *sp;
494
495 /* First, we must force all of the windows to be spilled out */
496
497 asm("save %sp, -64, %sp\n\t"
498 "save %sp, -64, %sp\n\t"
499 "save %sp, -64, %sp\n\t"
500 "save %sp, -64, %sp\n\t"
501 "save %sp, -64, %sp\n\t"
502 "save %sp, -64, %sp\n\t"
503 "save %sp, -64, %sp\n\t"
504 "save %sp, -64, %sp\n\t"
505 "restore\n\t"
506 "restore\n\t"
507 "restore\n\t"
508 "restore\n\t"
509 "restore\n\t"
510 "restore\n\t"
511 "restore\n\t"
512 "restore\n\t");
513
514 lock_kernel();
515 if (registers[PC] == (unsigned long)breakinst) {
516 /* Skip over breakpoint trap insn */
517 registers[PC] = registers[NPC];
518 registers[NPC] += 4;
519 }
520
521 sp = (unsigned long *)registers[SP];
522
523 tt = (registers[TBR] >> 4) & 0xff;
524
525 /* reply to host that an exception has occurred */
526 sigval = computeSignal(tt);
527 ptr = remcomOutBuffer;
528
529 *ptr++ = 'T';
530 *ptr++ = hexchars[sigval >> 4];
531 *ptr++ = hexchars[sigval & 0xf];
532
533 *ptr++ = hexchars[PC >> 4];
534 *ptr++ = hexchars[PC & 0xf];
535 *ptr++ = ':';
536 ptr = mem2hex((char *)&registers[PC], ptr, 4);
537 *ptr++ = ';';
538
539 *ptr++ = hexchars[FP >> 4];
540 *ptr++ = hexchars[FP & 0xf];
541 *ptr++ = ':';
542 ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
543 *ptr++ = ';';
544
545 *ptr++ = hexchars[SP >> 4];
546 *ptr++ = hexchars[SP & 0xf];
547 *ptr++ = ':';
548 ptr = mem2hex((char *)&sp, ptr, 4);
549 *ptr++ = ';';
550
551 *ptr++ = hexchars[NPC >> 4];
552 *ptr++ = hexchars[NPC & 0xf];
553 *ptr++ = ':';
554 ptr = mem2hex((char *)&registers[NPC], ptr, 4);
555 *ptr++ = ';';
556
557 *ptr++ = hexchars[O7 >> 4];
558 *ptr++ = hexchars[O7 & 0xf];
559 *ptr++ = ':';
560 ptr = mem2hex((char *)&registers[O7], ptr, 4);
561 *ptr++ = ';';
562
563 *ptr++ = 0;
564
565 putpacket(remcomOutBuffer);
566
567 /* XXX We may want to add some features dealing with poking the
568 * XXX page tables, the real ones on the srmmu, and what is currently
569 * XXX loaded in the sun4/sun4c tlb at this point in time. But this
570 * XXX also required hacking to the gdb sources directly...
571 */
572
573 while (1) {
574 remcomOutBuffer[0] = 0;
575
576 getpacket(remcomInBuffer);
577 switch (remcomInBuffer[0]) {
578 case '?':
579 remcomOutBuffer[0] = 'S';
580 remcomOutBuffer[1] = hexchars[sigval >> 4];
581 remcomOutBuffer[2] = hexchars[sigval & 0xf];
582 remcomOutBuffer[3] = 0;
583 break;
584
585 case 'd':
586 /* toggle debug flag */
587 break;
588
589 case 'g': /* return the value of the CPU registers */
590 {
591 ptr = remcomOutBuffer;
592 /* G & O regs */
593 ptr = mem2hex((char *)registers, ptr, 16 * 4);
594 /* L & I regs */
595 ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
596 /* Floating point */
597 memset(ptr, '0', 32 * 8);
598 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
599 mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
600 }
601 break;
602
603 case 'G': /* set the value of the CPU registers - return OK */
604 {
605 unsigned long *newsp, psr;
606
607 psr = registers[PSR];
608
609 ptr = &remcomInBuffer[1];
610 /* G & O regs */
611 hex2mem(ptr, (char *)registers, 16 * 4);
612 /* L & I regs */
613 hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
614 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
615 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
616
617 /* See if the stack pointer has moved. If so,
618 * then copy the saved locals and ins to the
619 * new location. This keeps the window
620 * overflow and underflow routines happy.
621 */
622
623 newsp = (unsigned long *)registers[SP];
624 if (sp != newsp)
625 sp = memcpy(newsp, sp, 16 * 4);
626
627 /* Don't allow CWP to be modified. */
628
629 if (psr != registers[PSR])
630 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
631
632 strcpy(remcomOutBuffer,"OK");
633 }
634 break;
635
636 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
637 /* Try to read %x,%x. */
638
639 ptr = &remcomInBuffer[1];
640
641 if (hexToInt(&ptr, &addr)
642 && *ptr++ == ','
643 && hexToInt(&ptr, &length)) {
644 if (mem2hex((char *)addr, remcomOutBuffer, length))
645 break;
646
647 strcpy (remcomOutBuffer, "E03");
648 } else {
649 strcpy(remcomOutBuffer,"E01");
650 }
651 break;
652
653 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
654 /* Try to read '%x,%x:'. */
655
656 ptr = &remcomInBuffer[1];
657
658 if (hexToInt(&ptr, &addr)
659 && *ptr++ == ','
660 && hexToInt(&ptr, &length)
661 && *ptr++ == ':') {
662 if (hex2mem(ptr, (char *)addr, length)) {
663 strcpy(remcomOutBuffer, "OK");
664 } else {
665 strcpy(remcomOutBuffer, "E03");
666 }
667 } else {
668 strcpy(remcomOutBuffer, "E02");
669 }
670 break;
671
672 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
673 /* try to read optional parameter, pc unchanged if no parm */
674
675 ptr = &remcomInBuffer[1];
676 if (hexToInt(&ptr, &addr)) {
677 registers[PC] = addr;
678 registers[NPC] = addr + 4;
679 }
680
681/* Need to flush the instruction cache here, as we may have deposited a
682 * breakpoint, and the icache probably has no way of knowing that a data ref to
683 * some location may have changed something that is in the instruction cache.
684 */
685 flush_cache_all();
686 unlock_kernel();
687 return;
688
689 /* kill the program */
690 case 'k' : /* do nothing */
691 break;
692 case 'r': /* Reset */
693 asm ("call 0\n\t"
694 "nop\n\t");
695 break;
696 } /* switch */
697
698 /* reply to the request */
699 putpacket(remcomOutBuffer);
700 } /* while(1) */
701}
702
703/* This function will generate a breakpoint exception. It is used at the
704 beginning of a program to sync up with a debugger and can be used
705 otherwise as a quick means to stop program execution and "break" into
706 the debugger. */
707
708void
709breakpoint(void)
710{
711 if (!initialized)
712 return;
713
714 /* Again, watch those c-prefixes for ELF kernels */
715#if defined(__svr4__) || defined(__ELF__)
716 asm(".globl breakinst\n"
717 "breakinst:\n\t"
718 "ta 1\n");
719#else
720 asm(".globl _breakinst\n"
721 "_breakinst:\n\t"
722 "ta 1\n");
723#endif
724}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 0bcf98a7ef38..aa8ee06cf488 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -282,3 +282,5 @@ EXPORT_SYMBOL(do_BUG);
282 282
283/* Sun Power Management Idle Handler */ 283/* Sun Power Management Idle Handler */
284EXPORT_SYMBOL(pm_idle); 284EXPORT_SYMBOL(pm_idle);
285
286EXPORT_SYMBOL(empty_zero_page);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 0def48158c7d..dfde77ff0848 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -335,37 +335,6 @@ void smp4d_cross_call_irq(void)
335 ccall_info.processors_out[i] = 1; 335 ccall_info.processors_out[i] = 1;
336} 336}
337 337
338static int smp4d_stop_cpu_sender;
339
340static void smp4d_stop_cpu(void)
341{
342 int me = hard_smp4d_processor_id();
343
344 if (me != smp4d_stop_cpu_sender)
345 while(1) barrier();
346}
347
348/* Cross calls, in order to work efficiently and atomically do all
349 * the message passing work themselves, only stopcpu and reschedule
350 * messages come through here.
351 */
352void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
353{
354 int me = hard_smp4d_processor_id();
355
356 SMP_PRINTK(("smp4d_message_pass %d %d %08lx %d\n", target, msg, data, wait));
357 if (msg == MSG_STOP_CPU && target == MSG_ALL_BUT_SELF) {
358 unsigned long flags;
359 static DEFINE_SPINLOCK(stop_cpu_lock);
360 spin_lock_irqsave(&stop_cpu_lock, flags);
361 smp4d_stop_cpu_sender = me;
362 smp4d_cross_call((smpfunc_t)smp4d_stop_cpu, 0, 0, 0, 0, 0);
363 spin_unlock_irqrestore(&stop_cpu_lock, flags);
364 }
365 printk("Yeeee, trying to send SMP msg(%d) to %d on cpu %d\n", msg, target, me);
366 panic("Bogon SMP message pass.");
367}
368
369void smp4d_percpu_timer_interrupt(struct pt_regs *regs) 338void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
370{ 339{
371 struct pt_regs *old_regs; 340 struct pt_regs *old_regs;
@@ -439,7 +408,6 @@ void __init sun4d_init_smp(void)
439 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); 408 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
440 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); 409 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
441 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); 410 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
442 BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM);
443 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); 411 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
444 412
445 for (i = 0; i < NR_CPUS; i++) { 413 for (i = 0; i < NR_CPUS; i++) {
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 0b9407267162..ffb875aacb7e 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -34,8 +34,6 @@
34 34
35#include "irq.h" 35#include "irq.h"
36 36
37#define IRQ_RESCHEDULE 13
38#define IRQ_STOP_CPU 14
39#define IRQ_CROSS_CALL 15 37#define IRQ_CROSS_CALL 15
40 38
41extern ctxd_t *srmmu_ctx_table_phys; 39extern ctxd_t *srmmu_ctx_table_phys;
@@ -232,48 +230,6 @@ void smp4m_irq_rotate(int cpu)
232 set_irq_udt(next); 230 set_irq_udt(next);
233} 231}
234 232
235/* Cross calls, in order to work efficiently and atomically do all
236 * the message passing work themselves, only stopcpu and reschedule
237 * messages come through here.
238 */
239void smp4m_message_pass(int target, int msg, unsigned long data, int wait)
240{
241 static unsigned long smp_cpu_in_msg[NR_CPUS];
242 cpumask_t mask;
243 int me = smp_processor_id();
244 int irq, i;
245
246 if(msg == MSG_RESCHEDULE) {
247 irq = IRQ_RESCHEDULE;
248
249 if(smp_cpu_in_msg[me])
250 return;
251 } else if(msg == MSG_STOP_CPU) {
252 irq = IRQ_STOP_CPU;
253 } else {
254 goto barf;
255 }
256
257 smp_cpu_in_msg[me]++;
258 if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) {
259 mask = cpu_online_map;
260 if(target == MSG_ALL_BUT_SELF)
261 cpu_clear(me, mask);
262 for(i = 0; i < 4; i++) {
263 if (cpu_isset(i, mask))
264 set_cpu_int(i, irq);
265 }
266 } else {
267 set_cpu_int(target, irq);
268 }
269 smp_cpu_in_msg[me]--;
270
271 return;
272barf:
273 printk("Yeeee, trying to send SMP msg(%d) on cpu %d\n", msg, me);
274 panic("Bogon SMP message pass.");
275}
276
277static struct smp_funcall { 233static struct smp_funcall {
278 smpfunc_t func; 234 smpfunc_t func;
279 unsigned long arg1; 235 unsigned long arg1;
@@ -413,6 +369,5 @@ void __init sun4m_init_smp(void)
413 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id); 369 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
414 BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); 370 BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
415 BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); 371 BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
416 BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM);
417 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); 372 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
418} 373}
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index f188b5dc9fd0..3c6b49a53ae8 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -219,12 +219,11 @@ out:
219 return err; 219 return err;
220} 220}
221 221
222int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) 222int sparc_mmap_check(unsigned long addr, unsigned long len)
223{ 223{
224 if (ARCH_SUN4C_SUN4 && 224 if (ARCH_SUN4C_SUN4 &&
225 (len > 0x20000000 || 225 (len > 0x20000000 ||
226 ((flags & MAP_FIXED) && 226 (addr < 0xe0000000 && addr + len > 0x20000000)))
227 addr < 0xe0000000 && addr + len > 0x20000000)))
228 return -EINVAL; 227 return -EINVAL;
229 228
230 /* See asm-sparc/uaccess.h */ 229 /* See asm-sparc/uaccess.h */
@@ -296,52 +295,14 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
296 unsigned long old_len, unsigned long new_len, 295 unsigned long old_len, unsigned long new_len,
297 unsigned long flags, unsigned long new_addr) 296 unsigned long flags, unsigned long new_addr)
298{ 297{
299 struct vm_area_struct *vma;
300 unsigned long ret = -EINVAL; 298 unsigned long ret = -EINVAL;
301 if (ARCH_SUN4C_SUN4) { 299
302 if (old_len > 0x20000000 || new_len > 0x20000000) 300 if (unlikely(sparc_mmap_check(addr, old_len)))
303 goto out; 301 goto out;
304 if (addr < 0xe0000000 && addr + old_len > 0x20000000) 302 if (unlikely(sparc_mmap_check(new_addr, new_len)))
305 goto out;
306 }
307 if (old_len > TASK_SIZE - PAGE_SIZE ||
308 new_len > TASK_SIZE - PAGE_SIZE)
309 goto out; 303 goto out;
310 down_write(&current->mm->mmap_sem); 304 down_write(&current->mm->mmap_sem);
311 if (flags & MREMAP_FIXED) {
312 if (ARCH_SUN4C_SUN4 &&
313 new_addr < 0xe0000000 &&
314 new_addr + new_len > 0x20000000)
315 goto out_sem;
316 if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
317 goto out_sem;
318 } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
319 addr + new_len > 0x20000000) ||
320 addr + new_len > TASK_SIZE - PAGE_SIZE) {
321 unsigned long map_flags = 0;
322 struct file *file = NULL;
323
324 ret = -ENOMEM;
325 if (!(flags & MREMAP_MAYMOVE))
326 goto out_sem;
327
328 vma = find_vma(current->mm, addr);
329 if (vma) {
330 if (vma->vm_flags & VM_SHARED)
331 map_flags |= MAP_SHARED;
332 file = vma->vm_file;
333 }
334
335 new_addr = get_unmapped_area(file, addr, new_len,
336 vma ? vma->vm_pgoff : 0,
337 map_flags);
338 ret = new_addr;
339 if (new_addr & ~PAGE_MASK)
340 goto out_sem;
341 flags |= MREMAP_FIXED;
342 }
343 ret = do_mremap(addr, old_len, new_len, flags, new_addr); 305 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
344out_sem:
345 up_write(&current->mm->mmap_sem); 306 up_write(&current->mm->mmap_sem);
346out: 307out:
347 return ret; 308 return ret;