aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300/kernel')
-rw-r--r--arch/mn10300/kernel/Makefile27
-rw-r--r--arch/mn10300/kernel/asm-offsets.c108
-rw-r--r--arch/mn10300/kernel/entry.S721
-rw-r--r--arch/mn10300/kernel/fpu-low.S197
-rw-r--r--arch/mn10300/kernel/fpu.c223
-rw-r--r--arch/mn10300/kernel/gdb-cache.S105
-rw-r--r--arch/mn10300/kernel/gdb-io-serial-low.S90
-rw-r--r--arch/mn10300/kernel/gdb-io-serial.c155
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm-low.S93
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm.c299
-rw-r--r--arch/mn10300/kernel/gdb-low.S115
-rw-r--r--arch/mn10300/kernel/gdb-stub.c1947
-rw-r--r--arch/mn10300/kernel/head.S255
-rw-r--r--arch/mn10300/kernel/init_task.c45
-rw-r--r--arch/mn10300/kernel/internal.h20
-rw-r--r--arch/mn10300/kernel/io.c30
-rw-r--r--arch/mn10300/kernel/irq.c235
-rw-r--r--arch/mn10300/kernel/kernel_execve.S37
-rw-r--r--arch/mn10300/kernel/kprobes.c653
-rw-r--r--arch/mn10300/kernel/kthread.S31
-rw-r--r--arch/mn10300/kernel/mn10300-debug.c58
-rw-r--r--arch/mn10300/kernel/mn10300-serial-low.S191
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c1480
-rw-r--r--arch/mn10300/kernel/mn10300-serial.h126
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog-low.S59
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog.c183
-rw-r--r--arch/mn10300/kernel/mn10300_ksyms.c37
-rw-r--r--arch/mn10300/kernel/module.c206
-rw-r--r--arch/mn10300/kernel/process.c297
-rw-r--r--arch/mn10300/kernel/profile-low.S72
-rw-r--r--arch/mn10300/kernel/profile.c51
-rw-r--r--arch/mn10300/kernel/ptrace.c379
-rw-r--r--arch/mn10300/kernel/rtc.c173
-rw-r--r--arch/mn10300/kernel/semaphore.c149
-rw-r--r--arch/mn10300/kernel/setup.c298
-rw-r--r--arch/mn10300/kernel/sigframe.h33
-rw-r--r--arch/mn10300/kernel/signal.c564
-rw-r--r--arch/mn10300/kernel/switch_to.S71
-rw-r--r--arch/mn10300/kernel/sys_mn10300.c193
-rw-r--r--arch/mn10300/kernel/time.c129
-rw-r--r--arch/mn10300/kernel/traps.c619
-rw-r--r--arch/mn10300/kernel/vmlinux.lds.S159
42 files changed, 10913 insertions, 0 deletions
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
new file mode 100644
index 000000000000..ef07c956170a
--- /dev/null
+++ b/arch/mn10300/kernel/Makefile
@@ -0,0 +1,27 @@
1#
2# Makefile for the MN10300-specific core kernel code
3#
4extra-y := head.o init_task.o vmlinux.lds
5
6obj-y := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \
7 ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
8 switch_to.o mn10300_ksyms.o kernel_execve.o
9
10obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
11
12obj-$(CONFIG_FPU) += fpu-low.o
13
14obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
15 mn10300-debug.o
16obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
17obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
18obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
19
20ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y)
21obj-$(CONFIG_GDBSTUB) += gdb-cache.o
22endif
23
24obj-$(CONFIG_MN10300_RTC) += rtc.o
25obj-$(CONFIG_PROFILE) += profile.o profile-low.o
26obj-$(CONFIG_MODULES) += module.o
27obj-$(CONFIG_KPROBES) += kprobes.o
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
new file mode 100644
index 000000000000..ee2d9f8af5ad
--- /dev/null
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -0,0 +1,108 @@
1/*
2 * Generate definitions needed by assembly language modules.
3 * This code generates raw asm output which is post-processed
4 * to extract and format the required data.
5 */
6
7#include <linux/sched.h>
8#include <linux/signal.h>
9#include <linux/personality.h>
10#include <asm/ucontext.h>
11#include <asm/processor.h>
12#include <asm/thread_info.h>
13#include <asm/ptrace.h>
14#include "sigframe.h"
15#include "mn10300-serial.h"
16
17#define DEFINE(sym, val) \
18 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
19
20#define BLANK() asm volatile("\n->")
21
22#define OFFSET(sym, str, mem) \
23 DEFINE(sym, offsetof(struct str, mem));
24
25void foo(void)
26{
27 OFFSET(SIGCONTEXT_d0, sigcontext, d0);
28 OFFSET(SIGCONTEXT_d1, sigcontext, d1);
29 BLANK();
30
31 OFFSET(TI_task, thread_info, task);
32 OFFSET(TI_exec_domain, thread_info, exec_domain);
33 OFFSET(TI_flags, thread_info, flags);
34 OFFSET(TI_cpu, thread_info, cpu);
35 OFFSET(TI_preempt_count, thread_info, preempt_count);
36 OFFSET(TI_addr_limit, thread_info, addr_limit);
37 OFFSET(TI_restart_block, thread_info, restart_block);
38 BLANK();
39
40 OFFSET(REG_D0, pt_regs, d0);
41 OFFSET(REG_D1, pt_regs, d1);
42 OFFSET(REG_D2, pt_regs, d2);
43 OFFSET(REG_D3, pt_regs, d3);
44 OFFSET(REG_A0, pt_regs, a0);
45 OFFSET(REG_A1, pt_regs, a1);
46 OFFSET(REG_A2, pt_regs, a2);
47 OFFSET(REG_A3, pt_regs, a3);
48 OFFSET(REG_E0, pt_regs, e0);
49 OFFSET(REG_E1, pt_regs, e1);
50 OFFSET(REG_E2, pt_regs, e2);
51 OFFSET(REG_E3, pt_regs, e3);
52 OFFSET(REG_E4, pt_regs, e4);
53 OFFSET(REG_E5, pt_regs, e5);
54 OFFSET(REG_E6, pt_regs, e6);
55 OFFSET(REG_E7, pt_regs, e7);
56 OFFSET(REG_SP, pt_regs, sp);
57 OFFSET(REG_EPSW, pt_regs, epsw);
58 OFFSET(REG_PC, pt_regs, pc);
59 OFFSET(REG_LAR, pt_regs, lar);
60 OFFSET(REG_LIR, pt_regs, lir);
61 OFFSET(REG_MDR, pt_regs, mdr);
62 OFFSET(REG_MCVF, pt_regs, mcvf);
63 OFFSET(REG_MCRL, pt_regs, mcrl);
64 OFFSET(REG_MCRH, pt_regs, mcrh);
65 OFFSET(REG_MDRQ, pt_regs, mdrq);
66 OFFSET(REG_ORIG_D0, pt_regs, orig_d0);
67 OFFSET(REG_NEXT, pt_regs, next);
68 DEFINE(REG__END, sizeof(struct pt_regs));
69 BLANK();
70
71 OFFSET(THREAD_UREGS, thread_struct, uregs);
72 OFFSET(THREAD_PC, thread_struct, pc);
73 OFFSET(THREAD_SP, thread_struct, sp);
74 OFFSET(THREAD_A3, thread_struct, a3);
75 OFFSET(THREAD_USP, thread_struct, usp);
76 OFFSET(THREAD_FRAME, thread_struct, __frame);
77 BLANK();
78
79 DEFINE(CLONE_VM_asm, CLONE_VM);
80 DEFINE(CLONE_FS_asm, CLONE_FS);
81 DEFINE(CLONE_FILES_asm, CLONE_FILES);
82 DEFINE(CLONE_SIGHAND_asm, CLONE_SIGHAND);
83 DEFINE(CLONE_UNTRACED_asm, CLONE_UNTRACED);
84 DEFINE(SIGCHLD_asm, SIGCHLD);
85 BLANK();
86
87 OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
88 OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
89
90 DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
91
92 OFFSET(__rx_buffer, mn10300_serial_port, rx_buffer);
93 OFFSET(__rx_inp, mn10300_serial_port, rx_inp);
94 OFFSET(__rx_outp, mn10300_serial_port, rx_outp);
95 OFFSET(__tx_info_buffer, mn10300_serial_port, uart.info);
96 OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar);
97 OFFSET(__tx_break, mn10300_serial_port, tx_break);
98 OFFSET(__intr_flags, mn10300_serial_port, intr_flags);
99 OFFSET(__rx_icr, mn10300_serial_port, rx_icr);
100 OFFSET(__tx_icr, mn10300_serial_port, tx_icr);
101 OFFSET(__tm_icr, mn10300_serial_port, _tmicr);
102 OFFSET(__iobase, mn10300_serial_port, _iobase);
103
104 DEFINE(__UART_XMIT_SIZE, UART_XMIT_SIZE);
105 OFFSET(__xmit_buffer, uart_info, xmit.buf);
106 OFFSET(__xmit_head, uart_info, xmit.head);
107 OFFSET(__xmit_tail, uart_info, xmit.tail);
108}
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
new file mode 100644
index 000000000000..11de3606eee6
--- /dev/null
+++ b/arch/mn10300/kernel/entry.S
@@ -0,0 +1,721 @@
1###############################################################################
2#
3# MN10300 Exception and interrupt entry points
4#
5# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
6# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
7# Modified by David Howells (dhowells@redhat.com)
8#
9# This program is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public Licence
11# as published by the Free Software Foundation; either version
12# 2 of the Licence, or (at your option) any later version.
13#
14###############################################################################
15#include <linux/sys.h>
16#include <linux/linkage.h>
17#include <asm/smp.h>
18#include <asm/system.h>
19#include <asm/thread_info.h>
20#include <asm/intctl-regs.h>
21#include <asm/busctl-regs.h>
22#include <asm/timer-regs.h>
23#include <asm/unit/leds.h>
24#include <asm/page.h>
25#include <asm/pgtable.h>
26#include <asm/errno.h>
27#include <asm/asm-offsets.h>
28#include <asm/frame.inc>
29
30#ifdef CONFIG_PREEMPT
31#define preempt_stop __cli
32#else
33#define preempt_stop
34#define resume_kernel restore_all
35#endif
36
37 .macro __cli
38 and ~EPSW_IM,epsw
39 or EPSW_IE|MN10300_CLI_LEVEL,epsw
40 nop
41 nop
42 nop
43 .endm
44 .macro __sti
45 or EPSW_IE|EPSW_IM_7,epsw
46 .endm
47
48
49 .am33_2
50
51###############################################################################
52#
53# the return path for a forked child
54# - on entry, D0 holds the address of the previous task to run
55#
56###############################################################################
57ENTRY(ret_from_fork)
58 call schedule_tail[],0
59 GET_THREAD_INFO a2
60
61 # return 0 to indicate child process
62 clr d0
63 mov d0,(REG_D0,fp)
64 jmp syscall_exit
65
66###############################################################################
67#
68# system call handler
69#
70###############################################################################
71ENTRY(system_call)
72 add -4,sp
73 SAVE_ALL
74 mov d0,(REG_ORIG_D0,fp)
75 GET_THREAD_INFO a2
76 cmp nr_syscalls,d0
77 bcc syscall_badsys
78 btst _TIF_SYSCALL_TRACE,(TI_flags,a2)
79 bne syscall_trace_entry
80syscall_call:
81 add d0,d0,a1
82 add a1,a1
83 mov (REG_A0,fp),d0
84 mov (sys_call_table,a1),a0
85 calls (a0)
86 mov d0,(REG_D0,fp)
87syscall_exit:
88 # make sure we don't miss an interrupt setting need_resched or
89 # sigpending between sampling and the rti
90 __cli
91 mov (TI_flags,a2),d2
92 btst _TIF_ALLWORK_MASK,d2
93 bne syscall_exit_work
94restore_all:
95 RESTORE_ALL
96
97###############################################################################
98#
99# perform work that needs to be done immediately before resumption and syscall
100# tracing
101#
102###############################################################################
103 ALIGN
104syscall_exit_work:
105 btst _TIF_SYSCALL_TRACE,d2
106 beq work_pending
107 __sti # could let do_syscall_trace() call
108 # schedule() instead
109 mov fp,d0
110 mov 1,d1
111 call do_syscall_trace[],0 # do_syscall_trace(regs,entryexit)
112 jmp resume_userspace
113
114 ALIGN
115work_pending:
116 btst _TIF_NEED_RESCHED,d2
117 beq work_notifysig
118
119work_resched:
120 call schedule[],0
121
122 # make sure we don't miss an interrupt setting need_resched or
123 # sigpending between sampling and the rti
124 __cli
125
126 # is there any work to be done other than syscall tracing?
127 mov (TI_flags,a2),d2
128 btst _TIF_WORK_MASK,d2
129 beq restore_all
130 btst _TIF_NEED_RESCHED,d2
131 bne work_resched
132
133 # deal with pending signals and notify-resume requests
134work_notifysig:
135 mov fp,d0
136 mov d2,d1
137 call do_notify_resume[],0
138 jmp resume_userspace
139
140 # perform syscall entry tracing
141syscall_trace_entry:
142 mov -ENOSYS,d0
143 mov d0,(REG_D0,fp)
144 mov fp,d0
145 clr d1
146 call do_syscall_trace[],0
147 mov (REG_ORIG_D0,fp),d0
148 mov (REG_D1,fp),d1
149 cmp nr_syscalls,d0
150 bcs syscall_call
151 jmp syscall_exit
152
153syscall_badsys:
154 mov -ENOSYS,d0
155 mov d0,(REG_D0,fp)
156 jmp resume_userspace
157
158 # userspace resumption stub bypassing syscall exit tracing
159 .globl ret_from_exception, ret_from_intr
160 ALIGN
161ret_from_exception:
162 preempt_stop
163ret_from_intr:
164 GET_THREAD_INFO a2
165 mov (REG_EPSW,fp),d0 # need to deliver signals before
166 # returning to userspace
167 and EPSW_nSL,d0
168 beq resume_kernel # returning to supervisor mode
169
170ENTRY(resume_userspace)
171 # make sure we don't miss an interrupt setting need_resched or
172 # sigpending between sampling and the rti
173 __cli
174
175 # is there any work to be done on int/exception return?
176 mov (TI_flags,a2),d2
177 btst _TIF_WORK_MASK,d2
178 bne work_pending
179 jmp restore_all
180
181#ifdef CONFIG_PREEMPT
182ENTRY(resume_kernel)
183 mov (TI_preempt_count,a2),d0 # non-zero preempt_count ?
184 cmp 0,d0
185 bne restore_all
186
187need_resched:
188 btst _TIF_NEED_RESCHED,(TI_flags,a2)
189 beq restore_all
190 mov (REG_EPSW,fp),d0
191 and EPSW_IM,d0
192 cmp EPSW_IM_7,d0 # interrupts off (exception path) ?
193 beq restore_all
194 call preempt_schedule_irq[],0
195 jmp need_resched
196#endif
197
198
199###############################################################################
200#
201# IRQ handler entry point
202# - intended to be entered at multiple priorities
203#
204###############################################################################
205ENTRY(irq_handler)
206 add -4,sp
207 SAVE_ALL
208
209 # it's not a syscall
210 mov 0xffffffff,d0
211 mov d0,(REG_ORIG_D0,fp)
212
213 mov fp,d0
214 call do_IRQ[],0 # do_IRQ(regs)
215
216 jmp ret_from_intr
217
218###############################################################################
219#
220# Monitor Signal handler entry point
221#
222###############################################################################
223ENTRY(monitor_signal)
224 movbu (0xae000001),d1
225 cmp 1,d1
226 beq monsignal
227 ret [],0
228
229monsignal:
230 or EPSW_NMID,epsw
231 mov d0,a0
232 mov a0,sp
233 mov (REG_EPSW,fp),d1
234 and ~EPSW_nSL,d1
235 mov d1,(REG_EPSW,fp)
236 movm (sp),[d2,d3,a2,a3,exreg0,exreg1,exother]
237 mov (sp),a1
238 mov a1,usp
239 movm (sp),[other]
240 add 4,sp
241here: jmp 0x8e000008-here+0x8e000008
242
243###############################################################################
244#
245# Double Fault handler entry point
246# - note that there will not be a stack, D0/A0 will hold EPSW/PC as were
247#
248###############################################################################
249 .section .bss
250 .balign THREAD_SIZE
251 .space THREAD_SIZE
252__df_stack:
253 .previous
254
255ENTRY(double_fault)
256 mov a0,(__df_stack-4) # PC as was
257 mov d0,(__df_stack-8) # EPSW as was
258 mn10300_set_dbfleds # display 'db-f' on the LEDs
259 mov 0xaa55aa55,d0
260 mov d0,(__df_stack-12) # no ORIG_D0
261 mov sp,a0 # save corrupted SP
262 mov __df_stack-12,sp # emergency supervisor stack
263 SAVE_ALL
264 mov a0,(REG_A0,fp) # save corrupted SP as A0 (which got
265 # clobbered by the CPU)
266 mov fp,d0
267 calls do_double_fault
268double_fault_loop:
269 bra double_fault_loop
270
271###############################################################################
272#
273# Bus Error handler entry point
274# - handle external (async) bus errors separately
275#
276###############################################################################
277ENTRY(raw_bus_error)
278 add -4,sp
279 mov d0,(sp)
280 mov (BCBERR),d0 # what
281 btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error
282 beq __common_exception_aux # it wasn't
283
284 SAVE_ALL
285 mov (BCBEAR),d1 # destination of erroneous access
286
287 mov (REG_ORIG_D0,fp),d2
288 mov d2,(REG_D0,fp)
289 mov -1,d2
290 mov d2,(REG_ORIG_D0,fp)
291
292 add -4,sp
293 mov fp,(12,sp) # frame pointer
294 call io_bus_error[],0
295 jmp restore_all
296
297###############################################################################
298#
299# Miscellaneous exception entry points
300#
301###############################################################################
302ENTRY(nmi_handler)
303 add -4,sp
304 mov d0,(sp)
305 mov (TBR),d0
306 bra __common_exception_nonmi
307
308ENTRY(__common_exception)
309 add -4,sp
310 mov d0,(sp)
311
312__common_exception_aux:
313 mov (TBR),d0
314 and ~EPSW_NMID,epsw # turn NMIs back on if not NMI
315 or EPSW_IE,epsw
316
317__common_exception_nonmi:
318 and 0x0000FFFF,d0 # turn the exception code into a vector
319 # table index
320
321 btst 0x00000007,d0
322 bne 1f
323 cmp 0x00000400,d0
324 bge 1f
325
326 SAVE_ALL # build the stack frame
327
328 mov (REG_D0,fp),a2 # get the exception number
329 mov (REG_ORIG_D0,fp),d0
330 mov d0,(REG_D0,fp)
331 mov -1,d0
332 mov d0,(REG_ORIG_D0,fp)
333
334#ifdef CONFIG_GDBSTUB
335 btst 0x01,(gdbstub_busy)
336 beq 2f
337 and ~EPSW_IE,epsw
338 mov fp,d0
339 mov a2,d1
340 call gdbstub_exception[],0 # gdbstub itself caused an exception
341 bra restore_all
3422:
343#endif
344
345 mov fp,d0 # arg 0: stacked register file
346 mov a2,d1 # arg 1: exception number
347 lsr 1,a2
348
349 mov (exception_table,a2),a2
350 calls (a2)
351 jmp ret_from_exception
352
3531: pi # BUG() equivalent
354
355###############################################################################
356#
357# Exception handler functions table
358#
359###############################################################################
360 .data
361ENTRY(exception_table)
362 .rept 0x400>>1
363 .long uninitialised_exception
364 .endr
365 .previous
366
367###############################################################################
368#
369# Change an entry in the exception table
370# - D0 exception code, D1 handler
371#
372###############################################################################
373ENTRY(set_excp_vector)
374 lsr 1,d0
375 add exception_table,d0
376 mov d1,(d0)
377 mov 4,d1
378#if defined(CONFIG_MN10300_CACHE_WBACK)
379 jmp mn10300_dcache_flush_inv_range2
380#else
381 ret [],0
382#endif
383
384###############################################################################
385#
386# System call table
387#
388###############################################################################
389 .data
390ENTRY(sys_call_table)
391 .long sys_restart_syscall /* 0 */
392 .long sys_exit
393 .long sys_fork
394 .long sys_read
395 .long sys_write
396 .long sys_open /* 5 */
397 .long sys_close
398 .long sys_waitpid
399 .long sys_creat
400 .long sys_link
401 .long sys_unlink /* 10 */
402 .long sys_execve
403 .long sys_chdir
404 .long sys_time
405 .long sys_mknod
406 .long sys_chmod /* 15 */
407 .long sys_lchown16
408 .long sys_ni_syscall /* old break syscall holder */
409 .long sys_stat
410 .long sys_lseek
411 .long sys_getpid /* 20 */
412 .long sys_mount
413 .long sys_oldumount
414 .long sys_setuid16
415 .long sys_getuid16
416 .long sys_stime /* 25 */
417 .long sys_ptrace
418 .long sys_alarm
419 .long sys_fstat
420 .long sys_pause
421 .long sys_utime /* 30 */
422 .long sys_ni_syscall /* old stty syscall holder */
423 .long sys_ni_syscall /* old gtty syscall holder */
424 .long sys_access
425 .long sys_nice
426 .long sys_ni_syscall /* 35 - old ftime syscall holder */
427 .long sys_sync
428 .long sys_kill
429 .long sys_rename
430 .long sys_mkdir
431 .long sys_rmdir /* 40 */
432 .long sys_dup
433 .long sys_pipe
434 .long sys_times
435 .long sys_ni_syscall /* old prof syscall holder */
436 .long sys_brk /* 45 */
437 .long sys_setgid16
438 .long sys_getgid16
439 .long sys_signal
440 .long sys_geteuid16
441 .long sys_getegid16 /* 50 */
442 .long sys_acct
443 .long sys_umount /* recycled never used phys() */
444 .long sys_ni_syscall /* old lock syscall holder */
445 .long sys_ioctl
446 .long sys_fcntl /* 55 */
447 .long sys_ni_syscall /* old mpx syscall holder */
448 .long sys_setpgid
449 .long sys_ni_syscall /* old ulimit syscall holder */
450 .long sys_ni_syscall /* old sys_olduname */
451 .long sys_umask /* 60 */
452 .long sys_chroot
453 .long sys_ustat
454 .long sys_dup2
455 .long sys_getppid
456 .long sys_getpgrp /* 65 */
457 .long sys_setsid
458 .long sys_sigaction
459 .long sys_sgetmask
460 .long sys_ssetmask
461 .long sys_setreuid16 /* 70 */
462 .long sys_setregid16
463 .long sys_sigsuspend
464 .long sys_sigpending
465 .long sys_sethostname
466 .long sys_setrlimit /* 75 */
467 .long sys_old_getrlimit
468 .long sys_getrusage
469 .long sys_gettimeofday
470 .long sys_settimeofday
471 .long sys_getgroups16 /* 80 */
472 .long sys_setgroups16
473 .long old_select
474 .long sys_symlink
475 .long sys_lstat
476 .long sys_readlink /* 85 */
477 .long sys_uselib
478 .long sys_swapon
479 .long sys_reboot
480 .long old_readdir
481 .long old_mmap /* 90 */
482 .long sys_munmap
483 .long sys_truncate
484 .long sys_ftruncate
485 .long sys_fchmod
486 .long sys_fchown16 /* 95 */
487 .long sys_getpriority
488 .long sys_setpriority
489 .long sys_ni_syscall /* old profil syscall holder */
490 .long sys_statfs
491 .long sys_fstatfs /* 100 */
492 .long sys_ni_syscall /* ioperm */
493 .long sys_socketcall
494 .long sys_syslog
495 .long sys_setitimer
496 .long sys_getitimer /* 105 */
497 .long sys_newstat
498 .long sys_newlstat
499 .long sys_newfstat
500 .long sys_ni_syscall /* old sys_uname */
501 .long sys_ni_syscall /* 110 - iopl */
502 .long sys_vhangup
503 .long sys_ni_syscall /* old "idle" system call */
504 .long sys_ni_syscall /* vm86old */
505 .long sys_wait4
506 .long sys_swapoff /* 115 */
507 .long sys_sysinfo
508 .long sys_ipc
509 .long sys_fsync
510 .long sys_sigreturn
511 .long sys_clone /* 120 */
512 .long sys_setdomainname
513 .long sys_newuname
514 .long sys_ni_syscall /* modify_ldt */
515 .long sys_adjtimex
516 .long sys_mprotect /* 125 */
517 .long sys_sigprocmask
518 .long sys_ni_syscall /* old "create_module" */
519 .long sys_init_module
520 .long sys_delete_module
521 .long sys_ni_syscall /* 130: old "get_kernel_syms" */
522 .long sys_quotactl
523 .long sys_getpgid
524 .long sys_fchdir
525 .long sys_bdflush
526 .long sys_sysfs /* 135 */
527 .long sys_personality
528 .long sys_ni_syscall /* reserved for afs_syscall */
529 .long sys_setfsuid16
530 .long sys_setfsgid16
531 .long sys_llseek /* 140 */
532 .long sys_getdents
533 .long sys_select
534 .long sys_flock
535 .long sys_msync
536 .long sys_readv /* 145 */
537 .long sys_writev
538 .long sys_getsid
539 .long sys_fdatasync
540 .long sys_sysctl
541 .long sys_mlock /* 150 */
542 .long sys_munlock
543 .long sys_mlockall
544 .long sys_munlockall
545 .long sys_sched_setparam
546 .long sys_sched_getparam /* 155 */
547 .long sys_sched_setscheduler
548 .long sys_sched_getscheduler
549 .long sys_sched_yield
550 .long sys_sched_get_priority_max
551 .long sys_sched_get_priority_min /* 160 */
552 .long sys_sched_rr_get_interval
553 .long sys_nanosleep
554 .long sys_mremap
555 .long sys_setresuid16
556 .long sys_getresuid16 /* 165 */
557 .long sys_ni_syscall /* vm86 */
558 .long sys_ni_syscall /* Old sys_query_module */
559 .long sys_poll
560 .long sys_nfsservctl
561 .long sys_setresgid16 /* 170 */
562 .long sys_getresgid16
563 .long sys_prctl
564 .long sys_rt_sigreturn
565 .long sys_rt_sigaction
566 .long sys_rt_sigprocmask /* 175 */
567 .long sys_rt_sigpending
568 .long sys_rt_sigtimedwait
569 .long sys_rt_sigqueueinfo
570 .long sys_rt_sigsuspend
571 .long sys_pread64 /* 180 */
572 .long sys_pwrite64
573 .long sys_chown16
574 .long sys_getcwd
575 .long sys_capget
576 .long sys_capset /* 185 */
577 .long sys_sigaltstack
578 .long sys_sendfile
579 .long sys_ni_syscall /* reserved for streams1 */
580 .long sys_ni_syscall /* reserved for streams2 */
581 .long sys_vfork /* 190 */
582 .long sys_getrlimit
583 .long sys_mmap2
584 .long sys_truncate64
585 .long sys_ftruncate64
586 .long sys_stat64 /* 195 */
587 .long sys_lstat64
588 .long sys_fstat64
589 .long sys_lchown
590 .long sys_getuid
591 .long sys_getgid /* 200 */
592 .long sys_geteuid
593 .long sys_getegid
594 .long sys_setreuid
595 .long sys_setregid
596 .long sys_getgroups /* 205 */
597 .long sys_setgroups
598 .long sys_fchown
599 .long sys_setresuid
600 .long sys_getresuid
601 .long sys_setresgid /* 210 */
602 .long sys_getresgid
603 .long sys_chown
604 .long sys_setuid
605 .long sys_setgid
606 .long sys_setfsuid /* 215 */
607 .long sys_setfsgid
608 .long sys_pivot_root
609 .long sys_mincore
610 .long sys_madvise
611 .long sys_getdents64 /* 220 */
612 .long sys_fcntl64
613 .long sys_ni_syscall /* reserved for TUX */
614 .long sys_ni_syscall
615 .long sys_gettid
616 .long sys_readahead /* 225 */
617 .long sys_setxattr
618 .long sys_lsetxattr
619 .long sys_fsetxattr
620 .long sys_getxattr
621 .long sys_lgetxattr /* 230 */
622 .long sys_fgetxattr
623 .long sys_listxattr
624 .long sys_llistxattr
625 .long sys_flistxattr
626 .long sys_removexattr /* 235 */
627 .long sys_lremovexattr
628 .long sys_fremovexattr
629 .long sys_tkill
630 .long sys_sendfile64
631 .long sys_futex /* 240 */
632 .long sys_sched_setaffinity
633 .long sys_sched_getaffinity
634 .long sys_ni_syscall /* sys_set_thread_area */
635 .long sys_ni_syscall /* sys_get_thread_area */
636 .long sys_io_setup /* 245 */
637 .long sys_io_destroy
638 .long sys_io_getevents
639 .long sys_io_submit
640 .long sys_io_cancel
641 .long sys_fadvise64 /* 250 */
642 .long sys_ni_syscall
643 .long sys_exit_group
644 .long sys_lookup_dcookie
645 .long sys_epoll_create
646 .long sys_epoll_ctl /* 255 */
647 .long sys_epoll_wait
648 .long sys_remap_file_pages
649 .long sys_set_tid_address
650 .long sys_timer_create
651 .long sys_timer_settime /* 260 */
652 .long sys_timer_gettime
653 .long sys_timer_getoverrun
654 .long sys_timer_delete
655 .long sys_clock_settime
656 .long sys_clock_gettime /* 265 */
657 .long sys_clock_getres
658 .long sys_clock_nanosleep
659 .long sys_statfs64
660 .long sys_fstatfs64
661 .long sys_tgkill /* 270 */
662 .long sys_utimes
663 .long sys_fadvise64_64
664 .long sys_ni_syscall /* sys_vserver */
665 .long sys_mbind
666 .long sys_get_mempolicy /* 275 */
667 .long sys_set_mempolicy
668 .long sys_mq_open
669 .long sys_mq_unlink
670 .long sys_mq_timedsend
671 .long sys_mq_timedreceive /* 280 */
672 .long sys_mq_notify
673 .long sys_mq_getsetattr
674 .long sys_kexec_load
675 .long sys_waitid
676 .long sys_ni_syscall /* 285 */ /* available */
677 .long sys_add_key
678 .long sys_request_key
679 .long sys_keyctl
680 .long sys_cacheflush
681 .long sys_ioprio_set /* 290 */
682 .long sys_ioprio_get
683 .long sys_inotify_init
684 .long sys_inotify_add_watch
685 .long sys_inotify_rm_watch
686 .long sys_migrate_pages /* 295 */
687 .long sys_openat
688 .long sys_mkdirat
689 .long sys_mknodat
690 .long sys_fchownat
691 .long sys_futimesat /* 300 */
692 .long sys_fstatat64
693 .long sys_unlinkat
694 .long sys_renameat
695 .long sys_linkat
696 .long sys_symlinkat /* 305 */
697 .long sys_readlinkat
698 .long sys_fchmodat
699 .long sys_faccessat
700 .long sys_pselect6
701 .long sys_ppoll /* 310 */
702 .long sys_unshare
703 .long sys_set_robust_list
704 .long sys_get_robust_list
705 .long sys_splice
706 .long sys_sync_file_range /* 315 */
707 .long sys_tee
708 .long sys_vmsplice
709 .long sys_move_pages
710 .long sys_getcpu
711 .long sys_epoll_pwait /* 320 */
712 .long sys_utimensat
713 .long sys_signalfd
714 .long sys_timerfd_create
715 .long sys_eventfd
716 .long sys_fallocate /* 325 */
717 .long sys_timerfd_settime
718 .long sys_timerfd_gettime
719
720
721nr_syscalls=(.-sys_call_table)/4
diff --git a/arch/mn10300/kernel/fpu-low.S b/arch/mn10300/kernel/fpu-low.S
new file mode 100644
index 000000000000..96cfd47e68d5
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-low.S
@@ -0,0 +1,197 @@
1/* MN10300 Low level FPU management operations
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/cpu-regs.h>
12
13###############################################################################
14#
15# void fpu_init_state(void)
16# - initialise the FPU
17#
18###############################################################################
19 .globl fpu_init_state
20 .type fpu_init_state,@function
21fpu_init_state:
22 mov epsw,d0
23 or EPSW_FE,epsw
24
25#ifdef CONFIG_MN10300_PROC_MN103E010
26 nop
27 nop
28 nop
29#endif
30 fmov 0,fs0
31 fmov fs0,fs1
32 fmov fs0,fs2
33 fmov fs0,fs3
34 fmov fs0,fs4
35 fmov fs0,fs5
36 fmov fs0,fs6
37 fmov fs0,fs7
38 fmov fs0,fs8
39 fmov fs0,fs9
40 fmov fs0,fs10
41 fmov fs0,fs11
42 fmov fs0,fs12
43 fmov fs0,fs13
44 fmov fs0,fs14
45 fmov fs0,fs15
46 fmov fs0,fs16
47 fmov fs0,fs17
48 fmov fs0,fs18
49 fmov fs0,fs19
50 fmov fs0,fs20
51 fmov fs0,fs21
52 fmov fs0,fs22
53 fmov fs0,fs23
54 fmov fs0,fs24
55 fmov fs0,fs25
56 fmov fs0,fs26
57 fmov fs0,fs27
58 fmov fs0,fs28
59 fmov fs0,fs29
60 fmov fs0,fs30
61 fmov fs0,fs31
62 fmov FPCR_INIT,fpcr
63
64#ifdef CONFIG_MN10300_PROC_MN103E010
65 nop
66 nop
67 nop
68#endif
69 mov d0,epsw
70 ret [],0
71
72 .size fpu_init_state,.-fpu_init_state
73
74###############################################################################
75#
76# void fpu_save(struct fpu_state_struct *)
77# - save the fpu state
78# - note that an FPU Operational exception might occur during this process
79#
80###############################################################################
81 .globl fpu_save
82 .type fpu_save,@function
83fpu_save:
84 mov epsw,d1
85 or EPSW_FE,epsw /* enable the FPU so we can access it */
86
87#ifdef CONFIG_MN10300_PROC_MN103E010
88 nop
89 nop
90#endif
91 mov d0,a0
92 fmov fs0,(a0+)
93 fmov fs1,(a0+)
94 fmov fs2,(a0+)
95 fmov fs3,(a0+)
96 fmov fs4,(a0+)
97 fmov fs5,(a0+)
98 fmov fs6,(a0+)
99 fmov fs7,(a0+)
100 fmov fs8,(a0+)
101 fmov fs9,(a0+)
102 fmov fs10,(a0+)
103 fmov fs11,(a0+)
104 fmov fs12,(a0+)
105 fmov fs13,(a0+)
106 fmov fs14,(a0+)
107 fmov fs15,(a0+)
108 fmov fs16,(a0+)
109 fmov fs17,(a0+)
110 fmov fs18,(a0+)
111 fmov fs19,(a0+)
112 fmov fs20,(a0+)
113 fmov fs21,(a0+)
114 fmov fs22,(a0+)
115 fmov fs23,(a0+)
116 fmov fs24,(a0+)
117 fmov fs25,(a0+)
118 fmov fs26,(a0+)
119 fmov fs27,(a0+)
120 fmov fs28,(a0+)
121 fmov fs29,(a0+)
122 fmov fs30,(a0+)
123 fmov fs31,(a0+)
124 fmov fpcr,d0
125 mov d0,(a0)
126#ifdef CONFIG_MN10300_PROC_MN103E010
127 nop
128 nop
129#endif
130
131 mov d1,epsw
132 ret [],0
133
134 .size fpu_save,.-fpu_save
135
136###############################################################################
137#
138# void fpu_restore(struct fpu_state_struct *)
139# - restore the fpu state
140# - note that an FPU Operational exception might occur during this process
141#
142###############################################################################
143 .globl fpu_restore
144 .type fpu_restore,@function
145fpu_restore:
146 mov epsw,d1
147 or EPSW_FE,epsw /* enable the FPU so we can access it */
148
149#ifdef CONFIG_MN10300_PROC_MN103E010
150 nop
151 nop
152#endif
153 mov d0,a0
154 fmov (a0+),fs0
155 fmov (a0+),fs1
156 fmov (a0+),fs2
157 fmov (a0+),fs3
158 fmov (a0+),fs4
159 fmov (a0+),fs5
160 fmov (a0+),fs6
161 fmov (a0+),fs7
162 fmov (a0+),fs8
163 fmov (a0+),fs9
164 fmov (a0+),fs10
165 fmov (a0+),fs11
166 fmov (a0+),fs12
167 fmov (a0+),fs13
168 fmov (a0+),fs14
169 fmov (a0+),fs15
170 fmov (a0+),fs16
171 fmov (a0+),fs17
172 fmov (a0+),fs18
173 fmov (a0+),fs19
174 fmov (a0+),fs20
175 fmov (a0+),fs21
176 fmov (a0+),fs22
177 fmov (a0+),fs23
178 fmov (a0+),fs24
179 fmov (a0+),fs25
180 fmov (a0+),fs26
181 fmov (a0+),fs27
182 fmov (a0+),fs28
183 fmov (a0+),fs29
184 fmov (a0+),fs30
185 fmov (a0+),fs31
186 mov (a0),d0
187 fmov d0,fpcr
188#ifdef CONFIG_MN10300_PROC_MN103E010
189 nop
190 nop
191 nop
192#endif
193
194 mov d1,epsw
195 ret [],0
196
197 .size fpu_restore,.-fpu_restore
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
new file mode 100644
index 000000000000..e705f25ad5ff
--- /dev/null
+++ b/arch/mn10300/kernel/fpu.c
@@ -0,0 +1,223 @@
1/* MN10300 FPU management
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/uaccess.h>
12#include <asm/fpu.h>
13#include <asm/elf.h>
14#include <asm/exceptions.h>
15
16struct task_struct *fpu_state_owner;
17
18/*
19 * handle an exception due to the FPU being disabled
20 */
21asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
22{
23 struct task_struct *tsk = current;
24
25 if (!user_mode(regs))
26 die_if_no_fixup("An FPU Disabled exception happened in"
27 " kernel space\n",
28 regs, code);
29
30#ifdef CONFIG_FPU
31 preempt_disable();
32
33 /* transfer the last process's FPU state to memory */
34 if (fpu_state_owner) {
35 fpu_save(&fpu_state_owner->thread.fpu_state);
36 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
37 }
38
39 /* the current process now owns the FPU state */
40 fpu_state_owner = tsk;
41 regs->epsw |= EPSW_FE;
42
43 /* load the FPU with the current process's FPU state or invent a new
44 * clean one if the process doesn't have one */
45 if (is_using_fpu(tsk)) {
46 fpu_restore(&tsk->thread.fpu_state);
47 } else {
48 fpu_init_state();
49 set_using_fpu(tsk);
50 }
51
52 preempt_enable();
53#else
54 {
55 siginfo_t info;
56
57 info.si_signo = SIGFPE;
58 info.si_errno = 0;
59 info.si_addr = (void *) tsk->thread.uregs->pc;
60 info.si_code = FPE_FLTINV;
61
62 force_sig_info(SIGFPE, &info, tsk);
63 }
64#endif /* CONFIG_FPU */
65}
66
67/*
68 * handle an FPU operational exception
69 * - there's a possibility that if the FPU is asynchronous, the signal might
70 * be meant for a process other than the current one
71 */
72asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
73{
74 struct task_struct *tsk = fpu_state_owner;
75 siginfo_t info;
76
77 if (!user_mode(regs))
78 die_if_no_fixup("An FPU Operation exception happened in"
79 " kernel space\n",
80 regs, code);
81
82 if (!tsk)
83 die_if_no_fixup("An FPU Operation exception happened,"
84 " but the FPU is not in use",
85 regs, code);
86
87 info.si_signo = SIGFPE;
88 info.si_errno = 0;
89 info.si_addr = (void *) tsk->thread.uregs->pc;
90 info.si_code = FPE_FLTINV;
91
92#ifdef CONFIG_FPU
93 {
94 u32 fpcr;
95
96 /* get FPCR (we need to enable the FPU whilst we do this) */
97 asm volatile(" or %1,epsw \n"
98#ifdef CONFIG_MN10300_PROC_MN103E010
99 " nop \n"
100 " nop \n"
101 " nop \n"
102#endif
103 " fmov fpcr,%0 \n"
104#ifdef CONFIG_MN10300_PROC_MN103E010
105 " nop \n"
106 " nop \n"
107 " nop \n"
108#endif
109 " and %2,epsw \n"
110 : "=&d"(fpcr)
111 : "i"(EPSW_FE), "i"(~EPSW_FE)
112 );
113
114 if (fpcr & FPCR_EC_Z)
115 info.si_code = FPE_FLTDIV;
116 else if (fpcr & FPCR_EC_O)
117 info.si_code = FPE_FLTOVF;
118 else if (fpcr & FPCR_EC_U)
119 info.si_code = FPE_FLTUND;
120 else if (fpcr & FPCR_EC_I)
121 info.si_code = FPE_FLTRES;
122 }
123#endif
124
125 force_sig_info(SIGFPE, &info, tsk);
126}
127
128/*
129 * save the FPU state to a signal context
130 */
131int fpu_setup_sigcontext(struct fpucontext *fpucontext)
132{
133#ifdef CONFIG_FPU
134 struct task_struct *tsk = current;
135
136 if (!is_using_fpu(tsk))
137 return 0;
138
139 /* transfer the current FPU state to memory and cause fpu_init() to be
140 * triggered by the next attempted FPU operation by the current
141 * process.
142 */
143 preempt_disable();
144
145 if (fpu_state_owner == tsk) {
146 fpu_save(&tsk->thread.fpu_state);
147 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
148 fpu_state_owner = NULL;
149 }
150
151 preempt_enable();
152
153 /* we no longer have a valid current FPU state */
154 clear_using_fpu(tsk);
155
156 /* transfer the saved FPU state onto the userspace stack */
157 if (copy_to_user(fpucontext,
158 &tsk->thread.fpu_state,
159 min(sizeof(struct fpu_state_struct),
160 sizeof(struct fpucontext))))
161 return -1;
162
163 return 1;
164#else
165 return 0;
166#endif
167}
168
169/*
170 * kill a process's FPU state during restoration after signal handling
171 */
172void fpu_kill_state(struct task_struct *tsk)
173{
174#ifdef CONFIG_FPU
175 /* disown anything left in the FPU */
176 preempt_disable();
177
178 if (fpu_state_owner == tsk) {
179 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
180 fpu_state_owner = NULL;
181 }
182
183 preempt_enable();
184#endif
185 /* we no longer have a valid current FPU state */
186 clear_using_fpu(tsk);
187}
188
189/*
190 * restore the FPU state from a signal context
191 */
192int fpu_restore_sigcontext(struct fpucontext *fpucontext)
193{
194 struct task_struct *tsk = current;
195 int ret;
196
197 /* load up the old FPU state */
198 ret = copy_from_user(&tsk->thread.fpu_state,
199 fpucontext,
200 min(sizeof(struct fpu_state_struct),
201 sizeof(struct fpucontext)));
202 if (!ret)
203 set_using_fpu(tsk);
204
205 return ret;
206}
207
208/*
209 * fill in the FPU structure for a core dump
210 */
211int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
212{
213 struct task_struct *tsk = current;
214 int fpvalid;
215
216 fpvalid = is_using_fpu(tsk);
217 if (fpvalid) {
218 unlazy_fpu(tsk);
219 memcpy(fpreg, &tsk->thread.fpu_state, sizeof(*fpreg));
220 }
221
222 return fpvalid;
223}
diff --git a/arch/mn10300/kernel/gdb-cache.S b/arch/mn10300/kernel/gdb-cache.S
new file mode 100644
index 000000000000..1108badc3d32
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-cache.S
@@ -0,0 +1,105 @@
1###############################################################################
2#
3# MN10300 Low-level cache purging routines for gdbstub
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/smp.h>
17#include <asm/cache.h>
18#include <asm/cpu-regs.h>
19#include <asm/exceptions.h>
20#include <asm/frame.inc>
21#include <asm/serial-regs.h>
22
23 .text
24
25###############################################################################
26#
27# GDB stub cache purge
28#
29###############################################################################
30 .type gdbstub_purge_cache,@function
31ENTRY(gdbstub_purge_cache)
32 #######################################################################
33 # read the addresses tagged in the cache's tag RAM and attempt to flush
34 # those addresses specifically
35 # - we rely on the hardware to filter out invalid tag entry addresses
36 mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
37 mov DCACHE_PURGE(0,0),a1 # dcache purge request address
38 mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
39
40mn10300_dcache_flush_loop:
41 mov (a0),d0
42 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
43 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
44 # cache
45 mov d0,(a1) # conditional purge
46
47mn10300_dcache_flush_skip:
48 add L1_CACHE_BYTES,a0
49 add L1_CACHE_BYTES,a1
50 add -1,d1
51 bne mn10300_dcache_flush_loop
52
53;; # unconditionally flush and invalidate the dcache
54;; mov DCACHE_PURGE(0,0),a1 # dcache purge request address
55;; mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of
56;; # entries
57;;
58;; gdbstub_purge_cache__dcache_loop:
59;; mov (a1),d0 # unconditional purge
60;;
61;; add L1_CACHE_BYTES,a1
62;; add -1,d1
63;; bne gdbstub_purge_cache__dcache_loop
64
65 #######################################################################
66 # now invalidate the icache
67 mov CHCTR,a0
68 movhu (a0),a1
69
70 mov epsw,d1
71 and ~EPSW_IE,epsw
72 nop
73 nop
74
75 # disable the icache
76 and ~CHCTR_ICEN,d0
77 movhu d0,(a0)
78
79 # and wait for it to calm down
80 setlb
81 movhu (a0),d0
82 btst CHCTR_ICBUSY,d0
83 lne
84
85 # invalidate
86 or CHCTR_ICINV,d0
87 movhu d0,(a0)
88
89 # wait for the cache to finish
90 mov CHCTR,a0
91 setlb
92 movhu (a0),d0
93 btst CHCTR_ICBUSY,d0
94 lne
95
96 # and reenable it
97 movhu a1,(a0)
98 movhu (a0),d0 # read back to flush
99 # (SIGILLs all over without this)
100
101 mov d1,epsw
102
103 ret [],0
104
105 .size gdbstub_purge_cache,.-gdbstub_purge_cache
diff --git a/arch/mn10300/kernel/gdb-io-serial-low.S b/arch/mn10300/kernel/gdb-io-serial-low.S
new file mode 100644
index 000000000000..c68dcd052201
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-serial-low.S
@@ -0,0 +1,90 @@
1###############################################################################
2#
3# 16550 serial Rx interrupt handler for gdbstub I/O
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/smp.h>
17#include <asm/cpu-regs.h>
18#include <asm/thread_info.h>
19#include <asm/frame.inc>
20#include <asm/intctl-regs.h>
21#include <asm/unit/serial.h>
22
23 .text
24
25###############################################################################
26#
27# GDB stub serial receive interrupt entry point
28# - intended to run at interrupt priority 0
29#
30###############################################################################
31 .globl gdbstub_io_rx_handler
32 .type gdbstub_io_rx_handler,@function
33gdbstub_io_rx_handler:
34 movm [d2,d3,a2,a3],(sp)
35
36#if 1
37 movbu (GDBPORT_SERIAL_IIR),d2
38#endif
39
40 mov (gdbstub_rx_inp),a3
41gdbstub_io_rx_more:
42 mov a3,a2
43 add 2,a3
44 and 0x00000fff,a3
45 mov (gdbstub_rx_outp),d3
46 cmp a3,d3
47 beq gdbstub_io_rx_overflow
48
49 movbu (GDBPORT_SERIAL_LSR),d3
50 btst UART_LSR_DR,d3
51 beq gdbstub_io_rx_done
52 movbu (GDBPORT_SERIAL_RX),d2
53 movbu d3,(gdbstub_rx_buffer+1,a2)
54 movbu d2,(gdbstub_rx_buffer,a2)
55 mov a3,(gdbstub_rx_inp)
56 bra gdbstub_io_rx_more
57
58gdbstub_io_rx_done:
59 mov GxICR_DETECT,d2
60 movbu d2,(XIRQxICR(GDBPORT_SERIAL_IRQ)) # ACK the interrupt
61 movhu (XIRQxICR(GDBPORT_SERIAL_IRQ)),d2 # flush
62 movm (sp),[d2,d3,a2,a3]
63 bset 0x01,(gdbstub_busy)
64 beq gdbstub_io_rx_enter
65 rti
66
67gdbstub_io_rx_overflow:
68 bset 0x01,(gdbstub_rx_overflow)
69 bra gdbstub_io_rx_done
70
71gdbstub_io_rx_enter:
72 or EPSW_IE|EPSW_IM_1,epsw
73 add -4,sp
74 SAVE_ALL
75
76 mov 0xffffffff,d0
77 mov d0,(REG_ORIG_D0,fp)
78 mov 0x280,d1
79
80 mov fp,d0
81 call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep)
82
83 and ~EPSW_IE,epsw
84 bclr 0x01,(gdbstub_busy)
85
86 .globl gdbstub_return
87gdbstub_return:
88 RESTORE_ALL
89
90 .size gdbstub_io_rx_handler,.-gdbstub_io_rx_handler
diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c
new file mode 100644
index 000000000000..9a6d4e8ebe73
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-serial.c
@@ -0,0 +1,155 @@
1/* 16550 serial driver for gdbstub I/O
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/string.h>
12#include <linux/kernel.h>
13#include <linux/signal.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/console.h>
17#include <linux/init.h>
18#include <linux/nmi.h>
19
20#include <asm/pgtable.h>
21#include <asm/system.h>
22#include <asm/gdb-stub.h>
23#include <asm/exceptions.h>
24#include <asm/serial-regs.h>
25#include <asm/unit/serial.h>
26
27/*
28 * initialise the GDB stub
29 */
30void gdbstub_io_init(void)
31{
32 u16 tmp;
33
34 /* set up the serial port */
35 GDBPORT_SERIAL_LCR = UART_LCR_WLEN8; /* 1N8 */
36 GDBPORT_SERIAL_FCR = (UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
37 UART_FCR_CLEAR_XMIT);
38
39 FLOWCTL_CLEAR(DTR);
40 FLOWCTL_SET(RTS);
41
42 gdbstub_io_set_baud(115200);
43
44 /* we want to get serial receive interrupts */
45 XIRQxICR(GDBPORT_SERIAL_IRQ) = 0;
46 tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
47
48 IVAR0 = EXCEP_IRQ_LEVEL0;
49 set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
50
51 XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST;
52 XIRQxICR(GDBPORT_SERIAL_IRQ) = GxICR_ENABLE | GxICR_LEVEL_0;
53 tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
54
55 GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
56
57 /* permit level 0 IRQs to take place */
58 asm volatile(
59 " and %0,epsw \n"
60 " or %1,epsw \n"
61 :
62 : "i"(~EPSW_IM), "i"(EPSW_IE | EPSW_IM_1)
63 );
64}
65
66/*
67 * set up the GDB stub serial port baud rate timers
68 */
69void gdbstub_io_set_baud(unsigned baud)
70{
71 unsigned value;
72 u8 lcr;
73
74 value = 18432000 / 16 / baud;
75
76 lcr = GDBPORT_SERIAL_LCR;
77 GDBPORT_SERIAL_LCR |= UART_LCR_DLAB;
78 GDBPORT_SERIAL_DLL = value & 0xff;
79 GDBPORT_SERIAL_DLM = (value >> 8) & 0xff;
80 GDBPORT_SERIAL_LCR = lcr;
81}
82
83/*
84 * wait for a character to come from the debugger
85 */
86int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
87{
88 unsigned ix;
89 u8 ch, st;
90
91 *_ch = 0xff;
92
93 if (gdbstub_rx_unget) {
94 *_ch = gdbstub_rx_unget;
95 gdbstub_rx_unget = 0;
96 return 0;
97 }
98
99 try_again:
100 /* pull chars out of the buffer */
101 ix = gdbstub_rx_outp;
102 if (ix == gdbstub_rx_inp) {
103 if (nonblock)
104 return -EAGAIN;
105#ifdef CONFIG_MN10300_WD_TIMER
106 watchdog_alert_counter = 0;
107#endif /* CONFIG_MN10300_WD_TIMER */
108 goto try_again;
109 }
110
111 ch = gdbstub_rx_buffer[ix++];
112 st = gdbstub_rx_buffer[ix++];
113 gdbstub_rx_outp = ix & 0x00000fff;
114
115 if (st & UART_LSR_BI) {
116 gdbstub_proto("### GDB Rx Break Detected ###\n");
117 return -EINTR;
118 } else if (st & (UART_LSR_FE | UART_LSR_OE | UART_LSR_PE)) {
119 gdbstub_proto("### GDB Rx Error (st=%02x) ###\n", st);
120 return -EIO;
121 } else {
122 gdbstub_proto("### GDB Rx %02x (st=%02x) ###\n", ch, st);
123 *_ch = ch & 0x7f;
124 return 0;
125 }
126}
127
128/*
129 * send a character to the debugger
130 */
131void gdbstub_io_tx_char(unsigned char ch)
132{
133 FLOWCTL_SET(DTR);
134 LSR_WAIT_FOR(THRE);
135 /* FLOWCTL_WAIT_FOR(CTS); */
136
137 if (ch == 0x0a) {
138 GDBPORT_SERIAL_TX = 0x0d;
139 LSR_WAIT_FOR(THRE);
140 /* FLOWCTL_WAIT_FOR(CTS); */
141 }
142 GDBPORT_SERIAL_TX = ch;
143
144 FLOWCTL_CLEAR(DTR);
145}
146
147/*
148 * send a character to the debugger
149 */
150void gdbstub_io_tx_flush(void)
151{
152 LSR_WAIT_FOR(TEMT);
153 LSR_WAIT_FOR(THRE);
154 FLOWCTL_CLEAR(DTR);
155}
diff --git a/arch/mn10300/kernel/gdb-io-ttysm-low.S b/arch/mn10300/kernel/gdb-io-ttysm-low.S
new file mode 100644
index 000000000000..677c7876307c
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm-low.S
@@ -0,0 +1,93 @@
1###############################################################################
2#
3# MN10300 On-chip serial Rx interrupt handler for GDB stub I/O
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/smp.h>
17#include <asm/thread_info.h>
18#include <asm/cpu-regs.h>
19#include <asm/frame.inc>
20#include <asm/intctl-regs.h>
21#include <asm/unit/serial.h>
22#include "mn10300-serial.h"
23
24 .text
25
26###############################################################################
27#
28# GDB stub serial receive interrupt entry point
29# - intended to run at interrupt priority 0
30#
31###############################################################################
32 .globl gdbstub_io_rx_handler
33 .type gdbstub_io_rx_handler,@function
34gdbstub_io_rx_handler:
35 movm [d2,d3,a2,a3],(sp)
36
37 mov (gdbstub_rx_inp),a3
38gdbstub_io_rx_more:
39 mov a3,a2
40 add 2,a3
41 and PAGE_SIZE_asm-1,a3
42 mov (gdbstub_rx_outp),d3
43 cmp a3,d3
44 beq gdbstub_io_rx_overflow
45
46 movbu (SCgSTR),d3
47 btst SC01STR_RBF,d3
48 beq gdbstub_io_rx_done
49 movbu (SCgRXB),d2
50 movbu d3,(gdbstub_rx_buffer+1,a2)
51 movbu d2,(gdbstub_rx_buffer,a2)
52 mov a3,(gdbstub_rx_inp)
53 bra gdbstub_io_rx_more
54
55gdbstub_io_rx_done:
56 mov GxICR_DETECT,d2
57 movbu d2,(GxICR(SCgRXIRQ)) # ACK the interrupt
58 movhu (GxICR(SCgRXIRQ)),d2 # flush
59
60 movm (sp),[d2,d3,a2,a3]
61 bset 0x01,(gdbstub_busy)
62 beq gdbstub_io_rx_enter
63 rti
64
65gdbstub_io_rx_overflow:
66 bset 0x01,(gdbstub_rx_overflow)
67 bra gdbstub_io_rx_done
68
69###############################################################################
70#
71# debugging interrupt - enter the GDB stub proper
72#
73###############################################################################
74gdbstub_io_rx_enter:
75 or EPSW_IE|EPSW_IM_1,epsw
76 add -4,sp
77 SAVE_ALL
78
79 mov 0xffffffff,d0
80 mov d0,(REG_ORIG_D0,fp)
81 mov 0x280,d1
82
83 mov fp,d0
84 call gdbstub_rx_irq[],0 # gdbstub_io_rx_irq(regs,excep)
85
86 and ~EPSW_IE,epsw
87 bclr 0x01,(gdbstub_busy)
88
89 .globl gdbstub_return
90gdbstub_return:
91 RESTORE_ALL
92
93 .size gdbstub_io_rx_handler,.-gdbstub_io_rx_handler
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c
new file mode 100644
index 000000000000..c5451592d403
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm.c
@@ -0,0 +1,299 @@
1/* MN10300 On-chip serial driver for gdbstub I/O
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/string.h>
12#include <linux/kernel.h>
13#include <linux/signal.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/console.h>
17#include <linux/init.h>
18#include <linux/tty.h>
19#include <asm/pgtable.h>
20#include <asm/system.h>
21#include <asm/gdb-stub.h>
22#include <asm/exceptions.h>
23#include <asm/unit/clock.h>
24#include "mn10300-serial.h"
25
26#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
27struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0;
28#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
29struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1;
30#else
31struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2;
32#endif
33
34
35/*
36 * initialise the GDB stub I/O routines
37 */
38void __init gdbstub_io_init(void)
39{
40 uint16_t scxctr;
41 int tmp;
42
43 switch (gdbstub_port->clock_src) {
44 case MNSCx_CLOCK_SRC_IOCLK:
45 gdbstub_port->ioclk = MN10300_IOCLK;
46 break;
47
48#ifdef MN10300_IOBCLK
49 case MNSCx_CLOCK_SRC_IOBCLK:
50 gdbstub_port->ioclk = MN10300_IOBCLK;
51 break;
52#endif
53 default:
54 BUG();
55 }
56
57 /* set up the serial port */
58 gdbstub_io_set_baud(115200);
59
60 /* we want to get serial receive interrupts */
61 set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0);
62 set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0);
63 set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
64
65 *gdbstub_port->rx_icr |= GxICR_ENABLE;
66 tmp = *gdbstub_port->rx_icr;
67
68 /* enable the device */
69 scxctr = SC01CTR_CLN_8BIT; /* 1N8 */
70 switch (gdbstub_port->div_timer) {
71 case MNSCx_DIV_TIMER_16BIT:
72 scxctr |= SC0CTR_CK_TM8UFLOW_8; /* == SC1CTR_CK_TM9UFLOW_8
73 == SC2CTR_CK_TM10UFLOW_8 */
74 break;
75
76 case MNSCx_DIV_TIMER_8BIT:
77 scxctr |= SC0CTR_CK_TM2UFLOW_8;
78 break;
79 }
80
81 scxctr |= SC01CTR_TXE | SC01CTR_RXE;
82
83 *gdbstub_port->_control = scxctr;
84 tmp = *gdbstub_port->_control;
85
86 /* permit level 0 IRQs only */
87 asm volatile(
88 " and %0,epsw \n"
89 " or %1,epsw \n"
90 :
91 : "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1)
92 );
93}
94
95/*
96 * set up the GDB stub serial port baud rate timers
97 */
98void gdbstub_io_set_baud(unsigned baud)
99{
100 const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] +
101 * 1 [stop] */
102 unsigned long ioclk = gdbstub_port->ioclk;
103 unsigned xdiv, tmp;
104 uint16_t tmxbr;
105 uint8_t tmxmd;
106
107 if (!baud) {
108 baud = 9600;
109 } else if (baud == 134) {
110 baud = 269; /* 134 is really 134.5 */
111 xdiv = 2;
112 }
113
114try_alternative:
115 xdiv = 1;
116
117 switch (gdbstub_port->div_timer) {
118 case MNSCx_DIV_TIMER_16BIT:
119 tmxmd = TM8MD_SRC_IOCLK;
120 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
121 if (tmp > 0 && tmp <= 65535)
122 goto timer_okay;
123
124 tmxmd = TM8MD_SRC_IOCLK_8;
125 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
126 if (tmp > 0 && tmp <= 65535)
127 goto timer_okay;
128
129 tmxmd = TM8MD_SRC_IOCLK_32;
130 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
131 if (tmp > 0 && tmp <= 65535)
132 goto timer_okay;
133
134 break;
135
136 case MNSCx_DIV_TIMER_8BIT:
137 tmxmd = TM2MD_SRC_IOCLK;
138 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
139 if (tmp > 0 && tmp <= 255)
140 goto timer_okay;
141
142 tmxmd = TM2MD_SRC_IOCLK_8;
143 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
144 if (tmp > 0 && tmp <= 255)
145 goto timer_okay;
146
147 tmxmd = TM2MD_SRC_IOCLK_32;
148 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
149 if (tmp > 0 && tmp <= 255)
150 goto timer_okay;
151 break;
152 }
153
154 /* as a last resort, if the quotient is zero, default to 9600 bps */
155 baud = 9600;
156 goto try_alternative;
157
158timer_okay:
159 gdbstub_port->uart.timeout = (2 * bits * HZ) / baud;
160 gdbstub_port->uart.timeout += HZ / 50;
161
162 /* set the timer to produce the required baud rate */
163 switch (gdbstub_port->div_timer) {
164 case MNSCx_DIV_TIMER_16BIT:
165 *gdbstub_port->_tmxmd = 0;
166 *gdbstub_port->_tmxbr = tmxbr;
167 *gdbstub_port->_tmxmd = TM8MD_INIT_COUNTER;
168 *gdbstub_port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
169 break;
170
171 case MNSCx_DIV_TIMER_8BIT:
172 *gdbstub_port->_tmxmd = 0;
173 *(volatile u8 *) gdbstub_port->_tmxbr = (u8)tmxbr;
174 *gdbstub_port->_tmxmd = TM2MD_INIT_COUNTER;
175 *gdbstub_port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
176 break;
177 }
178}
179
180/*
181 * wait for a character to come from the debugger
182 */
183int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
184{
185 unsigned ix;
186 u8 ch, st;
187
188 *_ch = 0xff;
189
190 if (gdbstub_rx_unget) {
191 *_ch = gdbstub_rx_unget;
192 gdbstub_rx_unget = 0;
193 return 0;
194 }
195
196try_again:
197 /* pull chars out of the buffer */
198 ix = gdbstub_rx_outp;
199 if (ix == gdbstub_rx_inp) {
200 if (nonblock)
201 return -EAGAIN;
202#ifdef CONFIG_MN10300_WD_TIMER
203 watchdog_alert_counter = 0;
204#endif /* CONFIG_MN10300_WD_TIMER */
205 goto try_again;
206 }
207
208 ch = gdbstub_rx_buffer[ix++];
209 st = gdbstub_rx_buffer[ix++];
210 gdbstub_rx_outp = ix & (PAGE_SIZE - 1);
211
212 st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF |
213 SC01STR_OEF;
214
215 /* deal with what we've got
216 * - note that the UART doesn't do BREAK-detection for us
217 */
218 if (st & SC01STR_FEF && ch == 0) {
219 switch (gdbstub_port->rx_brk) {
220 case 0: gdbstub_port->rx_brk = 1; goto try_again;
221 case 1: gdbstub_port->rx_brk = 2; goto try_again;
222 case 2:
223 gdbstub_port->rx_brk = 3;
224 gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
225 " ###\n");
226 return -EINTR;
227 default:
228 goto try_again;
229 }
230 } else if (st & SC01STR_FEF) {
231 if (gdbstub_port->rx_brk)
232 goto try_again;
233
234 gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
235 return -EIO;
236 } else if (st & SC01STR_OEF) {
237 if (gdbstub_port->rx_brk)
238 goto try_again;
239
240 gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
241 return -EIO;
242 } else if (st & SC01STR_PEF) {
243 if (gdbstub_port->rx_brk)
244 goto try_again;
245
246 gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
247 return -EIO;
248 } else {
249 /* look for the tail-end char on a break run */
250 if (gdbstub_port->rx_brk == 3) {
251 switch (ch) {
252 case 0xFF:
253 case 0xFE:
254 case 0xFC:
255 case 0xF8:
256 case 0xF0:
257 case 0xE0:
258 case 0xC0:
259 case 0x80:
260 case 0x00:
261 gdbstub_port->rx_brk = 0;
262 goto try_again;
263 default:
264 break;
265 }
266 }
267
268 gdbstub_port->rx_brk = 0;
269 gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st);
270 *_ch = ch & 0x7f;
271 return 0;
272 }
273}
274
275/*
276 * send a character to the debugger
277 */
278void gdbstub_io_tx_char(unsigned char ch)
279{
280 while (*gdbstub_port->_status & SC01STR_TBF)
281 continue;
282
283 if (ch == 0x0a) {
284 *(u8 *) gdbstub_port->_txb = 0x0d;
285 while (*gdbstub_port->_status & SC01STR_TBF)
286 continue;
287 }
288
289 *(u8 *) gdbstub_port->_txb = ch;
290}
291
292/*
293 * flush the transmission buffers
294 */
295void gdbstub_io_tx_flush(void)
296{
297 while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
298 continue;
299}
diff --git a/arch/mn10300/kernel/gdb-low.S b/arch/mn10300/kernel/gdb-low.S
new file mode 100644
index 000000000000..e2725552cd82
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-low.S
@@ -0,0 +1,115 @@
1###############################################################################
2#
3# MN10300 Low-level gdbstub routines
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/smp.h>
17#include <asm/cache.h>
18#include <asm/cpu-regs.h>
19#include <asm/exceptions.h>
20#include <asm/frame.inc>
21#include <asm/serial-regs.h>
22
23 .text
24
25###############################################################################
26#
27# GDB stub read memory with guard
28# - D0 holds the memory address to read
29# - D1 holds the address to store the byte into
30#
31###############################################################################
32 .globl gdbstub_read_byte_guard
33 .globl gdbstub_read_byte_cont
34ENTRY(gdbstub_read_byte)
35 mov d0,a0
36 mov d1,a1
37 clr d0
38gdbstub_read_byte_guard:
39 movbu (a0),d1
40gdbstub_read_byte_cont:
41 movbu d1,(a1)
42 ret [],0
43
44 .globl gdbstub_read_word_guard
45 .globl gdbstub_read_word_cont
46ENTRY(gdbstub_read_word)
47 mov d0,a0
48 mov d1,a1
49 clr d0
50gdbstub_read_word_guard:
51 movhu (a0),d1
52gdbstub_read_word_cont:
53 movhu d1,(a1)
54 ret [],0
55
56 .globl gdbstub_read_dword_guard
57 .globl gdbstub_read_dword_cont
58ENTRY(gdbstub_read_dword)
59 mov d0,a0
60 mov d1,a1
61 clr d0
62gdbstub_read_dword_guard:
63 mov (a0),d1
64gdbstub_read_dword_cont:
65 mov d1,(a1)
66 ret [],0
67
68###############################################################################
69#
70# GDB stub write memory with guard
71# - D0 holds the byte to store
72# - D1 holds the memory address to write
73#
74###############################################################################
75 .globl gdbstub_write_byte_guard
76 .globl gdbstub_write_byte_cont
77ENTRY(gdbstub_write_byte)
78 mov d0,a0
79 mov d1,a1
80 clr d0
81gdbstub_write_byte_guard:
82 movbu a0,(a1)
83gdbstub_write_byte_cont:
84 ret [],0
85
86 .globl gdbstub_write_word_guard
87 .globl gdbstub_write_word_cont
88ENTRY(gdbstub_write_word)
89 mov d0,a0
90 mov d1,a1
91 clr d0
92gdbstub_write_word_guard:
93 movhu a0,(a1)
94gdbstub_write_word_cont:
95 ret [],0
96
97 .globl gdbstub_write_dword_guard
98 .globl gdbstub_write_dword_cont
99ENTRY(gdbstub_write_dword)
100 mov d0,a0
101 mov d1,a1
102 clr d0
103gdbstub_write_dword_guard:
104 mov a0,(a1)
105gdbstub_write_dword_cont:
106 ret [],0
107
108###############################################################################
109#
110# GDB stub BUG() trap
111#
112###############################################################################
113ENTRY(__gdbstub_bug_trap)
114 .byte 0xF7,0xF7 # don't use 0xFF as the JTAG unit preempts that
115 ret [],0
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
new file mode 100644
index 000000000000..21891c71d549
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -0,0 +1,1947 @@
1/* MN10300 GDB stub
2 *
3 * Originally written by Glenn Engel, Lake Stevens Instrument Division
4 *
5 * Contributed by HP Systems
6 *
7 * Modified for SPARC by Stu Grossman, Cygnus Support.
8 *
9 * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
10 * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
11 *
12 * Copyright (C) 1995 Andreas Busse
13 *
14 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
15 * Modified for Linux/mn10300 by David Howells <dhowells@redhat.com>
16 */
17
18/*
19 * To enable debugger support, two things need to happen. One, a
20 * call to set_debug_traps() is necessary in order to allow any breakpoints
21 * or error conditions to be properly intercepted and reported to gdb.
22 * Two, a breakpoint needs to be generated to begin communication. This
23 * is most easily accomplished by a call to breakpoint(). Breakpoint()
24 * simulates a breakpoint by executing a BREAK instruction.
25 *
26 *
27 * The following gdb commands are supported:
28 *
29 * command function Return value
30 *
31 * g return the value of the CPU registers hex data or ENN
32 * G set the value of the CPU registers OK or ENN
33 *
34 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
35 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
36 *
37 * c Resume at current address SNN ( signal NN)
38 * cAA..AA Continue at address AA..AA SNN
39 *
40 * s Step one instruction SNN
41 * sAA..AA Step one instruction from AA..AA SNN
42 *
43 * k kill
44 *
45 * ? What was the last sigval ? SNN (signal NN)
46 *
47 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
48 * baud rate
49 *
50 * All commands and responses are sent with a packet which includes a
51 * checksum. A packet consists of
52 *
53 * $<packet info>#<checksum>.
54 *
55 * where
56 * <packet info> :: <characters representing the command or response>
57 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
58 *
59 * When a packet is received, it is first acknowledged with either '+' or '-'.
60 * '+' indicates a successful transfer. '-' indicates a failed transfer.
61 *
62 * Example:
63 *
64 * Host: Reply:
65 * $m0,10#2a +$00010203040506070809101112131415#42
66 *
67 *
68 * ==============
69 * MORE EXAMPLES:
70 * ==============
71 *
72 * For reference -- the following are the steps that one
73 * company took (RidgeRun Inc) to get remote gdb debugging
74 * going. In this scenario the host machine was a PC and the
75 * target platform was a Galileo EVB64120A MIPS evaluation
76 * board.
77 *
78 * Step 1:
79 * First download gdb-5.0.tar.gz from the internet.
80 * and then build/install the package.
81 *
82 * Example:
83 * $ tar zxf gdb-5.0.tar.gz
84 * $ cd gdb-5.0
85 * $ ./configure --target=am33_2.0-linux-gnu
86 * $ make
87 * $ install
88 * am33_2.0-linux-gnu-gdb
89 *
90 * Step 2:
91 * Configure linux for remote debugging and build it.
92 *
93 * Example:
94 * $ cd ~/linux
95 * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
96 * $ make dep; make vmlinux
97 *
98 * Step 3:
99 * Download the kernel to the remote target and start
100 * the kernel running. It will promptly halt and wait
101 * for the host gdb session to connect. It does this
102 * since the "Kernel Hacking" option has defined
103 * CONFIG_REMOTE_DEBUG which in turn enables your calls
104 * to:
105 * set_debug_traps();
106 * breakpoint();
107 *
108 * Step 4:
109 * Start the gdb session on the host.
110 *
111 * Example:
112 * $ am33_2.0-linux-gnu-gdb vmlinux
113 * (gdb) set remotebaud 115200
114 * (gdb) target remote /dev/ttyS1
115 * ...at this point you are connected to
116 * the remote target and can use gdb
117 * in the normal fasion. Setting
118 * breakpoints, single stepping,
119 * printing variables, etc.
120 *
121 */
122
123#include <linux/string.h>
124#include <linux/kernel.h>
125#include <linux/signal.h>
126#include <linux/sched.h>
127#include <linux/mm.h>
128#include <linux/console.h>
129#include <linux/init.h>
130#include <linux/bug.h>
131
132#include <asm/pgtable.h>
133#include <asm/system.h>
134#include <asm/gdb-stub.h>
135#include <asm/exceptions.h>
136#include <asm/cacheflush.h>
137#include <asm/serial-regs.h>
138#include <asm/busctl-regs.h>
139#include <asm/unit/leds.h>
140#include <asm/unit/serial.h>
141
142/* define to use F7F7 rather than FF which is subverted by JTAG debugger */
143#undef GDBSTUB_USE_F7F7_AS_BREAKPOINT
144
145/*
146 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
147 * at least NUMREGBYTES*2 are needed for register packets
148 */
149#define BUFMAX 2048
150
151static const char gdbstub_banner[] =
152 "Linux/MN10300 GDB Stub (c) RedHat 2007\n";
153
154u8 gdbstub_rx_buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
155u32 gdbstub_rx_inp;
156u32 gdbstub_rx_outp;
157u8 gdbstub_busy;
158u8 gdbstub_rx_overflow;
159u8 gdbstub_rx_unget;
160
161static u8 gdbstub_flush_caches;
162static char input_buffer[BUFMAX];
163static char output_buffer[BUFMAX];
164static char trans_buffer[BUFMAX];
165
166static const char hexchars[] = "0123456789abcdef";
167
168struct gdbstub_bkpt {
169 u8 *addr; /* address of breakpoint */
170 u8 len; /* size of breakpoint */
171 u8 origbytes[7]; /* original bytes */
172};
173
174static struct gdbstub_bkpt gdbstub_bkpts[256];
175
176/*
177 * local prototypes
178 */
179static void getpacket(char *buffer);
180static int putpacket(char *buffer);
181static int computeSignal(enum exception_code excep);
182static int hex(unsigned char ch);
183static int hexToInt(char **ptr, int *intValue);
184static unsigned char *mem2hex(const void *mem, char *buf, int count,
185 int may_fault);
186static const char *hex2mem(const char *buf, void *_mem, int count,
187 int may_fault);
188
189/*
190 * Convert ch from a hex digit to an int
191 */
192static int hex(unsigned char ch)
193{
194 if (ch >= 'a' && ch <= 'f')
195 return ch - 'a' + 10;
196 if (ch >= '0' && ch <= '9')
197 return ch - '0';
198 if (ch >= 'A' && ch <= 'F')
199 return ch - 'A' + 10;
200 return -1;
201}
202
203#ifdef CONFIG_GDBSTUB_DEBUGGING
204
205void debug_to_serial(const char *p, int n)
206{
207 __debug_to_serial(p, n);
208 /* gdbstub_console_write(NULL, p, n); */
209}
210
211void gdbstub_printk(const char *fmt, ...)
212{
213 va_list args;
214 int len;
215
216 /* Emit the output into the temporary buffer */
217 va_start(args, fmt);
218 len = vsnprintf(trans_buffer, sizeof(trans_buffer), fmt, args);
219 va_end(args);
220 debug_to_serial(trans_buffer, len);
221}
222
223#endif
224
225static inline char *gdbstub_strcpy(char *dst, const char *src)
226{
227 int loop = 0;
228 while ((dst[loop] = src[loop]))
229 loop++;
230 return dst;
231}
232
233/*
234 * scan for the sequence $<data>#<checksum>
235 */
236static void getpacket(char *buffer)
237{
238 unsigned char checksum;
239 unsigned char xmitcsum;
240 unsigned char ch;
241 int count, i, ret, error;
242
243 for (;;) {
244 /*
245 * wait around for the start character,
246 * ignore all other characters
247 */
248 do {
249 gdbstub_io_rx_char(&ch, 0);
250 } while (ch != '$');
251
252 checksum = 0;
253 xmitcsum = -1;
254 count = 0;
255 error = 0;
256
257 /*
258 * now, read until a # or end of buffer is found
259 */
260 while (count < BUFMAX) {
261 ret = gdbstub_io_rx_char(&ch, 0);
262 if (ret < 0)
263 error = ret;
264
265 if (ch == '#')
266 break;
267 checksum += ch;
268 buffer[count] = ch;
269 count++;
270 }
271
272 if (error == -EIO) {
273 gdbstub_proto("### GDB Rx Error - Skipping packet"
274 " ###\n");
275 gdbstub_proto("### GDB Tx NAK\n");
276 gdbstub_io_tx_char('-');
277 continue;
278 }
279
280 if (count >= BUFMAX || error)
281 continue;
282
283 buffer[count] = 0;
284
285 /* read the checksum */
286 ret = gdbstub_io_rx_char(&ch, 0);
287 if (ret < 0)
288 error = ret;
289 xmitcsum = hex(ch) << 4;
290
291 ret = gdbstub_io_rx_char(&ch, 0);
292 if (ret < 0)
293 error = ret;
294 xmitcsum |= hex(ch);
295
296 if (error) {
297 if (error == -EIO)
298 gdbstub_io("### GDB Rx Error -"
299 " Skipping packet\n");
300 gdbstub_io("### GDB Tx NAK\n");
301 gdbstub_io_tx_char('-');
302 continue;
303 }
304
305 /* check the checksum */
306 if (checksum != xmitcsum) {
307 gdbstub_io("### GDB Tx NAK\n");
308 gdbstub_io_tx_char('-'); /* failed checksum */
309 continue;
310 }
311
312 gdbstub_proto("### GDB Rx '$%s#%02x' ###\n", buffer, checksum);
313 gdbstub_io("### GDB Tx ACK\n");
314 gdbstub_io_tx_char('+'); /* successful transfer */
315
316 /*
317 * if a sequence char is present,
318 * reply the sequence ID
319 */
320 if (buffer[2] == ':') {
321 gdbstub_io_tx_char(buffer[0]);
322 gdbstub_io_tx_char(buffer[1]);
323
324 /*
325 * remove sequence chars from buffer
326 */
327 count = 0;
328 while (buffer[count])
329 count++;
330 for (i = 3; i <= count; i++)
331 buffer[i - 3] = buffer[i];
332 }
333
334 break;
335 }
336}
337
338/*
339 * send the packet in buffer.
340 * - return 0 if successfully ACK'd
341 * - return 1 if abandoned due to new incoming packet
342 */
343static int putpacket(char *buffer)
344{
345 unsigned char checksum;
346 unsigned char ch;
347 int count;
348
349 /*
350 * $<packet info>#<checksum>.
351 */
352 gdbstub_proto("### GDB Tx $'%s'#?? ###\n", buffer);
353
354 do {
355 gdbstub_io_tx_char('$');
356 checksum = 0;
357 count = 0;
358
359 while ((ch = buffer[count]) != 0) {
360 gdbstub_io_tx_char(ch);
361 checksum += ch;
362 count += 1;
363 }
364
365 gdbstub_io_tx_char('#');
366 gdbstub_io_tx_char(hexchars[checksum >> 4]);
367 gdbstub_io_tx_char(hexchars[checksum & 0xf]);
368
369 } while (gdbstub_io_rx_char(&ch, 0),
370 ch == '-' && (gdbstub_io("### GDB Rx NAK\n"), 0),
371 ch != '-' && ch != '+' &&
372 (gdbstub_io("### GDB Rx ??? %02x\n", ch), 0),
373 ch != '+' && ch != '$');
374
375 if (ch == '+') {
376 gdbstub_io("### GDB Rx ACK\n");
377 return 0;
378 }
379
380 gdbstub_io("### GDB Tx Abandoned\n");
381 gdbstub_rx_unget = ch;
382 return 1;
383}
384
385/*
386 * While we find nice hex chars, build an int.
387 * Return number of chars processed.
388 */
389static int hexToInt(char **ptr, int *intValue)
390{
391 int numChars = 0;
392 int hexValue;
393
394 *intValue = 0;
395
396 while (**ptr) {
397 hexValue = hex(**ptr);
398 if (hexValue < 0)
399 break;
400
401 *intValue = (*intValue << 4) | hexValue;
402 numChars++;
403
404 (*ptr)++;
405 }
406
407 return (numChars);
408}
409
410/*
411 * We single-step by setting breakpoints. When an exception
412 * is handled, we need to restore the instructions hoisted
413 * when the breakpoints were set.
414 *
415 * This is where we save the original instructions.
416 */
417static struct gdb_bp_save {
418 u8 *addr;
419 u8 opcode[2];
420} step_bp[2];
421
422static const unsigned char gdbstub_insn_sizes[256] =
423{
424 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
425 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, /* 0 */
426 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
427 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
428 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
429 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
430 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
431 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
432 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
433 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
434 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
435 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
436 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
438 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
439 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
440 0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1 /* f */
441};
442
443static int __gdbstub_mark_bp(u8 *addr, int ix)
444{
445 if (addr < (u8 *) 0x70000000UL)
446 return 0;
447 /* 70000000-7fffffff: vmalloc area */
448 if (addr < (u8 *) 0x80000000UL)
449 goto okay;
450 if (addr < (u8 *) 0x8c000000UL)
451 return 0;
452 /* 8c000000-93ffffff: SRAM, SDRAM */
453 if (addr < (u8 *) 0x94000000UL)
454 goto okay;
455 return 0;
456
457okay:
458 if (gdbstub_read_byte(addr + 0, &step_bp[ix].opcode[0]) < 0 ||
459 gdbstub_read_byte(addr + 1, &step_bp[ix].opcode[1]) < 0)
460 return 0;
461
462 step_bp[ix].addr = addr;
463 return 1;
464}
465
466static inline void __gdbstub_restore_bp(void)
467{
468#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
469 if (step_bp[0].addr) {
470 gdbstub_write_byte(step_bp[0].opcode[0], step_bp[0].addr + 0);
471 gdbstub_write_byte(step_bp[0].opcode[1], step_bp[0].addr + 1);
472 }
473 if (step_bp[1].addr) {
474 gdbstub_write_byte(step_bp[1].opcode[0], step_bp[1].addr + 0);
475 gdbstub_write_byte(step_bp[1].opcode[1], step_bp[1].addr + 1);
476 }
477#else
478 if (step_bp[0].addr)
479 gdbstub_write_byte(step_bp[0].opcode[0], step_bp[0].addr + 0);
480 if (step_bp[1].addr)
481 gdbstub_write_byte(step_bp[1].opcode[0], step_bp[1].addr + 0);
482#endif
483
484 gdbstub_flush_caches = 1;
485
486 step_bp[0].addr = NULL;
487 step_bp[0].opcode[0] = 0;
488 step_bp[0].opcode[1] = 0;
489 step_bp[1].addr = NULL;
490 step_bp[1].opcode[0] = 0;
491 step_bp[1].opcode[1] = 0;
492}
493
494/*
495 * emulate single stepping by means of breakpoint instructions
496 */
497static int gdbstub_single_step(struct pt_regs *regs)
498{
499 unsigned size;
500 uint32_t x;
501 uint8_t cur, *pc, *sp;
502
503 step_bp[0].addr = NULL;
504 step_bp[0].opcode[0] = 0;
505 step_bp[0].opcode[1] = 0;
506 step_bp[1].addr = NULL;
507 step_bp[1].opcode[0] = 0;
508 step_bp[1].opcode[1] = 0;
509 x = 0;
510
511 pc = (u8 *) regs->pc;
512 sp = (u8 *) (regs + 1);
513 if (gdbstub_read_byte(pc, &cur) < 0)
514 return -EFAULT;
515
516 gdbstub_bkpt("Single Step from %p { %02x }\n", pc, cur);
517
518 gdbstub_flush_caches = 1;
519
520 size = gdbstub_insn_sizes[cur];
521 if (size > 0) {
522 if (!__gdbstub_mark_bp(pc + size, 0))
523 goto fault;
524 } else {
525 switch (cur) {
526 /* Bxx (d8,PC) */
527 case 0xc0:
528 case 0xc1:
529 case 0xc2:
530 case 0xc3:
531 case 0xc4:
532 case 0xc5:
533 case 0xc6:
534 case 0xc7:
535 case 0xc8:
536 case 0xc9:
537 case 0xca:
538 if (gdbstub_read_byte(pc + 1, (u8 *) &x) < 0)
539 goto fault;
540 if (!__gdbstub_mark_bp(pc + 2, 0))
541 goto fault;
542 if ((x < 0 || x > 2) &&
543 !__gdbstub_mark_bp(pc + (s8) x, 1))
544 goto fault;
545 break;
546
547 /* LXX (d8,PC) */
548 case 0xd0:
549 case 0xd1:
550 case 0xd2:
551 case 0xd3:
552 case 0xd4:
553 case 0xd5:
554 case 0xd6:
555 case 0xd7:
556 case 0xd8:
557 case 0xd9:
558 case 0xda:
559 if (!__gdbstub_mark_bp(pc + 1, 0))
560 goto fault;
561 if (regs->pc != regs->lar &&
562 !__gdbstub_mark_bp((u8 *) regs->lar, 1))
563 goto fault;
564 break;
565
566 /* SETLB - loads the next for bytes into the LIR
567 * register */
568 case 0xdb:
569 if (!__gdbstub_mark_bp(pc + 1, 0))
570 goto fault;
571 break;
572
573 /* JMP (d16,PC) or CALL (d16,PC) */
574 case 0xcc:
575 case 0xcd:
576 if (gdbstub_read_byte(pc + 1, ((u8 *) &x) + 0) < 0 ||
577 gdbstub_read_byte(pc + 2, ((u8 *) &x) + 1) < 0)
578 goto fault;
579 if (!__gdbstub_mark_bp(pc + (s16) x, 0))
580 goto fault;
581 break;
582
583 /* JMP (d32,PC) or CALL (d32,PC) */
584 case 0xdc:
585 case 0xdd:
586 if (gdbstub_read_byte(pc + 1, ((u8 *) &x) + 0) < 0 ||
587 gdbstub_read_byte(pc + 2, ((u8 *) &x) + 1) < 0 ||
588 gdbstub_read_byte(pc + 3, ((u8 *) &x) + 2) < 0 ||
589 gdbstub_read_byte(pc + 4, ((u8 *) &x) + 3) < 0)
590 goto fault;
591 if (!__gdbstub_mark_bp(pc + (s32) x, 0))
592 goto fault;
593 break;
594
595 /* RETF */
596 case 0xde:
597 if (!__gdbstub_mark_bp((u8 *) regs->mdr, 0))
598 goto fault;
599 break;
600
601 /* RET */
602 case 0xdf:
603 if (gdbstub_read_byte(pc + 2, (u8 *) &x) < 0)
604 goto fault;
605 sp += (s8)x;
606 if (gdbstub_read_byte(sp + 0, ((u8 *) &x) + 0) < 0 ||
607 gdbstub_read_byte(sp + 1, ((u8 *) &x) + 1) < 0 ||
608 gdbstub_read_byte(sp + 2, ((u8 *) &x) + 2) < 0 ||
609 gdbstub_read_byte(sp + 3, ((u8 *) &x) + 3) < 0)
610 goto fault;
611 if (!__gdbstub_mark_bp((u8 *) x, 0))
612 goto fault;
613 break;
614
615 case 0xf0:
616 if (gdbstub_read_byte(pc + 1, &cur) < 0)
617 goto fault;
618
619 if (cur >= 0xf0 && cur <= 0xf7) {
620 /* JMP (An) / CALLS (An) */
621 switch (cur & 3) {
622 case 0: x = regs->a0; break;
623 case 1: x = regs->a1; break;
624 case 2: x = regs->a2; break;
625 case 3: x = regs->a3; break;
626 }
627 if (!__gdbstub_mark_bp((u8 *) x, 0))
628 goto fault;
629 } else if (cur == 0xfc) {
630 /* RETS */
631 if (gdbstub_read_byte(
632 sp + 0, ((u8 *) &x) + 0) < 0 ||
633 gdbstub_read_byte(
634 sp + 1, ((u8 *) &x) + 1) < 0 ||
635 gdbstub_read_byte(
636 sp + 2, ((u8 *) &x) + 2) < 0 ||
637 gdbstub_read_byte(
638 sp + 3, ((u8 *) &x) + 3) < 0)
639 goto fault;
640 if (!__gdbstub_mark_bp((u8 *) x, 0))
641 goto fault;
642 } else if (cur == 0xfd) {
643 /* RTI */
644 if (gdbstub_read_byte(
645 sp + 4, ((u8 *) &x) + 0) < 0 ||
646 gdbstub_read_byte(
647 sp + 5, ((u8 *) &x) + 1) < 0 ||
648 gdbstub_read_byte(
649 sp + 6, ((u8 *) &x) + 2) < 0 ||
650 gdbstub_read_byte(
651 sp + 7, ((u8 *) &x) + 3) < 0)
652 goto fault;
653 if (!__gdbstub_mark_bp((u8 *) x, 0))
654 goto fault;
655 } else {
656 if (!__gdbstub_mark_bp(pc + 2, 0))
657 goto fault;
658 }
659
660 break;
661
662 /* potential 3-byte conditional branches */
663 case 0xf8:
664 if (gdbstub_read_byte(pc + 1, &cur) < 0)
665 goto fault;
666 if (!__gdbstub_mark_bp(pc + 3, 0))
667 goto fault;
668
669 if (cur >= 0xe8 && cur <= 0xeb) {
670 if (gdbstub_read_byte(
671 pc + 2, ((u8 *) &x) + 0) < 0)
672 goto fault;
673 if ((x < 0 || x > 3) &&
674 !__gdbstub_mark_bp(pc + (s8) x, 1))
675 goto fault;
676 }
677 break;
678
679 case 0xfa:
680 if (gdbstub_read_byte(pc + 1, &cur) < 0)
681 goto fault;
682
683 if (cur == 0xff) {
684 /* CALLS (d16,PC) */
685 if (gdbstub_read_byte(
686 pc + 2, ((u8 *) &x) + 0) < 0 ||
687 gdbstub_read_byte(
688 pc + 3, ((u8 *) &x) + 1) < 0)
689 goto fault;
690 if (!__gdbstub_mark_bp(pc + (s16) x, 0))
691 goto fault;
692 } else {
693 if (!__gdbstub_mark_bp(pc + 4, 0))
694 goto fault;
695 }
696 break;
697
698 case 0xfc:
699 if (gdbstub_read_byte(pc + 1, &cur) < 0)
700 goto fault;
701 if (cur == 0xff) {
702 /* CALLS (d32,PC) */
703 if (gdbstub_read_byte(
704 pc + 2, ((u8 *) &x) + 0) < 0 ||
705 gdbstub_read_byte(
706 pc + 3, ((u8 *) &x) + 1) < 0 ||
707 gdbstub_read_byte(
708 pc + 4, ((u8 *) &x) + 2) < 0 ||
709 gdbstub_read_byte(
710 pc + 5, ((u8 *) &x) + 3) < 0)
711 goto fault;
712 if (!__gdbstub_mark_bp(
713 pc + (s32) x, 0))
714 goto fault;
715 } else {
716 if (!__gdbstub_mark_bp(
717 pc + 6, 0))
718 goto fault;
719 }
720 break;
721
722 }
723 }
724
725 gdbstub_bkpt("Step: %02x at %p; %02x at %p\n",
726 step_bp[0].opcode[0], step_bp[0].addr,
727 step_bp[1].opcode[0], step_bp[1].addr);
728
729 if (step_bp[0].addr) {
730#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
731 if (gdbstub_write_byte(0xF7, step_bp[0].addr + 0) < 0 ||
732 gdbstub_write_byte(0xF7, step_bp[0].addr + 1) < 0)
733 goto fault;
734#else
735 if (gdbstub_write_byte(0xFF, step_bp[0].addr + 0) < 0)
736 goto fault;
737#endif
738 }
739
740 if (step_bp[1].addr) {
741#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
742 if (gdbstub_write_byte(0xF7, step_bp[1].addr + 0) < 0 ||
743 gdbstub_write_byte(0xF7, step_bp[1].addr + 1) < 0)
744 goto fault;
745#else
746 if (gdbstub_write_byte(0xFF, step_bp[1].addr + 0) < 0)
747 goto fault;
748#endif
749 }
750
751 return 0;
752
753 fault:
754 /* uh-oh - silly address alert, try and restore things */
755 __gdbstub_restore_bp();
756 return -EFAULT;
757}
758
759#ifdef CONFIG_GDBSTUB_CONSOLE
760
761void gdbstub_console_write(struct console *con, const char *p, unsigned n)
762{
763 static const char gdbstub_cr[] = { 0x0d };
764 char outbuf[26];
765 int qty;
766 u8 busy;
767
768 busy = gdbstub_busy;
769 gdbstub_busy = 1;
770
771 outbuf[0] = 'O';
772
773 while (n > 0) {
774 qty = 1;
775
776 while (n > 0 && qty < 20) {
777 mem2hex(p, outbuf + qty, 2, 0);
778 qty += 2;
779 if (*p == 0x0a) {
780 mem2hex(gdbstub_cr, outbuf + qty, 2, 0);
781 qty += 2;
782 }
783 p++;
784 n--;
785 }
786
787 outbuf[qty] = 0;
788 putpacket(outbuf);
789 }
790
791 gdbstub_busy = busy;
792}
793
794static kdev_t gdbstub_console_dev(struct console *con)
795{
796 return MKDEV(1, 3); /* /dev/null */
797}
798
799static struct console gdbstub_console = {
800 .name = "gdb",
801 .write = gdbstub_console_write,
802 .device = gdbstub_console_dev,
803 .flags = CON_PRINTBUFFER,
804 .index = -1,
805};
806
807#endif
808
809/*
810 * Convert the memory pointed to by mem into hex, placing result in buf.
811 * - if successful, return a pointer to the last char put in buf (NUL)
812 * - in case of mem fault, return NULL
813 * may_fault is non-zero if we are reading from arbitrary memory, but is
814 * currently not used.
815 */
816static
817unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
818{
819 const u8 *mem = _mem;
820 u8 ch[4];
821
822 if ((u32) mem & 1 && count >= 1) {
823 if (gdbstub_read_byte(mem, ch) != 0)
824 return 0;
825 *buf++ = hexchars[ch[0] >> 4];
826 *buf++ = hexchars[ch[0] & 0xf];
827 mem++;
828 count--;
829 }
830
831 if ((u32) mem & 3 && count >= 2) {
832 if (gdbstub_read_word(mem, ch) != 0)
833 return 0;
834 *buf++ = hexchars[ch[0] >> 4];
835 *buf++ = hexchars[ch[0] & 0xf];
836 *buf++ = hexchars[ch[1] >> 4];
837 *buf++ = hexchars[ch[1] & 0xf];
838 mem += 2;
839 count -= 2;
840 }
841
842 while (count >= 4) {
843 if (gdbstub_read_dword(mem, ch) != 0)
844 return 0;
845 *buf++ = hexchars[ch[0] >> 4];
846 *buf++ = hexchars[ch[0] & 0xf];
847 *buf++ = hexchars[ch[1] >> 4];
848 *buf++ = hexchars[ch[1] & 0xf];
849 *buf++ = hexchars[ch[2] >> 4];
850 *buf++ = hexchars[ch[2] & 0xf];
851 *buf++ = hexchars[ch[3] >> 4];
852 *buf++ = hexchars[ch[3] & 0xf];
853 mem += 4;
854 count -= 4;
855 }
856
857 if (count >= 2) {
858 if (gdbstub_read_word(mem, ch) != 0)
859 return 0;
860 *buf++ = hexchars[ch[0] >> 4];
861 *buf++ = hexchars[ch[0] & 0xf];
862 *buf++ = hexchars[ch[1] >> 4];
863 *buf++ = hexchars[ch[1] & 0xf];
864 mem += 2;
865 count -= 2;
866 }
867
868 if (count >= 1) {
869 if (gdbstub_read_byte(mem, ch) != 0)
870 return 0;
871 *buf++ = hexchars[ch[0] >> 4];
872 *buf++ = hexchars[ch[0] & 0xf];
873 }
874
875 *buf = 0;
876 return buf;
877}
878
879/*
880 * convert the hex array pointed to by buf into binary to be placed in mem
881 * return a pointer to the character AFTER the last byte written
882 * may_fault is non-zero if we are reading from arbitrary memory, but is
883 * currently not used.
884 */
885static
886const char *hex2mem(const char *buf, void *_mem, int count, int may_fault)
887{
888 u8 *mem = _mem;
889 union {
890 u32 val;
891 u8 b[4];
892 } ch;
893
894 if ((u32) mem & 1 && count >= 1) {
895 ch.b[0] = hex(*buf++) << 4;
896 ch.b[0] |= hex(*buf++);
897 if (gdbstub_write_byte(ch.val, mem) != 0)
898 return 0;
899 mem++;
900 count--;
901 }
902
903 if ((u32) mem & 3 && count >= 2) {
904 ch.b[0] = hex(*buf++) << 4;
905 ch.b[0] |= hex(*buf++);
906 ch.b[1] = hex(*buf++) << 4;
907 ch.b[1] |= hex(*buf++);
908 if (gdbstub_write_word(ch.val, mem) != 0)
909 return 0;
910 mem += 2;
911 count -= 2;
912 }
913
914 while (count >= 4) {
915 ch.b[0] = hex(*buf++) << 4;
916 ch.b[0] |= hex(*buf++);
917 ch.b[1] = hex(*buf++) << 4;
918 ch.b[1] |= hex(*buf++);
919 ch.b[2] = hex(*buf++) << 4;
920 ch.b[2] |= hex(*buf++);
921 ch.b[3] = hex(*buf++) << 4;
922 ch.b[3] |= hex(*buf++);
923 if (gdbstub_write_dword(ch.val, mem) != 0)
924 return 0;
925 mem += 4;
926 count -= 4;
927 }
928
929 if (count >= 2) {
930 ch.b[0] = hex(*buf++) << 4;
931 ch.b[0] |= hex(*buf++);
932 ch.b[1] = hex(*buf++) << 4;
933 ch.b[1] |= hex(*buf++);
934 if (gdbstub_write_word(ch.val, mem) != 0)
935 return 0;
936 mem += 2;
937 count -= 2;
938 }
939
940 if (count >= 1) {
941 ch.b[0] = hex(*buf++) << 4;
942 ch.b[0] |= hex(*buf++);
943 if (gdbstub_write_byte(ch.val, mem) != 0)
944 return 0;
945 }
946
947 return buf;
948}
949
950/*
951 * This table contains the mapping between MN10300 exception codes, and
952 * signals, which are primarily what GDB understands. It also indicates
953 * which hardware traps we need to commandeer when initializing the stub.
954 */
955static const struct excep_to_sig_map {
956 enum exception_code excep; /* MN10300 exception code */
957 unsigned char signo; /* Signal that we map this into */
958} excep_to_sig_map[] = {
959 { EXCEP_ITLBMISS, SIGSEGV },
960 { EXCEP_DTLBMISS, SIGSEGV },
961 { EXCEP_TRAP, SIGTRAP },
962 { EXCEP_ISTEP, SIGTRAP },
963 { EXCEP_IBREAK, SIGTRAP },
964 { EXCEP_OBREAK, SIGTRAP },
965 { EXCEP_UNIMPINS, SIGILL },
966 { EXCEP_UNIMPEXINS, SIGILL },
967 { EXCEP_MEMERR, SIGSEGV },
968 { EXCEP_MISALIGN, SIGSEGV },
969 { EXCEP_BUSERROR, SIGBUS },
970 { EXCEP_ILLINSACC, SIGSEGV },
971 { EXCEP_ILLDATACC, SIGSEGV },
972 { EXCEP_IOINSACC, SIGSEGV },
973 { EXCEP_PRIVINSACC, SIGSEGV },
974 { EXCEP_PRIVDATACC, SIGSEGV },
975 { EXCEP_FPU_DISABLED, SIGFPE },
976 { EXCEP_FPU_UNIMPINS, SIGFPE },
977 { EXCEP_FPU_OPERATION, SIGFPE },
978 { EXCEP_WDT, SIGALRM },
979 { EXCEP_NMI, SIGQUIT },
980 { EXCEP_IRQ_LEVEL0, SIGINT },
981 { EXCEP_IRQ_LEVEL1, SIGINT },
982 { EXCEP_IRQ_LEVEL2, SIGINT },
983 { EXCEP_IRQ_LEVEL3, SIGINT },
984 { EXCEP_IRQ_LEVEL4, SIGINT },
985 { EXCEP_IRQ_LEVEL5, SIGINT },
986 { EXCEP_IRQ_LEVEL6, SIGINT },
987 { 0, 0}
988};
989
990/*
991 * convert the MN10300 exception code into a UNIX signal number
992 */
993static int computeSignal(enum exception_code excep)
994{
995 const struct excep_to_sig_map *map;
996
997 for (map = excep_to_sig_map; map->signo; map++)
998 if (map->excep == excep)
999 return map->signo;
1000
1001 return SIGHUP; /* default for things we don't know about */
1002}
1003
1004static u32 gdbstub_fpcr, gdbstub_fpufs_array[32];
1005
1006/*
1007 *
1008 */
1009static void gdbstub_store_fpu(void)
1010{
1011#ifdef CONFIG_FPU
1012
1013 asm volatile(
1014 "or %2,epsw\n"
1015#ifdef CONFIG_MN10300_PROC_MN103E010
1016 "nop\n"
1017 "nop\n"
1018#endif
1019 "mov %1, a1\n"
1020 "fmov fs0, (a1+)\n"
1021 "fmov fs1, (a1+)\n"
1022 "fmov fs2, (a1+)\n"
1023 "fmov fs3, (a1+)\n"
1024 "fmov fs4, (a1+)\n"
1025 "fmov fs5, (a1+)\n"
1026 "fmov fs6, (a1+)\n"
1027 "fmov fs7, (a1+)\n"
1028 "fmov fs8, (a1+)\n"
1029 "fmov fs9, (a1+)\n"
1030 "fmov fs10, (a1+)\n"
1031 "fmov fs11, (a1+)\n"
1032 "fmov fs12, (a1+)\n"
1033 "fmov fs13, (a1+)\n"
1034 "fmov fs14, (a1+)\n"
1035 "fmov fs15, (a1+)\n"
1036 "fmov fs16, (a1+)\n"
1037 "fmov fs17, (a1+)\n"
1038 "fmov fs18, (a1+)\n"
1039 "fmov fs19, (a1+)\n"
1040 "fmov fs20, (a1+)\n"
1041 "fmov fs21, (a1+)\n"
1042 "fmov fs22, (a1+)\n"
1043 "fmov fs23, (a1+)\n"
1044 "fmov fs24, (a1+)\n"
1045 "fmov fs25, (a1+)\n"
1046 "fmov fs26, (a1+)\n"
1047 "fmov fs27, (a1+)\n"
1048 "fmov fs28, (a1+)\n"
1049 "fmov fs29, (a1+)\n"
1050 "fmov fs30, (a1+)\n"
1051 "fmov fs31, (a1+)\n"
1052 "fmov fpcr, %0\n"
1053 : "=d"(gdbstub_fpcr)
1054 : "g" (&gdbstub_fpufs_array), "i"(EPSW_FE)
1055 : "a1"
1056 );
1057#endif
1058}
1059
1060/*
1061 *
1062 */
1063static void gdbstub_load_fpu(void)
1064{
1065#ifdef CONFIG_FPU
1066
1067 asm volatile(
1068 "or %1,epsw\n"
1069#ifdef CONFIG_MN10300_PROC_MN103E010
1070 "nop\n"
1071 "nop\n"
1072#endif
1073 "mov %0, a1\n"
1074 "fmov (a1+), fs0\n"
1075 "fmov (a1+), fs1\n"
1076 "fmov (a1+), fs2\n"
1077 "fmov (a1+), fs3\n"
1078 "fmov (a1+), fs4\n"
1079 "fmov (a1+), fs5\n"
1080 "fmov (a1+), fs6\n"
1081 "fmov (a1+), fs7\n"
1082 "fmov (a1+), fs8\n"
1083 "fmov (a1+), fs9\n"
1084 "fmov (a1+), fs10\n"
1085 "fmov (a1+), fs11\n"
1086 "fmov (a1+), fs12\n"
1087 "fmov (a1+), fs13\n"
1088 "fmov (a1+), fs14\n"
1089 "fmov (a1+), fs15\n"
1090 "fmov (a1+), fs16\n"
1091 "fmov (a1+), fs17\n"
1092 "fmov (a1+), fs18\n"
1093 "fmov (a1+), fs19\n"
1094 "fmov (a1+), fs20\n"
1095 "fmov (a1+), fs21\n"
1096 "fmov (a1+), fs22\n"
1097 "fmov (a1+), fs23\n"
1098 "fmov (a1+), fs24\n"
1099 "fmov (a1+), fs25\n"
1100 "fmov (a1+), fs26\n"
1101 "fmov (a1+), fs27\n"
1102 "fmov (a1+), fs28\n"
1103 "fmov (a1+), fs29\n"
1104 "fmov (a1+), fs30\n"
1105 "fmov (a1+), fs31\n"
1106 "fmov %2, fpcr\n"
1107 :
1108 : "g" (&gdbstub_fpufs_array), "i"(EPSW_FE), "d"(gdbstub_fpcr)
1109 : "a1"
1110 );
1111#endif
1112}
1113
1114/*
1115 * set a software breakpoint
1116 */
1117int gdbstub_set_breakpoint(u8 *addr, int len)
1118{
1119 int bkpt, loop, xloop;
1120
1121#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
1122 len = (len + 1) & ~1;
1123#endif
1124
1125 gdbstub_bkpt("setbkpt(%p,%d)\n", addr, len);
1126
1127 for (bkpt = 255; bkpt >= 0; bkpt--)
1128 if (!gdbstub_bkpts[bkpt].addr)
1129 break;
1130 if (bkpt < 0)
1131 return -ENOSPC;
1132
1133 for (loop = 0; loop < len; loop++)
1134 if (gdbstub_read_byte(&addr[loop],
1135 &gdbstub_bkpts[bkpt].origbytes[loop]
1136 ) < 0)
1137 return -EFAULT;
1138
1139 gdbstub_flush_caches = 1;
1140
1141#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
1142 for (loop = 0; loop < len; loop++)
1143 if (gdbstub_write_byte(0xF7, &addr[loop]) < 0)
1144 goto restore;
1145#else
1146 for (loop = 0; loop < len; loop++)
1147 if (gdbstub_write_byte(0xFF, &addr[loop]) < 0)
1148 goto restore;
1149#endif
1150
1151 gdbstub_bkpts[bkpt].addr = addr;
1152 gdbstub_bkpts[bkpt].len = len;
1153
1154 gdbstub_bkpt("Set BKPT[%02x]: %p-%p {%02x%02x%02x%02x%02x%02x%02x}\n",
1155 bkpt,
1156 gdbstub_bkpts[bkpt].addr,
1157 gdbstub_bkpts[bkpt].addr + gdbstub_bkpts[bkpt].len - 1,
1158 gdbstub_bkpts[bkpt].origbytes[0],
1159 gdbstub_bkpts[bkpt].origbytes[1],
1160 gdbstub_bkpts[bkpt].origbytes[2],
1161 gdbstub_bkpts[bkpt].origbytes[3],
1162 gdbstub_bkpts[bkpt].origbytes[4],
1163 gdbstub_bkpts[bkpt].origbytes[5],
1164 gdbstub_bkpts[bkpt].origbytes[6]
1165 );
1166
1167 return 0;
1168
1169restore:
1170 for (xloop = 0; xloop < loop; xloop++)
1171 gdbstub_write_byte(gdbstub_bkpts[bkpt].origbytes[xloop],
1172 addr + xloop);
1173 return -EFAULT;
1174}
1175
1176/*
1177 * clear a software breakpoint
1178 */
1179int gdbstub_clear_breakpoint(u8 *addr, int len)
1180{
1181 int bkpt, loop;
1182
1183#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
1184 len = (len + 1) & ~1;
1185#endif
1186
1187 gdbstub_bkpt("clearbkpt(%p,%d)\n", addr, len);
1188
1189 for (bkpt = 255; bkpt >= 0; bkpt--)
1190 if (gdbstub_bkpts[bkpt].addr == addr &&
1191 gdbstub_bkpts[bkpt].len == len)
1192 break;
1193 if (bkpt < 0)
1194 return -ENOENT;
1195
1196 gdbstub_bkpts[bkpt].addr = NULL;
1197
1198 gdbstub_flush_caches = 1;
1199
1200 for (loop = 0; loop < len; loop++)
1201 if (gdbstub_write_byte(gdbstub_bkpts[bkpt].origbytes[loop],
1202 addr + loop) < 0)
1203 return -EFAULT;
1204
1205 return 0;
1206}
1207
1208/*
1209 * This function does all command processing for interfacing to gdb
1210 * - returns 1 if the exception should be skipped, 0 otherwise.
1211 */
1212static int gdbstub(struct pt_regs *regs, enum exception_code excep)
1213{
1214 unsigned long *stack;
1215 unsigned long epsw, mdr;
1216 uint32_t zero, ssp;
1217 uint8_t broke;
1218 char *ptr;
1219 int sigval;
1220 int addr;
1221 int length;
1222 int loop;
1223
1224 if (excep == EXCEP_FPU_DISABLED)
1225 return 0;
1226
1227 gdbstub_flush_caches = 0;
1228
1229 mn10300_set_gdbleds(1);
1230
1231 asm volatile("mov mdr,%0" : "=d"(mdr));
1232 asm volatile("mov epsw,%0" : "=d"(epsw));
1233 asm volatile("mov %0,epsw"
1234 :: "d"((epsw & ~EPSW_IM) | EPSW_IE | EPSW_IM_1));
1235
1236 gdbstub_store_fpu();
1237
1238#ifdef CONFIG_GDBSTUB_IMMEDIATE
1239 /* skip the initial pause loop */
1240 if (regs->pc == (unsigned long) __gdbstub_pause)
1241 regs->pc = (unsigned long) start_kernel;
1242#endif
1243
1244 /* if we were single stepping, restore the opcodes hoisted for the
1245 * breakpoint[s] */
1246 broke = 0;
1247 if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
1248 (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
1249 broke = 1;
1250
1251 __gdbstub_restore_bp();
1252
1253 if (gdbstub_rx_unget) {
1254 sigval = SIGINT;
1255 if (gdbstub_rx_unget != 3)
1256 goto packet_waiting;
1257 gdbstub_rx_unget = 0;
1258 }
1259
1260 stack = (unsigned long *) regs->sp;
1261 sigval = broke ? SIGTRAP : computeSignal(excep);
1262
1263 /* send information about a BUG() */
1264 if (!user_mode(regs) && excep == EXCEP_SYSCALL15) {
1265 const struct bug_entry *bug;
1266
1267 bug = find_bug(regs->pc);
1268 if (bug)
1269 goto found_bug;
1270 length = snprintf(trans_buffer, sizeof(trans_buffer),
1271 "BUG() at address %lx\n", regs->pc);
1272 goto send_bug_pkt;
1273
1274 found_bug:
1275 length = snprintf(trans_buffer, sizeof(trans_buffer),
1276 "BUG() at address %lx (%s:%d)\n",
1277 regs->pc, bug->file, bug->line);
1278
1279 send_bug_pkt:
1280 ptr = output_buffer;
1281 *ptr++ = 'O';
1282 ptr = mem2hex(trans_buffer, ptr, length, 0);
1283 *ptr = 0;
1284 putpacket(output_buffer);
1285
1286 regs->pc -= 2;
1287 sigval = SIGABRT;
1288 } else if (regs->pc == (unsigned long) __gdbstub_bug_trap) {
1289 regs->pc = regs->mdr;
1290 sigval = SIGABRT;
1291 }
1292
1293 /*
1294 * send a message to the debugger's user saying what happened if it may
1295 * not be clear cut (we can't map exceptions onto signals properly)
1296 */
1297 if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) {
1298 static const char title[] = "Excep ", tbcberr[] = "BCBERR ";
1299 static const char crlf[] = "\r\n";
1300 char hx;
1301 u32 bcberr = BCBERR;
1302
1303 ptr = output_buffer;
1304 *ptr++ = 'O';
1305 ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
1306
1307 hx = hexchars[(excep & 0xf000) >> 12];
1308 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1309 hx = hexchars[(excep & 0x0f00) >> 8];
1310 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1311 hx = hexchars[(excep & 0x00f0) >> 4];
1312 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1313 hx = hexchars[(excep & 0x000f)];
1314 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1315
1316 ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
1317 *ptr = 0;
1318 putpacket(output_buffer); /* send it off... */
1319
1320 /* BCBERR */
1321 ptr = output_buffer;
1322 *ptr++ = 'O';
1323 ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
1324
1325 hx = hexchars[(bcberr & 0xf0000000) >> 28];
1326 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1327 hx = hexchars[(bcberr & 0x0f000000) >> 24];
1328 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1329 hx = hexchars[(bcberr & 0x00f00000) >> 20];
1330 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1331 hx = hexchars[(bcberr & 0x000f0000) >> 16];
1332 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1333 hx = hexchars[(bcberr & 0x0000f000) >> 12];
1334 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1335 hx = hexchars[(bcberr & 0x00000f00) >> 8];
1336 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1337 hx = hexchars[(bcberr & 0x000000f0) >> 4];
1338 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1339 hx = hexchars[(bcberr & 0x0000000f)];
1340 *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
1341
1342 ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
1343 *ptr = 0;
1344 putpacket(output_buffer); /* send it off... */
1345 }
1346
1347 /*
1348 * tell the debugger that an exception has occurred
1349 */
1350 ptr = output_buffer;
1351
1352 /*
1353 * Send trap type (converted to signal)
1354 */
1355 *ptr++ = 'T';
1356 *ptr++ = hexchars[sigval >> 4];
1357 *ptr++ = hexchars[sigval & 0xf];
1358
1359 /*
1360 * Send Error PC
1361 */
1362 *ptr++ = hexchars[GDB_REGID_PC >> 4];
1363 *ptr++ = hexchars[GDB_REGID_PC & 0xf];
1364 *ptr++ = ':';
1365 ptr = mem2hex(&regs->pc, ptr, 4, 0);
1366 *ptr++ = ';';
1367
1368 /*
1369 * Send frame pointer
1370 */
1371 *ptr++ = hexchars[GDB_REGID_FP >> 4];
1372 *ptr++ = hexchars[GDB_REGID_FP & 0xf];
1373 *ptr++ = ':';
1374 ptr = mem2hex(&regs->a3, ptr, 4, 0);
1375 *ptr++ = ';';
1376
1377 /*
1378 * Send stack pointer
1379 */
1380 ssp = (unsigned long) (regs + 1);
1381 *ptr++ = hexchars[GDB_REGID_SP >> 4];
1382 *ptr++ = hexchars[GDB_REGID_SP & 0xf];
1383 *ptr++ = ':';
1384 ptr = mem2hex(&ssp, ptr, 4, 0);
1385 *ptr++ = ';';
1386
1387 *ptr++ = 0;
1388 putpacket(output_buffer); /* send it off... */
1389
1390packet_waiting:
1391 /*
1392 * Wait for input from remote GDB
1393 */
1394 while (1) {
1395 output_buffer[0] = 0;
1396 getpacket(input_buffer);
1397
1398 switch (input_buffer[0]) {
1399 /* request repeat of last signal number */
1400 case '?':
1401 output_buffer[0] = 'S';
1402 output_buffer[1] = hexchars[sigval >> 4];
1403 output_buffer[2] = hexchars[sigval & 0xf];
1404 output_buffer[3] = 0;
1405 break;
1406
1407 case 'd':
1408 /* toggle debug flag */
1409 break;
1410
1411 /*
1412 * Return the value of the CPU registers
1413 */
1414 case 'g':
1415 zero = 0;
1416 ssp = (u32) (regs + 1);
1417 ptr = output_buffer;
1418 ptr = mem2hex(&regs->d0, ptr, 4, 0);
1419 ptr = mem2hex(&regs->d1, ptr, 4, 0);
1420 ptr = mem2hex(&regs->d2, ptr, 4, 0);
1421 ptr = mem2hex(&regs->d3, ptr, 4, 0);
1422 ptr = mem2hex(&regs->a0, ptr, 4, 0);
1423 ptr = mem2hex(&regs->a1, ptr, 4, 0);
1424 ptr = mem2hex(&regs->a2, ptr, 4, 0);
1425 ptr = mem2hex(&regs->a3, ptr, 4, 0);
1426
1427 ptr = mem2hex(&ssp, ptr, 4, 0); /* 8 */
1428 ptr = mem2hex(&regs->pc, ptr, 4, 0);
1429 ptr = mem2hex(&regs->mdr, ptr, 4, 0);
1430 ptr = mem2hex(&regs->epsw, ptr, 4, 0);
1431 ptr = mem2hex(&regs->lir, ptr, 4, 0);
1432 ptr = mem2hex(&regs->lar, ptr, 4, 0);
1433 ptr = mem2hex(&regs->mdrq, ptr, 4, 0);
1434
1435 ptr = mem2hex(&regs->e0, ptr, 4, 0); /* 15 */
1436 ptr = mem2hex(&regs->e1, ptr, 4, 0);
1437 ptr = mem2hex(&regs->e2, ptr, 4, 0);
1438 ptr = mem2hex(&regs->e3, ptr, 4, 0);
1439 ptr = mem2hex(&regs->e4, ptr, 4, 0);
1440 ptr = mem2hex(&regs->e5, ptr, 4, 0);
1441 ptr = mem2hex(&regs->e6, ptr, 4, 0);
1442 ptr = mem2hex(&regs->e7, ptr, 4, 0);
1443
1444 ptr = mem2hex(&ssp, ptr, 4, 0);
1445 ptr = mem2hex(&regs, ptr, 4, 0);
1446 ptr = mem2hex(&regs->sp, ptr, 4, 0);
1447 ptr = mem2hex(&regs->mcrh, ptr, 4, 0); /* 26 */
1448 ptr = mem2hex(&regs->mcrl, ptr, 4, 0);
1449 ptr = mem2hex(&regs->mcvf, ptr, 4, 0);
1450
1451 ptr = mem2hex(&gdbstub_fpcr, ptr, 4, 0); /* 29 - FPCR */
1452 ptr = mem2hex(&zero, ptr, 4, 0);
1453 ptr = mem2hex(&zero, ptr, 4, 0);
1454 for (loop = 0; loop < 32; loop++)
1455 ptr = mem2hex(&gdbstub_fpufs_array[loop],
1456 ptr, 4, 0); /* 32 - FS0-31 */
1457
1458 break;
1459
1460 /*
1461 * set the value of the CPU registers - return OK
1462 */
1463 case 'G':
1464 {
1465 const char *ptr;
1466
1467 ptr = &input_buffer[1];
1468 ptr = hex2mem(ptr, &regs->d0, 4, 0);
1469 ptr = hex2mem(ptr, &regs->d1, 4, 0);
1470 ptr = hex2mem(ptr, &regs->d2, 4, 0);
1471 ptr = hex2mem(ptr, &regs->d3, 4, 0);
1472 ptr = hex2mem(ptr, &regs->a0, 4, 0);
1473 ptr = hex2mem(ptr, &regs->a1, 4, 0);
1474 ptr = hex2mem(ptr, &regs->a2, 4, 0);
1475 ptr = hex2mem(ptr, &regs->a3, 4, 0);
1476
1477 ptr = hex2mem(ptr, &ssp, 4, 0); /* 8 */
1478 ptr = hex2mem(ptr, &regs->pc, 4, 0);
1479 ptr = hex2mem(ptr, &regs->mdr, 4, 0);
1480 ptr = hex2mem(ptr, &regs->epsw, 4, 0);
1481 ptr = hex2mem(ptr, &regs->lir, 4, 0);
1482 ptr = hex2mem(ptr, &regs->lar, 4, 0);
1483 ptr = hex2mem(ptr, &regs->mdrq, 4, 0);
1484
1485 ptr = hex2mem(ptr, &regs->e0, 4, 0); /* 15 */
1486 ptr = hex2mem(ptr, &regs->e1, 4, 0);
1487 ptr = hex2mem(ptr, &regs->e2, 4, 0);
1488 ptr = hex2mem(ptr, &regs->e3, 4, 0);
1489 ptr = hex2mem(ptr, &regs->e4, 4, 0);
1490 ptr = hex2mem(ptr, &regs->e5, 4, 0);
1491 ptr = hex2mem(ptr, &regs->e6, 4, 0);
1492 ptr = hex2mem(ptr, &regs->e7, 4, 0);
1493
1494 ptr = hex2mem(ptr, &ssp, 4, 0);
1495 ptr = hex2mem(ptr, &zero, 4, 0);
1496 ptr = hex2mem(ptr, &regs->sp, 4, 0);
1497 ptr = hex2mem(ptr, &regs->mcrh, 4, 0); /* 26 */
1498 ptr = hex2mem(ptr, &regs->mcrl, 4, 0);
1499 ptr = hex2mem(ptr, &regs->mcvf, 4, 0);
1500
1501 ptr = hex2mem(ptr, &zero, 4, 0); /* 29 - FPCR */
1502 ptr = hex2mem(ptr, &zero, 4, 0);
1503 ptr = hex2mem(ptr, &zero, 4, 0);
1504 for (loop = 0; loop < 32; loop++) /* 32 - FS0-31 */
1505 ptr = hex2mem(ptr, &zero, 4, 0);
1506
1507#if 0
1508 /*
1509 * See if the stack pointer has moved. If so, then copy
1510 * the saved locals and ins to the new location.
1511 */
1512 unsigned long *newsp = (unsigned long *) registers[SP];
1513 if (sp != newsp)
1514 sp = memcpy(newsp, sp, 16 * 4);
1515#endif
1516
1517 gdbstub_strcpy(output_buffer, "OK");
1518 }
1519 break;
1520
1521 /*
1522 * mAA..AA,LLLL Read LLLL bytes at address AA..AA
1523 */
1524 case 'm':
1525 ptr = &input_buffer[1];
1526
1527 if (hexToInt(&ptr, &addr) &&
1528 *ptr++ == ',' &&
1529 hexToInt(&ptr, &length)
1530 ) {
1531 if (mem2hex((char *) addr, output_buffer,
1532 length, 1))
1533 break;
1534 gdbstub_strcpy(output_buffer, "E03");
1535 } else {
1536 gdbstub_strcpy(output_buffer, "E01");
1537 }
1538 break;
1539
1540 /*
1541 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
1542 * return OK
1543 */
1544 case 'M':
1545 ptr = &input_buffer[1];
1546
1547 if (hexToInt(&ptr, &addr) &&
1548 *ptr++ == ',' &&
1549 hexToInt(&ptr, &length) &&
1550 *ptr++ == ':'
1551 ) {
1552 if (hex2mem(ptr, (char *) addr, length, 1))
1553 gdbstub_strcpy(output_buffer, "OK");
1554 else
1555 gdbstub_strcpy(output_buffer, "E03");
1556
1557 gdbstub_flush_caches = 1;
1558 } else {
1559 gdbstub_strcpy(output_buffer, "E02");
1560 }
1561 break;
1562
1563 /*
1564 * cAA..AA Continue at address AA..AA(optional)
1565 */
1566 case 'c':
1567 /* try to read optional parameter, pc unchanged if no
1568 * parm */
1569
1570 ptr = &input_buffer[1];
1571 if (hexToInt(&ptr, &addr))
1572 regs->pc = addr;
1573 goto done;
1574
1575 /*
1576 * kill the program
1577 */
1578 case 'k' :
1579 goto done; /* just continue */
1580
1581 /*
1582 * Reset the whole machine (FIXME: system dependent)
1583 */
1584 case 'r':
1585 break;
1586
1587 /*
1588 * Step to next instruction
1589 */
1590 case 's':
1591 /*
1592 * using the T flag doesn't seem to perform single
1593 * stepping (it seems to wind up being caught by the
1594 * JTAG unit), so we have to use breakpoints and
1595 * continue instead.
1596 */
1597 if (gdbstub_single_step(regs) < 0)
1598 /* ignore any fault error for now */
1599 gdbstub_printk("unable to set single-step"
1600 " bp\n");
1601 goto done;
1602
1603 /*
1604 * Set baud rate (bBB)
1605 */
1606 case 'b':
1607 do {
1608 int baudrate;
1609
1610 ptr = &input_buffer[1];
1611 if (!hexToInt(&ptr, &baudrate)) {
1612 gdbstub_strcpy(output_buffer, "B01");
1613 break;
1614 }
1615
1616 if (baudrate) {
1617 /* ACK before changing speed */
1618 putpacket("OK");
1619 gdbstub_io_set_baud(baudrate);
1620 }
1621 } while (0);
1622 break;
1623
1624 /*
1625 * Set breakpoint
1626 */
1627 case 'Z':
1628 ptr = &input_buffer[1];
1629
1630 if (!hexToInt(&ptr, &loop) || *ptr++ != ',' ||
1631 !hexToInt(&ptr, &addr) || *ptr++ != ',' ||
1632 !hexToInt(&ptr, &length)
1633 ) {
1634 gdbstub_strcpy(output_buffer, "E01");
1635 break;
1636 }
1637
1638 /* only support software breakpoints */
1639 gdbstub_strcpy(output_buffer, "E03");
1640 if (loop != 0 ||
1641 length < 1 ||
1642 length > 7 ||
1643 (unsigned long) addr < 4096)
1644 break;
1645
1646 if (gdbstub_set_breakpoint((u8 *) addr, length) < 0)
1647 break;
1648
1649 gdbstub_strcpy(output_buffer, "OK");
1650 break;
1651
1652 /*
1653 * Clear breakpoint
1654 */
1655 case 'z':
1656 ptr = &input_buffer[1];
1657
1658 if (!hexToInt(&ptr, &loop) || *ptr++ != ',' ||
1659 !hexToInt(&ptr, &addr) || *ptr++ != ',' ||
1660 !hexToInt(&ptr, &length)
1661 ) {
1662 gdbstub_strcpy(output_buffer, "E01");
1663 break;
1664 }
1665
1666 /* only support software breakpoints */
1667 gdbstub_strcpy(output_buffer, "E03");
1668 if (loop != 0 ||
1669 length < 1 ||
1670 length > 7 ||
1671 (unsigned long) addr < 4096)
1672 break;
1673
1674 if (gdbstub_clear_breakpoint((u8 *) addr, length) < 0)
1675 break;
1676
1677 gdbstub_strcpy(output_buffer, "OK");
1678 break;
1679
1680 default:
1681 gdbstub_proto("### GDB Unsupported Cmd '%s'\n",
1682 input_buffer);
1683 break;
1684 }
1685
1686 /* reply to the request */
1687 putpacket(output_buffer);
1688 }
1689
1690done:
1691 /*
1692 * Need to flush the instruction cache here, as we may
1693 * have deposited a breakpoint, and the icache probably
1694 * has no way of knowing that a data ref to some location
1695 * may have changed something that is in the instruction
1696 * cache.
1697 * NB: We flush both caches, just to be sure...
1698 */
1699 if (gdbstub_flush_caches)
1700 gdbstub_purge_cache();
1701
1702 gdbstub_load_fpu();
1703 mn10300_set_gdbleds(0);
1704 if (excep == EXCEP_NMI)
1705 NMICR = NMICR_NMIF;
1706
1707 touch_softlockup_watchdog();
1708
1709 local_irq_restore(epsw);
1710 return 1;
1711}
1712
1713/*
1714 * handle event interception
1715 */
1716asmlinkage int gdbstub_intercept(struct pt_regs *regs,
1717 enum exception_code excep)
1718{
1719 static u8 notfirst = 1;
1720 int ret;
1721
1722 if (gdbstub_busy)
1723 gdbstub_printk("--> gdbstub reentered itself\n");
1724 gdbstub_busy = 1;
1725
1726 if (notfirst) {
1727 unsigned long mdr;
1728 asm("mov mdr,%0" : "=d"(mdr));
1729
1730 gdbstub_entry(
1731 "--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
1732 regs, excep, mdr, regs->pc);
1733
1734 gdbstub_entry(
1735 "PC: %08lx EPSW: %08lx SSP: %08lx mode: %s\n",
1736 regs->pc, regs->epsw, (unsigned long) &ret,
1737 user_mode(regs) ? "User" : "Super");
1738 gdbstub_entry(
1739 "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
1740 regs->d0, regs->d1, regs->d2, regs->d3);
1741 gdbstub_entry(
1742 "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n",
1743 regs->a0, regs->a1, regs->a2, regs->a3);
1744 gdbstub_entry(
1745 "e0: %08lx e1: %08lx e2: %08lx e3: %08lx\n",
1746 regs->e0, regs->e1, regs->e2, regs->e3);
1747 gdbstub_entry(
1748 "e4: %08lx e5: %08lx e6: %08lx e7: %08lx\n",
1749 regs->e4, regs->e5, regs->e6, regs->e7);
1750 gdbstub_entry(
1751 "lar: %08lx lir: %08lx mdr: %08lx usp: %08lx\n",
1752 regs->lar, regs->lir, regs->mdr, regs->sp);
1753 gdbstub_entry(
1754 "cvf: %08lx crl: %08lx crh: %08lx drq: %08lx\n",
1755 regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq);
1756 gdbstub_entry(
1757 "threadinfo=%p task=%p)\n",
1758 current_thread_info(), current);
1759 } else {
1760 notfirst = 1;
1761 }
1762
1763 ret = gdbstub(regs, excep);
1764
1765 gdbstub_entry("<-- gdbstub_intercept()\n");
1766 gdbstub_busy = 0;
1767 return ret;
1768}
1769
1770/*
1771 * handle the GDB stub itself causing an exception
1772 */
1773asmlinkage void gdbstub_exception(struct pt_regs *regs,
1774 enum exception_code excep)
1775{
1776 unsigned long mdr;
1777
1778 asm("mov mdr,%0" : "=d"(mdr));
1779 gdbstub_entry("--> gdbstub exception({%p},%04x) [MDR=%lx]\n",
1780 regs, excep, mdr);
1781
1782 while ((unsigned long) regs == 0xffffffff) {}
1783
1784 /* handle guarded memory accesses where we know it might fault */
1785 if (regs->pc == (unsigned) gdbstub_read_byte_guard) {
1786 regs->pc = (unsigned) gdbstub_read_byte_cont;
1787 goto fault;
1788 }
1789
1790 if (regs->pc == (unsigned) gdbstub_read_word_guard) {
1791 regs->pc = (unsigned) gdbstub_read_word_cont;
1792 goto fault;
1793 }
1794
1795 if (regs->pc == (unsigned) gdbstub_read_dword_guard) {
1796 regs->pc = (unsigned) gdbstub_read_dword_cont;
1797 goto fault;
1798 }
1799
1800 if (regs->pc == (unsigned) gdbstub_write_byte_guard) {
1801 regs->pc = (unsigned) gdbstub_write_byte_cont;
1802 goto fault;
1803 }
1804
1805 if (regs->pc == (unsigned) gdbstub_write_word_guard) {
1806 regs->pc = (unsigned) gdbstub_write_word_cont;
1807 goto fault;
1808 }
1809
1810 if (regs->pc == (unsigned) gdbstub_write_dword_guard) {
1811 regs->pc = (unsigned) gdbstub_write_dword_cont;
1812 goto fault;
1813 }
1814
1815 gdbstub_printk("\n### GDB stub caused an exception ###\n");
1816
1817 /* something went horribly wrong */
1818 console_verbose();
1819 show_registers(regs);
1820
1821 panic("GDB Stub caused an unexpected exception - can't continue\n");
1822
1823 /* we caught an attempt by the stub to access silly memory */
1824fault:
1825 gdbstub_entry("<-- gdbstub exception() = EFAULT\n");
1826 regs->d0 = -EFAULT;
1827 return;
1828}
1829
1830/*
1831 * send an exit message to GDB
1832 */
1833void gdbstub_exit(int status)
1834{
1835 unsigned char checksum;
1836 unsigned char ch;
1837 int count;
1838
1839 gdbstub_busy = 1;
1840 output_buffer[0] = 'W';
1841 output_buffer[1] = hexchars[(status >> 4) & 0x0F];
1842 output_buffer[2] = hexchars[status & 0x0F];
1843 output_buffer[3] = 0;
1844
1845 gdbstub_io_tx_char('$');
1846 checksum = 0;
1847 count = 0;
1848
1849 while ((ch = output_buffer[count]) != 0) {
1850 gdbstub_io_tx_char(ch);
1851 checksum += ch;
1852 count += 1;
1853 }
1854
1855 gdbstub_io_tx_char('#');
1856 gdbstub_io_tx_char(hexchars[checksum >> 4]);
1857 gdbstub_io_tx_char(hexchars[checksum & 0xf]);
1858
1859 /* make sure the output is flushed, or else RedBoot might clobber it */
1860 gdbstub_io_tx_flush();
1861
1862 gdbstub_busy = 0;
1863}
1864
1865/*
1866 * initialise the GDB stub
1867 */
1868asmlinkage void __init gdbstub_init(void)
1869{
1870#ifdef CONFIG_GDBSTUB_IMMEDIATE
1871 unsigned char ch;
1872 int ret;
1873#endif
1874
1875 gdbstub_busy = 1;
1876
1877 printk(KERN_INFO "%s", gdbstub_banner);
1878
1879 gdbstub_io_init();
1880
1881 gdbstub_entry("--> gdbstub_init\n");
1882
1883 /* try to talk to GDB (or anyone insane enough to want to type GDB
1884 * protocol by hand) */
1885 gdbstub_io("### GDB Tx ACK\n");
1886 gdbstub_io_tx_char('+'); /* 'hello world' */
1887
1888#ifdef CONFIG_GDBSTUB_IMMEDIATE
1889 gdbstub_printk("GDB Stub waiting for packet\n");
1890
1891 /* in case GDB is started before us, ACK any packets that are already
1892 * sitting there (presumably "$?#xx")
1893 */
1894 do { gdbstub_io_rx_char(&ch, 0); } while (ch != '$');
1895 do { gdbstub_io_rx_char(&ch, 0); } while (ch != '#');
1896 /* eat first csum byte */
1897 do { ret = gdbstub_io_rx_char(&ch, 0); } while (ret != 0);
1898 /* eat second csum byte */
1899 do { ret = gdbstub_io_rx_char(&ch, 0); } while (ret != 0);
1900
1901 gdbstub_io("### GDB Tx NAK\n");
1902 gdbstub_io_tx_char('-'); /* NAK it */
1903
1904#else
1905 printk("GDB Stub ready\n");
1906#endif
1907
1908 gdbstub_busy = 0;
1909 gdbstub_entry("<-- gdbstub_init\n");
1910}
1911
1912/*
1913 * register the console at a more appropriate time
1914 */
1915#ifdef CONFIG_GDBSTUB_CONSOLE
1916static int __init gdbstub_postinit(void)
1917{
1918 printk(KERN_NOTICE "registering console\n");
1919 register_console(&gdbstub_console);
1920 return 0;
1921}
1922
1923__initcall(gdbstub_postinit);
1924#endif
1925
1926/*
1927 * handle character reception on GDB serial port
1928 * - jump into the GDB stub if BREAK is detected on the serial line
1929 */
1930asmlinkage void gdbstub_rx_irq(struct pt_regs *regs, enum exception_code excep)
1931{
1932 char ch;
1933 int ret;
1934
1935 gdbstub_entry("--> gdbstub_rx_irq\n");
1936
1937 do {
1938 ret = gdbstub_io_rx_char(&ch, 1);
1939 if (ret != -EIO && ret != -EAGAIN) {
1940 if (ret != -EINTR)
1941 gdbstub_rx_unget = ch;
1942 gdbstub(regs, excep);
1943 }
1944 } while (ret != -EAGAIN);
1945
1946 gdbstub_entry("<-- gdbstub_rx_irq\n");
1947}
diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S
new file mode 100644
index 000000000000..606bd8c6758d
--- /dev/null
+++ b/arch/mn10300/kernel/head.S
@@ -0,0 +1,255 @@
1/* Boot entry point for MN10300 kernel
2 *
3 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/threads.h>
13#include <linux/linkage.h>
14#include <linux/serial_reg.h>
15#include <asm/thread_info.h>
16#include <asm/page.h>
17#include <asm/pgtable.h>
18#include <asm/frame.inc>
19#include <asm/param.h>
20#include <asm/unit/serial.h>
21
22 .section .text.head,"ax"
23
24###############################################################################
25#
26# bootloader entry point
27#
28###############################################################################
29 .globl _start
30 .type _start,@function
31_start:
32 # save commandline pointer
33 mov d0,a3
34
35 # preload the PGD pointer register
36 mov swapper_pg_dir,d0
37 mov d0,(PTBR)
38
39 # turn on the TLBs
40 mov MMUCTR_IIV|MMUCTR_DIV,d0
41 mov d0,(MMUCTR)
42 mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
43 mov d0,(MMUCTR)
44
45 # turn on AM33v2 exception handling mode and set the trap table base
46 movhu (CPUP),d0
47 or CPUP_EXM_AM33V2,d0
48 movhu d0,(CPUP)
49 mov CONFIG_INTERRUPT_VECTOR_BASE,d0
50 mov d0,(TBR)
51
52 # invalidate and enable both of the caches
53 mov CHCTR,a0
54 clr d0
55 movhu d0,(a0) # turn off first
56 mov CHCTR_ICINV|CHCTR_DCINV,d0
57 movhu d0,(a0)
58 setlb
59 mov (a0),d0
60 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
61 lne
62
63#ifndef CONFIG_MN10300_CACHE_DISABLED
64#ifdef CONFIG_MN10300_CACHE_WBACK
65#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
66 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
67#else
68 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
69#endif /* CACHE_DISABLED */
70#else
71 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
72#endif /* WBACK */
73 movhu d0,(a0) # enable
74#endif /* NOWRALLOC */
75
76 # turn on RTS on the debug serial port if applicable
77#ifdef CONFIG_MN10300_UNIT_ASB2305
78 bset UART_MCR_RTS,(ASB2305_DEBUG_MCR)
79#endif
80
81 # clear the BSS area
82 mov __bss_start,a0
83 mov __bss_stop,a1
84 clr d0
85bssclear:
86 cmp a1,a0
87 bge bssclear_end
88 mov d0,(a0)
89 inc4 a0
90 bra bssclear
91bssclear_end:
92
93 # retrieve the parameters (including command line) before we overwrite
94 # them
95 cmp 0xabadcafe,d1
96 bne __no_parameters
97
98__copy_parameters:
99 mov redboot_command_line,a0
100 mov a0,a1
101 add COMMAND_LINE_SIZE,a1
1021:
103 movbu (a3),d0
104 inc a3
105 movbu d0,(a0)
106 inc a0
107 cmp a1,a0
108 blt 1b
109
110 mov redboot_platform_name,a0
111 mov a0,a1
112 add COMMAND_LINE_SIZE,a1
113 mov d2,a3
1141:
115 movbu (a3),d0
116 inc a3
117 movbu d0,(a0)
118 inc a0
119 cmp a1,a0
120 blt 1b
121
122__no_parameters:
123
124 # set up the registers with recognisable rubbish in them
125 mov init_thread_union+THREAD_SIZE-12,sp
126
127 mov 0xea01eaea,d0
128 mov d0,(4,sp) # EPSW save area
129 mov 0xea02eaea,d0
130 mov d0,(8,sp) # PC save area
131
132 mov 0xeb0060ed,d0
133 mov d0,mdr
134 mov 0xeb0061ed,d0
135 mov d0,mdrq
136 mov 0xeb0062ed,d0
137 mov d0,mcrh
138 mov 0xeb0063ed,d0
139 mov d0,mcrl
140 mov 0xeb0064ed,d0
141 mov d0,mcvf
142 mov 0xed0065ed,a3
143 mov a3,usp
144
145 mov 0xed00e0ed,e0
146 mov 0xed00e1ed,e1
147 mov 0xed00e2ed,e2
148 mov 0xed00e3ed,e3
149 mov 0xed00e4ed,e4
150 mov 0xed00e5ed,e5
151 mov 0xed00e6ed,e6
152 mov 0xed00e7ed,e7
153
154 mov 0xed00d0ed,d0
155 mov 0xed00d1ed,d1
156 mov 0xed00d2ed,d2
157 mov 0xed00d3ed,d3
158 mov 0xed00a0ed,a0
159 mov 0xed00a1ed,a1
160 mov 0xed00a2ed,a2
161 mov 0,a3
162
163 # set up the initial kernel stack
164 SAVE_ALL
165 mov 0xffffffff,d0
166 mov d0,(REG_ORIG_D0,fp)
167
168 # put different recognisable rubbish in the regs
169 mov 0xfb0060ed,d0
170 mov d0,mdr
171 mov 0xfb0061ed,d0
172 mov d0,mdrq
173 mov 0xfb0062ed,d0
174 mov d0,mcrh
175 mov 0xfb0063ed,d0
176 mov d0,mcrl
177 mov 0xfb0064ed,d0
178 mov d0,mcvf
179 mov 0xfd0065ed,a0
180 mov a0,usp
181
182 mov 0xfd00e0ed,e0
183 mov 0xfd00e1ed,e1
184 mov 0xfd00e2ed,e2
185 mov 0xfd00e3ed,e3
186 mov 0xfd00e4ed,e4
187 mov 0xfd00e5ed,e5
188 mov 0xfd00e6ed,e6
189 mov 0xfd00e7ed,e7
190
191 mov 0xfd00d0ed,d0
192 mov 0xfd00d1ed,d1
193 mov 0xfd00d2ed,d2
194 mov 0xfd00d3ed,d3
195 mov 0xfd00a0ed,a0
196 mov 0xfd00a1ed,a1
197 mov 0xfd00a2ed,a2
198
199 # we may be holding current in E2
200#ifdef CONFIG_MN10300_CURRENT_IN_E2
201 mov init_task,e2
202#endif
203
204 # initialise the processor and the unit
205 call processor_init[],0
206 call unit_init[],0
207
208#ifdef CONFIG_GDBSTUB
209 call gdbstub_init[],0
210
211#ifdef CONFIG_GDBSTUB_IMMEDIATE
212 .globl __gdbstub_pause
213__gdbstub_pause:
214 bra __gdbstub_pause
215#endif
216#endif
217
218 jmp start_kernel
219 .size _start, _start-.
220ENTRY(__head_end)
221
222/*
223 * This is initialized to disallow all access to the low 2G region
224 * - the high 2G region is managed directly by the MMU
225 * - range 0x70000000-0x7C000000 are initialised for use by VMALLOC
226 */
227 .section .bss
228 .balign PAGE_SIZE
229ENTRY(swapper_pg_dir)
230 .space PTRS_PER_PGD*4
231
232/*
233 * The page tables are initialized to only 8MB here - the final page
234 * tables are set up later depending on memory size.
235 */
236
237 .balign PAGE_SIZE
238ENTRY(empty_zero_page)
239 .space PAGE_SIZE
240
241 .balign PAGE_SIZE
242ENTRY(empty_bad_page)
243 .space PAGE_SIZE
244
245 .balign PAGE_SIZE
246ENTRY(empty_bad_pte_table)
247 .space PAGE_SIZE
248
249 .balign PAGE_SIZE
250ENTRY(large_page_table)
251 .space PAGE_SIZE
252
253 .balign PAGE_SIZE
254ENTRY(kernel_vmalloc_ptes)
255 .space ((VMALLOC_END-VMALLOC_START)/PAGE_SIZE)*4
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c
new file mode 100644
index 000000000000..39fe6882dd1d
--- /dev/null
+++ b/arch/mn10300/kernel/init_task.c
@@ -0,0 +1,45 @@
1/* MN10300 Initial task definitions
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/mm.h>
12#include <linux/module.h>
13#include <linux/sched.h>
14#include <linux/init.h>
15#include <linux/init_task.h>
16#include <linux/fs.h>
17#include <linux/mqueue.h>
18#include <asm/uaccess.h>
19#include <asm/pgtable.h>
20
21static struct fs_struct init_fs = INIT_FS;
22static struct files_struct init_files = INIT_FILES;
23static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
24static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
25struct mm_struct init_mm = INIT_MM(init_mm);
26EXPORT_SYMBOL(init_mm);
27
28/*
29 * Initial thread structure.
30 *
31 * We need to make sure that this is THREAD_SIZE aligned due to the
32 * way process stacks are handled. This is done by having a special
33 * "init_task" linker map entry..
34 */
35union thread_union init_thread_union
36 __attribute__((__section__(".data.init_task"))) =
37 { INIT_THREAD_INFO(init_task) };
38
39/*
40 * Initial task structure.
41 *
42 * All other task structs will be allocated on slabs in fork.c
43 */
44struct task_struct init_task = INIT_TASK(init_task);
45EXPORT_SYMBOL(init_task);
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
new file mode 100644
index 000000000000..eee2eee86267
--- /dev/null
+++ b/arch/mn10300/kernel/internal.h
@@ -0,0 +1,20 @@
1/* Internal definitions for the arch part of the core kernel
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12/*
13 * kthread.S
14 */
15extern int kernel_thread_helper(int);
16
17/*
18 * entry.S
19 */
20extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
diff --git a/arch/mn10300/kernel/io.c b/arch/mn10300/kernel/io.c
new file mode 100644
index 000000000000..e96fdf6bb542
--- /dev/null
+++ b/arch/mn10300/kernel/io.c
@@ -0,0 +1,30 @@
1/* MN10300 Misaligned multibyte-word I/O
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/string.h>
13#include <linux/kernel.h>
14#include <asm/io.h>
15
16/*
17 * output data from a potentially misaligned buffer
18 */
19void __outsl(unsigned long addr, const void *buffer, int count)
20{
21 const unsigned char *buf = buffer;
22 unsigned long val;
23
24 while (count--) {
25 memcpy(&val, buf, 4);
26 outl(val, addr);
27 buf += 4;
28 }
29}
30EXPORT_SYMBOL(__outsl);
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
new file mode 100644
index 000000000000..761c434a2488
--- /dev/null
+++ b/arch/mn10300/kernel/irq.c
@@ -0,0 +1,235 @@
1/* MN10300 Arch-specific interrupt handling
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/interrupt.h>
13#include <linux/kernel_stat.h>
14#include <linux/seq_file.h>
15#include <asm/setup.h>
16
17unsigned long __mn10300_irq_enabled_epsw = EPSW_IE | EPSW_IM_7;
18EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
19
20atomic_t irq_err_count;
21
22/*
23 * MN10300 INTC controller operations
24 */
25static void mn10300_cpupic_disable(unsigned int irq)
26{
27 u16 tmp = GxICR(irq);
28 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
29 tmp = GxICR(irq);
30}
31
32static void mn10300_cpupic_enable(unsigned int irq)
33{
34 u16 tmp = GxICR(irq);
35 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
36 tmp = GxICR(irq);
37}
38
39static void mn10300_cpupic_ack(unsigned int irq)
40{
41 u16 tmp;
42 *(volatile u8 *) &GxICR(irq) = GxICR_DETECT;
43 tmp = GxICR(irq);
44}
45
46static void mn10300_cpupic_mask(unsigned int irq)
47{
48 u16 tmp = GxICR(irq);
49 GxICR(irq) = (tmp & GxICR_LEVEL);
50 tmp = GxICR(irq);
51}
52
53static void mn10300_cpupic_mask_ack(unsigned int irq)
54{
55 u16 tmp = GxICR(irq);
56 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
57 tmp = GxICR(irq);
58}
59
60static void mn10300_cpupic_unmask(unsigned int irq)
61{
62 u16 tmp = GxICR(irq);
63 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
64 tmp = GxICR(irq);
65}
66
67static void mn10300_cpupic_end(unsigned int irq)
68{
69 u16 tmp = GxICR(irq);
70 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
71 tmp = GxICR(irq);
72}
73
74static struct irq_chip mn10300_cpu_pic = {
75 .name = "cpu",
76 .disable = mn10300_cpupic_disable,
77 .enable = mn10300_cpupic_enable,
78 .ack = mn10300_cpupic_ack,
79 .mask = mn10300_cpupic_mask,
80 .mask_ack = mn10300_cpupic_mask_ack,
81 .unmask = mn10300_cpupic_unmask,
82 .end = mn10300_cpupic_end,
83};
84
85/*
86 * 'what should we do if we get a hw irq event on an illegal vector'.
87 * each architecture has to answer this themselves.
88 */
89void ack_bad_irq(int irq)
90{
91 printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
92}
93
94/*
95 * change the level at which an IRQ executes
96 * - must not be called whilst interrupts are being processed!
97 */
98void set_intr_level(int irq, u16 level)
99{
100 u16 tmp;
101
102 if (in_interrupt())
103 BUG();
104
105 tmp = GxICR(irq);
106 GxICR(irq) = (tmp & GxICR_ENABLE) | level;
107 tmp = GxICR(irq);
108}
109
110/*
111 * mark an interrupt to be ACK'd after interrupt handlers have been run rather
112 * than before
113 * - see Documentation/mn10300/features.txt
114 */
115void set_intr_postackable(int irq)
116{
117 set_irq_handler(irq, handle_level_irq);
118}
119
120/*
121 * initialise the interrupt system
122 */
123void __init init_IRQ(void)
124{
125 int irq;
126
127 for (irq = 0; irq < NR_IRQS; irq++)
128 if (irq_desc[irq].chip == &no_irq_type)
129 set_irq_chip_and_handler(irq, &mn10300_cpu_pic,
130 handle_edge_irq);
131 unit_init_IRQ();
132}
133
134/*
135 * handle normal device IRQs
136 */
137asmlinkage void do_IRQ(void)
138{
139 unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw;
140 int irq;
141
142 sp = current_stack_pointer();
143 if (sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN)
144 BUG();
145
146 /* make sure local_irq_enable() doesn't muck up the interrupt priority
147 * setting in EPSW */
148 old_irq_enabled_epsw = __mn10300_irq_enabled_epsw;
149 local_save_flags(epsw);
150 __mn10300_irq_enabled_epsw = EPSW_IE | (EPSW_IM & epsw);
151 irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL;
152
153 __IRQ_STAT(smp_processor_id(), __irq_count)++;
154
155 irq_enter();
156
157 for (;;) {
158 /* ask the interrupt controller for the next IRQ to process
159 * - the result we get depends on EPSW.IM
160 */
161 irq = IAGR & IAGR_GN;
162 if (!irq)
163 break;
164
165 local_irq_restore(irq_disabled_epsw);
166
167 generic_handle_irq(irq >> 2);
168
169 /* restore IRQ controls for IAGR access */
170 local_irq_restore(epsw);
171 }
172
173 __mn10300_irq_enabled_epsw = old_irq_enabled_epsw;
174
175 irq_exit();
176}
177
178/*
179 * Display interrupt management information through /proc/interrupts
180 */
181int show_interrupts(struct seq_file *p, void *v)
182{
183 int i = *(loff_t *) v, j, cpu;
184 struct irqaction *action;
185 unsigned long flags;
186
187 switch (i) {
188 /* display column title bar naming CPUs */
189 case 0:
190 seq_printf(p, " ");
191 for (j = 0; j < NR_CPUS; j++)
192 if (cpu_online(j))
193 seq_printf(p, "CPU%d ", j);
194 seq_putc(p, '\n');
195 break;
196
197 /* display information rows, one per active CPU */
198 case 1 ... NR_IRQS - 1:
199 spin_lock_irqsave(&irq_desc[i].lock, flags);
200
201 action = irq_desc[i].action;
202 if (action) {
203 seq_printf(p, "%3d: ", i);
204 for_each_present_cpu(cpu)
205 seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
206 seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
207 (GxICR(i) & GxICR_LEVEL) >>
208 GxICR_LEVEL_SHIFT);
209 seq_printf(p, " %s", action->name);
210
211 for (action = action->next;
212 action;
213 action = action->next)
214 seq_printf(p, ", %s", action->name);
215
216 seq_putc(p, '\n');
217 }
218
219 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
220 break;
221
222 /* polish off with NMI and error counters */
223 case NR_IRQS:
224 seq_printf(p, "NMI: ");
225 for (j = 0; j < NR_CPUS; j++)
226 if (cpu_online(j))
227 seq_printf(p, "%10u ", nmi_count(j));
228 seq_putc(p, '\n');
229
230 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
231 break;
232 }
233
234 return 0;
235}
diff --git a/arch/mn10300/kernel/kernel_execve.S b/arch/mn10300/kernel/kernel_execve.S
new file mode 100644
index 000000000000..86039f105268
--- /dev/null
+++ b/arch/mn10300/kernel/kernel_execve.S
@@ -0,0 +1,37 @@
1/* MN10300 In-kernel program execution
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/linkage.h>
12#include <asm/unistd.h>
13
14###############################################################################
15#
16# Do a system call from kernel instead of calling sys_execve so we end up with
17# proper pt_regs.
18#
19# int kernel_execve(const char *filename, char *const argv[],
20# char *const envp[])
21#
22# On entry: D0/D1/8(SP): arguments to function
23# On return: D0: syscall return.
24#
25###############################################################################
26 .globl kernel_execve
27 .type kernel_execve,@function
28kernel_execve:
29 mov a3,a1
30 mov d0,a0
31 mov (12,sp),a3
32 mov +__NR_execve,d0
33 syscall 0
34 mov a1,a3
35 rets
36
37 .size kernel_execve,.-kernel_execve
diff --git a/arch/mn10300/kernel/kprobes.c b/arch/mn10300/kernel/kprobes.c
new file mode 100644
index 000000000000..dacafab00eb2
--- /dev/null
+++ b/arch/mn10300/kernel/kprobes.c
@@ -0,0 +1,653 @@
1/* MN10300 Kernel probes implementation
2 *
3 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4 * Written by Mark Salter (msalter@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public Licence as published by
8 * the Free Software Foundation; either version 2 of the Licence, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public Licence for more details.
15 *
16 * You should have received a copy of the GNU General Public Licence
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20#include <linux/kprobes.h>
21#include <linux/ptrace.h>
22#include <linux/spinlock.h>
23#include <linux/preempt.h>
24#include <linux/kdebug.h>
25#include <asm/cacheflush.h>
26
27struct kretprobe_blackpoint kretprobe_blacklist[] = { { NULL, NULL } };
28const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
29
30/* kprobe_status settings */
31#define KPROBE_HIT_ACTIVE 0x00000001
32#define KPROBE_HIT_SS 0x00000002
33
34static struct kprobe *current_kprobe;
35static unsigned long current_kprobe_orig_pc;
36static unsigned long current_kprobe_next_pc;
37static int current_kprobe_ss_flags;
38static unsigned long kprobe_status;
39static kprobe_opcode_t current_kprobe_ss_buf[MAX_INSN_SIZE + 2];
40static unsigned long current_kprobe_bp_addr;
41
42DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
43
44
45/* singlestep flag bits */
46#define SINGLESTEP_BRANCH 1
47#define SINGLESTEP_PCREL 2
48
49#define READ_BYTE(p, valp) \
50 do { *(u8 *)(valp) = *(u8 *)(p); } while (0)
51
52#define READ_WORD16(p, valp) \
53 do { \
54 READ_BYTE((p), (valp)); \
55 READ_BYTE((u8 *)(p) + 1, (u8 *)(valp) + 1); \
56 } while (0)
57
58#define READ_WORD32(p, valp) \
59 do { \
60 READ_BYTE((p), (valp)); \
61 READ_BYTE((u8 *)(p) + 1, (u8 *)(valp) + 1); \
62 READ_BYTE((u8 *)(p) + 2, (u8 *)(valp) + 2); \
63 READ_BYTE((u8 *)(p) + 3, (u8 *)(valp) + 3); \
64 } while (0)
65
66
67static const u8 mn10300_insn_sizes[256] =
68{
69 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
70 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, /* 0 */
71 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
72 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
73 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
74 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
75 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
76 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
77 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
78 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
79 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
80 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
81 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
84 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
85 0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1 /* f */
86};
87
88#define LT (1 << 0)
89#define GT (1 << 1)
90#define GE (1 << 2)
91#define LE (1 << 3)
92#define CS (1 << 4)
93#define HI (1 << 5)
94#define CC (1 << 6)
95#define LS (1 << 7)
96#define EQ (1 << 8)
97#define NE (1 << 9)
98#define RA (1 << 10)
99#define VC (1 << 11)
100#define VS (1 << 12)
101#define NC (1 << 13)
102#define NS (1 << 14)
103
104static const u16 cond_table[] = {
105 /* V C N Z */
106 /* 0 0 0 0 */ (NE | NC | CC | VC | GE | GT | HI),
107 /* 0 0 0 1 */ (EQ | NC | CC | VC | GE | LE | LS),
108 /* 0 0 1 0 */ (NE | NS | CC | VC | LT | LE | HI),
109 /* 0 0 1 1 */ (EQ | NS | CC | VC | LT | LE | LS),
110 /* 0 1 0 0 */ (NE | NC | CS | VC | GE | GT | LS),
111 /* 0 1 0 1 */ (EQ | NC | CS | VC | GE | LE | LS),
112 /* 0 1 1 0 */ (NE | NS | CS | VC | LT | LE | LS),
113 /* 0 1 1 1 */ (EQ | NS | CS | VC | LT | LE | LS),
114 /* 1 0 0 0 */ (NE | NC | CC | VS | LT | LE | HI),
115 /* 1 0 0 1 */ (EQ | NC | CC | VS | LT | LE | LS),
116 /* 1 0 1 0 */ (NE | NS | CC | VS | GE | GT | HI),
117 /* 1 0 1 1 */ (EQ | NS | CC | VS | GE | LE | LS),
118 /* 1 1 0 0 */ (NE | NC | CS | VS | LT | LE | LS),
119 /* 1 1 0 1 */ (EQ | NC | CS | VS | LT | LE | LS),
120 /* 1 1 1 0 */ (NE | NS | CS | VS | GE | GT | LS),
121 /* 1 1 1 1 */ (EQ | NS | CS | VS | GE | LE | LS),
122};
123
124/*
125 * Calculate what the PC will be after executing next instruction
126 */
127static unsigned find_nextpc(struct pt_regs *regs, int *flags)
128{
129 unsigned size;
130 s8 x8;
131 s16 x16;
132 s32 x32;
133 u8 opc, *pc, *sp, *next;
134
135 next = 0;
136 *flags = SINGLESTEP_PCREL;
137
138 pc = (u8 *) regs->pc;
139 sp = (u8 *) (regs + 1);
140 opc = *pc;
141
142 size = mn10300_insn_sizes[opc];
143 if (size > 0) {
144 next = pc + size;
145 } else {
146 switch (opc) {
147 /* Bxx (d8,PC) */
148 case 0xc0 ... 0xca:
149 x8 = 2;
150 if (cond_table[regs->epsw & 0xf] & (1 << (opc & 0xf)))
151 x8 = (s8)pc[1];
152 next = pc + x8;
153 *flags |= SINGLESTEP_BRANCH;
154 break;
155
156 /* JMP (d16,PC) or CALL (d16,PC) */
157 case 0xcc:
158 case 0xcd:
159 READ_WORD16(pc + 1, &x16);
160 next = pc + x16;
161 *flags |= SINGLESTEP_BRANCH;
162 break;
163
164 /* JMP (d32,PC) or CALL (d32,PC) */
165 case 0xdc:
166 case 0xdd:
167 READ_WORD32(pc + 1, &x32);
168 next = pc + x32;
169 *flags |= SINGLESTEP_BRANCH;
170 break;
171
172 /* RETF */
173 case 0xde:
174 next = (u8 *)regs->mdr;
175 *flags &= ~SINGLESTEP_PCREL;
176 *flags |= SINGLESTEP_BRANCH;
177 break;
178
179 /* RET */
180 case 0xdf:
181 sp += pc[2];
182 READ_WORD32(sp, &x32);
183 next = (u8 *)x32;
184 *flags &= ~SINGLESTEP_PCREL;
185 *flags |= SINGLESTEP_BRANCH;
186 break;
187
188 case 0xf0:
189 next = pc + 2;
190 opc = pc[1];
191 if (opc >= 0xf0 && opc <= 0xf7) {
192 /* JMP (An) / CALLS (An) */
193 switch (opc & 3) {
194 case 0:
195 next = (u8 *)regs->a0;
196 break;
197 case 1:
198 next = (u8 *)regs->a1;
199 break;
200 case 2:
201 next = (u8 *)regs->a2;
202 break;
203 case 3:
204 next = (u8 *)regs->a3;
205 break;
206 }
207 *flags &= ~SINGLESTEP_PCREL;
208 *flags |= SINGLESTEP_BRANCH;
209 } else if (opc == 0xfc) {
210 /* RETS */
211 READ_WORD32(sp, &x32);
212 next = (u8 *)x32;
213 *flags &= ~SINGLESTEP_PCREL;
214 *flags |= SINGLESTEP_BRANCH;
215 } else if (opc == 0xfd) {
216 /* RTI */
217 READ_WORD32(sp + 4, &x32);
218 next = (u8 *)x32;
219 *flags &= ~SINGLESTEP_PCREL;
220 *flags |= SINGLESTEP_BRANCH;
221 }
222 break;
223
224 /* potential 3-byte conditional branches */
225 case 0xf8:
226 next = pc + 3;
227 opc = pc[1];
228 if (opc >= 0xe8 && opc <= 0xeb &&
229 (cond_table[regs->epsw & 0xf] &
230 (1 << ((opc & 0xf) + 3)))
231 ) {
232 READ_BYTE(pc+2, &x8);
233 next = pc + x8;
234 *flags |= SINGLESTEP_BRANCH;
235 }
236 break;
237
238 case 0xfa:
239 if (pc[1] == 0xff) {
240 /* CALLS (d16,PC) */
241 READ_WORD16(pc + 2, &x16);
242 next = pc + x16;
243 } else
244 next = pc + 4;
245 *flags |= SINGLESTEP_BRANCH;
246 break;
247
248 case 0xfc:
249 x32 = 6;
250 if (pc[1] == 0xff) {
251 /* CALLS (d32,PC) */
252 READ_WORD32(pc + 2, &x32);
253 }
254 next = pc + x32;
255 *flags |= SINGLESTEP_BRANCH;
256 break;
257 /* LXX (d8,PC) */
258 /* SETLB - loads the next four bytes into the LIR reg */
259 case 0xd0 ... 0xda:
260 case 0xdb:
261 panic("Can't singlestep Lxx/SETLB\n");
262 break;
263 }
264 }
265 return (unsigned)next;
266
267}
268
269/*
270 * set up out of place singlestep of some branching instructions
271 */
272static unsigned __kprobes singlestep_branch_setup(struct pt_regs *regs)
273{
274 u8 opc, *pc, *sp, *next;
275
276 next = NULL;
277 pc = (u8 *) regs->pc;
278 sp = (u8 *) (regs + 1);
279
280 switch (pc[0]) {
281 case 0xc0 ... 0xca: /* Bxx (d8,PC) */
282 case 0xcc: /* JMP (d16,PC) */
283 case 0xdc: /* JMP (d32,PC) */
284 case 0xf8: /* Bxx (d8,PC) 3-byte version */
285 /* don't really need to do anything except cause trap */
286 next = pc;
287 break;
288
289 case 0xcd: /* CALL (d16,PC) */
290 pc[1] = 5;
291 pc[2] = 0;
292 next = pc + 5;
293 break;
294
295 case 0xdd: /* CALL (d32,PC) */
296 pc[1] = 7;
297 pc[2] = 0;
298 pc[3] = 0;
299 pc[4] = 0;
300 next = pc + 7;
301 break;
302
303 case 0xde: /* RETF */
304 next = pc + 3;
305 regs->mdr = (unsigned) next;
306 break;
307
308 case 0xdf: /* RET */
309 sp += pc[2];
310 next = pc + 3;
311 *(unsigned *)sp = (unsigned) next;
312 break;
313
314 case 0xf0:
315 next = pc + 2;
316 opc = pc[1];
317 if (opc >= 0xf0 && opc <= 0xf3) {
318 /* CALLS (An) */
319 /* use CALLS (d16,PC) to avoid mucking with An */
320 pc[0] = 0xfa;
321 pc[1] = 0xff;
322 pc[2] = 4;
323 pc[3] = 0;
324 next = pc + 4;
325 } else if (opc >= 0xf4 && opc <= 0xf7) {
326 /* JMP (An) */
327 next = pc;
328 } else if (opc == 0xfc) {
329 /* RETS */
330 next = pc + 2;
331 *(unsigned *) sp = (unsigned) next;
332 } else if (opc == 0xfd) {
333 /* RTI */
334 next = pc + 2;
335 *(unsigned *)(sp + 4) = (unsigned) next;
336 }
337 break;
338
339 case 0xfa: /* CALLS (d16,PC) */
340 pc[2] = 4;
341 pc[3] = 0;
342 next = pc + 4;
343 break;
344
345 case 0xfc: /* CALLS (d32,PC) */
346 pc[2] = 6;
347 pc[3] = 0;
348 pc[4] = 0;
349 pc[5] = 0;
350 next = pc + 6;
351 break;
352
353 case 0xd0 ... 0xda: /* LXX (d8,PC) */
354 case 0xdb: /* SETLB */
355 panic("Can't singlestep Lxx/SETLB\n");
356 }
357
358 return (unsigned) next;
359}
360
361int __kprobes arch_prepare_kprobe(struct kprobe *p)
362{
363 return 0;
364}
365
366void __kprobes arch_copy_kprobe(struct kprobe *p)
367{
368 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
369}
370
371void __kprobes arch_arm_kprobe(struct kprobe *p)
372{
373 *p->addr = BREAKPOINT_INSTRUCTION;
374 flush_icache_range((unsigned long) p->addr,
375 (unsigned long) p->addr + sizeof(kprobe_opcode_t));
376}
377
378void __kprobes arch_disarm_kprobe(struct kprobe *p)
379{
380 mn10300_dcache_flush();
381 mn10300_icache_inv();
382}
383
384void arch_remove_kprobe(struct kprobe *p)
385{
386}
387
388static inline
389void __kprobes disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
390{
391 *p->addr = p->opcode;
392 regs->pc = (unsigned long) p->addr;
393 mn10300_dcache_flush();
394 mn10300_icache_inv();
395}
396
397static inline
398void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
399{
400 unsigned long nextpc;
401
402 current_kprobe_orig_pc = regs->pc;
403 memcpy(current_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE);
404 regs->pc = (unsigned long) current_kprobe_ss_buf;
405
406 nextpc = find_nextpc(regs, &current_kprobe_ss_flags);
407 if (current_kprobe_ss_flags & SINGLESTEP_PCREL)
408 current_kprobe_next_pc =
409 current_kprobe_orig_pc + (nextpc - regs->pc);
410 else
411 current_kprobe_next_pc = nextpc;
412
413 /* branching instructions need special handling */
414 if (current_kprobe_ss_flags & SINGLESTEP_BRANCH)
415 nextpc = singlestep_branch_setup(regs);
416
417 current_kprobe_bp_addr = nextpc;
418
419 *(u8 *) nextpc = BREAKPOINT_INSTRUCTION;
420 mn10300_dcache_flush_range2((unsigned) current_kprobe_ss_buf,
421 sizeof(current_kprobe_ss_buf));
422 mn10300_icache_inv();
423}
424
425static inline int __kprobes kprobe_handler(struct pt_regs *regs)
426{
427 struct kprobe *p;
428 int ret = 0;
429 unsigned int *addr = (unsigned int *) regs->pc;
430
431 /* We're in an interrupt, but this is clear and BUG()-safe. */
432 preempt_disable();
433
434 /* Check we're not actually recursing */
435 if (kprobe_running()) {
436 /* We *are* holding lock here, so this is safe.
437 Disarm the probe we just hit, and ignore it. */
438 p = get_kprobe(addr);
439 if (p) {
440 disarm_kprobe(p, regs);
441 ret = 1;
442 } else {
443 p = current_kprobe;
444 if (p->break_handler && p->break_handler(p, regs))
445 goto ss_probe;
446 }
447 /* If it's not ours, can't be delete race, (we hold lock). */
448 goto no_kprobe;
449 }
450
451 p = get_kprobe(addr);
452 if (!p) {
453 if (*addr != BREAKPOINT_INSTRUCTION) {
454 /* The breakpoint instruction was removed right after
455 * we hit it. Another cpu has removed either a
456 * probepoint or a debugger breakpoint at this address.
457 * In either case, no further handling of this
458 * interrupt is appropriate.
459 */
460 ret = 1;
461 }
462 /* Not one of ours: let kernel handle it */
463 goto no_kprobe;
464 }
465
466 kprobe_status = KPROBE_HIT_ACTIVE;
467 current_kprobe = p;
468 if (p->pre_handler(p, regs)) {
469 /* handler has already set things up, so skip ss setup */
470 return 1;
471 }
472
473ss_probe:
474 prepare_singlestep(p, regs);
475 kprobe_status = KPROBE_HIT_SS;
476 return 1;
477
478no_kprobe:
479 preempt_enable_no_resched();
480 return ret;
481}
482
483/*
484 * Called after single-stepping. p->addr is the address of the
485 * instruction whose first byte has been replaced by the "breakpoint"
486 * instruction. To avoid the SMP problems that can occur when we
487 * temporarily put back the original opcode to single-step, we
488 * single-stepped a copy of the instruction. The address of this
489 * copy is p->ainsn.insn.
490 */
491static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
492{
493 /* we may need to fixup regs/stack after singlestepping a call insn */
494 if (current_kprobe_ss_flags & SINGLESTEP_BRANCH) {
495 regs->pc = current_kprobe_orig_pc;
496 switch (p->ainsn.insn[0]) {
497 case 0xcd: /* CALL (d16,PC) */
498 *(unsigned *) regs->sp = regs->mdr = regs->pc + 5;
499 break;
500 case 0xdd: /* CALL (d32,PC) */
501 /* fixup mdr and return address on stack */
502 *(unsigned *) regs->sp = regs->mdr = regs->pc + 7;
503 break;
504 case 0xf0:
505 if (p->ainsn.insn[1] >= 0xf0 &&
506 p->ainsn.insn[1] <= 0xf3) {
507 /* CALLS (An) */
508 /* fixup MDR and return address on stack */
509 regs->mdr = regs->pc + 2;
510 *(unsigned *) regs->sp = regs->mdr;
511 }
512 break;
513
514 case 0xfa: /* CALLS (d16,PC) */
515 /* fixup MDR and return address on stack */
516 *(unsigned *) regs->sp = regs->mdr = regs->pc + 4;
517 break;
518
519 case 0xfc: /* CALLS (d32,PC) */
520 /* fixup MDR and return address on stack */
521 *(unsigned *) regs->sp = regs->mdr = regs->pc + 6;
522 break;
523 }
524 }
525
526 regs->pc = current_kprobe_next_pc;
527 current_kprobe_bp_addr = 0;
528}
529
530static inline int __kprobes post_kprobe_handler(struct pt_regs *regs)
531{
532 if (!kprobe_running())
533 return 0;
534
535 if (current_kprobe->post_handler)
536 current_kprobe->post_handler(current_kprobe, regs, 0);
537
538 resume_execution(current_kprobe, regs);
539 reset_current_kprobe();
540 preempt_enable_no_resched();
541 return 1;
542}
543
544/* Interrupts disabled, kprobe_lock held. */
545static inline
546int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
547{
548 if (current_kprobe->fault_handler &&
549 current_kprobe->fault_handler(current_kprobe, regs, trapnr))
550 return 1;
551
552 if (kprobe_status & KPROBE_HIT_SS) {
553 resume_execution(current_kprobe, regs);
554 reset_current_kprobe();
555 preempt_enable_no_resched();
556 }
557 return 0;
558}
559
560/*
561 * Wrapper routine to for handling exceptions.
562 */
563int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
564 unsigned long val, void *data)
565{
566 struct die_args *args = data;
567
568 switch (val) {
569 case DIE_BREAKPOINT:
570 if (current_kprobe_bp_addr != args->regs->pc) {
571 if (kprobe_handler(args->regs))
572 return NOTIFY_STOP;
573 } else {
574 if (post_kprobe_handler(args->regs))
575 return NOTIFY_STOP;
576 }
577 break;
578 case DIE_GPF:
579 if (kprobe_running() &&
580 kprobe_fault_handler(args->regs, args->trapnr))
581 return NOTIFY_STOP;
582 break;
583 default:
584 break;
585 }
586 return NOTIFY_DONE;
587}
588
589/* Jprobes support. */
590static struct pt_regs jprobe_saved_regs;
591static struct pt_regs *jprobe_saved_regs_location;
592static kprobe_opcode_t jprobe_saved_stack[MAX_STACK_SIZE];
593
594int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
595{
596 struct jprobe *jp = container_of(p, struct jprobe, kp);
597
598 jprobe_saved_regs_location = regs;
599 memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
600
601 /* Save a whole stack frame, this gets arguments
602 * pushed onto the stack after using up all the
603 * arg registers.
604 */
605 memcpy(&jprobe_saved_stack, regs + 1, sizeof(jprobe_saved_stack));
606
607 /* setup return addr to the jprobe handler routine */
608 regs->pc = (unsigned long) jp->entry;
609 return 1;
610}
611
612void __kprobes jprobe_return(void)
613{
614 void *orig_sp = jprobe_saved_regs_location + 1;
615
616 preempt_enable_no_resched();
617 asm volatile(" mov %0,sp\n"
618 ".globl jprobe_return_bp_addr\n"
619 "jprobe_return_bp_addr:\n\t"
620 " .byte 0xff\n"
621 : : "d" (orig_sp));
622}
623
624extern void jprobe_return_bp_addr(void);
625
626int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
627{
628 u8 *addr = (u8 *) regs->pc;
629
630 if (addr == (u8 *) jprobe_return_bp_addr) {
631 if (jprobe_saved_regs_location != regs) {
632 printk(KERN_ERR"JPROBE:"
633 " Current regs (%p) does not match saved regs"
634 " (%p).\n",
635 regs, jprobe_saved_regs_location);
636 BUG();
637 }
638
639 /* Restore old register state.
640 */
641 memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
642
643 memcpy(regs + 1, &jprobe_saved_stack,
644 sizeof(jprobe_saved_stack));
645 return 1;
646 }
647 return 0;
648}
649
650int __init arch_init_kprobes(void)
651{
652 return 0;
653}
diff --git a/arch/mn10300/kernel/kthread.S b/arch/mn10300/kernel/kthread.S
new file mode 100644
index 000000000000..b5ae467ac5ec
--- /dev/null
+++ b/arch/mn10300/kernel/kthread.S
@@ -0,0 +1,31 @@
1/* MN10300 Kernel thread trampoline function
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by Mark Salter (msalter@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11 .text
12
13###############################################################################
14#
15# kernel_thread_helper - trampoline for kernel_thread()
16#
17# On entry:
18# A2 = address of function to call
19# D2 = function argument
20#
21###############################################################################
22 .globl kernel_thread_helper
23 .type kernel_thread_helper,@function
24kernel_thread_helper:
25 mov do_exit,d1
26 mov d1,(sp)
27 mov d1,mdr
28 mov d2,d0
29 jmp (a2)
30
31 .size kernel_thread_helper,.-kernel_thread_helper
diff --git a/arch/mn10300/kernel/mn10300-debug.c b/arch/mn10300/kernel/mn10300-debug.c
new file mode 100644
index 000000000000..bd8196478cbc
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-debug.c
@@ -0,0 +1,58 @@
1/* Debugging stuff for the MN10300-based processors
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sched.h>
12#include <asm/serial-regs.h>
13
14#undef MN10300_CONSOLE_ON_SERIO
15
16/*
17 * write a string directly through one of the serial ports on-board the MN10300
18 */
19#ifdef MN10300_CONSOLE_ON_SERIO
20void debug_to_serial_mnser(const char *p, int n)
21{
22 char ch;
23
24 for (; n > 0; n--) {
25 ch = *p++;
26
27#if MN10300_CONSOLE_ON_SERIO == 0
28 while (SC0STR & (SC01STR_TBF)) continue;
29 SC0TXB = ch;
30 while (SC0STR & (SC01STR_TBF)) continue;
31 if (ch == 0x0a) {
32 SC0TXB = 0x0d;
33 while (SC0STR & (SC01STR_TBF)) continue;
34 }
35
36#elif MN10300_CONSOLE_ON_SERIO == 1
37 while (SC1STR & (SC01STR_TBF)) continue;
38 SC1TXB = ch;
39 while (SC1STR & (SC01STR_TBF)) continue;
40 if (ch == 0x0a) {
41 SC1TXB = 0x0d;
42 while (SC1STR & (SC01STR_TBF)) continue;
43 }
44
45#elif MN10300_CONSOLE_ON_SERIO == 2
46 while (SC2STR & (SC2STR_TBF)) continue;
47 SC2TXB = ch;
48 while (SC2STR & (SC2STR_TBF)) continue;
49 if (ch == 0x0a) {
50 SC2TXB = 0x0d;
51 while (SC2STR & (SC2STR_TBF)) continue;
52 }
53
54#endif
55 }
56}
57#endif
58
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S
new file mode 100644
index 000000000000..ef3f4c1df2a4
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial-low.S
@@ -0,0 +1,191 @@
1###############################################################################
2#
3# Virtual DMA driver for MN10300 serial ports
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/page.h>
17#include <asm/smp.h>
18#include <asm/cpu-regs.h>
19#include <asm/frame.inc>
20#include <asm/timer-regs.h>
21#include <asm/proc/cache.h>
22#include <asm/unit/timex.h>
23#include "mn10300-serial.h"
24
25#define SCxCTR 0x00
26#define SCxICR 0x04
27#define SCxTXB 0x08
28#define SCxRXB 0x09
29#define SCxSTR 0x0c
30#define SCxTIM 0x0d
31
32 .text
33
34###############################################################################
35#
36# serial port interrupt virtual DMA entry point
37# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
38#
39###############################################################################
40 .balign L1_CACHE_BYTES
41ENTRY(mn10300_serial_vdma_interrupt)
42 or EPSW_IE,psw # permit overriding by
43 # debugging interrupts
44 movm [d2,d3,a2,a3,exreg0],(sp)
45
46 movhu (IAGR),a2 # see if which interrupt is
47 # pending
48 and IAGR_GN,a2
49 add a2,a2
50 add mn10300_serial_int_tbl,a2
51
52 mov (a2+),a3
53 mov (__iobase,a3),e2
54 mov (a2),a2
55 jmp (a2)
56
57###############################################################################
58#
59# serial port receive interrupt virtual DMA entry point
60# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
61# - stores data/status byte pairs in the ring buffer
62# - induces a scheduler tick timer interrupt when done, which we then subvert
63# on entry:
64# A3 struct mn10300_serial_port *
65# E2 I/O port base
66#
67###############################################################################
68ENTRY(mn10300_serial_vdma_rx_handler)
69 mov (__rx_icr,a3),e3
70 mov GxICR_DETECT,d2
71 movbu d2,(e3) # ACK the interrupt
72 movhu (e3),d2 # flush
73
74 mov (__rx_inp,a3),d3
75 mov d3,a2
76 add 2,d3
77 and MNSC_BUFFER_SIZE-1,d3
78 mov (__rx_outp,a3),d2
79 cmp d3,d2
80 beq mnsc_vdma_rx_overflow
81
82 mov (__rx_buffer,a3),d2
83 add d2,a2
84 movhu (SCxSTR,e2),d2
85 movbu d2,(1,a2)
86 movbu (SCxRXB,e2),d2
87 movbu d2,(a2)
88 mov d3,(__rx_inp,a3)
89 bset MNSCx_RX_AVAIL,(__intr_flags,a3)
90
91mnsc_vdma_rx_done:
92 mov (__tm_icr,a3),a2
93 mov GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
94 movhu d2,(a2) # request a slow interrupt
95 movhu (a2),d2 # flush
96
97 movm (sp),[d2,d3,a2,a3,exreg0]
98 rti
99
100mnsc_vdma_rx_overflow:
101 bset MNSCx_RX_OVERF,(__intr_flags,a3)
102 bra mnsc_vdma_rx_done
103
104###############################################################################
105#
106# serial port transmit interrupt virtual DMA entry point
107# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
108# - retrieves data bytes from the ring buffer and passes them to the serial port
109# - induces a scheduler tick timer interrupt when done, which we then subvert
110# A3 struct mn10300_serial_port *
111# E2 I/O port base
112#
113###############################################################################
114 .balign L1_CACHE_BYTES
115ENTRY(mn10300_serial_vdma_tx_handler)
116 mov (__tx_icr,a3),e3
117 mov GxICR_DETECT,d2
118 movbu d2,(e3) # ACK the interrupt
119 movhu (e3),d2 # flush
120
121 btst 0x01,(__tx_break,a3) # handle transmit break request
122 bne mnsc_vdma_tx_break
123
124 movbu (SCxSTR,e2),d2 # don't try and transmit a char if the
125 # buffer is not empty
126 btst SC01STR_TBF,d2 # (may have tried to jumpstart)
127 bne mnsc_vdma_tx_noint
128
129 movbu (__tx_xchar,a3),d2 # handle hi-pri XON/XOFF
130 or d2,d2
131 bne mnsc_vdma_tx_xchar
132
133 mov (__tx_info_buffer,a3),a2 # get the uart_info struct for Tx
134 mov (__xmit_tail,a2),d3
135 mov (__xmit_head,a2),d2
136 cmp d3,d2
137 beq mnsc_vdma_tx_empty
138
139 mov (__xmit_buffer,a2),d2 # get a char from the buffer and
140 # transmit it
141 movbu (d3,d2),d2
142 movbu d2,(SCxTXB,e2) # Tx
143
144 inc d3 # advance the buffer pointer
145 and __UART_XMIT_SIZE-1,d3
146 mov (__xmit_head,a2),d2
147 mov d3,(__xmit_tail,a2)
148
149 sub d3,d2 # see if we've written everything
150 beq mnsc_vdma_tx_empty
151
152 and __UART_XMIT_SIZE-1,d2 # see if we just made a hole
153 cmp __UART_XMIT_SIZE-2,d2
154 beq mnsc_vdma_tx_made_hole
155
156mnsc_vdma_tx_done:
157 mov (__tm_icr,a3),a2
158 mov GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
159 movhu d2,(a2) # request a slow interrupt
160 movhu (a2),d2 # flush
161
162mnsc_vdma_tx_noint:
163 movm (sp),[d2,d3,a2,a3,exreg0]
164 rti
165
166mnsc_vdma_tx_empty:
167 mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
168 movhu d2,(e3) # disable the interrupt
169 movhu (e3),d2 # flush
170
171 bset MNSCx_TX_EMPTY,(__intr_flags,a3)
172 bra mnsc_vdma_tx_done
173
174mnsc_vdma_tx_break:
175 movhu (SCxCTR,e2),d2 # turn on break mode
176 or SC01CTR_BKE,d2
177 movhu d2,(SCxCTR,e2)
178 mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
179 movhu d2,(e3) # disable transmit interrupts on this
180 # channel
181 movhu (e3),d2 # flush
182 bra mnsc_vdma_tx_noint
183
184mnsc_vdma_tx_xchar:
185 bclr 0xff,(__tx_xchar,a3)
186 movbu d2,(SCxTXB,e2)
187 bra mnsc_vdma_tx_done
188
189mnsc_vdma_tx_made_hole:
190 bset MNSCx_TX_SPACE,(__intr_flags,a3)
191 bra mnsc_vdma_tx_done
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
new file mode 100644
index 000000000000..b9c268c6b2fb
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -0,0 +1,1480 @@
1/* MN10300 On-chip serial port UART driver
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12static const char serial_name[] = "MN10300 Serial driver";
13static const char serial_version[] = "mn10300_serial-1.0";
14static const char serial_revdate[] = "2007-11-06";
15
16#if defined(CONFIG_MN10300_TTYSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
17#define SUPPORT_SYSRQ
18#endif
19
20#include <linux/version.h>
21#include <linux/module.h>
22#include <linux/serial.h>
23#include <linux/circ_buf.h>
24#include <linux/errno.h>
25#include <linux/signal.h>
26#include <linux/sched.h>
27#include <linux/timer.h>
28#include <linux/interrupt.h>
29#include <linux/tty.h>
30#include <linux/tty_flip.h>
31#include <linux/major.h>
32#include <linux/string.h>
33#include <linux/ioport.h>
34#include <linux/mm.h>
35#include <linux/slab.h>
36#include <linux/init.h>
37#include <linux/console.h>
38#include <linux/sysrq.h>
39
40#include <asm/system.h>
41#include <asm/io.h>
42#include <asm/irq.h>
43#include <asm/bitops.h>
44#include <asm/serial-regs.h>
45#include <asm/unit/timex.h>
46#include "mn10300-serial.h"
47
48static inline __attribute__((format(printf, 1, 2)))
49void no_printk(const char *fmt, ...)
50{
51}
52
53#define kenter(FMT, ...) \
54 printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
55#define _enter(FMT, ...) \
56 no_printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
57#define kdebug(FMT, ...) \
58 printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__)
59#define _debug(FMT, ...) \
60 no_printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__)
61#define kproto(FMT, ...) \
62 printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
63#define _proto(FMT, ...) \
64 no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
65
66#define NR_UARTS 3
67
68#ifdef CONFIG_MN10300_TTYSM_CONSOLE
69static void mn10300_serial_console_write(struct console *co,
70 const char *s, unsigned count);
71static int __init mn10300_serial_console_setup(struct console *co,
72 char *options);
73
74static struct uart_driver mn10300_serial_driver;
75static struct console mn10300_serial_console = {
76 .name = "ttySM",
77 .write = mn10300_serial_console_write,
78 .device = uart_console_device,
79 .setup = mn10300_serial_console_setup,
80 .flags = CON_PRINTBUFFER,
81 .index = -1,
82 .data = &mn10300_serial_driver,
83};
84#endif
85
86static struct uart_driver mn10300_serial_driver = {
87 .owner = NULL,
88 .driver_name = "mn10300-serial",
89 .dev_name = "ttySM",
90 .major = TTY_MAJOR,
91 .minor = 128,
92 .nr = NR_UARTS,
93#ifdef CONFIG_MN10300_TTYSM_CONSOLE
94 .cons = &mn10300_serial_console,
95#endif
96};
97
98static unsigned int mn10300_serial_tx_empty(struct uart_port *);
99static void mn10300_serial_set_mctrl(struct uart_port *, unsigned int mctrl);
100static unsigned int mn10300_serial_get_mctrl(struct uart_port *);
101static void mn10300_serial_stop_tx(struct uart_port *);
102static void mn10300_serial_start_tx(struct uart_port *);
103static void mn10300_serial_send_xchar(struct uart_port *, char ch);
104static void mn10300_serial_stop_rx(struct uart_port *);
105static void mn10300_serial_enable_ms(struct uart_port *);
106static void mn10300_serial_break_ctl(struct uart_port *, int ctl);
107static int mn10300_serial_startup(struct uart_port *);
108static void mn10300_serial_shutdown(struct uart_port *);
109static void mn10300_serial_set_termios(struct uart_port *,
110 struct ktermios *new,
111 struct ktermios *old);
112static const char *mn10300_serial_type(struct uart_port *);
113static void mn10300_serial_release_port(struct uart_port *);
114static int mn10300_serial_request_port(struct uart_port *);
115static void mn10300_serial_config_port(struct uart_port *, int);
116static int mn10300_serial_verify_port(struct uart_port *,
117 struct serial_struct *);
118
119static const struct uart_ops mn10300_serial_ops = {
120 .tx_empty = mn10300_serial_tx_empty,
121 .set_mctrl = mn10300_serial_set_mctrl,
122 .get_mctrl = mn10300_serial_get_mctrl,
123 .stop_tx = mn10300_serial_stop_tx,
124 .start_tx = mn10300_serial_start_tx,
125 .send_xchar = mn10300_serial_send_xchar,
126 .stop_rx = mn10300_serial_stop_rx,
127 .enable_ms = mn10300_serial_enable_ms,
128 .break_ctl = mn10300_serial_break_ctl,
129 .startup = mn10300_serial_startup,
130 .shutdown = mn10300_serial_shutdown,
131 .set_termios = mn10300_serial_set_termios,
132 .type = mn10300_serial_type,
133 .release_port = mn10300_serial_release_port,
134 .request_port = mn10300_serial_request_port,
135 .config_port = mn10300_serial_config_port,
136 .verify_port = mn10300_serial_verify_port,
137};
138
139static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
140
141/*
142 * the first on-chip serial port: ttySM0 (aka SIF0)
143 */
144#ifdef CONFIG_MN10300_TTYSM0
145struct mn10300_serial_port mn10300_serial_port_sif0 = {
146 .uart.ops = &mn10300_serial_ops,
147 .uart.membase = (void __iomem *) &SC0CTR,
148 .uart.mapbase = (unsigned long) &SC0CTR,
149 .uart.iotype = UPIO_MEM,
150 .uart.irq = 0,
151 .uart.uartclk = 0, /* MN10300_IOCLK, */
152 .uart.fifosize = 1,
153 .uart.flags = UPF_BOOT_AUTOCONF,
154 .uart.line = 0,
155 .uart.type = PORT_MN10300,
156 .uart.lock =
157 __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif0.uart.lock),
158 .name = "ttySM0",
159 ._iobase = &SC0CTR,
160 ._control = &SC0CTR,
161 ._status = (volatile u8 *) &SC0STR,
162 ._intr = &SC0ICR,
163 ._rxb = &SC0RXB,
164 ._txb = &SC0TXB,
165 .rx_name = "ttySM0/Rx",
166 .tx_name = "ttySM0/Tx",
167#ifdef CONFIG_MN10300_TTYSM0_TIMER8
168 .tm_name = "ttySM0/Timer8",
169 ._tmxmd = &TM8MD,
170 ._tmxbr = &TM8BR,
171 ._tmicr = &TM8ICR,
172 .tm_irq = TM8IRQ,
173 .div_timer = MNSCx_DIV_TIMER_16BIT,
174#else /* CONFIG_MN10300_TTYSM0_TIMER2 */
175 .tm_name = "ttySM0/Timer2",
176 ._tmxmd = &TM2MD,
177 ._tmxbr = (volatile u16 *) &TM2BR,
178 ._tmicr = &TM2ICR,
179 .tm_irq = TM2IRQ,
180 .div_timer = MNSCx_DIV_TIMER_8BIT,
181#endif
182 .rx_irq = SC0RXIRQ,
183 .tx_irq = SC0TXIRQ,
184 .rx_icr = &GxICR(SC0RXIRQ),
185 .tx_icr = &GxICR(SC0TXIRQ),
186 .clock_src = MNSCx_CLOCK_SRC_IOCLK,
187 .options = 0,
188#ifdef CONFIG_GDBSTUB_ON_TTYSM0
189 .gdbstub = 1,
190#endif
191};
192#endif /* CONFIG_MN10300_TTYSM0 */
193
194/*
195 * the second on-chip serial port: ttySM1 (aka SIF1)
196 */
197#ifdef CONFIG_MN10300_TTYSM1
198struct mn10300_serial_port mn10300_serial_port_sif1 = {
199 .uart.ops = &mn10300_serial_ops,
200 .uart.membase = (void __iomem *) &SC1CTR,
201 .uart.mapbase = (unsigned long) &SC1CTR,
202 .uart.iotype = UPIO_MEM,
203 .uart.irq = 0,
204 .uart.uartclk = 0, /* MN10300_IOCLK, */
205 .uart.fifosize = 1,
206 .uart.flags = UPF_BOOT_AUTOCONF,
207 .uart.line = 1,
208 .uart.type = PORT_MN10300,
209 .uart.lock =
210 __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif1.uart.lock),
211 .name = "ttySM1",
212 ._iobase = &SC1CTR,
213 ._control = &SC1CTR,
214 ._status = (volatile u8 *) &SC1STR,
215 ._intr = &SC1ICR,
216 ._rxb = &SC1RXB,
217 ._txb = &SC1TXB,
218 .rx_name = "ttySM1/Rx",
219 .tx_name = "ttySM1/Tx",
220#ifdef CONFIG_MN10300_TTYSM1_TIMER9
221 .tm_name = "ttySM1/Timer9",
222 ._tmxmd = &TM9MD,
223 ._tmxbr = &TM9BR,
224 ._tmicr = &TM9ICR,
225 .tm_irq = TM9IRQ,
226 .div_timer = MNSCx_DIV_TIMER_16BIT,
227#else /* CONFIG_MN10300_TTYSM1_TIMER3 */
228 .tm_name = "ttySM1/Timer3",
229 ._tmxmd = &TM3MD,
230 ._tmxbr = (volatile u16 *) &TM3BR,
231 ._tmicr = &TM3ICR,
232 .tm_irq = TM3IRQ,
233 .div_timer = MNSCx_DIV_TIMER_8BIT,
234#endif
235 .rx_irq = SC1RXIRQ,
236 .tx_irq = SC1TXIRQ,
237 .rx_icr = &GxICR(SC1RXIRQ),
238 .tx_icr = &GxICR(SC1TXIRQ),
239 .clock_src = MNSCx_CLOCK_SRC_IOCLK,
240 .options = 0,
241#ifdef CONFIG_GDBSTUB_ON_TTYSM1
242 .gdbstub = 1,
243#endif
244};
245#endif /* CONFIG_MN10300_TTYSM1 */
246
247/*
248 * the third on-chip serial port: ttySM2 (aka SIF2)
249 */
250#ifdef CONFIG_MN10300_TTYSM2
251struct mn10300_serial_port mn10300_serial_port_sif2 = {
252 .uart.ops = &mn10300_serial_ops,
253 .uart.membase = (void __iomem *) &SC2CTR,
254 .uart.mapbase = (unsigned long) &SC2CTR,
255 .uart.iotype = UPIO_MEM,
256 .uart.irq = 0,
257 .uart.uartclk = 0, /* MN10300_IOCLK, */
258 .uart.fifosize = 1,
259 .uart.flags = UPF_BOOT_AUTOCONF,
260 .uart.line = 2,
261#ifdef CONFIG_MN10300_TTYSM2_CTS
262 .uart.type = PORT_MN10300_CTS,
263#else
264 .uart.type = PORT_MN10300,
265#endif
266 .uart.lock =
267 __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock),
268 .name = "ttySM2",
269 .rx_name = "ttySM2/Rx",
270 .tx_name = "ttySM2/Tx",
271 .tm_name = "ttySM2/Timer10",
272 ._iobase = &SC2CTR,
273 ._control = &SC2CTR,
274 ._status = &SC2STR,
275 ._intr = &SC2ICR,
276 ._rxb = &SC2RXB,
277 ._txb = &SC2TXB,
278 ._tmxmd = &TM10MD,
279 ._tmxbr = &TM10BR,
280 ._tmicr = &TM10ICR,
281 .tm_irq = TM10IRQ,
282 .div_timer = MNSCx_DIV_TIMER_16BIT,
283 .rx_irq = SC2RXIRQ,
284 .tx_irq = SC2TXIRQ,
285 .rx_icr = &GxICR(SC2RXIRQ),
286 .tx_icr = &GxICR(SC2TXIRQ),
287 .clock_src = MNSCx_CLOCK_SRC_IOCLK,
288#ifdef CONFIG_MN10300_TTYSM2_CTS
289 .options = MNSCx_OPT_CTS,
290#else
291 .options = 0,
292#endif
293#ifdef CONFIG_GDBSTUB_ON_TTYSM2
294 .gdbstub = 1,
295#endif
296};
297#endif /* CONFIG_MN10300_TTYSM2 */
298
299
300/*
301 * list of available serial ports
302 */
303struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = {
304#ifdef CONFIG_MN10300_TTYSM0
305 [0] = &mn10300_serial_port_sif0,
306#endif
307#ifdef CONFIG_MN10300_TTYSM1
308 [1] = &mn10300_serial_port_sif1,
309#endif
310#ifdef CONFIG_MN10300_TTYSM2
311 [2] = &mn10300_serial_port_sif2,
312#endif
313 [NR_UARTS] = NULL,
314};
315
316
317/*
318 * we abuse the serial ports' baud timers' interrupt lines to get the ability
319 * to deliver interrupts to userspace as we use the ports' interrupt lines to
320 * do virtual DMA on account of the ports having no hardware FIFOs
321 *
322 * we can generate an interrupt manually in the assembly stubs by writing to
323 * the enable and detect bits in the interrupt control register, so all we need
324 * to do here is disable the interrupt line
325 *
326 * note that we can't just leave the line enabled as the baud rate timer *also*
327 * generates interrupts
328 */
329static void mn10300_serial_mask_ack(unsigned int irq)
330{
331 u16 tmp;
332 GxICR(irq) = GxICR_LEVEL_6;
333 tmp = GxICR(irq); /* flush write buffer */
334}
335
336static void mn10300_serial_nop(unsigned int irq)
337{
338}
339
340static struct irq_chip mn10300_serial_pic = {
341 .name = "mnserial",
342 .ack = mn10300_serial_mask_ack,
343 .mask = mn10300_serial_mask_ack,
344 .mask_ack = mn10300_serial_mask_ack,
345 .unmask = mn10300_serial_nop,
346 .end = mn10300_serial_nop,
347};
348
349
350/*
351 * serial virtual DMA interrupt jump table
352 */
353struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
354
355static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
356{
357 u16 x;
358 *port->tx_icr = GxICR_LEVEL_1 | GxICR_DETECT;
359 x = *port->tx_icr;
360}
361
362static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
363{
364 u16 x;
365 *port->tx_icr = GxICR_LEVEL_1 | GxICR_ENABLE;
366 x = *port->tx_icr;
367}
368
369static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
370{
371 u16 x;
372 *port->rx_icr = GxICR_LEVEL_1 | GxICR_DETECT;
373 x = *port->rx_icr;
374}
375
376/*
377 * multi-bit equivalent of test_and_clear_bit()
378 */
379static int mask_test_and_clear(volatile u8 *ptr, u8 mask)
380{
381 u32 epsw;
382 asm volatile(" bclr %1,(%2) \n"
383 " mov epsw,%0 \n"
384 : "=d"(epsw) : "d"(mask), "a"(ptr));
385 return !(epsw & EPSW_FLAG_Z);
386}
387
388/*
389 * receive chars from the ring buffer for this serial port
390 * - must do break detection here (not done in the UART)
391 */
392static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
393{
394 struct uart_icount *icount = &port->uart.icount;
395 struct tty_struct *tty = port->uart.info->tty;
396 unsigned ix;
397 int count;
398 u8 st, ch, push, status, overrun;
399
400 _enter("%s", port->name);
401
402 push = 0;
403
404 count = CIRC_CNT(port->rx_inp, port->rx_outp, MNSC_BUFFER_SIZE);
405 count = tty_buffer_request_room(tty, count);
406 if (count == 0) {
407 if (!tty->low_latency)
408 tty_flip_buffer_push(tty);
409 return;
410 }
411
412try_again:
413 /* pull chars out of the hat */
414 ix = port->rx_outp;
415 if (ix == port->rx_inp) {
416 if (push && !tty->low_latency)
417 tty_flip_buffer_push(tty);
418 return;
419 }
420
421 ch = port->rx_buffer[ix++];
422 st = port->rx_buffer[ix++];
423 smp_rmb();
424 port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
425 port->uart.icount.rx++;
426
427 st &= SC01STR_FEF | SC01STR_PEF | SC01STR_OEF;
428 status = 0;
429 overrun = 0;
430
431 /* the UART doesn't detect BREAK, so we have to do that ourselves
432 * - it starts as a framing error on a NUL character
433 * - then we count another two NUL characters before issuing TTY_BREAK
434 * - then we end on a normal char or one that has all the bottom bits
435 * zero and the top bits set
436 */
437 switch (port->rx_brk) {
438 case 0:
439 /* not breaking at the moment */
440 break;
441
442 case 1:
443 if (st & SC01STR_FEF && ch == 0) {
444 port->rx_brk = 2;
445 goto try_again;
446 }
447 goto not_break;
448
449 case 2:
450 if (st & SC01STR_FEF && ch == 0) {
451 port->rx_brk = 3;
452 _proto("Rx Break Detected");
453 icount->brk++;
454 if (uart_handle_break(&port->uart))
455 goto ignore_char;
456 status |= 1 << TTY_BREAK;
457 goto insert;
458 }
459 goto not_break;
460
461 default:
462 if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF))
463 goto try_again; /* still breaking */
464
465 port->rx_brk = 0; /* end of the break */
466
467 switch (ch) {
468 case 0xFF:
469 case 0xFE:
470 case 0xFC:
471 case 0xF8:
472 case 0xF0:
473 case 0xE0:
474 case 0xC0:
475 case 0x80:
476 case 0x00:
477 /* discard char at probable break end */
478 goto try_again;
479 }
480 break;
481 }
482
483process_errors:
484 /* handle framing error */
485 if (st & SC01STR_FEF) {
486 if (ch == 0) {
487 /* framing error with NUL char is probably a BREAK */
488 port->rx_brk = 1;
489 goto try_again;
490 }
491
492 _proto("Rx Framing Error");
493 icount->frame++;
494 status |= 1 << TTY_FRAME;
495 }
496
497 /* handle parity error */
498 if (st & SC01STR_PEF) {
499 _proto("Rx Parity Error");
500 icount->parity++;
501 status = TTY_PARITY;
502 }
503
504 /* handle normal char */
505 if (status == 0) {
506 if (uart_handle_sysrq_char(&port->uart, ch))
507 goto ignore_char;
508 status = (1 << TTY_NORMAL);
509 }
510
511 /* handle overrun error */
512 if (st & SC01STR_OEF) {
513 if (port->rx_brk)
514 goto try_again;
515
516 _proto("Rx Overrun Error");
517 icount->overrun++;
518 overrun = 1;
519 }
520
521insert:
522 status &= port->uart.read_status_mask;
523
524 if (!overrun && !(status & port->uart.ignore_status_mask)) {
525 int flag;
526
527 if (status & (1 << TTY_BREAK))
528 flag = TTY_BREAK;
529 else if (status & (1 << TTY_PARITY))
530 flag = TTY_PARITY;
531 else if (status & (1 << TTY_FRAME))
532 flag = TTY_FRAME;
533 else
534 flag = TTY_NORMAL;
535
536 tty_insert_flip_char(tty, ch, flag);
537 }
538
539 /* overrun is special, since it's reported immediately, and doesn't
540 * affect the current character
541 */
542 if (overrun)
543 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
544
545 count--;
546 if (count <= 0) {
547 if (!tty->low_latency)
548 tty_flip_buffer_push(tty);
549 return;
550 }
551
552ignore_char:
553 push = 1;
554 goto try_again;
555
556not_break:
557 port->rx_brk = 0;
558 goto process_errors;
559}
560
561/*
562 * handle an interrupt from the serial transmission "virtual DMA" driver
563 * - note: the interrupt routine will disable its own interrupts when the Tx
564 * buffer is empty
565 */
566static void mn10300_serial_transmit_interrupt(struct mn10300_serial_port *port)
567{
568 _enter("%s", port->name);
569
570 if (uart_tx_stopped(&port->uart) ||
571 uart_circ_empty(&port->uart.info->xmit))
572 mn10300_serial_dis_tx_intr(port);
573
574 if (uart_circ_chars_pending(&port->uart.info->xmit) < WAKEUP_CHARS)
575 uart_write_wakeup(&port->uart);
576}
577
578/*
579 * deal with a change in the status of the CTS line
580 */
581static void mn10300_serial_cts_changed(struct mn10300_serial_port *port, u8 st)
582{
583 u16 ctr;
584
585 port->tx_cts = st;
586 port->uart.icount.cts++;
587
588 /* flip the CTS state selector flag to interrupt when it changes
589 * back */
590 ctr = *port->_control;
591 ctr ^= SC2CTR_TWS;
592 *port->_control = ctr;
593
594 uart_handle_cts_change(&port->uart, st & SC2STR_CTS);
595 wake_up_interruptible(&port->uart.info->delta_msr_wait);
596}
597
598/*
599 * handle a virtual interrupt generated by the lower level "virtual DMA"
600 * routines (irq is the baud timer interrupt)
601 */
602static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id)
603{
604 struct mn10300_serial_port *port = dev_id;
605 u8 st;
606
607 spin_lock(&port->uart.lock);
608
609 if (port->intr_flags) {
610 _debug("INT %s: %x", port->name, port->intr_flags);
611
612 if (mask_test_and_clear(&port->intr_flags, MNSCx_RX_AVAIL))
613 mn10300_serial_receive_interrupt(port);
614
615 if (mask_test_and_clear(&port->intr_flags,
616 MNSCx_TX_SPACE | MNSCx_TX_EMPTY))
617 mn10300_serial_transmit_interrupt(port);
618 }
619
620 /* the only modem control line amongst the whole lot is CTS on
621 * serial port 2 */
622 if (port->type == PORT_MN10300_CTS) {
623 st = *port->_status;
624 if ((port->tx_cts ^ st) & SC2STR_CTS)
625 mn10300_serial_cts_changed(port, st);
626 }
627
628 spin_unlock(&port->uart.lock);
629
630 return IRQ_HANDLED;
631}
632
633/*
634 * return indication of whether the hardware transmit buffer is empty
635 */
636static unsigned int mn10300_serial_tx_empty(struct uart_port *_port)
637{
638 struct mn10300_serial_port *port =
639 container_of(_port, struct mn10300_serial_port, uart);
640
641 _enter("%s", port->name);
642
643 return (*port->_status & (SC01STR_TXF | SC01STR_TBF)) ?
644 0 : TIOCSER_TEMT;
645}
646
647/*
648 * set the modem control lines (we don't have any)
649 */
650static void mn10300_serial_set_mctrl(struct uart_port *_port,
651 unsigned int mctrl)
652{
653 struct mn10300_serial_port *port =
654 container_of(_port, struct mn10300_serial_port, uart);
655
656 _enter("%s,%x", port->name, mctrl);
657}
658
659/*
660 * get the modem control line statuses
661 */
662static unsigned int mn10300_serial_get_mctrl(struct uart_port *_port)
663{
664 struct mn10300_serial_port *port =
665 container_of(_port, struct mn10300_serial_port, uart);
666
667 _enter("%s", port->name);
668
669 if (port->type == PORT_MN10300_CTS && !(*port->_status & SC2STR_CTS))
670 return TIOCM_CAR | TIOCM_DSR;
671
672 return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR;
673}
674
675/*
676 * stop transmitting characters
677 */
678static void mn10300_serial_stop_tx(struct uart_port *_port)
679{
680 struct mn10300_serial_port *port =
681 container_of(_port, struct mn10300_serial_port, uart);
682
683 _enter("%s", port->name);
684
685 /* disable the virtual DMA */
686 mn10300_serial_dis_tx_intr(port);
687}
688
689/*
690 * start transmitting characters
691 * - jump-start transmission if it has stalled
692 * - enable the serial Tx interrupt (used by the virtual DMA controller)
693 * - force an interrupt to happen if necessary
694 */
695static void mn10300_serial_start_tx(struct uart_port *_port)
696{
697 struct mn10300_serial_port *port =
698 container_of(_port, struct mn10300_serial_port, uart);
699
700 u16 x;
701
702 _enter("%s{%lu}",
703 port->name,
704 CIRC_CNT(&port->uart.info->xmit.head,
705 &port->uart.info->xmit.tail,
706 UART_XMIT_SIZE));
707
708 /* kick the virtual DMA controller */
709 x = *port->tx_icr;
710 x |= GxICR_ENABLE;
711
712 if (*port->_status & SC01STR_TBF)
713 x &= ~(GxICR_REQUEST | GxICR_DETECT);
714 else
715 x |= GxICR_REQUEST | GxICR_DETECT;
716
717 _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
718 *port->_control, *port->_intr, *port->_status,
719 *port->_tmxmd, *port->_tmxbr, *port->tx_icr);
720
721 *port->tx_icr = x;
722 x = *port->tx_icr;
723}
724
725/*
726 * transmit a high-priority XON/XOFF character
727 */
728static void mn10300_serial_send_xchar(struct uart_port *_port, char ch)
729{
730 struct mn10300_serial_port *port =
731 container_of(_port, struct mn10300_serial_port, uart);
732
733 _enter("%s,%02x", port->name, ch);
734
735 if (likely(port->gdbstub)) {
736 port->tx_xchar = ch;
737 if (ch)
738 mn10300_serial_en_tx_intr(port);
739 }
740}
741
742/*
743 * stop receiving characters
744 * - called whilst the port is being closed
745 */
746static void mn10300_serial_stop_rx(struct uart_port *_port)
747{
748 struct mn10300_serial_port *port =
749 container_of(_port, struct mn10300_serial_port, uart);
750
751 u16 ctr;
752
753 _enter("%s", port->name);
754
755 ctr = *port->_control;
756 ctr &= ~SC01CTR_RXE;
757 *port->_control = ctr;
758
759 mn10300_serial_dis_rx_intr(port);
760}
761
762/*
763 * enable modem status interrupts
764 */
765static void mn10300_serial_enable_ms(struct uart_port *_port)
766{
767 struct mn10300_serial_port *port =
768 container_of(_port, struct mn10300_serial_port, uart);
769
770 u16 ctr, cts;
771
772 _enter("%s", port->name);
773
774 if (port->type == PORT_MN10300_CTS) {
775 /* want to interrupt when CTS goes low if CTS is now high and
776 * vice versa
777 */
778 port->tx_cts = *port->_status;
779
780 cts = (port->tx_cts & SC2STR_CTS) ?
781 SC2CTR_TWE : SC2CTR_TWE | SC2CTR_TWS;
782
783 ctr = *port->_control;
784 ctr &= ~SC2CTR_TWS;
785 ctr |= cts;
786 *port->_control = ctr;
787
788 mn10300_serial_en_tx_intr(port);
789 }
790}
791
792/*
793 * transmit or cease transmitting a break signal
794 */
795static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl)
796{
797 struct mn10300_serial_port *port =
798 container_of(_port, struct mn10300_serial_port, uart);
799
800 _enter("%s,%d", port->name, ctl);
801
802 if (ctl) {
803 /* tell the virtual DMA handler to assert BREAK */
804 port->tx_break = 1;
805 mn10300_serial_en_tx_intr(port);
806 } else {
807 port->tx_break = 0;
808 *port->_control &= ~SC01CTR_BKE;
809 mn10300_serial_en_tx_intr(port);
810 }
811}
812
813/*
814 * grab the interrupts and enable the port for reception
815 */
816static int mn10300_serial_startup(struct uart_port *_port)
817{
818 struct mn10300_serial_port *port =
819 container_of(_port, struct mn10300_serial_port, uart);
820 struct mn10300_serial_int *pint;
821
822 _enter("%s{%d}", port->name, port->gdbstub);
823
824 if (unlikely(port->gdbstub))
825 return -EBUSY;
826
827 /* allocate an Rx buffer for the virtual DMA handler */
828 port->rx_buffer = kmalloc(MNSC_BUFFER_SIZE, GFP_KERNEL);
829 if (!port->rx_buffer)
830 return -ENOMEM;
831
832 port->rx_inp = port->rx_outp = 0;
833
834 /* finally, enable the device */
835 *port->_intr = SC01ICR_TI;
836 *port->_control |= SC01CTR_TXE | SC01CTR_RXE;
837
838 pint = &mn10300_serial_int_tbl[port->rx_irq];
839 pint->port = port;
840 pint->vdma = mn10300_serial_vdma_rx_handler;
841 pint = &mn10300_serial_int_tbl[port->tx_irq];
842 pint->port = port;
843 pint->vdma = mn10300_serial_vdma_tx_handler;
844
845 set_intr_level(port->rx_irq, GxICR_LEVEL_1);
846 set_intr_level(port->tx_irq, GxICR_LEVEL_1);
847 set_irq_chip(port->tm_irq, &mn10300_serial_pic);
848
849 if (request_irq(port->rx_irq, mn10300_serial_interrupt,
850 IRQF_DISABLED, port->rx_name, port) < 0)
851 goto error;
852
853 if (request_irq(port->tx_irq, mn10300_serial_interrupt,
854 IRQF_DISABLED, port->tx_name, port) < 0)
855 goto error2;
856
857 if (request_irq(port->tm_irq, mn10300_serial_interrupt,
858 IRQF_DISABLED, port->tm_name, port) < 0)
859 goto error3;
860 mn10300_serial_mask_ack(port->tm_irq);
861
862 return 0;
863
864error3:
865 free_irq(port->tx_irq, port);
866error2:
867 free_irq(port->rx_irq, port);
868error:
869 kfree(port->rx_buffer);
870 port->rx_buffer = NULL;
871 return -EBUSY;
872}
873
874/*
875 * shutdown the port and release interrupts
876 */
877static void mn10300_serial_shutdown(struct uart_port *_port)
878{
879 struct mn10300_serial_port *port =
880 container_of(_port, struct mn10300_serial_port, uart);
881
882 _enter("%s", port->name);
883
884 /* disable the serial port and its baud rate timer */
885 port->tx_break = 0;
886 *port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
887 *port->_tmxmd = 0;
888
889 if (port->rx_buffer) {
890 void *buf = port->rx_buffer;
891 port->rx_buffer = NULL;
892 kfree(buf);
893 }
894
895 /* disable all intrs */
896 free_irq(port->tm_irq, port);
897 free_irq(port->rx_irq, port);
898 free_irq(port->tx_irq, port);
899
900 *port->rx_icr = GxICR_LEVEL_1;
901 *port->tx_icr = GxICR_LEVEL_1;
902}
903
904/*
905 * this routine is called to set the UART divisor registers to match the
906 * specified baud rate for a serial port.
907 */
908static void mn10300_serial_change_speed(struct mn10300_serial_port *port,
909 struct ktermios *new,
910 struct ktermios *old)
911{
912 unsigned long flags;
913 unsigned long ioclk = port->ioclk;
914 unsigned cflag;
915 int baud, bits, xdiv, tmp;
916 u16 tmxbr, scxctr;
917 u8 tmxmd, battempt;
918 u8 div_timer = port->div_timer;
919
920 _enter("%s{%lu}", port->name, ioclk);
921
922 /* byte size and parity */
923 cflag = new->c_cflag;
924 switch (cflag & CSIZE) {
925 case CS7: scxctr = SC01CTR_CLN_7BIT; bits = 9; break;
926 case CS8: scxctr = SC01CTR_CLN_8BIT; bits = 10; break;
927 default: scxctr = SC01CTR_CLN_8BIT; bits = 10; break;
928 }
929
930 if (cflag & CSTOPB) {
931 scxctr |= SC01CTR_STB_2BIT;
932 bits++;
933 }
934
935 if (cflag & PARENB) {
936 bits++;
937 if (cflag & PARODD)
938 scxctr |= SC01CTR_PB_ODD;
939#ifdef CMSPAR
940 else if (cflag & CMSPAR)
941 scxctr |= SC01CTR_PB_FIXED0;
942#endif
943 else
944 scxctr |= SC01CTR_PB_EVEN;
945 }
946
947 /* Determine divisor based on baud rate */
948 battempt = 0;
949
950 if (div_timer == MNSCx_DIV_TIMER_16BIT)
951 scxctr |= SC0CTR_CK_TM8UFLOW_8; /* ( == SC1CTR_CK_TM9UFLOW_8
952 * == SC2CTR_CK_TM10UFLOW) */
953 else if (div_timer == MNSCx_DIV_TIMER_8BIT)
954 scxctr |= SC0CTR_CK_TM2UFLOW_8;
955
956try_alternative:
957 baud = uart_get_baud_rate(&port->uart, new, old, 0,
958 port->ioclk / 8);
959
960 _debug("ALT %d [baud %d]", battempt, baud);
961
962 if (!baud)
963 baud = 9600; /* B0 transition handled in rs_set_termios */
964 xdiv = 1;
965 if (baud == 134) {
966 baud = 269; /* 134 is really 134.5 */
967 xdiv = 2;
968 }
969
970 if (baud == 38400 &&
971 (port->uart.flags & UPF_SPD_MASK) == UPF_SPD_CUST
972 ) {
973 _debug("CUSTOM %u", port->uart.custom_divisor);
974
975 if (div_timer == MNSCx_DIV_TIMER_16BIT) {
976 if (port->uart.custom_divisor <= 65535) {
977 tmxmd = TM8MD_SRC_IOCLK;
978 tmxbr = port->uart.custom_divisor;
979 port->uart.uartclk = ioclk;
980 goto timer_okay;
981 }
982 if (port->uart.custom_divisor / 8 <= 65535) {
983 tmxmd = TM8MD_SRC_IOCLK_8;
984 tmxbr = port->uart.custom_divisor / 8;
985 port->uart.custom_divisor = tmxbr * 8;
986 port->uart.uartclk = ioclk / 8;
987 goto timer_okay;
988 }
989 if (port->uart.custom_divisor / 32 <= 65535) {
990 tmxmd = TM8MD_SRC_IOCLK_32;
991 tmxbr = port->uart.custom_divisor / 32;
992 port->uart.custom_divisor = tmxbr * 32;
993 port->uart.uartclk = ioclk / 32;
994 goto timer_okay;
995 }
996
997 } else if (div_timer == MNSCx_DIV_TIMER_8BIT) {
998 if (port->uart.custom_divisor <= 255) {
999 tmxmd = TM2MD_SRC_IOCLK;
1000 tmxbr = port->uart.custom_divisor;
1001 port->uart.uartclk = ioclk;
1002 goto timer_okay;
1003 }
1004 if (port->uart.custom_divisor / 8 <= 255) {
1005 tmxmd = TM2MD_SRC_IOCLK_8;
1006 tmxbr = port->uart.custom_divisor / 8;
1007 port->uart.custom_divisor = tmxbr * 8;
1008 port->uart.uartclk = ioclk / 8;
1009 goto timer_okay;
1010 }
1011 if (port->uart.custom_divisor / 32 <= 255) {
1012 tmxmd = TM2MD_SRC_IOCLK_32;
1013 tmxbr = port->uart.custom_divisor / 32;
1014 port->uart.custom_divisor = tmxbr * 32;
1015 port->uart.uartclk = ioclk / 32;
1016 goto timer_okay;
1017 }
1018 }
1019 }
1020
1021 switch (div_timer) {
1022 case MNSCx_DIV_TIMER_16BIT:
1023 port->uart.uartclk = ioclk;
1024 tmxmd = TM8MD_SRC_IOCLK;
1025 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
1026 if (tmp > 0 && tmp <= 65535)
1027 goto timer_okay;
1028
1029 port->uart.uartclk = ioclk / 8;
1030 tmxmd = TM8MD_SRC_IOCLK_8;
1031 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
1032 if (tmp > 0 && tmp <= 65535)
1033 goto timer_okay;
1034
1035 port->uart.uartclk = ioclk / 32;
1036 tmxmd = TM8MD_SRC_IOCLK_32;
1037 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
1038 if (tmp > 0 && tmp <= 65535)
1039 goto timer_okay;
1040 break;
1041
1042 case MNSCx_DIV_TIMER_8BIT:
1043 port->uart.uartclk = ioclk;
1044 tmxmd = TM2MD_SRC_IOCLK;
1045 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
1046 if (tmp > 0 && tmp <= 255)
1047 goto timer_okay;
1048
1049 port->uart.uartclk = ioclk / 8;
1050 tmxmd = TM2MD_SRC_IOCLK_8;
1051 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
1052 if (tmp > 0 && tmp <= 255)
1053 goto timer_okay;
1054
1055 port->uart.uartclk = ioclk / 32;
1056 tmxmd = TM2MD_SRC_IOCLK_32;
1057 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
1058 if (tmp > 0 && tmp <= 255)
1059 goto timer_okay;
1060 break;
1061
1062 default:
1063 BUG();
1064 return;
1065 }
1066
1067 /* refuse to change to a baud rate we can't support */
1068 _debug("CAN'T SUPPORT");
1069
1070 switch (battempt) {
1071 case 0:
1072 if (old) {
1073 new->c_cflag &= ~CBAUD;
1074 new->c_cflag |= (old->c_cflag & CBAUD);
1075 battempt = 1;
1076 goto try_alternative;
1077 }
1078
1079 case 1:
1080 /* as a last resort, if the quotient is zero, default to 9600
1081 * bps */
1082 new->c_cflag &= ~CBAUD;
1083 new->c_cflag |= B9600;
1084 battempt = 2;
1085 goto try_alternative;
1086
1087 default:
1088 /* hmmm... can't seem to support 9600 either
1089 * - we could try iterating through the speeds we know about to
1090 * find the lowest
1091 */
1092 new->c_cflag &= ~CBAUD;
1093 new->c_cflag |= B0;
1094
1095 if (div_timer == MNSCx_DIV_TIMER_16BIT)
1096 tmxmd = TM8MD_SRC_IOCLK_32;
1097 else if (div_timer == MNSCx_DIV_TIMER_8BIT)
1098 tmxmd = TM2MD_SRC_IOCLK_32;
1099 tmxbr = 1;
1100
1101 port->uart.uartclk = ioclk / 32;
1102 break;
1103 }
1104timer_okay:
1105
1106 _debug("UARTCLK: %u / %hu", port->uart.uartclk, tmxbr);
1107
1108 /* make the changes */
1109 spin_lock_irqsave(&port->uart.lock, flags);
1110
1111 uart_update_timeout(&port->uart, new->c_cflag, baud);
1112
1113 /* set the timer to produce the required baud rate */
1114 switch (div_timer) {
1115 case MNSCx_DIV_TIMER_16BIT:
1116 *port->_tmxmd = 0;
1117 *port->_tmxbr = tmxbr;
1118 *port->_tmxmd = TM8MD_INIT_COUNTER;
1119 *port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
1120 break;
1121
1122 case MNSCx_DIV_TIMER_8BIT:
1123 *port->_tmxmd = 0;
1124 *(volatile u8 *) port->_tmxbr = (u8) tmxbr;
1125 *port->_tmxmd = TM2MD_INIT_COUNTER;
1126 *port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
1127 break;
1128 }
1129
1130 /* CTS flow control flag and modem status interrupts */
1131 scxctr &= ~(SC2CTR_TWE | SC2CTR_TWS);
1132
1133 if (port->type == PORT_MN10300_CTS && cflag & CRTSCTS) {
1134 /* want to interrupt when CTS goes low if CTS is now
1135 * high and vice versa
1136 */
1137 port->tx_cts = *port->_status;
1138
1139 if (port->tx_cts & SC2STR_CTS)
1140 scxctr |= SC2CTR_TWE;
1141 else
1142 scxctr |= SC2CTR_TWE | SC2CTR_TWS;
1143 }
1144
1145 /* set up parity check flag */
1146 port->uart.read_status_mask = (1 << TTY_NORMAL) | (1 << TTY_OVERRUN);
1147 if (new->c_iflag & INPCK)
1148 port->uart.read_status_mask |=
1149 (1 << TTY_PARITY) | (1 << TTY_FRAME);
1150 if (new->c_iflag & (BRKINT | PARMRK))
1151 port->uart.read_status_mask |= (1 << TTY_BREAK);
1152
1153 /* characters to ignore */
1154 port->uart.ignore_status_mask = 0;
1155 if (new->c_iflag & IGNPAR)
1156 port->uart.ignore_status_mask |=
1157 (1 << TTY_PARITY) | (1 << TTY_FRAME);
1158 if (new->c_iflag & IGNBRK) {
1159 port->uart.ignore_status_mask |= (1 << TTY_BREAK);
1160 /*
1161 * If we're ignoring parity and break indicators,
1162 * ignore overruns to (for real raw support).
1163 */
1164 if (new->c_iflag & IGNPAR)
1165 port->uart.ignore_status_mask |= (1 << TTY_OVERRUN);
1166 }
1167
1168 /* Ignore all characters if CREAD is not set */
1169 if ((new->c_cflag & CREAD) == 0)
1170 port->uart.ignore_status_mask |= (1 << TTY_NORMAL);
1171
1172 scxctr |= *port->_control & (SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
1173 *port->_control = scxctr;
1174
1175 spin_unlock_irqrestore(&port->uart.lock, flags);
1176}
1177
1178/*
1179 * set the terminal I/O parameters
1180 */
1181static void mn10300_serial_set_termios(struct uart_port *_port,
1182 struct ktermios *new,
1183 struct ktermios *old)
1184{
1185 struct mn10300_serial_port *port =
1186 container_of(_port, struct mn10300_serial_port, uart);
1187
1188 _enter("%s,%p,%p", port->name, new, old);
1189
1190 mn10300_serial_change_speed(port, new, old);
1191
1192 /* handle turning off CRTSCTS */
1193 if (!(new->c_cflag & CRTSCTS)) {
1194 u16 ctr = *port->_control;
1195 ctr &= ~SC2CTR_TWE;
1196 *port->_control = ctr;
1197 }
1198}
1199
1200/*
1201 * return description of port type
1202 */
1203static const char *mn10300_serial_type(struct uart_port *_port)
1204{
1205 struct mn10300_serial_port *port =
1206 container_of(_port, struct mn10300_serial_port, uart);
1207
1208 if (port->uart.type == PORT_MN10300_CTS)
1209 return "MN10300 SIF_CTS";
1210
1211 return "MN10300 SIF";
1212}
1213
1214/*
1215 * release I/O and memory regions in use by port
1216 */
1217static void mn10300_serial_release_port(struct uart_port *_port)
1218{
1219 struct mn10300_serial_port *port =
1220 container_of(_port, struct mn10300_serial_port, uart);
1221
1222 _enter("%s", port->name);
1223
1224 release_mem_region((unsigned long) port->_iobase, 16);
1225}
1226
1227/*
1228 * request I/O and memory regions for port
1229 */
1230static int mn10300_serial_request_port(struct uart_port *_port)
1231{
1232 struct mn10300_serial_port *port =
1233 container_of(_port, struct mn10300_serial_port, uart);
1234
1235 _enter("%s", port->name);
1236
1237 request_mem_region((unsigned long) port->_iobase, 16, port->name);
1238 return 0;
1239}
1240
1241/*
1242 * configure the type and reserve the ports
1243 */
1244static void mn10300_serial_config_port(struct uart_port *_port, int type)
1245{
1246 struct mn10300_serial_port *port =
1247 container_of(_port, struct mn10300_serial_port, uart);
1248
1249 _enter("%s", port->name);
1250
1251 port->uart.type = PORT_MN10300;
1252
1253 if (port->options & MNSCx_OPT_CTS)
1254 port->uart.type = PORT_MN10300_CTS;
1255
1256 mn10300_serial_request_port(_port);
1257}
1258
1259/*
1260 * verify serial parameters are suitable for this port type
1261 */
1262static int mn10300_serial_verify_port(struct uart_port *_port,
1263 struct serial_struct *ss)
1264{
1265 struct mn10300_serial_port *port =
1266 container_of(_port, struct mn10300_serial_port, uart);
1267 void *mapbase = (void *) (unsigned long) port->uart.mapbase;
1268
1269 _enter("%s", port->name);
1270
1271 /* these things may not be changed */
1272 if (ss->irq != port->uart.irq ||
1273 ss->port != port->uart.iobase ||
1274 ss->io_type != port->uart.iotype ||
1275 ss->iomem_base != mapbase ||
1276 ss->iomem_reg_shift != port->uart.regshift ||
1277 ss->hub6 != port->uart.hub6 ||
1278 ss->xmit_fifo_size != port->uart.fifosize)
1279 return -EINVAL;
1280
1281 /* type may be changed on a port that supports CTS */
1282 if (ss->type != port->uart.type) {
1283 if (!(port->options & MNSCx_OPT_CTS))
1284 return -EINVAL;
1285
1286 if (ss->type != PORT_MN10300 &&
1287 ss->type != PORT_MN10300_CTS)
1288 return -EINVAL;
1289 }
1290
1291 return 0;
1292}
1293
1294/*
1295 * initialise the MN10300 on-chip UARTs
1296 */
1297static int __init mn10300_serial_init(void)
1298{
1299 struct mn10300_serial_port *port;
1300 int ret, i;
1301
1302 printk(KERN_INFO "%s version %s (%s)\n",
1303 serial_name, serial_version, serial_revdate);
1304
1305#ifdef CONFIG_MN10300_TTYSM2
1306 SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
1307#endif
1308
1309 set_intr_stub(EXCEP_IRQ_LEVEL1, mn10300_serial_vdma_interrupt);
1310
1311 ret = uart_register_driver(&mn10300_serial_driver);
1312 if (!ret) {
1313 for (i = 0 ; i < NR_PORTS ; i++) {
1314 port = mn10300_serial_ports[i];
1315 if (!port || port->gdbstub)
1316 continue;
1317
1318 switch (port->clock_src) {
1319 case MNSCx_CLOCK_SRC_IOCLK:
1320 port->ioclk = MN10300_IOCLK;
1321 break;
1322
1323#ifdef MN10300_IOBCLK
1324 case MNSCx_CLOCK_SRC_IOBCLK:
1325 port->ioclk = MN10300_IOBCLK;
1326 break;
1327#endif
1328 default:
1329 BUG();
1330 }
1331
1332 ret = uart_add_one_port(&mn10300_serial_driver,
1333 &port->uart);
1334
1335 if (ret < 0) {
1336 _debug("ERROR %d", -ret);
1337 break;
1338 }
1339 }
1340
1341 if (ret)
1342 uart_unregister_driver(&mn10300_serial_driver);
1343 }
1344
1345 return ret;
1346}
1347
1348__initcall(mn10300_serial_init);
1349
1350
1351#ifdef CONFIG_MN10300_TTYSM_CONSOLE
1352
1353/*
1354 * print a string to the serial port without disturbing the real user of the
1355 * port too much
1356 * - the console must be locked by the caller
1357 */
1358static void mn10300_serial_console_write(struct console *co,
1359 const char *s, unsigned count)
1360{
1361 struct mn10300_serial_port *port;
1362 unsigned i;
1363 u16 scxctr, txicr, tmp;
1364 u8 tmxmd;
1365
1366 port = mn10300_serial_ports[co->index];
1367
1368 /* firstly hijack the serial port from the "virtual DMA" controller */
1369 txicr = *port->tx_icr;
1370 *port->tx_icr = GxICR_LEVEL_1;
1371 tmp = *port->tx_icr;
1372
1373 /* the transmitter may be disabled */
1374 scxctr = *port->_control;
1375 if (!(scxctr & SC01CTR_TXE)) {
1376 /* restart the UART clock */
1377 tmxmd = *port->_tmxmd;
1378
1379 switch (port->div_timer) {
1380 case MNSCx_DIV_TIMER_16BIT:
1381 *port->_tmxmd = 0;
1382 *port->_tmxmd = TM8MD_INIT_COUNTER;
1383 *port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
1384 break;
1385
1386 case MNSCx_DIV_TIMER_8BIT:
1387 *port->_tmxmd = 0;
1388 *port->_tmxmd = TM2MD_INIT_COUNTER;
1389 *port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
1390 break;
1391 }
1392
1393 /* enable the transmitter */
1394 *port->_control = (scxctr & ~SC01CTR_BKE) | SC01CTR_TXE;
1395
1396 } else if (scxctr & SC01CTR_BKE) {
1397 /* stop transmitting BREAK */
1398 *port->_control = (scxctr & ~SC01CTR_BKE);
1399 }
1400
1401 /* send the chars into the serial port (with LF -> LFCR conversion) */
1402 for (i = 0; i < count; i++) {
1403 char ch = *s++;
1404
1405 while (*port->_status & SC01STR_TBF)
1406 continue;
1407 *(u8 *) port->_txb = ch;
1408
1409 if (ch == 0x0a) {
1410 while (*port->_status & SC01STR_TBF)
1411 continue;
1412 *(u8 *) port->_txb = 0xd;
1413 }
1414 }
1415
1416 /* can't let the transmitter be turned off if it's actually
1417 * transmitting */
1418 while (*port->_status & (SC01STR_TXF | SC01STR_TBF))
1419 continue;
1420
1421 /* disable the transmitter if we re-enabled it */
1422 if (!(scxctr & SC01CTR_TXE))
1423 *port->_control = scxctr;
1424
1425 *port->tx_icr = txicr;
1426 tmp = *port->tx_icr;
1427}
1428
1429/*
1430 * set up a serial port as a console
1431 * - construct a cflag setting for the first rs_open()
1432 * - initialize the serial port
1433 * - return non-zero if we didn't find a serial port.
1434 */
1435static int __init mn10300_serial_console_setup(struct console *co,
1436 char *options)
1437{
1438 struct mn10300_serial_port *port;
1439 int i, parity = 'n', baud = 9600, bits = 8, flow = 0;
1440
1441 for (i = 0 ; i < NR_PORTS ; i++) {
1442 port = mn10300_serial_ports[i];
1443 if (port && !port->gdbstub && port->uart.line == co->index)
1444 goto found_device;
1445 }
1446
1447 return -ENODEV;
1448
1449found_device:
1450 switch (port->clock_src) {
1451 case MNSCx_CLOCK_SRC_IOCLK:
1452 port->ioclk = MN10300_IOCLK;
1453 break;
1454
1455#ifdef MN10300_IOBCLK
1456 case MNSCx_CLOCK_SRC_IOBCLK:
1457 port->ioclk = MN10300_IOBCLK;
1458 break;
1459#endif
1460 default:
1461 BUG();
1462 }
1463
1464 if (options)
1465 uart_parse_options(options, &baud, &parity, &bits, &flow);
1466
1467 return uart_set_options(&port->uart, co, baud, parity, bits, flow);
1468}
1469
1470/*
1471 * register console
1472 */
1473static int __init mn10300_serial_console_init(void)
1474{
1475 register_console(&mn10300_serial_console);
1476 return 0;
1477}
1478
1479console_initcall(mn10300_serial_console_init);
1480#endif
diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h
new file mode 100644
index 000000000000..6796499bf789
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial.h
@@ -0,0 +1,126 @@
1/* MN10300 On-chip serial port driver definitions
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#ifndef _MN10300_SERIAL_H
12#define _MN10300_SERIAL_H
13
14#ifndef __ASSEMBLY__
15#include <linux/serial_core.h>
16#include <linux/termios.h>
17#endif
18
19#include <asm/page.h>
20#include <asm/serial-regs.h>
21
22#define NR_PORTS 3 /* should be set 3 or 9 or 16 */
23
24#define MNSC_BUFFER_SIZE +(PAGE_SIZE / 2)
25
26/* intr_flags bits */
27#define MNSCx_RX_AVAIL 0x01
28#define MNSCx_RX_OVERF 0x02
29#define MNSCx_TX_SPACE 0x04
30#define MNSCx_TX_EMPTY 0x08
31
32#ifndef __ASSEMBLY__
33
34struct mn10300_serial_port {
35 char *rx_buffer; /* reception buffer base */
36 unsigned rx_inp; /* pointer to rx input offset */
37 unsigned rx_outp; /* pointer to rx output offset */
38 u8 tx_xchar; /* high-priority XON/XOFF buffer */
39 u8 tx_break; /* transmit break request */
40 u8 intr_flags; /* interrupt flags */
41 volatile u16 *rx_icr; /* Rx interrupt control register */
42 volatile u16 *tx_icr; /* Tx interrupt control register */
43 int rx_irq; /* reception IRQ */
44 int tx_irq; /* transmission IRQ */
45 int tm_irq; /* timer IRQ */
46
47 const char *name; /* name of serial port */
48 const char *rx_name; /* Rx interrupt handler name of serial port */
49 const char *tx_name; /* Tx interrupt handler name of serial port */
50 const char *tm_name; /* Timer interrupt handler name */
51 unsigned short type; /* type of serial port */
52 unsigned char isconsole; /* T if it's a console */
53 volatile void *_iobase; /* pointer to base of I/O control regs */
54 volatile u16 *_control; /* control register pointer */
55 volatile u8 *_status; /* status register pointer */
56 volatile u8 *_intr; /* interrupt register pointer */
57 volatile void *_rxb; /* receive buffer register pointer */
58 volatile void *_txb; /* transmit buffer register pointer */
59 volatile u16 *_tmicr; /* timer interrupt control register */
60 volatile u8 *_tmxmd; /* baud rate timer mode register */
61 volatile u16 *_tmxbr; /* baud rate timer base register */
62
63 /* this must come down here so that assembly can use BSET to access the
64 * above fields */
65 struct uart_port uart;
66
67 unsigned short rx_brk; /* current break reception status */
68 u16 tx_cts; /* current CTS status */
69 int gdbstub; /* preemptively stolen by GDB stub */
70
71 u8 clock_src; /* clock source */
72#define MNSCx_CLOCK_SRC_IOCLK 0
73#define MNSCx_CLOCK_SRC_IOBCLK 1
74
75 u8 div_timer; /* timer used as divisor */
76#define MNSCx_DIV_TIMER_16BIT 0
77#define MNSCx_DIV_TIMER_8BIT 1
78
79 u16 options; /* options */
80#define MNSCx_OPT_CTS 0x0001
81
82 unsigned long ioclk; /* base clock rate */
83};
84
85#ifdef CONFIG_MN10300_TTYSM0
86extern struct mn10300_serial_port mn10300_serial_port_sif0;
87#endif
88
89#ifdef CONFIG_MN10300_TTYSM1
90extern struct mn10300_serial_port mn10300_serial_port_sif1;
91#endif
92
93#ifdef CONFIG_MN10300_TTYSM2
94extern struct mn10300_serial_port mn10300_serial_port_sif2;
95#endif
96
97extern struct mn10300_serial_port *mn10300_serial_ports[];
98
99struct mn10300_serial_int {
100 struct mn10300_serial_port *port;
101 asmlinkage void (*vdma)(void);
102};
103
104extern struct mn10300_serial_int mn10300_serial_int_tbl[];
105
106extern asmlinkage void mn10300_serial_vdma_interrupt(void);
107extern asmlinkage void mn10300_serial_vdma_rx_handler(void);
108extern asmlinkage void mn10300_serial_vdma_tx_handler(void);
109
110#endif /* __ASSEMBLY__ */
111
112#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
113#define SCgSTR SC0STR
114#define SCgRXB SC0RXB
115#define SCgRXIRQ SC0RXIRQ
116#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
117#define SCgSTR SC1STR
118#define SCgRXB SC1RXB
119#define SCgRXIRQ SC1RXIRQ
120#elif defined(CONFIG_GDBSTUB_ON_TTYSM2)
121#define SCgSTR SC2STR
122#define SCgRXB SC2RXB
123#define SCgRXIRQ SC2RXIRQ
124#endif
125
126#endif /* _MN10300_SERIAL_H */
diff --git a/arch/mn10300/kernel/mn10300-watchdog-low.S b/arch/mn10300/kernel/mn10300-watchdog-low.S
new file mode 100644
index 000000000000..996244745cca
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-watchdog-low.S
@@ -0,0 +1,59 @@
1###############################################################################
2#
3# MN10300 Watchdog interrupt handler
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/intctl-regs.h>
17#include <asm/timer-regs.h>
18#include <asm/frame.inc>
19
20 .text
21
22###############################################################################
23#
24# Watchdog handler entry point
25# - special non-maskable interrupt
26#
27###############################################################################
28 .globl watchdog_handler
29 .type watchdog_handler,@function
30watchdog_handler:
31 add -4,sp
32 SAVE_ALL
33
34 mov 0xffffffff,d0
35 mov d0,(REG_ORIG_D0,fp)
36
37 mov fp,d0
38 lsr 2,d1
39 call watchdog_interrupt[],0 # watchdog_interrupt(regs,irq)
40
41 jmp ret_from_intr
42
43 .size watchdog_handler,.-watchdog_handler
44
45###############################################################################
46#
47# Watchdog touch entry point
48# - kept to absolute minimum (unfortunately, it's prototyped in linux/nmi.h so
49# we can't inline it)
50#
51###############################################################################
52 .globl touch_nmi_watchdog
53 .type touch_nmi_watchdog,@function
54touch_nmi_watchdog:
55 clr d0
56 mov d0,(watchdog_alert_counter)
57 ret [],0
58
59 .size touch_nmi_watchdog,.-touch_nmi_watchdog
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
new file mode 100644
index 000000000000..10811e981d20
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -0,0 +1,183 @@
1/* MN10300 Watchdog timer
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 * - Derived from arch/i386/kernel/nmi.c
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <linux/module.h>
13#include <linux/sched.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/interrupt.h>
18#include <linux/kernel_stat.h>
19#include <linux/nmi.h>
20#include <asm/processor.h>
21#include <asm/system.h>
22#include <asm/atomic.h>
23#include <asm/intctl-regs.h>
24#include <asm/rtc-regs.h>
25#include <asm/div64.h>
26#include <asm/smp.h>
27#include <asm/gdb-stub.h>
28#include <asm/proc/clock.h>
29
30static DEFINE_SPINLOCK(watchdog_print_lock);
31static unsigned int watchdog;
32static unsigned int watchdog_hz = 1;
33unsigned int watchdog_alert_counter;
34
35EXPORT_SYMBOL(touch_nmi_watchdog);
36
37/*
38 * the best way to detect whether a CPU has a 'hard lockup' problem
39 * is to check its timer makes IRQ counts. If they are not
40 * changing then that CPU has some problem.
41 *
42 * as these watchdog NMI IRQs are generated on every CPU, we only
43 * have to check the current processor.
44 *
45 * since NMIs dont listen to _any_ locks, we have to be extremely
46 * careful not to rely on unsafe variables. The printk might lock
47 * up though, so we have to break up any console locks first ...
48 * [when there will be more tty-related locks, break them up
49 * here too!]
50 */
51static unsigned int last_irq_sums[NR_CPUS];
52
53int __init check_watchdog(void)
54{
55 irq_cpustat_t tmp[1];
56
57 printk(KERN_INFO "Testing Watchdog... ");
58
59 memcpy(tmp, irq_stat, sizeof(tmp));
60 local_irq_enable();
61 mdelay((10 * 1000) / watchdog_hz); /* wait 10 ticks */
62 local_irq_disable();
63
64 if (nmi_count(0) - tmp[0].__nmi_count <= 5) {
65 printk(KERN_WARNING "CPU#%d: Watchdog appears to be stuck!\n",
66 0);
67 return -1;
68 }
69
70 printk(KERN_INFO "OK.\n");
71
72 /* now that we know it works we can reduce NMI frequency to
73 * something more reasonable; makes a difference in some configs
74 */
75 watchdog_hz = 1;
76
77 return 0;
78}
79
80static int __init setup_watchdog(char *str)
81{
82 unsigned tmp;
83 int opt;
84 u8 ctr;
85
86 get_option(&str, &opt);
87 if (opt != 1)
88 return 0;
89
90 watchdog = opt;
91 if (watchdog) {
92 set_intr_stub(EXCEP_WDT, watchdog_handler);
93 ctr = WDCTR_WDCK_65536th;
94 WDCTR = WDCTR_WDRST | ctr;
95 WDCTR = ctr;
96 tmp = WDCTR;
97
98 tmp = __muldiv64u(1 << (16 + ctr * 2), 1000000, MN10300_WDCLK);
99 tmp = 1000000000 / tmp;
100 watchdog_hz = (tmp + 500) / 1000;
101 }
102
103 return 1;
104}
105
106__setup("watchdog=", setup_watchdog);
107
108void __init watchdog_go(void)
109{
110 u8 wdt;
111
112 if (watchdog) {
113 printk(KERN_INFO "Watchdog: running at %uHz\n", watchdog_hz);
114 wdt = WDCTR & ~WDCTR_WDCNE;
115 WDCTR = wdt | WDCTR_WDRST;
116 wdt = WDCTR;
117 WDCTR = wdt | WDCTR_WDCNE;
118 wdt = WDCTR;
119
120 check_watchdog();
121 }
122}
123
124asmlinkage
125void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
126{
127
128 /*
129 * Since current-> is always on the stack, and we always switch
130 * the stack NMI-atomically, it's safe to use smp_processor_id().
131 */
132 int sum, cpu = smp_processor_id();
133 u8 wdt, tmp;
134
135 wdt = WDCTR & ~WDCTR_WDCNE;
136 WDCTR = wdt;
137 tmp = WDCTR;
138 NMICR = NMICR_WDIF;
139
140 nmi_count(cpu)++;
141 kstat_this_cpu.irqs[NMIIRQ]++;
142 sum = irq_stat[cpu].__irq_count;
143
144 if (last_irq_sums[cpu] == sum) {
145 /*
146 * Ayiee, looks like this CPU is stuck ...
147 * wait a few IRQs (5 seconds) before doing the oops ...
148 */
149 watchdog_alert_counter++;
150 if (watchdog_alert_counter == 5 * watchdog_hz) {
151 spin_lock(&watchdog_print_lock);
152 /*
153 * We are in trouble anyway, lets at least try
154 * to get a message out.
155 */
156 bust_spinlocks(1);
157 printk(KERN_ERR
158 "NMI Watchdog detected LOCKUP on CPU%d,"
159 " pc %08lx, registers:\n",
160 cpu, regs->pc);
161 show_registers(regs);
162 printk("console shuts up ...\n");
163 console_silent();
164 spin_unlock(&watchdog_print_lock);
165 bust_spinlocks(0);
166#ifdef CONFIG_GDBSTUB
167 if (gdbstub_busy)
168 gdbstub_exception(regs, excep);
169 else
170 gdbstub_intercept(regs, excep);
171#endif
172 do_exit(SIGSEGV);
173 }
174 } else {
175 last_irq_sums[cpu] = sum;
176 watchdog_alert_counter = 0;
177 }
178
179 WDCTR = wdt | WDCTR_WDRST;
180 tmp = WDCTR;
181 WDCTR = wdt | WDCTR_WDCNE;
182 tmp = WDCTR;
183}
diff --git a/arch/mn10300/kernel/mn10300_ksyms.c b/arch/mn10300/kernel/mn10300_ksyms.c
new file mode 100644
index 000000000000..6d19628634e3
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300_ksyms.c
@@ -0,0 +1,37 @@
1/* MN10300 Miscellaneous and library kernel exports
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <asm/uaccess.h>
13
14
15EXPORT_SYMBOL(change_bit);
16EXPORT_SYMBOL(test_and_change_bit);
17
18EXPORT_SYMBOL(memcpy);
19EXPORT_SYMBOL(memmove);
20EXPORT_SYMBOL(memset);
21
22EXPORT_SYMBOL(strncpy_from_user);
23EXPORT_SYMBOL(__strncpy_from_user);
24EXPORT_SYMBOL(clear_user);
25EXPORT_SYMBOL(__clear_user);
26EXPORT_SYMBOL(__generic_copy_from_user);
27EXPORT_SYMBOL(__generic_copy_to_user);
28EXPORT_SYMBOL(strnlen_user);
29
30extern u64 __ashrdi3(u64, unsigned);
31extern u64 __ashldi3(u64, unsigned);
32extern u64 __lshrdi3(u64, unsigned);
33extern s64 __negdi2(s64);
34EXPORT_SYMBOL(__ashrdi3);
35EXPORT_SYMBOL(__ashldi3);
36EXPORT_SYMBOL(__lshrdi3);
37EXPORT_SYMBOL(__negdi2);
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
new file mode 100644
index 000000000000..0e4d2f6fa6e8
--- /dev/null
+++ b/arch/mn10300/kernel/module.c
@@ -0,0 +1,206 @@
1/* MN10300 Kernel module helper routines
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by Mark Salter (msalter@redhat.com)
5 * - Derived from arch/i386/kernel/module.c
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public Licence as published by
9 * the Free Software Foundation; either version 2 of the Licence, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public Licence for more details.
16 *
17 * You should have received a copy of the GNU General Public Licence
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/moduleloader.h>
22#include <linux/elf.h>
23#include <linux/vmalloc.h>
24#include <linux/fs.h>
25#include <linux/string.h>
26#include <linux/kernel.h>
27
28#if 0
29#define DEBUGP printk
30#else
31#define DEBUGP(fmt, ...)
32#endif
33
34/*
35 * allocate storage for a module
36 */
37void *module_alloc(unsigned long size)
38{
39 if (size == 0)
40 return NULL;
41 return vmalloc_exec(size);
42}
43
44/*
45 * free memory returned from module_alloc()
46 */
47void module_free(struct module *mod, void *module_region)
48{
49 vfree(module_region);
50 /* FIXME: If module_region == mod->init_region, trim exception
51 * table entries. */
52}
53
54/*
55 * allow the arch to fix up the section table
56 * - we don't need anything special
57 */
58int module_frob_arch_sections(Elf_Ehdr *hdr,
59 Elf_Shdr *sechdrs,
60 char *secstrings,
61 struct module *mod)
62{
63 return 0;
64}
65
66static uint32_t reloc_get16(uint8_t *p)
67{
68 return p[0] | (p[1] << 8);
69}
70
71static uint32_t reloc_get24(uint8_t *p)
72{
73 return reloc_get16(p) | (p[2] << 16);
74}
75
76static uint32_t reloc_get32(uint8_t *p)
77{
78 return reloc_get16(p) | (reloc_get16(p+2) << 16);
79}
80
81static void reloc_put16(uint8_t *p, uint32_t val)
82{
83 p[0] = val & 0xff;
84 p[1] = (val >> 8) & 0xff;
85}
86
87static void reloc_put24(uint8_t *p, uint32_t val)
88{
89 reloc_put16(p, val);
90 p[2] = (val >> 16) & 0xff;
91}
92
93static void reloc_put32(uint8_t *p, uint32_t val)
94{
95 reloc_put16(p, val);
96 reloc_put16(p+2, val >> 16);
97}
98
99/*
100 * apply a REL relocation
101 */
102int apply_relocate(Elf32_Shdr *sechdrs,
103 const char *strtab,
104 unsigned int symindex,
105 unsigned int relsec,
106 struct module *me)
107{
108 printk(KERN_ERR "module %s: RELOCATION unsupported\n",
109 me->name);
110 return -ENOEXEC;
111}
112
113/*
114 * apply a RELA relocation
115 */
116int apply_relocate_add(Elf32_Shdr *sechdrs,
117 const char *strtab,
118 unsigned int symindex,
119 unsigned int relsec,
120 struct module *me)
121{
122 unsigned int i;
123 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
124 Elf32_Sym *sym;
125 Elf32_Addr relocation;
126 uint8_t *location;
127 uint32_t value;
128
129 DEBUGP("Applying relocate section %u to %u\n",
130 relsec, sechdrs[relsec].sh_info);
131
132 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
133 /* this is where to make the change */
134 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
135 + rel[i].r_offset;
136
137 /* this is the symbol the relocation is referring to (note that
138 * all undefined symbols have been resolved by the caller) */
139 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
140 + ELF32_R_SYM(rel[i].r_info);
141
142 /* this is the adjustment to be made */
143 relocation = sym->st_value + rel[i].r_addend;
144
145 switch (ELF32_R_TYPE(rel[i].r_info)) {
146 /* for the first four relocation types, we add the
147 * adjustment into the value at the location given */
148 case R_MN10300_32:
149 value = reloc_get32(location);
150 value += relocation;
151 reloc_put32(location, value);
152 break;
153 case R_MN10300_24:
154 value = reloc_get24(location);
155 value += relocation;
156 reloc_put24(location, value);
157 break;
158 case R_MN10300_16:
159 value = reloc_get16(location);
160 value += relocation;
161 reloc_put16(location, value);
162 break;
163 case R_MN10300_8:
164 *location += relocation;
165 break;
166
167 /* for the next three relocation types, we write the
168 * adjustment with the address subtracted over the
169 * value at the location given */
170 case R_MN10300_PCREL32:
171 value = relocation - (uint32_t) location;
172 reloc_put32(location, value);
173 break;
174 case R_MN10300_PCREL16:
175 value = relocation - (uint32_t) location;
176 reloc_put16(location, value);
177 break;
178 case R_MN10300_PCREL8:
179 *location = relocation - (uint32_t) location;
180 break;
181
182 default:
183 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
184 me->name, ELF32_R_TYPE(rel[i].r_info));
185 return -ENOEXEC;
186 }
187 }
188 return 0;
189}
190
191/*
192 * finish loading the module
193 */
194int module_finalize(const Elf_Ehdr *hdr,
195 const Elf_Shdr *sechdrs,
196 struct module *me)
197{
198 return 0;
199}
200
201/*
202 * finish clearing the module
203 */
204void module_arch_cleanup(struct module *mod)
205{
206}
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
new file mode 100644
index 000000000000..3b0d579fc15d
--- /dev/null
+++ b/arch/mn10300/kernel/process.c
@@ -0,0 +1,297 @@
1/* MN10300 Process handling code
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/errno.h>
13#include <linux/sched.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/smp_lock.h>
18#include <linux/stddef.h>
19#include <linux/unistd.h>
20#include <linux/ptrace.h>
21#include <linux/slab.h>
22#include <linux/user.h>
23#include <linux/a.out.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/reboot.h>
27#include <linux/percpu.h>
28#include <linux/err.h>
29#include <linux/fs.h>
30#include <asm/uaccess.h>
31#include <asm/pgtable.h>
32#include <asm/system.h>
33#include <asm/io.h>
34#include <asm/processor.h>
35#include <asm/mmu_context.h>
36#include <asm/fpu.h>
37#include <asm/reset-regs.h>
38#include <asm/gdb-stub.h>
39#include "internal.h"
40
41/*
42 * power management idle function, if any..
43 */
44void (*pm_idle)(void);
45EXPORT_SYMBOL(pm_idle);
46
47/*
48 * return saved PC of a blocked thread.
49 */
50unsigned long thread_saved_pc(struct task_struct *tsk)
51{
52 return ((unsigned long *) tsk->thread.sp)[3];
53}
54
55/*
56 * power off function, if any
57 */
58void (*pm_power_off)(void);
59EXPORT_SYMBOL(pm_power_off);
60
61/*
62 * we use this if we don't have any better idle routine
63 */
64static void default_idle(void)
65{
66 local_irq_disable();
67 if (!need_resched())
68 safe_halt();
69 else
70 local_irq_enable();
71}
72
73/*
74 * the idle thread
75 * - there's no useful work to be done, so just try to conserve power and have
76 * a low exit latency (ie sit in a loop waiting for somebody to say that
77 * they'd like to reschedule)
78 */
79void cpu_idle(void)
80{
81 int cpu = smp_processor_id();
82
83 /* endless idle loop with no priority at all */
84 for (;;) {
85 while (!need_resched()) {
86 void (*idle)(void);
87
88 smp_rmb();
89 idle = pm_idle;
90 if (!idle)
91 idle = default_idle;
92
93 irq_stat[cpu].idle_timestamp = jiffies;
94 idle();
95 }
96
97 preempt_enable_no_resched();
98 schedule();
99 preempt_disable();
100 }
101}
102
103void release_segments(struct mm_struct *mm)
104{
105}
106
107void machine_restart(char *cmd)
108{
109#ifdef CONFIG_GDBSTUB
110 gdbstub_exit(0);
111#endif
112
113#ifdef mn10300_unit_hard_reset
114 mn10300_unit_hard_reset();
115#else
116 mn10300_proc_hard_reset();
117#endif
118}
119
120void machine_halt(void)
121{
122#ifdef CONFIG_GDBSTUB
123 gdbstub_exit(0);
124#endif
125}
126
127void machine_power_off(void)
128{
129#ifdef CONFIG_GDBSTUB
130 gdbstub_exit(0);
131#endif
132}
133
134void show_regs(struct pt_regs *regs)
135{
136}
137
138/*
139 * create a kernel thread
140 */
141int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
142{
143 struct pt_regs regs;
144
145 memset(&regs, 0, sizeof(regs));
146
147 regs.a2 = (unsigned long) fn;
148 regs.d2 = (unsigned long) arg;
149 regs.pc = (unsigned long) kernel_thread_helper;
150 local_save_flags(regs.epsw);
151 regs.epsw |= EPSW_IE | EPSW_IM_7;
152
153 /* Ok, create the new process.. */
154 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
155 NULL, NULL);
156}
157
158/*
159 * free current thread data structures etc..
160 */
161void exit_thread(void)
162{
163 exit_fpu();
164}
165
166void flush_thread(void)
167{
168 flush_fpu();
169}
170
171void release_thread(struct task_struct *dead_task)
172{
173}
174
175/*
176 * we do not have to muck with descriptors here, that is
177 * done in switch_mm() as needed.
178 */
179void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
180{
181}
182
183/*
184 * this gets called before we allocate a new thread and copy the current task
185 * into it so that we can store lazy state into memory
186 */
187void prepare_to_copy(struct task_struct *tsk)
188{
189 unlazy_fpu(tsk);
190}
191
192/*
193 * set up the kernel stack for a new thread and copy arch-specific thread
194 * control information
195 */
196int copy_thread(int nr, unsigned long clone_flags,
197 unsigned long c_usp, unsigned long ustk_size,
198 struct task_struct *p, struct pt_regs *kregs)
199{
200 struct pt_regs *c_uregs, *c_kregs, *uregs;
201 unsigned long c_ksp;
202
203 uregs = current->thread.uregs;
204
205 c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
206
207 /* allocate the userspace exception frame and set it up */
208 c_ksp -= sizeof(struct pt_regs);
209 c_uregs = (struct pt_regs *) c_ksp;
210
211 p->thread.uregs = c_uregs;
212 *c_uregs = *uregs;
213 c_uregs->sp = c_usp;
214 c_uregs->epsw &= ~EPSW_FE; /* my FPU */
215
216 c_ksp -= 12; /* allocate function call ABI slack */
217
218 /* the new TLS pointer is passed in as arg #5 to sys_clone() */
219 if (clone_flags & CLONE_SETTLS)
220 c_uregs->e2 = __frame->d3;
221
222 /* set up the return kernel frame if called from kernel_thread() */
223 c_kregs = c_uregs;
224 if (kregs != uregs) {
225 c_ksp -= sizeof(struct pt_regs);
226 c_kregs = (struct pt_regs *) c_ksp;
227 *c_kregs = *kregs;
228 c_kregs->sp = c_usp;
229 c_kregs->next = c_uregs;
230#ifdef CONFIG_MN10300_CURRENT_IN_E2
231 c_kregs->e2 = (unsigned long) p; /* current */
232#endif
233
234 c_ksp -= 12; /* allocate function call ABI slack */
235 }
236
237 /* set up things up so the scheduler can start the new task */
238 p->thread.__frame = c_kregs;
239 p->thread.a3 = (unsigned long) c_kregs;
240 p->thread.sp = c_ksp;
241 p->thread.pc = (unsigned long) ret_from_fork;
242 p->thread.wchan = (unsigned long) ret_from_fork;
243 p->thread.usp = c_usp;
244
245 return 0;
246}
247
248/*
249 * clone a process
250 * - tlsptr is retrieved by copy_thread() from __frame->d3
251 */
252asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
253 int __user *parent_tidptr, int __user *child_tidptr,
254 int __user *tlsptr)
255{
256 return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
257 parent_tidptr, child_tidptr);
258}
259
260asmlinkage long sys_fork(void)
261{
262 return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL);
263}
264
265asmlinkage long sys_vfork(void)
266{
267 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
268 0, NULL, NULL);
269}
270
271asmlinkage long sys_execve(char __user *name,
272 char __user * __user *argv,
273 char __user * __user *envp)
274{
275 char *filename;
276 int error;
277
278 lock_kernel();
279
280 filename = getname(name);
281 error = PTR_ERR(filename);
282 if (!IS_ERR(filename)) {
283 error = do_execve(filename, argv, envp, __frame);
284 if (error == 0)
285 current->ptrace &= ~PT_DTRACE;
286
287 putname(filename);
288 }
289
290 unlock_kernel();
291 return error;
292}
293
294unsigned long get_wchan(struct task_struct *p)
295{
296 return p->thread.wchan;
297}
diff --git a/arch/mn10300/kernel/profile-low.S b/arch/mn10300/kernel/profile-low.S
new file mode 100644
index 000000000000..94ffac12d02d
--- /dev/null
+++ b/arch/mn10300/kernel/profile-low.S
@@ -0,0 +1,72 @@
1###############################################################################
2#
3# Fast profiling interrupt handler
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/segment.h>
17#include <asm/smp.h>
18#include <asm/intctl-regs.h>
19#include <asm/timer-regs.h>
20
21#define pi break
22
23 .balign 4
24counter:
25 .long -1
26
27###############################################################################
28#
29# Profiling interrupt entry point
30# - intended to run at interrupt priority 1
31#
32###############################################################################
33ENTRY(profile_handler)
34 movm [d2,d3,a2],(sp)
35
36 # ignore userspace
37 mov (12,sp),d2
38 and EPSW_nSL,d2
39 bne out
40
41 # do nothing if there's no buffer
42 mov (prof_buffer),a2
43 and a2,a2
44 beq out
45 or 0x20000000,a2
46
47 # calculate relative position in text segment
48 mov (16,sp),d2
49 sub _stext,d2
50 mov (prof_shift),d3
51 lsr d3,d2
52 mov (prof_len),d3
53 cmp d3,d2
54 bcc outside_text
55
56 # increment the appropriate profile bucket
57do_inc:
58 asl2 d2
59 mov (a2,d2),d3
60 inc d3
61 mov d3,(a2,d2)
62out:
63 mov GxICR_DETECT,d2
64 movbu d2,(TM11ICR) # ACK the interrupt
65 movbu (TM11ICR),d2
66 movm (sp),[d2,d3,a2]
67 rti
68
69outside_text:
70 sub 1,d3
71 mov d3,d2
72 bra do_inc
diff --git a/arch/mn10300/kernel/profile.c b/arch/mn10300/kernel/profile.c
new file mode 100644
index 000000000000..20d7d0306b16
--- /dev/null
+++ b/arch/mn10300/kernel/profile.c
@@ -0,0 +1,51 @@
1/* MN10300 Profiling setup
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12/*
13 * initialise the profiling if enabled
14 * - using with gdbstub will give anomalous results
15 * - can't be used with gdbstub if running at IRQ priority 0
16 */
17static __init int profile_init(void)
18{
19 u16 tmp;
20
21 if (!prof_buffer)
22 return 0;
23
24 /* use timer 11 to drive the profiling interrupts */
25 set_intr_stub(EXCEP_IRQ_LEVEL0, profile_handler);
26
27 /* set IRQ priority at which to run */
28 set_intr_level(TM11IRQ, GxICR_LEVEL_0);
29
30 /* set up timer 11
31 * - source: (IOCLK 33MHz)*2 = 66MHz
32 * - frequency: (33330000*2) / 8 / 20625 = 202Hz
33 */
34 TM11BR = 20625 - 1;
35 TM11MD = TM8MD_SRC_IOCLK_8;
36 TM11MD |= TM8MD_INIT_COUNTER;
37 TM11MD &= ~TM8MD_INIT_COUNTER;
38 TM11MD |= TM8MD_COUNT_ENABLE;
39
40 TM11ICR |= GxICR_ENABLE;
41 tmp = TM11ICR;
42
43 printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n",
44 mn10300_ioclk / 8 / (TM11BR + 1));
45 printk(KERN_INFO "Profile histogram stored %p-%p\n",
46 prof_buffer, (u8 *)(prof_buffer + prof_len) - 1);
47
48 return 0;
49}
50
51__initcall(profile_init);
diff --git a/arch/mn10300/kernel/ptrace.c b/arch/mn10300/kernel/ptrace.c
new file mode 100644
index 000000000000..d6d6cdc75c52
--- /dev/null
+++ b/arch/mn10300/kernel/ptrace.c
@@ -0,0 +1,379 @@
1/* MN10300 Process tracing
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Modified by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <linux/smp.h>
16#include <linux/smp_lock.h>
17#include <linux/errno.h>
18#include <linux/ptrace.h>
19#include <linux/user.h>
20#include <asm/uaccess.h>
21#include <asm/pgtable.h>
22#include <asm/system.h>
23#include <asm/processor.h>
24#include <asm/cacheflush.h>
25#include <asm/fpu.h>
26#include <asm/asm-offsets.h>
27
28/*
29 * translate ptrace register IDs into struct pt_regs offsets
30 */
31static const u8 ptrace_regid_to_frame[] = {
32 [PT_A3 << 2] = REG_A3,
33 [PT_A2 << 2] = REG_A2,
34 [PT_D3 << 2] = REG_D3,
35 [PT_D2 << 2] = REG_D2,
36 [PT_MCVF << 2] = REG_MCVF,
37 [PT_MCRL << 2] = REG_MCRL,
38 [PT_MCRH << 2] = REG_MCRH,
39 [PT_MDRQ << 2] = REG_MDRQ,
40 [PT_E1 << 2] = REG_E1,
41 [PT_E0 << 2] = REG_E0,
42 [PT_E7 << 2] = REG_E7,
43 [PT_E6 << 2] = REG_E6,
44 [PT_E5 << 2] = REG_E5,
45 [PT_E4 << 2] = REG_E4,
46 [PT_E3 << 2] = REG_E3,
47 [PT_E2 << 2] = REG_E2,
48 [PT_SP << 2] = REG_SP,
49 [PT_LAR << 2] = REG_LAR,
50 [PT_LIR << 2] = REG_LIR,
51 [PT_MDR << 2] = REG_MDR,
52 [PT_A1 << 2] = REG_A1,
53 [PT_A0 << 2] = REG_A0,
54 [PT_D1 << 2] = REG_D1,
55 [PT_D0 << 2] = REG_D0,
56 [PT_ORIG_D0 << 2] = REG_ORIG_D0,
57 [PT_EPSW << 2] = REG_EPSW,
58 [PT_PC << 2] = REG_PC,
59};
60
61static inline int get_stack_long(struct task_struct *task, int offset)
62{
63 return *(unsigned long *)
64 ((unsigned long) task->thread.uregs + offset);
65}
66
67/*
68 * this routine will put a word on the processes privileged stack.
69 * the offset is how far from the base addr as stored in the TSS.
70 * this routine assumes that all the privileged stacks are in our
71 * data space.
72 */
73static inline
74int put_stack_long(struct task_struct *task, int offset, unsigned long data)
75{
76 unsigned long stack;
77
78 stack = (unsigned long) task->thread.uregs + offset;
79 *(unsigned long *) stack = data;
80 return 0;
81}
82
83static inline unsigned long get_fpregs(struct fpu_state_struct *buf,
84 struct task_struct *tsk)
85{
86 return __copy_to_user(buf, &tsk->thread.fpu_state,
87 sizeof(struct fpu_state_struct));
88}
89
90static inline unsigned long set_fpregs(struct task_struct *tsk,
91 struct fpu_state_struct *buf)
92{
93 return __copy_from_user(&tsk->thread.fpu_state, buf,
94 sizeof(struct fpu_state_struct));
95}
96
97static inline void fpsave_init(struct task_struct *task)
98{
99 memset(&task->thread.fpu_state, 0, sizeof(struct fpu_state_struct));
100}
101
102/*
103 * make sure the single step bit is not set
104 */
105void ptrace_disable(struct task_struct *child)
106{
107#ifndef CONFIG_MN10300_USING_JTAG
108 struct user *dummy = NULL;
109 long tmp;
110
111 tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
112 tmp &= ~EPSW_T;
113 put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
114#endif
115}
116
117/*
118 * set the single step bit
119 */
120void ptrace_enable(struct task_struct *child)
121{
122#ifndef CONFIG_MN10300_USING_JTAG
123 struct user *dummy = NULL;
124 long tmp;
125
126 tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
127 tmp |= EPSW_T;
128 put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
129#endif
130}
131
132/*
133 * handle the arch-specific side of process tracing
134 */
135long arch_ptrace(struct task_struct *child, long request, long addr, long data)
136{
137 struct fpu_state_struct fpu_state;
138 int i, ret;
139
140 switch (request) {
141 /* read the word at location addr. */
142 case PTRACE_PEEKTEXT: {
143 unsigned long tmp;
144 int copied;
145
146 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
147 ret = -EIO;
148 if (copied != sizeof(tmp))
149 break;
150 ret = put_user(tmp, (unsigned long *) data);
151 break;
152 }
153
154 /* read the word at location addr. */
155 case PTRACE_PEEKDATA: {
156 unsigned long tmp;
157 int copied;
158
159 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
160 ret = -EIO;
161 if (copied != sizeof(tmp))
162 break;
163 ret = put_user(tmp, (unsigned long *) data);
164 break;
165 }
166
167 /* read the word at location addr in the USER area. */
168 case PTRACE_PEEKUSR: {
169 unsigned long tmp;
170
171 ret = -EIO;
172 if ((addr & 3) || addr < 0 ||
173 addr > sizeof(struct user) - 3)
174 break;
175
176 tmp = 0; /* Default return condition */
177 if (addr < NR_PTREGS << 2)
178 tmp = get_stack_long(child,
179 ptrace_regid_to_frame[addr]);
180 ret = put_user(tmp, (unsigned long *) data);
181 break;
182 }
183
184 /* write the word at location addr. */
185 case PTRACE_POKETEXT:
186 case PTRACE_POKEDATA:
187 if (access_process_vm(child, addr, &data, sizeof(data), 1) ==
188 sizeof(data))
189 ret = 0;
190 else
191 ret = -EIO;
192 break;
193
194 /* write the word at location addr in the USER area */
195 case PTRACE_POKEUSR:
196 ret = -EIO;
197 if ((addr & 3) || addr < 0 ||
198 addr > sizeof(struct user) - 3)
199 break;
200
201 ret = 0;
202 if (addr < NR_PTREGS << 2)
203 ret = put_stack_long(child, ptrace_regid_to_frame[addr],
204 data);
205 break;
206
207 /* continue and stop at next (return from) syscall */
208 case PTRACE_SYSCALL:
209 /* restart after signal. */
210 case PTRACE_CONT:
211 ret = -EIO;
212 if ((unsigned long) data > _NSIG)
213 break;
214 if (request == PTRACE_SYSCALL)
215 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
216 else
217 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
218 child->exit_code = data;
219 ptrace_disable(child);
220 wake_up_process(child);
221 ret = 0;
222 break;
223
224 /*
225 * make the child exit
226 * - the best I can do is send it a sigkill
227 * - perhaps it should be put in the status that it wants to
228 * exit
229 */
230 case PTRACE_KILL:
231 ret = 0;
232 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
233 break;
234 child->exit_code = SIGKILL;
235 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
236 ptrace_disable(child);
237 wake_up_process(child);
238 break;
239
240 case PTRACE_SINGLESTEP: /* set the trap flag. */
241#ifndef CONFIG_MN10300_USING_JTAG
242 ret = -EIO;
243 if ((unsigned long) data > _NSIG)
244 break;
245 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
246 ptrace_enable(child);
247 child->exit_code = data;
248 wake_up_process(child);
249 ret = 0;
250#else
251 ret = -EINVAL;
252#endif
253 break;
254
255 case PTRACE_DETACH: /* detach a process that was attached. */
256 ret = ptrace_detach(child, data);
257 break;
258
259 /* Get all gp regs from the child. */
260 case PTRACE_GETREGS: {
261 unsigned long tmp;
262
263 if (!access_ok(VERIFY_WRITE, (unsigned *) data, NR_PTREGS << 2)) {
264 ret = -EIO;
265 break;
266 }
267
268 for (i = 0; i < NR_PTREGS << 2; i += 4) {
269 tmp = get_stack_long(child, ptrace_regid_to_frame[i]);
270 __put_user(tmp, (unsigned long *) data);
271 data += sizeof(tmp);
272 }
273 ret = 0;
274 break;
275 }
276
277 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
278 unsigned long tmp;
279
280 if (!access_ok(VERIFY_READ, (unsigned long *)data,
281 sizeof(struct pt_regs))) {
282 ret = -EIO;
283 break;
284 }
285
286 for (i = 0; i < NR_PTREGS << 2; i += 4) {
287 __get_user(tmp, (unsigned long *) data);
288 put_stack_long(child, ptrace_regid_to_frame[i], tmp);
289 data += sizeof(tmp);
290 }
291 ret = 0;
292 break;
293 }
294
295 case PTRACE_GETFPREGS: { /* Get the child FPU state. */
296 if (is_using_fpu(child)) {
297 unlazy_fpu(child);
298 fpu_state = child->thread.fpu_state;
299 } else {
300 memset(&fpu_state, 0, sizeof(fpu_state));
301 }
302
303 ret = -EIO;
304 if (copy_to_user((void *) data, &fpu_state,
305 sizeof(fpu_state)) == 0)
306 ret = 0;
307 break;
308 }
309
310 case PTRACE_SETFPREGS: { /* Set the child FPU state. */
311 ret = -EFAULT;
312 if (copy_from_user(&fpu_state, (const void *) data,
313 sizeof(fpu_state)) == 0) {
314 fpu_kill_state(child);
315 child->thread.fpu_state = fpu_state;
316 set_using_fpu(child);
317 ret = 0;
318 }
319 break;
320 }
321
322 case PTRACE_SETOPTIONS: {
323 if (data & PTRACE_O_TRACESYSGOOD)
324 child->ptrace |= PT_TRACESYSGOOD;
325 else
326 child->ptrace &= ~PT_TRACESYSGOOD;
327 ret = 0;
328 break;
329 }
330
331 default:
332 ret = -EIO;
333 break;
334 }
335
336 return ret;
337}
338
339/*
340 * notification of system call entry/exit
341 * - triggered by current->work.syscall_trace
342 */
343asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
344{
345#if 0
346 /* just in case... */
347 printk(KERN_DEBUG "[%d] syscall_%lu(%lx,%lx,%lx,%lx) = %lx\n",
348 current->pid,
349 regs->orig_d0,
350 regs->a0,
351 regs->d1,
352 regs->a3,
353 regs->a2,
354 regs->d0);
355 return;
356#endif
357
358 if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
359 !test_thread_flag(TIF_SINGLESTEP))
360 return;
361 if (!(current->ptrace & PT_PTRACED))
362 return;
363
364 /* the 0x80 provides a way for the tracing parent to distinguish
365 between a syscall stop and SIGTRAP delivery */
366 ptrace_notify(SIGTRAP |
367 ((current->ptrace & PT_TRACESYSGOOD) &&
368 !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
369
370 /*
371 * this isn't the same as continuing with a signal, but it will do
372 * for normal use. strace only continues with a signal if the
373 * stopping signal is not SIGTRAP. -brl
374 */
375 if (current->exit_code) {
376 send_sig(current->exit_code, current, 1);
377 current->exit_code = 0;
378 }
379}
diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c
new file mode 100644
index 000000000000..042f792d8430
--- /dev/null
+++ b/arch/mn10300/kernel/rtc.c
@@ -0,0 +1,173 @@
1/* MN10300 RTC management
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/mc146818rtc.h>
15#include <linux/bcd.h>
16#include <linux/timex.h>
17#include <asm/rtc-regs.h>
18#include <asm/rtc.h>
19
20DEFINE_SPINLOCK(rtc_lock);
21EXPORT_SYMBOL(rtc_lock);
22
23/* last time the RTC got updated */
24static long last_rtc_update;
25
26/* time for RTC to update itself in ioclks */
27static unsigned long mn10300_rtc_update_period;
28
29/*
30 * read the current RTC time
31 */
32unsigned long __init get_initial_rtc_time(void)
33{
34 struct rtc_time tm;
35
36 get_rtc_time(&tm);
37
38 return mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
39 tm.tm_hour, tm.tm_min, tm.tm_sec);
40}
41
42/*
43 * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
44 * ms after the second nowtime has started, because when nowtime is written
45 * into the registers of the CMOS clock, it will jump to the next second
46 * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
47 * sheet for details.
48 *
49 * BUG: This routine does not handle hour overflow properly; it just
50 * sets the minutes. Usually you'll only notice that after reboot!
51 */
52static int set_rtc_mmss(unsigned long nowtime)
53{
54 unsigned char save_control, save_freq_select;
55 int retval = 0;
56 int real_seconds, real_minutes, cmos_minutes;
57
58 /* gets recalled with irq locally disabled */
59 spin_lock(&rtc_lock);
60 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being
61 * set */
62 CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
63
64 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset
65 * prescaler */
66 CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
67
68 cmos_minutes = CMOS_READ(RTC_MINUTES);
69 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
70 BCD_TO_BIN(cmos_minutes);
71
72 /*
73 * since we're only adjusting minutes and seconds,
74 * don't interfere with hour overflow. This avoids
75 * messing with unknown time zones but requires your
76 * RTC not to be off by more than 15 minutes
77 */
78 real_seconds = nowtime % 60;
79 real_minutes = nowtime / 60;
80 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
81 /* correct for half hour time zone */
82 real_minutes += 30;
83 real_minutes %= 60;
84
85 if (abs(real_minutes - cmos_minutes) < 30) {
86 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
87 BIN_TO_BCD(real_seconds);
88 BIN_TO_BCD(real_minutes);
89 }
90 CMOS_WRITE(real_seconds, RTC_SECONDS);
91 CMOS_WRITE(real_minutes, RTC_MINUTES);
92 } else {
93 printk(KERN_WARNING
94 "set_rtc_mmss: can't update from %d to %d\n",
95 cmos_minutes, real_minutes);
96 retval = -1;
97 }
98
99 /* The following flags have to be released exactly in this order,
100 * otherwise the DS12887 (popular MC146818A clone with integrated
101 * battery and quartz) will not reset the oscillator and will not
102 * update precisely 500 ms later. You won't find this mentioned in
103 * the Dallas Semiconductor data sheets, but who believes data
104 * sheets anyway ... -- Markus Kuhn
105 */
106 CMOS_WRITE(save_control, RTC_CONTROL);
107 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
108 spin_unlock(&rtc_lock);
109
110 return retval;
111}
112
113void check_rtc_time(void)
114{
115 /* the RTC clock just finished ticking over again this second
116 * - if we have an externally synchronized Linux clock, then update
117 * RTC clock accordingly every ~11 minutes. set_rtc_mmss() has to be
118 * called as close as possible to 500 ms before the new second starts.
119 */
120 if ((time_status & STA_UNSYNC) == 0 &&
121 xtime.tv_sec > last_rtc_update + 660 &&
122 xtime.tv_nsec / 1000 >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
123 xtime.tv_nsec / 1000 <= 500000 + ((unsigned) TICK_SIZE) / 2
124 ) {
125 if (set_rtc_mmss(xtime.tv_sec) == 0)
126 last_rtc_update = xtime.tv_sec;
127 else
128 /* do it again in 60s */
129 last_rtc_update = xtime.tv_sec - 600;
130 }
131}
132
133/*
134 * calibrate the TSC clock against the RTC
135 */
136void __init calibrate_clock(void)
137{
138 unsigned long count0, counth, count1;
139 unsigned char status;
140
141 /* make sure the RTC is running and is set to operate in 24hr mode */
142 status = RTSRC;
143 RTCRB |= RTCRB_SET;
144 RTCRB |= RTCRB_TM_24HR;
145 RTCRA |= RTCRA_DVR;
146 RTCRA &= ~RTCRA_DVR;
147 RTCRB &= ~RTCRB_SET;
148
149 /* work out the clock speed by counting clock cycles between ends of
150 * the RTC update cycle - track the RTC through one complete update
151 * cycle (1 second)
152 */
153 startup_timestamp_counter();
154
155 while (!(RTCRA & RTCRA_UIP)) {}
156 while ((RTCRA & RTCRA_UIP)) {}
157
158 count0 = TMTSCBC;
159
160 while (!(RTCRA & RTCRA_UIP)) {}
161
162 counth = TMTSCBC;
163
164 while ((RTCRA & RTCRA_UIP)) {}
165
166 count1 = TMTSCBC;
167
168 shutdown_timestamp_counter();
169
170 MN10300_TSCCLK = count0 - count1; /* the timers count down */
171 mn10300_rtc_update_period = counth - count1;
172 MN10300_TSC_PER_HZ = MN10300_TSCCLK / HZ;
173}
diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
new file mode 100644
index 000000000000..9153c4039fd2
--- /dev/null
+++ b/arch/mn10300/kernel/semaphore.c
@@ -0,0 +1,149 @@
1/* MN10300 Semaphore implementation
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sched.h>
12#include <linux/module.h>
13#include <asm/semaphore.h>
14
15struct sem_waiter {
16 struct list_head list;
17 struct task_struct *task;
18};
19
20#if SEMAPHORE_DEBUG
21void semtrace(struct semaphore *sem, const char *str)
22{
23 if (sem->debug)
24 printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
25 current->pid,
26 str,
27 atomic_read(&sem->count),
28 list_empty(&sem->wait_list) ? 0 : 1);
29}
30#else
31#define semtrace(SEM, STR) do { } while (0)
32#endif
33
34/*
35 * wait for a token to be granted from a semaphore
36 * - entered with lock held and interrupts disabled
37 */
38void __down(struct semaphore *sem, unsigned long flags)
39{
40 struct task_struct *tsk = current;
41 struct sem_waiter waiter;
42
43 semtrace(sem, "Entering __down");
44
45 /* set up my own style of waitqueue */
46 waiter.task = tsk;
47 get_task_struct(tsk);
48
49 list_add_tail(&waiter.list, &sem->wait_list);
50
51 /* we don't need to touch the semaphore struct anymore */
52 spin_unlock_irqrestore(&sem->wait_lock, flags);
53
54 /* wait to be given the semaphore */
55 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
56
57 for (;;) {
58 if (!waiter.task)
59 break;
60 schedule();
61 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
62 }
63
64 tsk->state = TASK_RUNNING;
65 semtrace(sem, "Leaving __down");
66}
67EXPORT_SYMBOL(__down);
68
69/*
70 * interruptibly wait for a token to be granted from a semaphore
71 * - entered with lock held and interrupts disabled
72 */
73int __down_interruptible(struct semaphore *sem, unsigned long flags)
74{
75 struct task_struct *tsk = current;
76 struct sem_waiter waiter;
77 int ret;
78
79 semtrace(sem, "Entering __down_interruptible");
80
81 /* set up my own style of waitqueue */
82 waiter.task = tsk;
83 get_task_struct(tsk);
84
85 list_add_tail(&waiter.list, &sem->wait_list);
86
87 /* we don't need to touch the semaphore struct anymore */
88 set_task_state(tsk, TASK_INTERRUPTIBLE);
89
90 spin_unlock_irqrestore(&sem->wait_lock, flags);
91
92 /* wait to be given the semaphore */
93 ret = 0;
94 for (;;) {
95 if (!waiter.task)
96 break;
97 if (unlikely(signal_pending(current)))
98 goto interrupted;
99 schedule();
100 set_task_state(tsk, TASK_INTERRUPTIBLE);
101 }
102
103 out:
104 tsk->state = TASK_RUNNING;
105 semtrace(sem, "Leaving __down_interruptible");
106 return ret;
107
108 interrupted:
109 spin_lock_irqsave(&sem->wait_lock, flags);
110 list_del(&waiter.list);
111 spin_unlock_irqrestore(&sem->wait_lock, flags);
112
113 ret = 0;
114 if (!waiter.task) {
115 put_task_struct(current);
116 ret = -EINTR;
117 }
118 goto out;
119}
120EXPORT_SYMBOL(__down_interruptible);
121
122/*
123 * release a single token back to a semaphore
124 * - entered with lock held and interrupts disabled
125 */
126void __up(struct semaphore *sem)
127{
128 struct task_struct *tsk;
129 struct sem_waiter *waiter;
130
131 semtrace(sem, "Entering __up");
132
133 /* grant the token to the process at the front of the queue */
134 waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
135
136 /* We must be careful not to touch 'waiter' after we set ->task = NULL.
137 * It is an allocated on the waiter's stack and may become invalid at
138 * any time after that point (due to a wakeup from another source).
139 */
140 list_del_init(&waiter->list);
141 tsk = waiter->task;
142 smp_mb();
143 waiter->task = NULL;
144 wake_up_process(tsk);
145 put_task_struct(tsk);
146
147 semtrace(sem, "Leaving __up");
148}
149EXPORT_SYMBOL(__up);
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c
new file mode 100644
index 000000000000..6b7ce2636851
--- /dev/null
+++ b/arch/mn10300/kernel/setup.c
@@ -0,0 +1,298 @@
1/* MN10300 Arch-specific initialisation
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/mm.h>
15#include <linux/stddef.h>
16#include <linux/unistd.h>
17#include <linux/ptrace.h>
18#include <linux/slab.h>
19#include <linux/user.h>
20#include <linux/a.out.h>
21#include <linux/tty.h>
22#include <linux/ioport.h>
23#include <linux/delay.h>
24#include <linux/init.h>
25#include <linux/bootmem.h>
26#include <linux/seq_file.h>
27#include <asm/processor.h>
28#include <linux/console.h>
29#include <asm/uaccess.h>
30#include <asm/system.h>
31#include <asm/setup.h>
32#include <asm/io.h>
33#include <asm/smp.h>
34#include <asm/proc/proc.h>
35#include <asm/busctl-regs.h>
36#include <asm/fpu.h>
37#include <asm/sections.h>
38
39struct mn10300_cpuinfo boot_cpu_data;
40
41/* For PCI or other memory-mapped resources */
42unsigned long pci_mem_start = 0x18000000;
43
44char redboot_command_line[COMMAND_LINE_SIZE] =
45 "console=ttyS0,115200 root=/dev/mtdblock3 rw";
46
47char __initdata redboot_platform_name[COMMAND_LINE_SIZE];
48
49static struct resource code_resource = {
50 .start = 0x100000,
51 .end = 0,
52 .name = "Kernel code",
53};
54
55static struct resource data_resource = {
56 .start = 0,
57 .end = 0,
58 .name = "Kernel data",
59};
60
61static unsigned long __initdata phys_memory_base;
62static unsigned long __initdata phys_memory_end;
63static unsigned long __initdata memory_end;
64unsigned long memory_size;
65
66struct thread_info *__current_ti = &init_thread_union.thread_info;
67struct task_struct *__current = &init_task;
68
69#define mn10300_known_cpus 3
70static const char *const mn10300_cputypes[] = {
71 "am33v1",
72 "am33v2",
73 "am34v1",
74 "unknown"
75};
76
77/*
78 *
79 */
80static void __init parse_mem_cmdline(char **cmdline_p)
81{
82 char *from, *to, c;
83
84 /* save unparsed command line copy for /proc/cmdline */
85 strcpy(boot_command_line, redboot_command_line);
86
87 /* see if there's an explicit memory size option */
88 from = redboot_command_line;
89 to = redboot_command_line;
90 c = ' ';
91
92 for (;;) {
93 if (c == ' ' && !memcmp(from, "mem=", 4)) {
94 if (to != redboot_command_line)
95 to--;
96 memory_size = memparse(from + 4, &from);
97 }
98
99 c = *(from++);
100 if (!c)
101 break;
102
103 *(to++) = c;
104 }
105
106 *to = '\0';
107 *cmdline_p = redboot_command_line;
108
109 if (memory_size == 0)
110 panic("Memory size not known\n");
111
112 memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
113 memory_size;
114 if (memory_end > phys_memory_end)
115 memory_end = phys_memory_end;
116}
117
118/*
119 * architecture specific setup
120 */
121void __init setup_arch(char **cmdline_p)
122{
123 unsigned long bootmap_size;
124 unsigned long kstart_pfn, start_pfn, free_pfn, end_pfn;
125
126 cpu_init();
127 unit_setup();
128 parse_mem_cmdline(cmdline_p);
129
130 init_mm.start_code = (unsigned long)&_text;
131 init_mm.end_code = (unsigned long) &_etext;
132 init_mm.end_data = (unsigned long) &_edata;
133 init_mm.brk = (unsigned long) &_end;
134
135 code_resource.start = virt_to_bus(&_text);
136 code_resource.end = virt_to_bus(&_etext)-1;
137 data_resource.start = virt_to_bus(&_etext);
138 data_resource.end = virt_to_bus(&_edata)-1;
139
140#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
141#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
142#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
143
144 start_pfn = (CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT);
145 kstart_pfn = PFN_UP(__pa(&_text));
146 free_pfn = PFN_UP(__pa(&_end));
147 end_pfn = PFN_DOWN(__pa(memory_end));
148
149 bootmap_size = init_bootmem_node(&contig_page_data,
150 free_pfn,
151 start_pfn,
152 end_pfn);
153
154 if (kstart_pfn > start_pfn)
155 free_bootmem(PFN_PHYS(start_pfn),
156 PFN_PHYS(kstart_pfn - start_pfn));
157
158 free_bootmem(PFN_PHYS(free_pfn),
159 PFN_PHYS(end_pfn - free_pfn));
160
161 /* If interrupt vector table is in main ram, then we need to
162 reserve the page it is occupying. */
163 if (CONFIG_INTERRUPT_VECTOR_BASE >= CONFIG_KERNEL_RAM_BASE_ADDRESS &&
164 CONFIG_INTERRUPT_VECTOR_BASE < memory_end)
165 reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, 1,
166 BOOTMEM_DEFAULT);
167
168 reserve_bootmem(PAGE_ALIGN(PFN_PHYS(free_pfn)), bootmap_size,
169 BOOTMEM_DEFAULT);
170
171#ifdef CONFIG_VT
172#if defined(CONFIG_VGA_CONSOLE)
173 conswitchp = &vga_con;
174#elif defined(CONFIG_DUMMY_CONSOLE)
175 conswitchp = &dummy_con;
176#endif
177#endif
178
179 paging_init();
180}
181
182/*
183 * perform CPU initialisation
184 */
185void __init cpu_init(void)
186{
187 unsigned long cpurev = CPUREV, type;
188 unsigned long base, size;
189
190 type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
191 if (type > mn10300_known_cpus)
192 type = mn10300_known_cpus;
193
194 printk(KERN_INFO "Matsushita %s, rev %ld\n",
195 mn10300_cputypes[type],
196 (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S);
197
198 /* determine the memory size and base from the memory controller regs */
199 memory_size = 0;
200
201 base = SDBASE(0);
202 if (base & SDBASE_CE) {
203 size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
204 size = ~size + 1;
205 base &= SDBASE_CBA;
206
207 printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
208 memory_size += size;
209 phys_memory_base = base;
210 }
211
212 base = SDBASE(1);
213 if (base & SDBASE_CE) {
214 size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
215 size = ~size + 1;
216 base &= SDBASE_CBA;
217
218 printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
219 memory_size += size;
220 if (phys_memory_base == 0)
221 phys_memory_base = base;
222 }
223
224 phys_memory_end = phys_memory_base + memory_size;
225
226#ifdef CONFIG_FPU
227 fpu_init_state();
228#endif
229}
230
231/*
232 * Get CPU information for use by the procfs.
233 */
234static int show_cpuinfo(struct seq_file *m, void *v)
235{
236 unsigned long cpurev = CPUREV, type, icachesz, dcachesz;
237
238 type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
239 if (type > mn10300_known_cpus)
240 type = mn10300_known_cpus;
241
242 icachesz =
243 ((cpurev & CPUREV_ICWAY ) >> CPUREV_ICWAY_S) *
244 ((cpurev & CPUREV_ICSIZE) >> CPUREV_ICSIZE_S) *
245 1024;
246
247 dcachesz =
248 ((cpurev & CPUREV_DCWAY ) >> CPUREV_DCWAY_S) *
249 ((cpurev & CPUREV_DCSIZE) >> CPUREV_DCSIZE_S) *
250 1024;
251
252 seq_printf(m,
253 "processor : 0\n"
254 "vendor_id : Matsushita\n"
255 "cpu core : %s\n"
256 "cpu rev : %lu\n"
257 "model name : " PROCESSOR_MODEL_NAME "\n"
258 "icache size: %lu\n"
259 "dcache size: %lu\n",
260 mn10300_cputypes[type],
261 (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S,
262 icachesz,
263 dcachesz
264 );
265
266 seq_printf(m,
267 "ioclk speed: %lu.%02luMHz\n"
268 "bogomips : %lu.%02lu\n\n",
269 MN10300_IOCLK / 1000000,
270 (MN10300_IOCLK / 10000) % 100,
271 loops_per_jiffy / (500000 / HZ),
272 (loops_per_jiffy / (5000 / HZ)) % 100
273 );
274
275 return 0;
276}
277
278static void *c_start(struct seq_file *m, loff_t *pos)
279{
280 return *pos < NR_CPUS ? cpu_data + *pos : NULL;
281}
282
283static void *c_next(struct seq_file *m, void *v, loff_t *pos)
284{
285 ++*pos;
286 return c_start(m, pos);
287}
288
289static void c_stop(struct seq_file *m, void *v)
290{
291}
292
293struct seq_operations cpuinfo_op = {
294 .start = c_start,
295 .next = c_next,
296 .stop = c_stop,
297 .show = show_cpuinfo,
298};
diff --git a/arch/mn10300/kernel/sigframe.h b/arch/mn10300/kernel/sigframe.h
new file mode 100644
index 000000000000..0decba28ae84
--- /dev/null
+++ b/arch/mn10300/kernel/sigframe.h
@@ -0,0 +1,33 @@
1/* MN10300 Signal frame definitions
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12struct sigframe
13{
14 void (*pretcode)(void);
15 int sig;
16 struct sigcontext *psc;
17 struct sigcontext sc;
18 struct fpucontext fpuctx;
19 unsigned long extramask[_NSIG_WORDS-1];
20 char retcode[8];
21};
22
23struct rt_sigframe
24{
25 void (*pretcode)(void);
26 int sig;
27 struct siginfo *pinfo;
28 void *puc;
29 struct siginfo info;
30 struct ucontext uc;
31 struct fpucontext fpuctx;
32 char retcode[8];
33};
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
new file mode 100644
index 000000000000..841ca9955a18
--- /dev/null
+++ b/arch/mn10300/kernel/signal.c
@@ -0,0 +1,564 @@
1/* MN10300 Signal handling
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
15#include <linux/smp_lock.h>
16#include <linux/kernel.h>
17#include <linux/signal.h>
18#include <linux/errno.h>
19#include <linux/wait.h>
20#include <linux/ptrace.h>
21#include <linux/unistd.h>
22#include <linux/stddef.h>
23#include <linux/tty.h>
24#include <linux/personality.h>
25#include <linux/suspend.h>
26#include <asm/cacheflush.h>
27#include <asm/ucontext.h>
28#include <asm/uaccess.h>
29#include <asm/fpu.h>
30#include "sigframe.h"
31
32#define DEBUG_SIG 0
33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35
36/*
37 * atomically swap in the new signal mask, and wait for a signal.
38 */
39asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
40{
41 mask &= _BLOCKABLE;
42 spin_lock_irq(&current->sighand->siglock);
43 current->saved_sigmask = current->blocked;
44 siginitset(&current->blocked, mask);
45 recalc_sigpending();
46 spin_unlock_irq(&current->sighand->siglock);
47
48 current->state = TASK_INTERRUPTIBLE;
49 schedule();
50 set_thread_flag(TIF_RESTORE_SIGMASK);
51 return -ERESTARTNOHAND;
52}
53
54/*
55 * set signal action syscall
56 */
57asmlinkage long sys_sigaction(int sig,
58 const struct old_sigaction __user *act,
59 struct old_sigaction __user *oact)
60{
61 struct k_sigaction new_ka, old_ka;
62 int ret;
63
64 if (act) {
65 old_sigset_t mask;
66 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
67 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
68 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
69 return -EFAULT;
70 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
71 __get_user(mask, &act->sa_mask);
72 siginitset(&new_ka.sa.sa_mask, mask);
73 }
74
75 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
76
77 if (!ret && oact) {
78 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
79 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
80 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
81 return -EFAULT;
82 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
83 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
84 }
85
86 return ret;
87}
88
89/*
90 * set alternate signal stack syscall
91 */
92asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
93{
94 return do_sigaltstack(uss, uoss, __frame->sp);
95}
96
97/*
98 * do a signal return; undo the signal stack.
99 */
100static int restore_sigcontext(struct pt_regs *regs,
101 struct sigcontext __user *sc, long *_d0)
102{
103 unsigned int err = 0;
104
105 if (is_using_fpu(current))
106 fpu_kill_state(current);
107
108#define COPY(x) err |= __get_user(regs->x, &sc->x)
109 COPY(d1); COPY(d2); COPY(d3);
110 COPY(a0); COPY(a1); COPY(a2); COPY(a3);
111 COPY(e0); COPY(e1); COPY(e2); COPY(e3);
112 COPY(e4); COPY(e5); COPY(e6); COPY(e7);
113 COPY(lar); COPY(lir);
114 COPY(mdr); COPY(mdrq);
115 COPY(mcvf); COPY(mcrl); COPY(mcrh);
116 COPY(sp); COPY(pc);
117#undef COPY
118
119 {
120 unsigned int tmpflags;
121#ifndef CONFIG_MN10300_USING_JTAG
122#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
123 EPSW_T | EPSW_nAR)
124#else
125#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
126 EPSW_nAR)
127#endif
128 err |= __get_user(tmpflags, &sc->epsw);
129 regs->epsw = (regs->epsw & ~USER_EPSW) |
130 (tmpflags & USER_EPSW);
131 regs->orig_d0 = -1; /* disable syscall checks */
132 }
133
134 {
135 struct fpucontext *buf;
136 err |= __get_user(buf, &sc->fpucontext);
137 if (buf) {
138 if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
139 goto badframe;
140 err |= fpu_restore_sigcontext(buf);
141 }
142 }
143
144 err |= __get_user(*_d0, &sc->d0);
145 return err;
146
147badframe:
148 return 1;
149}
150
151/*
152 * standard signal return syscall
153 */
154asmlinkage long sys_sigreturn(void)
155{
156 struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
157 sigset_t set;
158 long d0;
159
160 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
161 goto badframe;
162 if (__get_user(set.sig[0], &frame->sc.oldmask))
163 goto badframe;
164
165 if (_NSIG_WORDS > 1 &&
166 __copy_from_user(&set.sig[1], &frame->extramask,
167 sizeof(frame->extramask)))
168 goto badframe;
169
170 sigdelsetmask(&set, ~_BLOCKABLE);
171 spin_lock_irq(&current->sighand->siglock);
172 current->blocked = set;
173 recalc_sigpending();
174 spin_unlock_irq(&current->sighand->siglock);
175
176 if (restore_sigcontext(__frame, &frame->sc, &d0))
177 goto badframe;
178
179 return d0;
180
181badframe:
182 force_sig(SIGSEGV, current);
183 return 0;
184}
185
186/*
187 * realtime signal return syscall
188 */
189asmlinkage long sys_rt_sigreturn(void)
190{
191 struct rt_sigframe __user *frame =
192 (struct rt_sigframe __user *) __frame->sp;
193 sigset_t set;
194 unsigned long d0;
195
196 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
197 goto badframe;
198 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
199 goto badframe;
200
201 sigdelsetmask(&set, ~_BLOCKABLE);
202 spin_lock_irq(&current->sighand->siglock);
203 current->blocked = set;
204 recalc_sigpending();
205 spin_unlock_irq(&current->sighand->siglock);
206
207 if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0))
208 goto badframe;
209
210 if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
211 goto badframe;
212
213 return d0;
214
215badframe:
216 force_sig(SIGSEGV, current);
217 return 0;
218}
219
220/*
221 * store the userspace context into a signal frame
222 */
223static int setup_sigcontext(struct sigcontext __user *sc,
224 struct fpucontext *fpuctx,
225 struct pt_regs *regs,
226 unsigned long mask)
227{
228 int tmp, err = 0;
229
230#define COPY(x) err |= __put_user(regs->x, &sc->x)
231 COPY(d0); COPY(d1); COPY(d2); COPY(d3);
232 COPY(a0); COPY(a1); COPY(a2); COPY(a3);
233 COPY(e0); COPY(e1); COPY(e2); COPY(e3);
234 COPY(e4); COPY(e5); COPY(e6); COPY(e7);
235 COPY(lar); COPY(lir);
236 COPY(mdr); COPY(mdrq);
237 COPY(mcvf); COPY(mcrl); COPY(mcrh);
238 COPY(sp); COPY(epsw); COPY(pc);
239#undef COPY
240
241 tmp = fpu_setup_sigcontext(fpuctx);
242 if (tmp < 0)
243 err = 1;
244 else
245 err |= __put_user(tmp ? fpuctx : NULL, &sc->fpucontext);
246
247 /* non-iBCS2 extensions.. */
248 err |= __put_user(mask, &sc->oldmask);
249
250 return err;
251}
252
253/*
254 * determine which stack to use..
255 */
256static inline void __user *get_sigframe(struct k_sigaction *ka,
257 struct pt_regs *regs,
258 size_t frame_size)
259{
260 unsigned long sp;
261
262 /* default to using normal stack */
263 sp = regs->sp;
264
265 /* this is the X/Open sanctioned signal stack switching. */
266 if (ka->sa.sa_flags & SA_ONSTACK) {
267 if (!on_sig_stack(sp))
268 sp = current->sas_ss_sp + current->sas_ss_size;
269 }
270
271 return (void __user *) ((sp - frame_size) & ~7UL);
272}
273
274/*
275 * set up a normal signal frame
276 */
277static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
278 struct pt_regs *regs)
279{
280 struct sigframe __user *frame;
281 int rsig;
282
283 frame = get_sigframe(ka, regs, sizeof(*frame));
284
285 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
286 goto give_sigsegv;
287
288 rsig = sig;
289 if (sig < 32 &&
290 current_thread_info()->exec_domain &&
291 current_thread_info()->exec_domain->signal_invmap)
292 rsig = current_thread_info()->exec_domain->signal_invmap[sig];
293
294 if (__put_user(rsig, &frame->sig) < 0 ||
295 __put_user(&frame->sc, &frame->psc) < 0)
296 goto give_sigsegv;
297
298 if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
299 goto give_sigsegv;
300
301 if (_NSIG_WORDS > 1) {
302 if (__copy_to_user(frame->extramask, &set->sig[1],
303 sizeof(frame->extramask)))
304 goto give_sigsegv;
305 }
306
307 /* set up to return from userspace. If provided, use a stub already in
308 * userspace */
309 if (ka->sa.sa_flags & SA_RESTORER) {
310 if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
311 goto give_sigsegv;
312 } else {
313 if (__put_user((void (*)(void))frame->retcode,
314 &frame->pretcode))
315 goto give_sigsegv;
316 /* this is mov $,d0; syscall 0 */
317 if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
318 __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
319 __put_user(0x00, (char *)(frame->retcode + 2)) ||
320 __put_user(0xf0, (char *)(frame->retcode + 3)) ||
321 __put_user(0xe0, (char *)(frame->retcode + 4)))
322 goto give_sigsegv;
323 flush_icache_range((unsigned long) frame->retcode,
324 (unsigned long) frame->retcode + 5);
325 }
326
327 /* set up registers for signal handler */
328 regs->sp = (unsigned long) frame;
329 regs->pc = (unsigned long) ka->sa.sa_handler;
330 regs->d0 = sig;
331 regs->d1 = (unsigned long) &frame->sc;
332
333 set_fs(USER_DS);
334
335 /* the tracer may want to single-step inside the handler */
336 if (test_thread_flag(TIF_SINGLESTEP))
337 ptrace_notify(SIGTRAP);
338
339#if DEBUG_SIG
340 printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
341 sig, current->comm, current->pid, frame, regs->pc,
342 frame->pretcode);
343#endif
344
345 return 0;
346
347give_sigsegv:
348 force_sig(SIGSEGV, current);
349 return -EFAULT;
350}
351
352/*
353 * set up a realtime signal frame
354 */
355static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
356 sigset_t *set, struct pt_regs *regs)
357{
358 struct rt_sigframe __user *frame;
359 int rsig;
360
361 frame = get_sigframe(ka, regs, sizeof(*frame));
362
363 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
364 goto give_sigsegv;
365
366 rsig = sig;
367 if (sig < 32 &&
368 current_thread_info()->exec_domain &&
369 current_thread_info()->exec_domain->signal_invmap)
370 rsig = current_thread_info()->exec_domain->signal_invmap[sig];
371
372 if (__put_user(rsig, &frame->sig) ||
373 __put_user(&frame->info, &frame->pinfo) ||
374 __put_user(&frame->uc, &frame->puc) ||
375 copy_siginfo_to_user(&frame->info, info))
376 goto give_sigsegv;
377
378 /* create the ucontext. */
379 if (__put_user(0, &frame->uc.uc_flags) ||
380 __put_user(0, &frame->uc.uc_link) ||
381 __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
382 __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
383 __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size) ||
384 setup_sigcontext(&frame->uc.uc_mcontext,
385 &frame->fpuctx, regs, set->sig[0]) ||
386 __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
387 goto give_sigsegv;
388
389 /* set up to return from userspace. If provided, use a stub already in
390 * userspace */
391 if (ka->sa.sa_flags & SA_RESTORER) {
392 if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
393 goto give_sigsegv;
394 } else {
395 if (__put_user((void(*)(void))frame->retcode,
396 &frame->pretcode) ||
397 /* This is mov $,d0; syscall 0 */
398 __put_user(0x2c, (char *)(frame->retcode + 0)) ||
399 __put_user(__NR_rt_sigreturn,
400 (char *)(frame->retcode + 1)) ||
401 __put_user(0x00, (char *)(frame->retcode + 2)) ||
402 __put_user(0xf0, (char *)(frame->retcode + 3)) ||
403 __put_user(0xe0, (char *)(frame->retcode + 4)))
404 goto give_sigsegv;
405
406 flush_icache_range((u_long) frame->retcode,
407 (u_long) frame->retcode + 5);
408 }
409
410 /* Set up registers for signal handler */
411 regs->sp = (unsigned long) frame;
412 regs->pc = (unsigned long) ka->sa.sa_handler;
413 regs->d0 = sig;
414 regs->d1 = (long) &frame->info;
415
416 set_fs(USER_DS);
417
418 /* the tracer may want to single-step inside the handler */
419 if (test_thread_flag(TIF_SINGLESTEP))
420 ptrace_notify(SIGTRAP);
421
422#if DEBUG_SIG
423 printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
424 sig, current->comm, current->pid, frame, regs->pc,
425 frame->pretcode);
426#endif
427
428 return 0;
429
430give_sigsegv:
431 force_sig(SIGSEGV, current);
432 return -EFAULT;
433}
434
435/*
436 * handle the actual delivery of a signal to userspace
437 */
438static int handle_signal(int sig,
439 siginfo_t *info, struct k_sigaction *ka,
440 sigset_t *oldset, struct pt_regs *regs)
441{
442 int ret;
443
444 /* Are we from a system call? */
445 if (regs->orig_d0 >= 0) {
446 /* If so, check system call restarting.. */
447 switch (regs->d0) {
448 case -ERESTART_RESTARTBLOCK:
449 case -ERESTARTNOHAND:
450 regs->d0 = -EINTR;
451 break;
452
453 case -ERESTARTSYS:
454 if (!(ka->sa.sa_flags & SA_RESTART)) {
455 regs->d0 = -EINTR;
456 break;
457 }
458
459 /* fallthrough */
460 case -ERESTARTNOINTR:
461 regs->d0 = regs->orig_d0;
462 regs->pc -= 2;
463 }
464 }
465
466 /* Set up the stack frame */
467 if (ka->sa.sa_flags & SA_SIGINFO)
468 ret = setup_rt_frame(sig, ka, info, oldset, regs);
469 else
470 ret = setup_frame(sig, ka, oldset, regs);
471
472 if (ret == 0) {
473 spin_lock_irq(&current->sighand->siglock);
474 sigorsets(&current->blocked, &current->blocked,
475 &ka->sa.sa_mask);
476 if (!(ka->sa.sa_flags & SA_NODEFER))
477 sigaddset(&current->blocked, sig);
478 recalc_sigpending();
479 spin_unlock_irq(&current->sighand->siglock);
480 }
481
482 return ret;
483}
484
485/*
486 * handle a potential signal
487 */
488static void do_signal(struct pt_regs *regs)
489{
490 struct k_sigaction ka;
491 siginfo_t info;
492 sigset_t *oldset;
493 int signr;
494
495 /* we want the common case to go fast, which is why we may in certain
496 * cases get here from kernel mode */
497 if (!user_mode(regs))
498 return;
499
500 if (test_thread_flag(TIF_RESTORE_SIGMASK))
501 oldset = &current->saved_sigmask;
502 else
503 oldset = &current->blocked;
504
505 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
506 if (signr > 0) {
507 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
508 /* a signal was successfully delivered; the saved
509 * sigmask will have been stored in the signal frame,
510 * and will be restored by sigreturn, so we can simply
511 * clear the TIF_RESTORE_SIGMASK flag */
512 if (test_thread_flag(TIF_RESTORE_SIGMASK))
513 clear_thread_flag(TIF_RESTORE_SIGMASK);
514 }
515
516 return;
517 }
518
519 /* did we come from a system call? */
520 if (regs->orig_d0 >= 0) {
521 /* restart the system call - no handlers present */
522 switch (regs->d0) {
523 case -ERESTARTNOHAND:
524 case -ERESTARTSYS:
525 case -ERESTARTNOINTR:
526 regs->d0 = regs->orig_d0;
527 regs->pc -= 2;
528 break;
529
530 case -ERESTART_RESTARTBLOCK:
531 regs->d0 = __NR_restart_syscall;
532 regs->pc -= 2;
533 break;
534 }
535 }
536
537 /* if there's no signal to deliver, we just put the saved sigmask
538 * back */
539 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
540 clear_thread_flag(TIF_RESTORE_SIGMASK);
541 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
542 }
543}
544
545/*
546 * notification of userspace execution resumption
547 * - triggered by current->work.notify_resume
548 */
549asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
550{
551 /* Pending single-step? */
552 if (thread_info_flags & _TIF_SINGLESTEP) {
553#ifndef CONFIG_MN10300_USING_JTAG
554 regs->epsw |= EPSW_T;
555 clear_thread_flag(TIF_SINGLESTEP);
556#else
557 BUG(); /* no h/w single-step if using JTAG unit */
558#endif
559 }
560
561 /* deal with pending signal delivery */
562 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
563 do_signal(regs);
564}
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S
new file mode 100644
index 000000000000..630aad71b946
--- /dev/null
+++ b/arch/mn10300/kernel/switch_to.S
@@ -0,0 +1,71 @@
1###############################################################################
2#
3# MN10300 Context switch operation
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/thread_info.h>
17#include <asm/cpu-regs.h>
18
19 .text
20
21###############################################################################
22#
23# struct task_struct *__switch_to(struct thread_struct *prev,
24# struct thread_struct *next,
25# struct task_struct *prev_task)
26#
27###############################################################################
28ENTRY(__switch_to)
29 movm [d2,d3,a2,a3,exreg1],(sp)
30 or EPSW_NMID,epsw
31
32 mov (44,sp),d2
33
34 mov d0,a0
35 mov d1,a1
36
37 # save prev context
38 mov (__frame),d0
39 mov d0,(THREAD_FRAME,a0)
40 mov __switch_back,d0
41 mov d0,(THREAD_PC,a0)
42 mov sp,a2
43 mov a2,(THREAD_SP,a0)
44 mov a3,(THREAD_A3,a0)
45
46 mov (THREAD_A3,a1),a3
47 mov (THREAD_SP,a1),a2
48
49 # switch
50 mov a2,sp
51
52 # load next context
53 GET_THREAD_INFO a2
54 mov a2,(__current_ti)
55 mov (TI_task,a2),a2
56 mov a2,(__current)
57#ifdef CONFIG_MN10300_CURRENT_IN_E2
58 mov a2,e2
59#endif
60
61 mov (THREAD_FRAME,a1),a2
62 mov a2,(__frame)
63 mov (THREAD_PC,a1),a2
64 mov d2,d0 # for ret_from_fork
65 mov d0,a0 # for __switch_to
66
67 jmp (a2)
68
69__switch_back:
70 and ~EPSW_NMID,epsw
71 ret [d2,d3,a2,a3,exreg1],32
diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c
new file mode 100644
index 000000000000..5f17a1ebc825
--- /dev/null
+++ b/arch/mn10300/kernel/sys_mn10300.c
@@ -0,0 +1,193 @@
1/* MN10300 Weird system calls
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/syscalls.h>
14#include <linux/mm.h>
15#include <linux/smp.h>
16#include <linux/smp_lock.h>
17#include <linux/sem.h>
18#include <linux/msg.h>
19#include <linux/shm.h>
20#include <linux/stat.h>
21#include <linux/mman.h>
22#include <linux/file.h>
23#include <linux/utsname.h>
24#include <linux/syscalls.h>
25#include <linux/tty.h>
26
27#include <asm/uaccess.h>
28
29#define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */
30
31/*
32 * sys_pipe() is the normal C calling standard for creating
33 * a pipe. It's not the way Unix traditionally does this, though.
34 */
35asmlinkage long sys_pipe(unsigned long __user *fildes)
36{
37 int fd[2];
38 int error;
39
40 error = do_pipe(fd);
41 if (!error) {
42 if (copy_to_user(fildes, fd, 2 * sizeof(int)))
43 error = -EFAULT;
44 }
45 return error;
46}
47
48/*
49 * memory mapping syscall
50 */
51asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
52 unsigned long prot, unsigned long flags,
53 unsigned long fd, unsigned long pgoff)
54{
55 struct file *file = NULL;
56 long error = -EINVAL;
57
58 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
59
60 if (flags & MAP_FIXED && addr < MIN_MAP_ADDR)
61 goto out;
62
63 error = -EBADF;
64 if (!(flags & MAP_ANONYMOUS)) {
65 file = fget(fd);
66 if (!file)
67 goto out;
68 }
69
70 down_write(&current->mm->mmap_sem);
71 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
72 up_write(&current->mm->mmap_sem);
73
74 if (file)
75 fput(file);
76out:
77 return error;
78}
79
80asmlinkage long old_mmap(unsigned long addr, unsigned long len,
81 unsigned long prot, unsigned long flags,
82 unsigned long fd, unsigned long offset)
83{
84 if (offset & ~PAGE_MASK)
85 return -EINVAL;
86 return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
87}
88
89struct sel_arg_struct {
90 unsigned long n;
91 fd_set *inp;
92 fd_set *outp;
93 fd_set *exp;
94 struct timeval *tvp;
95};
96
97asmlinkage int old_select(struct sel_arg_struct __user *arg)
98{
99 struct sel_arg_struct a;
100
101 if (copy_from_user(&a, arg, sizeof(a)))
102 return -EFAULT;
103 /* sys_select() does the appropriate kernel locking */
104 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
105}
106
107/*
108 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
109 *
110 * This is really horribly ugly.
111 */
112asmlinkage long sys_ipc(uint call, int first, int second,
113 int third, void __user *ptr, long fifth)
114{
115 int version, ret;
116
117 version = call >> 16; /* hack for backward compatibility */
118 call &= 0xffff;
119
120 switch (call) {
121 case SEMOP:
122 return sys_semtimedop(first, (struct sembuf __user *)ptr,
123 second, NULL);
124 case SEMTIMEDOP:
125 return sys_semtimedop(first, (struct sembuf __user *)ptr,
126 second,
127 (const struct timespec __user *)fifth);
128 case SEMGET:
129 return sys_semget(first, second, third);
130 case SEMCTL: {
131 union semun fourth;
132 if (!ptr)
133 return -EINVAL;
134 if (get_user(fourth.__pad, (void __user * __user *) ptr))
135 return -EFAULT;
136 return sys_semctl(first, second, third, fourth);
137 }
138
139 case MSGSND:
140 return sys_msgsnd(first, (struct msgbuf __user *) ptr,
141 second, third);
142 case MSGRCV:
143 switch (version) {
144 case 0: {
145 struct ipc_kludge tmp;
146 if (!ptr)
147 return -EINVAL;
148
149 if (copy_from_user(&tmp,
150 (struct ipc_kludge __user *) ptr,
151 sizeof(tmp)))
152 return -EFAULT;
153 return sys_msgrcv(first, tmp.msgp, second,
154 tmp.msgtyp, third);
155 }
156 default:
157 return sys_msgrcv(first,
158 (struct msgbuf __user *) ptr,
159 second, fifth, third);
160 }
161 case MSGGET:
162 return sys_msgget((key_t) first, second);
163 case MSGCTL:
164 return sys_msgctl(first, second,
165 (struct msqid_ds __user *) ptr);
166
167 case SHMAT:
168 switch (version) {
169 default: {
170 ulong raddr;
171 ret = do_shmat(first, (char __user *) ptr, second,
172 &raddr);
173 if (ret)
174 return ret;
175 return put_user(raddr, (ulong *) third);
176 }
177 case 1: /* iBCS2 emulator entry point */
178 if (!segment_eq(get_fs(), get_ds()))
179 return -EINVAL;
180 return do_shmat(first, (char __user *) ptr, second,
181 (ulong *) third);
182 }
183 case SHMDT:
184 return sys_shmdt((char __user *)ptr);
185 case SHMGET:
186 return sys_shmget(first, second, third);
187 case SHMCTL:
188 return sys_shmctl(first, second,
189 (struct shmid_ds __user *) ptr);
190 default:
191 return -EINVAL;
192 }
193}
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c
new file mode 100644
index 000000000000..ff492e3b3457
--- /dev/null
+++ b/arch/mn10300/kernel/time.c
@@ -0,0 +1,129 @@
1/* MN10300 Low level time management
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 * - Derived from arch/i386/kernel/time.c
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/time.h>
16#include <linux/init.h>
17#include <linux/smp.h>
18#include <linux/profile.h>
19#include <asm/irq.h>
20#include <asm/div64.h>
21#include <asm/processor.h>
22#include <asm/intctl-regs.h>
23#include <asm/rtc.h>
24
25#ifdef CONFIG_MN10300_RTC
26unsigned long mn10300_ioclk; /* system I/O clock frequency */
27unsigned long mn10300_iobclk; /* system I/O clock frequency */
28unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */
29#endif /* CONFIG_MN10300_RTC */
30
31static unsigned long mn10300_last_tsc; /* time-stamp counter at last time
32 * interrupt occurred */
33
34static irqreturn_t timer_interrupt(int irq, void *dev_id);
35
36static struct irqaction timer_irq = {
37 .handler = timer_interrupt,
38 .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
39 .mask = CPU_MASK_NONE,
40 .name = "timer",
41};
42
43/*
44 * scheduler clock - returns current time in nanosec units.
45 */
46unsigned long long sched_clock(void)
47{
48 union {
49 unsigned long long l;
50 u32 w[2];
51 } quot;
52
53 quot.w[0] = mn10300_last_tsc - get_cycles();
54 quot.w[1] = 1000000000;
55
56 asm("mulu %2,%3,%0,%1"
57 : "=r"(quot.w[1]), "=r"(quot.w[0])
58 : "0"(quot.w[1]), "1"(quot.w[0])
59 : "cc");
60
61 do_div(quot.l, MN10300_TSCCLK);
62
63 return quot.l;
64}
65
66/*
67 * advance the kernel's time keeping clocks (xtime and jiffies)
68 * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
69 * there's a need to update
70 */
71static irqreturn_t timer_interrupt(int irq, void *dev_id)
72{
73 unsigned tsc, elapse;
74
75 write_seqlock(&xtime_lock);
76
77 while (tsc = get_cycles(),
78 elapse = mn10300_last_tsc - tsc, /* time elapsed since last
79 * tick */
80 elapse > MN10300_TSC_PER_HZ
81 ) {
82 mn10300_last_tsc -= MN10300_TSC_PER_HZ;
83
84 /* advance the kernel's time tracking system */
85 profile_tick(CPU_PROFILING);
86 do_timer(1);
87 update_process_times(user_mode(get_irq_regs()));
88 check_rtc_time();
89 }
90
91 write_sequnlock(&xtime_lock);
92 return IRQ_HANDLED;
93}
94
95/*
96 * initialise the various timers used by the main part of the kernel
97 */
98void __init time_init(void)
99{
100 /* we need the prescalar running to be able to use IOCLK/8
101 * - IOCLK runs at 1/4 (ST5 open) or 1/8 (ST5 closed) internal CPU clock
102 * - IOCLK runs at Fosc rate (crystal speed)
103 */
104 TMPSCNT |= TMPSCNT_ENABLE;
105
106 startup_timestamp_counter();
107
108 printk(KERN_INFO
109 "timestamp counter I/O clock running at %lu.%02lu"
110 " (calibrated against RTC)\n",
111 MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100);
112
113 xtime.tv_sec = get_initial_rtc_time();
114 xtime.tv_nsec = 0;
115
116 mn10300_last_tsc = TMTSCBC;
117
118 /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */
119 setup_irq(TMJCIRQ, &timer_irq);
120
121 set_intr_level(TMJCIRQ, TMJCICR_LEVEL);
122
123 startup_jiffies_counter();
124
125#ifdef CONFIG_MN10300_WD_TIMER
126 /* start the watchdog timer */
127 watchdog_go();
128#endif
129}
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
new file mode 100644
index 000000000000..8b9dc6d9dcc6
--- /dev/null
+++ b/arch/mn10300/kernel/traps.c
@@ -0,0 +1,619 @@
1/* MN10300 Exception handling
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Modified by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/string.h>
15#include <linux/errno.h>
16#include <linux/ptrace.h>
17#include <linux/timer.h>
18#include <linux/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/init.h>
22#include <linux/delay.h>
23#include <linux/spinlock.h>
24#include <linux/interrupt.h>
25#include <linux/kallsyms.h>
26#include <linux/pci.h>
27#include <linux/kdebug.h>
28#include <linux/bug.h>
29#include <linux/irq.h>
30#include <asm/processor.h>
31#include <asm/system.h>
32#include <asm/uaccess.h>
33#include <asm/io.h>
34#include <asm/atomic.h>
35#include <asm/smp.h>
36#include <asm/pgalloc.h>
37#include <asm/cacheflush.h>
38#include <asm/cpu-regs.h>
39#include <asm/busctl-regs.h>
40#include <asm/unit/leds.h>
41#include <asm/fpu.h>
42#include <asm/gdb-stub.h>
43#include <asm/sections.h>
44
45#if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff)
46#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
47#endif
48
49struct pt_regs *__frame; /* current frame pointer */
50EXPORT_SYMBOL(__frame);
51
52int kstack_depth_to_print = 24;
53
54spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
55
56ATOMIC_NOTIFIER_HEAD(mn10300_die_chain);
57
58/*
59 * These constants are for searching for possible module text
60 * segments. MODULE_RANGE is a guess of how much space is likely
61 * to be vmalloced.
62 */
63#define MODULE_RANGE (8 * 1024 * 1024)
64
65#define DO_ERROR(signr, prologue, str, name) \
66asmlinkage void name(struct pt_regs *regs, u32 intcode) \
67{ \
68 prologue; \
69 if (die_if_no_fixup(str, regs, intcode)) \
70 return; \
71 force_sig(signr, current); \
72}
73
74#define DO_EINFO(signr, prologue, str, name, sicode) \
75asmlinkage void name(struct pt_regs *regs, u32 intcode) \
76{ \
77 siginfo_t info; \
78 prologue; \
79 if (die_if_no_fixup(str, regs, intcode)) \
80 return; \
81 info.si_signo = signr; \
82 if (signr == SIGILL && sicode == ILL_ILLOPC) { \
83 uint8_t opcode; \
84 if (get_user(opcode, (uint8_t __user *)regs->pc) == 0) \
85 if (opcode == 0xff) \
86 info.si_signo = SIGTRAP; \
87 } \
88 info.si_errno = 0; \
89 info.si_code = sicode; \
90 info.si_addr = (void *) regs->pc; \
91 force_sig_info(info.si_signo, &info, current); \
92}
93
94DO_ERROR(SIGTRAP, {}, "trap", trap);
95DO_ERROR(SIGSEGV, {}, "ibreak", ibreak);
96DO_ERROR(SIGSEGV, {}, "obreak", obreak);
97DO_EINFO(SIGSEGV, {}, "access error", access_error, SEGV_ACCERR);
98DO_EINFO(SIGSEGV, {}, "insn access error", insn_acc_error, SEGV_ACCERR);
99DO_EINFO(SIGSEGV, {}, "data access error", data_acc_error, SEGV_ACCERR);
100DO_EINFO(SIGILL, {}, "privileged opcode", priv_op, ILL_PRVOPC);
101DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC);
102DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
103DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
104DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
105DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC);
106
107DO_ERROR(SIGTRAP,
108#ifndef CONFIG_MN10300_USING_JTAG
109 DCR &= ~0x0001,
110#else
111 {},
112#endif
113 "single step", istep);
114
115/*
116 * handle NMI
117 */
118asmlinkage void nmi(struct pt_regs *regs, enum exception_code code)
119{
120 /* see if gdbstub wants to deal with it */
121#ifdef CONFIG_GDBSTUB
122 if (gdbstub_intercept(regs, code))
123 return;
124#endif
125
126 printk(KERN_WARNING "--- Register Dump ---\n");
127 show_registers(regs);
128 printk(KERN_WARNING "---------------------\n");
129}
130
131/*
132 * show a stack trace from the specified stack pointer
133 */
134void show_trace(unsigned long *sp)
135{
136 unsigned long *stack, addr, module_start, module_end;
137 int i;
138
139 printk(KERN_EMERG "\n"
140 KERN_EMERG "Call Trace:");
141
142 stack = sp;
143 i = 0;
144 module_start = VMALLOC_START;
145 module_end = VMALLOC_END;
146
147 while (((long) stack & (THREAD_SIZE - 1)) != 0) {
148 addr = *stack++;
149 if (__kernel_text_address(addr)) {
150#if 1
151 printk(" [<%08lx>]", addr);
152 print_symbol(" %s", addr);
153 printk("\n");
154#else
155 if ((i % 6) == 0)
156 printk("\n" KERN_EMERG " ");
157 printk("[<%08lx>] ", addr);
158 i++;
159#endif
160 }
161 }
162
163 printk("\n");
164}
165
166/*
167 * show the raw stack from the specified stack pointer
168 */
169void show_stack(struct task_struct *task, unsigned long *sp)
170{
171 unsigned long *stack;
172 int i;
173
174 if (!sp)
175 sp = (unsigned long *) &sp;
176
177 stack = sp;
178 printk(KERN_EMERG "Stack:");
179 for (i = 0; i < kstack_depth_to_print; i++) {
180 if (((long) stack & (THREAD_SIZE - 1)) == 0)
181 break;
182 if ((i % 8) == 0)
183 printk("\n" KERN_EMERG " ");
184 printk("%08lx ", *stack++);
185 }
186
187 show_trace(sp);
188}
189
190/*
191 * the architecture-independent dump_stack generator
192 */
193void dump_stack(void)
194{
195 unsigned long stack;
196
197 show_stack(current, &stack);
198}
199EXPORT_SYMBOL(dump_stack);
200
201/*
202 * dump the register file in the specified exception frame
203 */
204void show_registers_only(struct pt_regs *regs)
205{
206 unsigned long ssp;
207
208 ssp = (unsigned long) regs + sizeof(*regs);
209
210 printk(KERN_EMERG "PC: %08lx EPSW: %08lx SSP: %08lx mode: %s\n",
211 regs->pc, regs->epsw, ssp, user_mode(regs) ? "User" : "Super");
212 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
213 regs->d0, regs->d1, regs->d2, regs->d3);
214 printk(KERN_EMERG "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n",
215 regs->a0, regs->a1, regs->a2, regs->a3);
216 printk(KERN_EMERG "e0: %08lx e1: %08lx e2: %08lx e3: %08lx\n",
217 regs->e0, regs->e1, regs->e2, regs->e3);
218 printk(KERN_EMERG "e4: %08lx e5: %08lx e6: %08lx e7: %08lx\n",
219 regs->e4, regs->e5, regs->e6, regs->e7);
220 printk(KERN_EMERG "lar: %08lx lir: %08lx mdr: %08lx usp: %08lx\n",
221 regs->lar, regs->lir, regs->mdr, regs->sp);
222 printk(KERN_EMERG "cvf: %08lx crl: %08lx crh: %08lx drq: %08lx\n",
223 regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq);
224 printk(KERN_EMERG "threadinfo=%p task=%p)\n",
225 current_thread_info(), current);
226
227 if ((unsigned long) current >= 0x90000000UL &&
228 (unsigned long) current < 0x94000000UL)
229 printk(KERN_EMERG "Process %s (pid: %d)\n",
230 current->comm, current->pid);
231
232 printk(KERN_EMERG "CPUP: %04hx\n", CPUP);
233 printk(KERN_EMERG "TBR: %08x\n", TBR);
234 printk(KERN_EMERG "DEAR: %08x\n", DEAR);
235 printk(KERN_EMERG "sISR: %08x\n", sISR);
236 printk(KERN_EMERG "NMICR: %04hx\n", NMICR);
237 printk(KERN_EMERG "BCBERR: %08x\n", BCBERR);
238 printk(KERN_EMERG "BCBEAR: %08x\n", BCBEAR);
239 printk(KERN_EMERG "MMUFCR: %08x\n", MMUFCR);
240 printk(KERN_EMERG "IPTEU : %08x IPTEL2: %08x\n", IPTEU, IPTEL2);
241 printk(KERN_EMERG "DPTEU: %08x DPTEL2: %08x\n", DPTEU, DPTEL2);
242}
243
244/*
245 * dump the registers and the stack
246 */
247void show_registers(struct pt_regs *regs)
248{
249 unsigned long sp;
250 int i;
251
252 show_registers_only(regs);
253
254 if (!user_mode(regs))
255 sp = (unsigned long) regs + sizeof(*regs);
256 else
257 sp = regs->sp;
258
259 /* when in-kernel, we also print out the stack and code at the
260 * time of the fault..
261 */
262 if (!user_mode(regs)) {
263 printk(KERN_EMERG "\n");
264 show_stack(current, (unsigned long *) sp);
265
266#if 0
267 printk(KERN_EMERG "\n"
268 KERN_EMERG "Code: ");
269 if (regs->pc < PAGE_OFFSET)
270 goto bad;
271
272 for (i = 0; i < 20; i++) {
273 unsigned char c;
274 if (__get_user(c, &((unsigned char *) regs->pc)[i]))
275 goto bad;
276 printk("%02x ", c);
277 }
278#else
279 i = 0;
280#endif
281 }
282
283 printk("\n");
284 return;
285
286#if 0
287bad:
288 printk(KERN_EMERG " Bad PC value.");
289 break;
290#endif
291}
292
293/*
294 *
295 */
296void show_trace_task(struct task_struct *tsk)
297{
298 unsigned long sp = tsk->thread.sp;
299
300 /* User space on another CPU? */
301 if ((sp ^ (unsigned long) tsk) & (PAGE_MASK << 1))
302 return;
303
304 show_trace((unsigned long *) sp);
305}
306
307/*
308 * note the untimely death of part of the kernel
309 */
310void die(const char *str, struct pt_regs *regs, enum exception_code code)
311{
312 console_verbose();
313 spin_lock_irq(&die_lock);
314 printk(KERN_EMERG "\n"
315 KERN_EMERG "%s: %04x\n",
316 str, code & 0xffff);
317 show_registers(regs);
318
319 if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 &&
320 (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) {
321 printk(KERN_EMERG "Exception in usermode interrupt handler\n");
322 printk(KERN_EMERG "\n"
323 KERN_EMERG " Please connect to kernel debugger !!\n");
324 asm volatile ("0: bra 0b");
325 }
326
327 spin_unlock_irq(&die_lock);
328 do_exit(SIGSEGV);
329}
330
331/*
332 * see if there's a fixup handler we can force a jump to when an exception
333 * happens due to something kernel code did
334 */
335int die_if_no_fixup(const char *str, struct pt_regs *regs,
336 enum exception_code code)
337{
338 if (user_mode(regs))
339 return 0;
340
341 peripheral_leds_display_exception(code);
342
343 switch (code) {
344 /* see if we can fixup the kernel accessing memory */
345 case EXCEP_ITLBMISS:
346 case EXCEP_DTLBMISS:
347 case EXCEP_IAERROR:
348 case EXCEP_DAERROR:
349 case EXCEP_MEMERR:
350 case EXCEP_MISALIGN:
351 case EXCEP_BUSERROR:
352 case EXCEP_ILLDATACC:
353 case EXCEP_IOINSACC:
354 case EXCEP_PRIVINSACC:
355 case EXCEP_PRIVDATACC:
356 case EXCEP_DATINSACC:
357 if (fixup_exception(regs))
358 return 1;
359 case EXCEP_UNIMPINS:
360 if (regs->pc && *(uint8_t *)regs->pc == 0xff)
361 if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
362 return 1;
363 break;
364 default:
365 break;
366 }
367
368 /* see if gdbstub wants to deal with it */
369#ifdef CONFIG_GDBSTUB
370 if (gdbstub_intercept(regs, code))
371 return 1;
372#endif
373
374 if (notify_die(DIE_GPF, str, regs, code, 0, 0))
375 return 1;
376
377 /* make the process die as the last resort */
378 die(str, regs, code);
379}
380
381/*
382 * handle unsupported syscall instructions (syscall 1-15)
383 */
384static asmlinkage void unsupported_syscall(struct pt_regs *regs,
385 enum exception_code code)
386{
387 struct task_struct *tsk = current;
388 siginfo_t info;
389
390 /* catch a kernel BUG() */
391 if (code == EXCEP_SYSCALL15 && !user_mode(regs)) {
392 if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) {
393#ifdef CONFIG_GDBSTUB
394 __gdbstub_bug_trap();
395#endif
396 }
397 }
398
399 regs->pc -= 2; /* syscall return addr is _after_ the instruction */
400
401 die_if_no_fixup("An unsupported syscall insn was used by the kernel\n",
402 regs, code);
403
404 info.si_signo = SIGILL;
405 info.si_errno = ENOSYS;
406 info.si_code = ILL_ILLTRP;
407 info.si_addr = (void *) regs->pc;
408 force_sig_info(SIGILL, &info, tsk);
409}
410
411/*
412 * display the register file when the stack pointer gets clobbered
413 */
414asmlinkage void do_double_fault(struct pt_regs *regs)
415{
416 struct task_struct *tsk = current;
417
418 strcpy(tsk->comm, "emergency tsk");
419 tsk->pid = 0;
420 console_verbose();
421 printk(KERN_EMERG "--- double fault ---\n");
422 show_registers(regs);
423}
424
425/*
426 * asynchronous bus error (external, usually I/O DMA)
427 */
428asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs)
429{
430 console_verbose();
431
432 printk(KERN_EMERG "\n"
433 KERN_EMERG "Asynchronous I/O Bus Error\n"
434 KERN_EMERG "==========================\n");
435
436 if (bcberr & BCBERR_BEME)
437 printk(KERN_EMERG "- Multiple recorded errors\n");
438
439 printk(KERN_EMERG "- Faulting Buses:%s%s%s\n",
440 bcberr & BCBERR_BEMR_CI ? " CPU-Ins-Fetch" : "",
441 bcberr & BCBERR_BEMR_CD ? " CPU-Data" : "",
442 bcberr & BCBERR_BEMR_DMA ? " DMA" : "");
443
444 printk(KERN_EMERG "- %s %s access made to %s at address %08x\n",
445 bcberr & BCBERR_BEBST ? "Burst" : "Single",
446 bcberr & BCBERR_BERW ? "Read" : "Write",
447 bcberr & BCBERR_BESB_MON ? "Monitor Space" :
448 bcberr & BCBERR_BESB_IO ? "Internal CPU I/O Space" :
449 bcberr & BCBERR_BESB_EX ? "External I/O Bus" :
450 bcberr & BCBERR_BESB_OPEX ? "External Memory Bus" :
451 "On Chip Memory",
452 bcbear
453 );
454
455 printk(KERN_EMERG "- Detected by the %s\n",
456 bcberr&BCBERR_BESD ? "Bus Control Unit" : "Slave Bus");
457
458#ifdef CONFIG_PCI
459#define BRIDGEREGB(X) (*(volatile __u8 *)(0xBE040000 + (X)))
460#define BRIDGEREGW(X) (*(volatile __u16 *)(0xBE040000 + (X)))
461#define BRIDGEREGL(X) (*(volatile __u32 *)(0xBE040000 + (X)))
462
463 printk(KERN_EMERG "- PCI Memory Paging Reg: %08x\n",
464 *(volatile __u32 *) (0xBFFFFFF4));
465 printk(KERN_EMERG "- PCI Bridge Base Address 0: %08x\n",
466 BRIDGEREGL(PCI_BASE_ADDRESS_0));
467 printk(KERN_EMERG "- PCI Bridge AMPCI Base Address: %08x\n",
468 BRIDGEREGL(0x48));
469 printk(KERN_EMERG "- PCI Bridge Command: %04hx\n",
470 BRIDGEREGW(PCI_COMMAND));
471 printk(KERN_EMERG "- PCI Bridge Status: %04hx\n",
472 BRIDGEREGW(PCI_STATUS));
473 printk(KERN_EMERG "- PCI Bridge Int Status: %08hx\n",
474 BRIDGEREGL(0x4c));
475#endif
476
477 printk(KERN_EMERG "\n");
478 show_registers(regs);
479
480 panic("Halted due to asynchronous I/O Bus Error\n");
481}
482
483/*
484 * handle an exception for which a handler has not yet been installed
485 */
486asmlinkage void uninitialised_exception(struct pt_regs *regs,
487 enum exception_code code)
488{
489
490 /* see if gdbstub wants to deal with it */
491#ifdef CONFIG_GDBSTUB
492 if (gdbstub_intercept(regs, code))
493 return;
494#endif
495
496 peripheral_leds_display_exception(code);
497 printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF);
498 show_registers(regs);
499
500 for (;;)
501 continue;
502}
503
504/*
505 * set an interrupt stub to jump to a handler
506 * ! NOTE: this does *not* flush the caches
507 */
508void __init __set_intr_stub(enum exception_code code, void *handler)
509{
510 unsigned long addr;
511 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
512
513 addr = (unsigned long) handler - (unsigned long) vector;
514 vector[0] = 0xdc; /* JMP handler */
515 vector[1] = addr;
516 vector[2] = addr >> 8;
517 vector[3] = addr >> 16;
518 vector[4] = addr >> 24;
519 vector[5] = 0xcb;
520 vector[6] = 0xcb;
521 vector[7] = 0xcb;
522}
523
524/*
525 * set an interrupt stub to jump to a handler
526 */
527void __init set_intr_stub(enum exception_code code, void *handler)
528{
529 unsigned long addr;
530 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
531
532 addr = (unsigned long) handler - (unsigned long) vector;
533 vector[0] = 0xdc; /* JMP handler */
534 vector[1] = addr;
535 vector[2] = addr >> 8;
536 vector[3] = addr >> 16;
537 vector[4] = addr >> 24;
538 vector[5] = 0xcb;
539 vector[6] = 0xcb;
540 vector[7] = 0xcb;
541
542 mn10300_dcache_flush_inv();
543 mn10300_icache_inv();
544}
545
546/*
547 * set an interrupt stub to invoke the JTAG unit and then jump to a handler
548 */
549void __init set_jtag_stub(enum exception_code code, void *handler)
550{
551 unsigned long addr;
552 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
553
554 addr = (unsigned long) handler - ((unsigned long) vector + 1);
555 vector[0] = 0xff; /* PI to jump into JTAG debugger */
556 vector[1] = 0xdc; /* jmp handler */
557 vector[2] = addr;
558 vector[3] = addr >> 8;
559 vector[4] = addr >> 16;
560 vector[5] = addr >> 24;
561 vector[6] = 0xcb;
562 vector[7] = 0xcb;
563
564 mn10300_dcache_flush_inv();
565 flush_icache_range((unsigned long) vector, (unsigned long) vector + 8);
566}
567
568/*
569 * initialise the exception table
570 */
571void __init trap_init(void)
572{
573 set_excp_vector(EXCEP_TRAP, trap);
574 set_excp_vector(EXCEP_ISTEP, istep);
575 set_excp_vector(EXCEP_IBREAK, ibreak);
576 set_excp_vector(EXCEP_OBREAK, obreak);
577
578 set_excp_vector(EXCEP_PRIVINS, priv_op);
579 set_excp_vector(EXCEP_UNIMPINS, invalid_op);
580 set_excp_vector(EXCEP_UNIMPEXINS, invalid_exop);
581 set_excp_vector(EXCEP_MEMERR, mem_error);
582 set_excp_vector(EXCEP_MISALIGN, misalignment);
583 set_excp_vector(EXCEP_BUSERROR, bus_error);
584 set_excp_vector(EXCEP_ILLINSACC, insn_acc_error);
585 set_excp_vector(EXCEP_ILLDATACC, data_acc_error);
586 set_excp_vector(EXCEP_IOINSACC, insn_acc_error);
587 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
588 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
589 set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
590 set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled);
591 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
592 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
593
594 set_excp_vector(EXCEP_NMI, nmi);
595
596 set_excp_vector(EXCEP_SYSCALL1, unsupported_syscall);
597 set_excp_vector(EXCEP_SYSCALL2, unsupported_syscall);
598 set_excp_vector(EXCEP_SYSCALL3, unsupported_syscall);
599 set_excp_vector(EXCEP_SYSCALL4, unsupported_syscall);
600 set_excp_vector(EXCEP_SYSCALL5, unsupported_syscall);
601 set_excp_vector(EXCEP_SYSCALL6, unsupported_syscall);
602 set_excp_vector(EXCEP_SYSCALL7, unsupported_syscall);
603 set_excp_vector(EXCEP_SYSCALL8, unsupported_syscall);
604 set_excp_vector(EXCEP_SYSCALL9, unsupported_syscall);
605 set_excp_vector(EXCEP_SYSCALL10, unsupported_syscall);
606 set_excp_vector(EXCEP_SYSCALL11, unsupported_syscall);
607 set_excp_vector(EXCEP_SYSCALL12, unsupported_syscall);
608 set_excp_vector(EXCEP_SYSCALL13, unsupported_syscall);
609 set_excp_vector(EXCEP_SYSCALL14, unsupported_syscall);
610 set_excp_vector(EXCEP_SYSCALL15, unsupported_syscall);
611}
612
613/*
614 * determine if a program counter value is a valid bug address
615 */
616int is_valid_bugaddr(unsigned long pc)
617{
618 return pc >= PAGE_OFFSET;
619}
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..a3e80f444f55
--- /dev/null
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -0,0 +1,159 @@
1/* MN10300 Main kernel linker script
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#define __VMLINUX_LDS__
12#include <asm-generic/vmlinux.lds.h>
13#include <asm/thread_info.h>
14
15OUTPUT_FORMAT("elf32-am33lin", "elf32-am33lin", "elf32-am33lin")
16OUTPUT_ARCH(mn10300)
17ENTRY(_start)
18jiffies = jiffies_64;
19#ifndef CONFIG_MN10300_CURRENT_IN_E2
20current = __current;
21#endif
22SECTIONS
23{
24 . = CONFIG_KERNEL_TEXT_ADDRESS;
25 /* read-only */
26 _stext = .;
27 _text = .; /* Text and read-only data */
28 .text : {
29 *(
30 .text.head
31 .text
32 )
33 TEXT_TEXT
34 SCHED_TEXT
35 LOCK_TEXT
36 KPROBES_TEXT
37 *(.fixup)
38 *(.gnu.warning)
39 } = 0xcb
40
41 _etext = .; /* End of text section */
42
43 . = ALIGN(16); /* Exception table */
44 __start___ex_table = .;
45 __ex_table : { *(__ex_table) }
46 __stop___ex_table = .;
47
48 BUG_TABLE
49
50 RODATA
51
52 /* writeable */
53 .data : { /* Data */
54 DATA_DATA
55 CONSTRUCTORS
56 }
57
58 . = ALIGN(4096);
59 __nosave_begin = .;
60 .data_nosave : { *(.data.nosave) }
61 . = ALIGN(4096);
62 __nosave_end = .;
63
64 . = ALIGN(4096);
65 .data.page_aligned : { *(.data.idt) }
66
67 . = ALIGN(32);
68 .data.cacheline_aligned : { *(.data.cacheline_aligned) }
69
70 /* rarely changed data like cpu maps */
71 . = ALIGN(32);
72 .data.read_mostly : AT(ADDR(.data.read_mostly)) {
73 *(.data.read_mostly)
74 _edata = .; /* End of data section */
75 }
76
77 . = ALIGN(THREAD_SIZE); /* init_task */
78 .data.init_task : { *(.data.init_task) }
79
80 /* might get freed after init */
81 . = ALIGN(4096);
82 .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
83 __smp_locks = .;
84 *(.smp_locks)
85 __smp_locks_end = .;
86 }
87
88 /* will be freed after init */
89 . = ALIGN(4096); /* Init code and data */
90 __init_begin = .;
91 .init.text : {
92 _sinittext = .;
93 *(.init.text)
94 _einittext = .;
95 }
96 .init.data : { *(.init.data) }
97 . = ALIGN(16);
98 __setup_start = .;
99 .setup.init : { KEEP(*(.init.setup)) }
100 __setup_end = .;
101
102 __initcall_start = .;
103 .initcall.init : {
104 INITCALLS
105 }
106 __initcall_end = .;
107 __con_initcall_start = .;
108 .con_initcall.init : { *(.con_initcall.init) }
109 __con_initcall_end = .;
110
111 SECURITY_INIT
112 . = ALIGN(4);
113 __alt_instructions = .;
114 .altinstructions : { *(.altinstructions) }
115 __alt_instructions_end = .;
116 .altinstr_replacement : { *(.altinstr_replacement) }
117 /* .exit.text is discard at runtime, not link time, to deal with references
118 from .altinstructions and .eh_frame */
119 .exit.text : { *(.exit.text) }
120 .exit.data : { *(.exit.data) }
121
122#ifdef CONFIG_BLK_DEV_INITRD
123 . = ALIGN(4096);
124 __initramfs_start = .;
125 .init.ramfs : { *(.init.ramfs) }
126 __initramfs_end = .;
127#endif
128
129 . = ALIGN(32);
130 __per_cpu_start = .;
131 .data.percpu : { *(.data.percpu) }
132 __per_cpu_end = .;
133 . = ALIGN(4096);
134 __init_end = .;
135 /* freed after init ends here */
136
137 __bss_start = .; /* BSS */
138 .bss : {
139 *(.bss.page_aligned)
140 *(.bss)
141 }
142 . = ALIGN(4);
143 __bss_stop = .;
144
145 _end = . ;
146
147 /* This is where the kernel creates the early boot page tables */
148 . = ALIGN(4096);
149 pg0 = .;
150
151 /* Sections to be discarded */
152 /DISCARD/ : {
153 *(.exitcall.exit)
154 }
155
156 STABS_DEBUG
157
158 DWARF_DEBUG
159}